@tnotesjs/ui 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/code/highlight.js +8 -3
- package/package.json +6 -5
- package/src/code/highlight.ts +17 -3
- package/src/styles/code.css +8 -2
package/dist/code/highlight.js
CHANGED
|
@@ -132,13 +132,17 @@ async function prepareCodeHighlighter(languages = []) {
|
|
|
132
132
|
);
|
|
133
133
|
return highlighter;
|
|
134
134
|
}
|
|
135
|
-
function
|
|
135
|
+
function lineNumberDigits(source, meta) {
|
|
136
|
+
return String(meta.startLine + source.split("\n").length - 1).length;
|
|
137
|
+
}
|
|
138
|
+
function transformers(meta, gutterDigits) {
|
|
136
139
|
return [
|
|
137
140
|
{
|
|
138
141
|
name: "tnotes-code-meta",
|
|
139
142
|
pre(node) {
|
|
140
143
|
this.addClassToHast(node, "tn-code-highlight");
|
|
141
144
|
node.properties.tabindex = 0;
|
|
145
|
+
node.properties.style = `--tn-line-digits: ${gutterDigits}`;
|
|
142
146
|
},
|
|
143
147
|
line(node, line) {
|
|
144
148
|
node.properties["data-line"] = String(meta.startLine + line - 1);
|
|
@@ -150,13 +154,14 @@ function transformers(meta) {
|
|
|
150
154
|
function highlightCodeSync(code, info = "") {
|
|
151
155
|
if (!ready) throw new Error("Call prepareCodeHighlighter before rendering Markdown");
|
|
152
156
|
const meta = parseCodeMeta(info);
|
|
157
|
+
const source = code.replace(/\n$/, "");
|
|
153
158
|
const normalizedLanguage = normalizeCodeLanguage(meta.language);
|
|
154
159
|
const language = ready.getLoadedLanguages().includes(normalizedLanguage) ? normalizedLanguage : "text";
|
|
155
|
-
return ready.codeToHtml(
|
|
160
|
+
return ready.codeToHtml(source, {
|
|
156
161
|
lang: language,
|
|
157
162
|
themes: { light: "github-light", dark: "github-dark" },
|
|
158
163
|
defaultColor: false,
|
|
159
|
-
transformers: transformers(meta)
|
|
164
|
+
transformers: transformers(meta, lineNumberDigits(source, meta))
|
|
160
165
|
});
|
|
161
166
|
}
|
|
162
167
|
async function highlightCode(code, info = "") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tnotesjs/ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Shared Vue UI for TNotes built-in blocks — consumed by the TNotes SSG and Desk.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -82,13 +82,13 @@
|
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
84
|
"@excalidraw/excalidraw": "0.18.1",
|
|
85
|
+
"@tnotesjs/mindmap-core": "workspace:^",
|
|
85
86
|
"marked": "^15.0.11",
|
|
86
87
|
"mermaid": "^11.17.0",
|
|
87
88
|
"react": "18.3.1",
|
|
88
89
|
"react-dom": "18.3.1",
|
|
89
90
|
"sass": "^1.90.0",
|
|
90
|
-
"shiki": "4.4.2"
|
|
91
|
-
"@tnotesjs/mindmap-core": "^0.2.2"
|
|
91
|
+
"shiki": "4.4.2"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@eslint/js": "^10.0.1",
|
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
135
135
|
"test": "vitest run",
|
|
136
136
|
"lint": "eslint . --max-warnings=0",
|
|
137
|
-
"lint:fix": "eslint . --fix"
|
|
137
|
+
"lint:fix": "eslint . --fix",
|
|
138
|
+
"prepublishOnly": "pnpm test && pnpm typecheck && pnpm build"
|
|
138
139
|
}
|
|
139
|
-
}
|
|
140
|
+
}
|
package/src/code/highlight.ts
CHANGED
|
@@ -127,7 +127,18 @@ export async function prepareCodeHighlighter(languages: string[] = []): Promise<
|
|
|
127
127
|
return highlighter
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
/**
|
|
131
|
+
* How many characters the line-number gutter has to hold.
|
|
132
|
+
*
|
|
133
|
+
* Counted from the source up front because the width belongs on the root `<pre>`
|
|
134
|
+
* and has to be set before Shiki visits the lines: sizing each `::before` from
|
|
135
|
+
* its own number would let the code text jump between lines.
|
|
136
|
+
*/
|
|
137
|
+
function lineNumberDigits(source: string, meta: CodeMeta): number {
|
|
138
|
+
return String(meta.startLine + source.split('\n').length - 1).length
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function transformers(meta: CodeMeta, gutterDigits: number): ShikiTransformer[] {
|
|
131
142
|
// Fence `{N}` line highlights only — match Desk CodeMirror. No Shiki
|
|
132
143
|
// notation transformers (`[!code ++]` etc.); Desk has no write path for them.
|
|
133
144
|
return [
|
|
@@ -136,6 +147,8 @@ function transformers(meta: CodeMeta): ShikiTransformer[] {
|
|
|
136
147
|
pre(node) {
|
|
137
148
|
this.addClassToHast(node, 'tn-code-highlight')
|
|
138
149
|
node.properties.tabindex = 0
|
|
150
|
+
// Inherited by every line's `::before`, which is what sizes the gutter.
|
|
151
|
+
node.properties.style = `--tn-line-digits: ${gutterDigits}`
|
|
139
152
|
},
|
|
140
153
|
line(node, line) {
|
|
141
154
|
node.properties['data-line'] = String(meta.startLine + line - 1)
|
|
@@ -149,15 +162,16 @@ function transformers(meta: CodeMeta): ShikiTransformer[] {
|
|
|
149
162
|
export function highlightCodeSync(code: string, info = ''): string {
|
|
150
163
|
if (!ready) throw new Error('Call prepareCodeHighlighter before rendering Markdown')
|
|
151
164
|
const meta = parseCodeMeta(info)
|
|
165
|
+
const source = code.replace(/\n$/, '')
|
|
152
166
|
const normalizedLanguage = normalizeCodeLanguage(meta.language)
|
|
153
167
|
const language = ready.getLoadedLanguages().includes(normalizedLanguage)
|
|
154
168
|
? normalizedLanguage
|
|
155
169
|
: 'text'
|
|
156
|
-
return ready.codeToHtml(
|
|
170
|
+
return ready.codeToHtml(source, {
|
|
157
171
|
lang: language,
|
|
158
172
|
themes: { light: 'github-light', dark: 'github-dark' },
|
|
159
173
|
defaultColor: false,
|
|
160
|
-
transformers: transformers(meta)
|
|
174
|
+
transformers: transformers(meta, lineNumberDigits(source, meta))
|
|
161
175
|
})
|
|
162
176
|
}
|
|
163
177
|
|
package/src/styles/code.css
CHANGED
|
@@ -116,8 +116,14 @@
|
|
|
116
116
|
.tn-code-block.has-line-numbers .line::before {
|
|
117
117
|
content: attr(data-line);
|
|
118
118
|
display: inline-block;
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
/*
|
|
120
|
+
* Gutter width follows the widest number this block actually prints — the
|
|
121
|
+
* highlighter sets `--tn-line-digits` per block, so a two-line snippet is not
|
|
122
|
+
* padded like a thousand-line file. 3ch is the fallback for renderers that
|
|
123
|
+
* bring their own line numbers.
|
|
124
|
+
*/
|
|
125
|
+
width: calc(var(--tn-line-digits, 3) * 1ch);
|
|
126
|
+
padding-right: 12px;
|
|
121
127
|
text-align: right;
|
|
122
128
|
color: var(--tn-c-text-2);
|
|
123
129
|
user-select: none;
|