diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common-util/wiki-data.js | 9 | ||||
-rw-r--r-- | src/content/dependencies/generateArtistCredit.js | 26 | ||||
-rw-r--r-- | src/content/dependencies/generateCommentaryEntry.js | 6 | ||||
-rw-r--r-- | src/content/dependencies/transformContent.js | 99 | ||||
-rw-r--r-- | src/data/checks.js | 4 | ||||
-rw-r--r-- | src/data/yaml.js | 2 | ||||
-rw-r--r-- | src/replacer.js | 7 | ||||
-rw-r--r-- | src/static/css/site.css | 53 |
8 files changed, 182 insertions, 24 deletions
diff --git a/src/common-util/wiki-data.js b/src/common-util/wiki-data.js index a4c6b3bd..c993f4ac 100644 --- a/src/common-util/wiki-data.js +++ b/src/common-util/wiki-data.js @@ -60,7 +60,7 @@ export function getKebabCase(name) { // Matches heading details from commentary data in roughly the formats: // // <i>artistReference:</i> (annotation, date) -// <i>artistReference|artistDisplayText:</i> (annotation, date) +// <i>artistReference|artistText:</i> (annotation, date) // // where capturing group "annotation" can be any text at all, except that the // last entry (past a comma or the only content within parentheses), if parsed @@ -83,8 +83,9 @@ export function getKebabCase(name) { // parentheses can be part of the actual annotation content. // // Capturing group "artistReference" is all the characters between <i> and </i> -// (apart from the pipe and "artistDisplayText" text, if present), and is either -// the name of an artist or an "artist:directory"-style reference. +// (apart from the pipe and the "artistText" group, if present), and is either +// the name of one or more artist or "artist:directory"-style references, +// joined by commas, if multiple. // // This regular expression *doesn't* match bodies, which will need to be parsed // out of the original string based on the indices matched using this. @@ -94,7 +95,7 @@ const dateRegex = groupName => String.raw`(?<${groupName}>[a-zA-Z]+ [0-9]{1,2}, [0-9]{4,4}|[0-9]{1,2} [^,]*[0-9]{4,4}|[0-9]{1,4}[-/][0-9]{1,4}[-/][0-9]{1,4})`; const commentaryRegexRaw = - String.raw`^<i>(?<artistReferences>.+?)(?:\|(?<artistDisplayText>.+))?:<\/i>(?: \((?<annotation>(?:.*?(?=,|\)[^)]*$))*?)(?:,? ?(?:(?<dateKind>sometime|throughout|around) )?${dateRegex('date')}(?: ?- ?${dateRegex('secondDate')})?(?: (?<accessKind>captured|accessed) ${dateRegex('accessDate')})?)?\))?`; + String.raw`^<i>(?<artistReferences>.+?)(?:\|(?<artistText>.+))?:<\/i>(?: \((?<annotation>(?:.*?(?=,|\)[^)]*$))*?)(?:,? ?(?:(?<dateKind>sometime|throughout|around) )?${dateRegex('date')}(?: ?- ?${dateRegex('secondDate')})?(?: (?<accessKind>captured|accessed) ${dateRegex('accessDate')})?)?\))?`; export const commentaryRegexCaseInsensitive = new RegExp(commentaryRegexRaw, 'gmi'); export const commentaryRegexCaseSensitive = diff --git a/src/content/dependencies/generateArtistCredit.js b/src/content/dependencies/generateArtistCredit.js index 6bdbeb23..bab32f7d 100644 --- a/src/content/dependencies/generateArtistCredit.js +++ b/src/content/dependencies/generateArtistCredit.js @@ -36,11 +36,18 @@ export default { // Note that the normal contributions will implicitly *always* // "differ from context" if no context contributions are given, // as in release info lines. - query.normalContributionsDifferFromContext = + + query.normalContributionArtistsDifferFromContext = !compareArrays( query.normalContributions.map(({artist}) => artist), contextNormalContributions.map(({artist}) => artist), - {checkOrder: false}); + {checkOrder: true}); + + query.normalContributionAnnotationsDifferFromContext = + !compareArrays( + query.normalContributions.map(({annotation}) => annotation), + contextNormalContributions.map(({annotation}) => annotation), + {checkOrder: true}); return query; }, @@ -60,8 +67,11 @@ export default { }), data: (query, _creditContributions, _contextContributions) => ({ - normalContributionsDifferFromContext: - query.normalContributionsDifferFromContext, + normalContributionArtistsDifferFromContext: + query.normalContributionArtistsDifferFromContext, + + normalContributionAnnotationsDifferFromContext: + query.normalContributionAnnotationsDifferFromContext, hasWikiEdits: !empty(query.wikiEditContributions), @@ -148,8 +158,12 @@ export default { ...relations.featuringContributionLinks, ]); + const effectivelyDiffers = + (slots.showAnnotation && data.normalContributionAnnotationsDifferFromContext) || + (data.normalContributionArtistsDifferFromContext); + if (empty(relations.featuringContributionLinks)) { - if (data.normalContributionsDifferFromContext) { + if (effectivelyDiffers) { return language.$(slots.normalStringKey, { ...slots.additionalStringOptions, artists: artistsList, @@ -159,7 +173,7 @@ export default { } } - if (data.normalContributionsDifferFromContext && slots.normalFeaturingStringKey) { + if (effectivelyDiffers && slots.normalFeaturingStringKey) { return language.$(slots.normalFeaturingStringKey, { ...slots.additionalStringOptions, artists: artistsList, diff --git a/src/content/dependencies/generateCommentaryEntry.js b/src/content/dependencies/generateCommentaryEntry.js index c93020f3..367de506 100644 --- a/src/content/dependencies/generateCommentaryEntry.js +++ b/src/content/dependencies/generateCommentaryEntry.js @@ -12,14 +12,14 @@ export default { relations: (relation, entry) => ({ artistLinks: - (!empty(entry.artists) && !entry.artistDisplayText + (!empty(entry.artists) && !entry.artistText ? entry.artists .map(artist => relation('linkArtist', artist)) : null), artistsContent: - (entry.artistDisplayText - ? relation('transformContent', entry.artistDisplayText) + (entry.artistText + ? relation('transformContent', entry.artistText) : null), annotationContent: diff --git a/src/content/dependencies/transformContent.js b/src/content/dependencies/transformContent.js index 1bbd45e2..805c3625 100644 --- a/src/content/dependencies/transformContent.js +++ b/src/content/dependencies/transformContent.js @@ -46,6 +46,14 @@ function getPlaceholder(node, content) { return {type: 'text', data: content.slice(node.i, node.iEnd)}; } +function getArg(node, argKey) { + return ( + node.data.args + ?.find(({key}) => key.data === argKey) + ?.value ?? + null); +} + export default { contentDependencies: [ ...( @@ -53,6 +61,8 @@ export default { .map(description => description.link) .filter(Boolean)), 'image', + 'generateTextWithTooltip', + 'generateTooltip', 'linkExternal', ], @@ -134,6 +144,30 @@ export default { return {i: node.i, iEnd: node.iEnd, type: 'internal-link', data}; } + if (replacerKey === 'tooltip') { + // TODO: Again, no recursive nodes. Sorry! + // const enteredLabel = node.data.label && transformNode(node.data.label, opts); + const enteredLabel = node.data.label?.data; + + return { + i: node.i, + iEnd: node.iEnd, + type: 'tooltip', + data: { + tooltip: + replacerValue ?? '(empty tooltip...)', + + label: + enteredLabel ?? '(tooltip without label)', + + link: + (getArg(node, 'link') + ? getArg(node, 'link')[0].data + : null), + }, + }; + } + // This will be another {type: 'tag'} node which gets processed in // generate. Extract replacerKey and replacerValue now, since it'd // be a pain to deal with later. @@ -191,6 +225,12 @@ export default { : getPlaceholder(node, content)); return { + textWithTooltip: + relation('generateTextWithTooltip'), + + tooltip: + relation('generateTooltip'), + internalLinks: nodes .filter(({type}) => type === 'internal-link') @@ -209,11 +249,15 @@ export default { externalLinks: nodes .filter(({type}) => type === 'external-link') - .map(node => { - const {href} = node.data; + .map(({data: {href}}) => + relation('linkExternal', href)), - return relation('linkExternal', href); - }), + externalLinksForTooltipNodes: + nodes + .filter(({type}) => type === 'tooltip') + .filter(({data}) => data.link) + .map(({data: {link: href}}) => + relation('linkExternal', href)), images: nodes @@ -259,6 +303,7 @@ export default { let imageIndex = 0; let internalLinkIndex = 0; let externalLinkIndex = 0; + let externalLinkForTooltipNodeIndex = 0; let offsetTextNode = 0; @@ -548,6 +593,52 @@ export default { return {type: 'processed-external-link', data: externalLink}; } + case 'tooltip': { + const {label, link, tooltip: tooltipContent} = node.data; + + const externalLink = + (link + ? relations.externalLinksForTooltipNodes + .at(externalLinkForTooltipNodeIndex++) + : null); + + if (externalLink) { + externalLink.setSlots({ + content: label, + fromContent: true, + }); + + if (slots.indicateExternalLinks) { + externalLink.setSlots({ + indicateExternal: true, + disableBrowserTooltip: true, + tab: 'separate', + style: 'platform', + }); + } + } + + const textWithTooltip = relations.textWithTooltip.clone(); + const tooltip = relations.tooltip.clone(); + + tooltip.setSlots({ + attributes: {class: 'content-tooltip'}, + content: tooltipContent, // Not sanitized! + }); + + textWithTooltip.setSlots({ + attributes: [ + {class: 'content-tooltip-guy'}, + externalLink && {class: 'has-link'}, + ], + + text: externalLink ?? label, + tooltip, + }); + + return {type: 'processed-tooltip', data: textWithTooltip}; + } + case 'tag': { const {replacerKey, replacerValue} = node.data; diff --git a/src/data/checks.js b/src/data/checks.js index 52024144..c395f2f0 100644 --- a/src/data/checks.js +++ b/src/data/checks.js @@ -567,13 +567,13 @@ export function reportContentTextErrors(wikiData, { const commentaryShape = { body: 'commentary body', - artistDisplayText: 'commentary artist display text', + artistText: 'commentary artist text', annotation: 'commentary annotation', }; const lyricsShape = { body: 'lyrics body', - artistDisplayText: 'lyrics artist display text', + artistText: 'lyrics artist text', annotation: 'lyrics annotation', }; diff --git a/src/data/yaml.js b/src/data/yaml.js index 036fe8a7..c6600121 100644 --- a/src/data/yaml.js +++ b/src/data/yaml.js @@ -835,7 +835,7 @@ export function parseContentEntries(thingClass, sourceText, {subdoc}) { .map(ref => ref.trim()), 'Artist Text': - matchEntry.artistDisplayText, + matchEntry.artistText, 'Annotation': matchEntry.annotation, diff --git a/src/replacer.js b/src/replacer.js index 32657a5a..d285a7ea 100644 --- a/src/replacer.js +++ b/src/replacer.js @@ -174,6 +174,11 @@ export const replacerSpec = { find: 'trackWithArtwork', link: 'linkTrackReferencingArtworks', }, + + 'tooltip': { + value: (ref) => ref, + link: null, + } }; // Syntax literals. @@ -649,6 +654,7 @@ export function postprocessVideos(inputNodes) { if (attributes.get('width')) node.width = parseInt(attributes.get('width')); if (attributes.get('height')) node.height = parseInt(attributes.get('height')); + if (attributes.get('align')) node.align = attributes.get('align'); if (attributes.get('pixelate')) node.pixelate = true; return node; @@ -662,6 +668,7 @@ export function postprocessAudios(inputNodes) { node.src = attributes.get('src'); node.inline = attributes.get('inline') ?? inline; + if (attributes.get('align')) node.align = attributes.get('align'); return node; }); diff --git a/src/static/css/site.css b/src/static/css/site.css index 962dc896..60e93708 100644 --- a/src/static/css/site.css +++ b/src/static/css/site.css @@ -1246,7 +1246,8 @@ li:not(:first-child:last-child) .tooltip:where(:not(.cover-artwork .tooltip)), .missing-duration-tooltip, .commentary-date-tooltip, .rerelease-tooltip, -.first-release-tooltip { +.first-release-tooltip, +.content-tooltip { padding: 3px 4px 2px 2px; left: -10px; } @@ -1428,6 +1429,30 @@ li:not(:first-child:last-child) .tooltip:where(:not(.cover-artwork .tooltip)), font-size: 0.9em; } +.content-tooltip-guy .hoverable a { + text-decoration-color: transparent; + text-decoration-style: dotted; +} + +.content-tooltip-guy { + display: inline-block; +} + +.content-tooltip-guy.has-link .text-with-tooltip-interaction-cue { + text-decoration-color: var(--primary-color); +} + +.content-tooltip .tooltip-content { + padding: 3px 4.5px; + width: 240px; +} + +.cover-artwork .content-tooltip { + font-size: 0.85rem; + padding: 2px 3px; + width: 220px; +} + .external-icon { display: inline-block; padding: 0 3px; @@ -1478,6 +1503,22 @@ s.spoiler::-moz-selection { background: white; } +span.path { + font-size: 0.9em; + font-family: "courier new", monospace; + font-weight: 800; +} + +span.path i { + display: inline-block; + font-style: normal; +} + +span.path i::before { + content: "\0020/\0020"; + color: #ccc; +} + progress { accent-color: var(--primary-color); } @@ -1741,9 +1782,7 @@ p.image-details.origin-details { margin-bottom: 1em; } -.content-image-container.align-center, -.content-video-container.align-center, -.content-audio-container.align-center { +.content-image-container.align-center { text-align: center; margin-top: 1.5em; margin-bottom: 1.5em; @@ -2469,6 +2508,12 @@ html[data-url-key="localized.listing"][data-url-value0="tags/network"] dl dt:las display: block; } +.content-video-container.align-center, +.content-audio-container.align-center { + margin-left: auto; + margin-right: auto; +} + .image-text-area { position: absolute; top: 0; |