diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/content/dependencies/generateTrackNavLinks.js | 4 | ||||
| -rw-r--r-- | src/content/dependencies/linkExternal.js | 4 | ||||
| -rw-r--r-- | src/html.js | 100 | ||||
| -rw-r--r-- | src/static/css/miscellany.css | 4 |
4 files changed, 96 insertions, 16 deletions
diff --git a/src/content/dependencies/generateTrackNavLinks.js b/src/content/dependencies/generateTrackNavLinks.js index 0fcd2118..836ada5f 100644 --- a/src/content/dependencies/generateTrackNavLinks.js +++ b/src/content/dependencies/generateTrackNavLinks.js @@ -12,7 +12,9 @@ export default { data: (track) => ({ showTrackSection: - track.album.showTrackSectionInNavBar, + track.album.showTrackSectionInNavBar && + (track.album.trackSections.length >= 2 || + !track.trackSection.isDefaultTrackSection), hasTrackNumbers: track.album.hasTrackNumbers, diff --git a/src/content/dependencies/linkExternal.js b/src/content/dependencies/linkExternal.js index 52e43250..5bfad5f4 100644 --- a/src/content/dependencies/linkExternal.js +++ b/src/content/dependencies/linkExternal.js @@ -133,6 +133,10 @@ export default { if (html.isBlank(slots.content)) { linkContent = formattedLink; + } else if (slots.fromContent) { + linkContent = + html.metatag('breakout', + slots.content); } else { linkContent = slots.content; } diff --git a/src/html.js b/src/html.js index cde86a5c..7b8f327a 100644 --- a/src/html.js +++ b/src/html.js @@ -152,6 +152,14 @@ export const blockwrap = Symbol(); // considered wrappable units, not the entire element! export const chunkwrap = Symbol(); +// Don't pass this directly, use html.metatag('breakout') instead. +// Causes *contained* content to be excluded from any *containing* metatag +// to do with special line breaking, i.e. blockwrap or chunkwrap, regardless +// the hierarchical distance. Practically, that means momentarily concluding +// the containing metatag's behavior wherever it operates, then starting more +// or less anew, so the metatag still applies to any following content. +export const breakout = Symbol(); + // Don't pass this directly, use html.metatag('imaginary-sibling') instead. // A tag without any content, which is completely ignored when serializing, // but makes siblings with [onlyIfSiblings] feel less shy and show up on @@ -391,6 +399,9 @@ export function metatag(identifier, ...args) { case 'chunkwrap': return new Tag(null, {[chunkwrap]: true, ...opts}, content); + case 'breakout': + return new Tag(null, {[breakout]: true}, content); + case 'imaginary-sibling': return new Tag(null, {[imaginarySibling]: true}, content); @@ -691,6 +702,14 @@ export class Tag { return this.#getAttributeFlag(chunkwrap); } + get breakout() { + return this.#getAttributeFlag(breakout); + } + + set breakout(value) { + this.#setAttributeFlag(breakout, value); + } + set imaginarySibling(value) { this.#setAttributeFlag(imaginarySibling, value); @@ -783,10 +802,7 @@ export class Tag { ? this.#getAttributeRaw('split') : null); - let seenChunkwrapSplitter = - (this.chunkwrap - ? false - : null); + let insideOpenChunkwrapChunk = false; const contentItems = (this.chunkwrap @@ -800,6 +816,10 @@ export class Tag { getItemContent: item => item.toString(), appendItemContent(content, itemContent, item) { + // We can only place our own chunkwrap splits within text content - + // we can't open a span and then close that span inside a tag that's + // CONTAINED inside the very same span. So check for splits in text, + // not in tags. const chunkwrapChunks = (typeof item === 'string' && chunkwrapSplitter ? Array.from(getChunkwrapChunks(itemContent, chunkwrapSplitter)) @@ -810,16 +830,33 @@ export class Tag { ? chunkwrapChunks.length > 1 : null); + // However, we can detect chunkwraps contained *within* non-text + // content, and adapt accordingly - by closing the current chunk and + // "deferring" to the chunks contained within this item. + const itemIncludesItsOwnChunkwrap = + typeof item !== 'string' && + chunkwrapSplitter && + itemContent.includes('<span class="chunkwrap"'); + + const itemIncludesBreakout = + typeof item !== 'string' && + itemContent.includes(`<span class="breakout"`); + if (content) { - if (itemIncludesChunkwrapSplit && !seenChunkwrapSplitter) { + if ( + itemIncludesChunkwrapSplit && !insideOpenChunkwrapChunk || + itemIncludesItsOwnChunkwrap && !insideOpenChunkwrapChunk || + itemIncludesBreakout && chunkwrapSplitter && !insideOpenChunkwrapChunk + ) { // The first time we see a chunkwrap splitter, backtrack and wrap // the content *so far* in a chunk. This will be treated just like // any other open chunkwrap, and closed after the first chunk of // this item! (That means the existing content is part of the same // chunk as the first chunk included in this content, which makes - // sense, because that first chink is really just more text that + // sense, because that first chunk is really just more text that // precedes the first split.) content = `<span class="chunkwrap">` + content; + insideOpenChunkwrapChunk = true; } content += joiner; @@ -830,10 +867,7 @@ export class Tag { // enter a chunkwrap wrapper *now*, so the first chunk of this // item will be properly wrapped. content = `<span class="chunkwrap">`; - } - - if (itemIncludesChunkwrapSplit) { - seenChunkwrapSplitter = true; + insideOpenChunkwrapChunk = true; } // Blockwraps only apply if they actually contain some content whose @@ -846,7 +880,41 @@ export class Tag { blockwrapClosers += `</span>`; } - if (itemIncludesChunkwrapSplit) { + if (itemIncludesItsOwnChunkwrap || itemIncludesBreakout) { + const trailingWhitespace = content.match(/\s*$/); + if (trailingWhitespace) { + content = content.slice(0, -trailingWhitespace.length); + } + + if (insideOpenChunkwrapChunk) { + content += '</span>'; + } else if (blockwrapClosers) { + content += blockwrapClosers; + blockwrapClosers = ''; + } + + content += trailingWhitespace; + content += itemContent; + + if (chunkwrapSplitter) { + // Instate a new EVIL chunkwrap: it's not a chunkwrap chunk at all, + // because it's treated as display: inline, but will be closed the + // same as <span class="chunkwrap">, and can be detected in CSS. + content += `<span class="chunkwrap chunkwrapnt">`; + insideOpenChunkwrapChunk = true; + } + + /* Bonus commentary re: above - + * An item that item includes its own chunkwrap purposely causes + * its last chunk to "grab" onto the following text out here. + * The in-between stuff (up to the chunk we start next - if any) + * isn't wrapped within a [display: inline-block] chunk at all, + * instead splitting by natural language rules... which probably + * isn't the right call, but it *is* the current approach without + * introducing new external-attribute logic to handle real world + * cases that just haven't come up yet. :pray: + */ + } else if (itemIncludesChunkwrapSplit) { for (const [index, {chunk, following}] of chunkwrapChunks.entries()) { if (index === 0) { // The first chunk isn't actually a chunk all on its own, it's @@ -878,11 +946,11 @@ export class Tag { } } } - - return content; + } else { + content += itemContent; } - return content += itemContent; + return content; }, }); @@ -891,7 +959,7 @@ export class Tag { } if (chunkwrapSplitter) { - if (seenChunkwrapSplitter) { + if (insideOpenChunkwrapChunk) { content += '</span>'; } else { // Since chunkwraps take responsibility for wrapping *away* from the @@ -900,6 +968,8 @@ export class Tag { // been seen at all, just wrap everything in one now. content = `<span class="chunkwrap">${content}</span>`; } + } else if (this.breakout) { + content = `<span class="breakout">${content}</span>`; } content += blockwrapClosers; diff --git a/src/static/css/miscellany.css b/src/static/css/miscellany.css index 9eb44004..eb3b1c35 100644 --- a/src/static/css/miscellany.css +++ b/src/static/css/miscellany.css @@ -9,6 +9,10 @@ display: inline-block; } + .chunkwrapnt { + display: inline; + } + p .current { font-weight: 800; } |