From f2128fbf10ae332328bbd2644ecaca179ac41622 Mon Sep 17 00:00:00 2001 From: dragonwocky Date: Tue, 28 May 2024 20:59:46 +1000 Subject: [PATCH] feat(line-numbers): border & bg decoration styles --- src/extensions/line-numbers/client.css | 63 --------------- src/extensions/line-numbers/client.mjs | 75 ++++++++++-------- .../line-numbers/code-line-numbers.png | Bin 5936 -> 0 bytes src/extensions/line-numbers/mod.json | 4 +- 4 files changed, 44 insertions(+), 98 deletions(-) delete mode 100644 src/extensions/line-numbers/client.css mode change 100644 => 100755 src/extensions/line-numbers/client.mjs delete mode 100644 src/extensions/line-numbers/code-line-numbers.png mode change 100644 => 100755 src/extensions/line-numbers/mod.json diff --git a/src/extensions/line-numbers/client.css b/src/extensions/line-numbers/client.css deleted file mode 100644 index 7179f0f..0000000 --- a/src/extensions/line-numbers/client.css +++ /dev/null @@ -1,63 +0,0 @@ -/** - * notion-enhancer: line numbers - * (c) 2020 CloudHill (https://github.com/CloudHill) - * (c) 2024 dragonwocky (https://dragonwocky.me/) - * (https://notion-enhancer.github.io/) under the MIT license - */ - -.notion-code-block.line-numbers { - position: relative; -} -.code_line_numbers--plain:not(:empty) + div, -.code_line_numbers--background:not(:empty) + div, -.code_line_numbers--border:not(:empty) + div { - padding-left: 64px !important; -} - -.code_line_numbers--plain, -.code_line_numbers--background, -.code_line_numbers--border { - position: absolute; - left: 0; - right: calc(100% - 64px); - top: 34px; - bottom: 32px; - padding-right: 27px; - - font-size: 85%; - font-family: var(--theme--font_code); - text-align: right; - line-height: 1.5; - opacity: 0.8; - color: var(--theme--text_secondary); - - overflow: hidden; - pointer-events: none; -} -.code_line_numbers--plain:empty, -.code_line_numbers--background:empty, -.code_line_numbers--border:empty { - display: none; -} -.code_line_numbers--background::before { - content: ''; - position: absolute; - top: 0; - left: 7.25px; - width: calc(100% - 27px); - height: 100%; - display: block; - background-color: var(--theme--bg); - border-radius: 4px; - z-index: -1; -} -.code_line_numbers--border::before { - content: ''; - position: absolute; - top: 0; - right: calc(100% - 52px); - width: 2px; - height: 100%; - display: block; - background-color: var(--theme--ui_divider); -} diff --git a/src/extensions/line-numbers/client.mjs b/src/extensions/line-numbers/client.mjs old mode 100644 new mode 100755 index b3cf511..b71c9e3 --- a/src/extensions/line-numbers/client.mjs +++ b/src/extensions/line-numbers/client.mjs @@ -5,21 +5,27 @@ * (https://notion-enhancer.github.io/) under the MIT license */ -function LineNumbers() { - const { html } = globalThis.__enhancerApi; +function LineNumbers({ decorationStyle = "None" }) { + const { html } = globalThis.__enhancerApi, + decorations = { + Border: `pr-[16px] border-r-([2px] + [color:var(--theme--bg-hover)])`, + Background: `pr-[4px] before:(absolute block + h-full w-[calc(100%-24px)] rounded-[4px] right-0 + content-empty bg-[var(--theme--bg-hover)] z-[-1])`, + }; return html`
`; } export default async (api, db) => { const { html, addMutationListener } = api, + decorationStyle = await db.get("decorationStyle"), numberSingleLines = await db.get("numberSingleLines"), - lineNumberDecoration = await db.get("lineNumberDecoration"), - lineNumbersClass = "notion-enhancer--line-numbers", codeBlockSelector = ".notion-code-block.line-numbers > .notranslate"; // get character width in pixels @@ -50,45 +56,48 @@ export default async (api, db) => { for (const $code of document.querySelectorAll(codeBlockSelector)) { const wrap = $code.style.wordBreak === "break-all", lines = $code.innerText.split("\n"), - lineCount = Math.max(lines.length - 1, 1), - lineNumDigits = (Math.log(lineCount) * Math.LOG10E + 1) | 0; + numLines = Math.max(lines.length - 1, 1), + numChars = lines.map((line) => line.length).join(","), + numDigits = (Math.log(numLines) * Math.LOG10E + 1) | 0; - const doUpdate = - $code.dataset.lines !== String(lineCount) || - $code.dataset.wrap !== String(wrap); - if (!doUpdate) continue; - $code.dataset.lines = lineCount; - $code.dataset.wrap = wrap; + if ($code.dataset.lines === wrap + "," + numChars) continue; + $code.dataset.lines = wrap + "," + numChars; + // do not add to single-line blocks if disabled + const visible = numberSingleLines || numLines > 1, + width = visible + ? decorationStyle === "Border" + ? `calc(100% - 50px - ${numDigits}ch)` + : `calc(100% - 32px - ${numDigits}ch)` + : "", + paddingLeft = visible && decorationStyle === "Border" ? "16px" : "32px"; // shrink block to allow space for numbers - const width = `calc(100% - 32px - ${lineNumDigits}ch)`; applyStyles($code.parentElement, { justifyContent: "flex-end" }); - applyStyles($code, { minWidth: width, maxWidth: width }); + applyStyles($code, { minWidth: width, maxWidth: width, paddingLeft }); - // work out height of wrapped lines + // calculate heights of wrapped lines and render line nums + let totalHeight = 0; const lineHeight = getLineHeight($code), charsPerLine = Math.floor(getLineWidth($code) / getCharWidth($code)); - - // update line numbers in dom - let totalHeight = 34; - $code._$lineNumbers ||= LineNumbers(); - for (let i = 1; i <= lineCount; i++) { - let $n = $code._$lineNumbers.children[i - 1]; - if (!$n) { - $n = html`${i}`; - $code._$lineNumbers.append($n); - } - const height = + $code._$lineNumbers ||= html`<${LineNumbers}...${{ decorationStyle }} />`; + for (let i = 1; i <= numLines; i++) { + const $n = $code._$lineNumbers.children[i - 1] || html`

${i}

`; + if (!$code._$lineNumbers.contains($n)) $code._$lineNumbers.append($n); + const wrappedHeight = wrap && lines[i - 1].length > charsPerLine ? Math.ceil(lines[i - 1].length / charsPerLine) * lineHeight : lineHeight; - applyStyles($n, { height: `${height}px` }); - totalHeight += height; + applyStyles($n, { height: `${wrappedHeight}px` }); + totalHeight += wrappedHeight; } - applyStyles($code._$lineNumbers, { height: `${totalHeight}px` }); + applyStyles($code._$lineNumbers, { + display: visible ? "" : "none", + height: `${totalHeight}px`, + }); - if (!document.contains($code._$lineNumbers)) + if (visible && !document.contains($code._$lineNumbers)) { $code.before($code._$lineNumbers); + } else if (!visible) $code._$lineNumbers.style.display = "none"; } }; diff --git a/src/extensions/line-numbers/code-line-numbers.png b/src/extensions/line-numbers/code-line-numbers.png deleted file mode 100644 index c1b6b08dbfc096d4c91ffc5dfe4de810ba878687..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5936 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 diff --git a/src/extensions/line-numbers/mod.json b/src/extensions/line-numbers/mod.json old mode 100644 new mode 100755 index 959d59a..cc2d35c --- a/src/extensions/line-numbers/mod.json +++ b/src/extensions/line-numbers/mod.json @@ -25,8 +25,8 @@ }, { "type": "select", - "key": "lineNumberDecoration", - "description": "Select a decoration style to distinguish line numbers from code block content.", + "key": "decorationStyle", + "description": "Decorate line numbers with additional styling to distinguish them from code block content.", "values": ["Border", "Background", "None"] } ],