@knapsack/rendering-utils 4.102.1--canary.7823.8675e86.0 → 4.102.1--canary.8157.a7ffa8f.0
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/.lintstagedrc.mjs +2 -2
- package/.turbo/turbo-test.log +8 -28
- package/dist/blocks-to-html.d.ts +10 -0
- package/dist/blocks-to-html.d.ts.map +1 -1
- package/dist/blocks-to-html.js +39 -1
- package/dist/blocks-to-html.js.map +1 -1
- package/package.json +11 -11
- package/src/blocks-to-html.ts +40 -1
- package/tsconfig.json +8 -1
package/.lintstagedrc.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { dirname } from 'node:path';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
|
|
4
|
-
import defaultConfig from '../../.lintstagedrc.mjs';
|
|
4
|
+
import defaultConfig, { buildEslintCommand } from '../../.lintstagedrc.mjs';
|
|
5
5
|
|
|
6
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
7
|
|
|
8
8
|
export default {
|
|
9
|
-
'*.{ts,tsx,js,jsx,cjs,mjs,mts,cts}':
|
|
9
|
+
'*.{ts,tsx,js,jsx,cjs,mjs,mts,cts}': buildEslintCommand(__dirname),
|
|
10
10
|
...defaultConfig,
|
|
11
11
|
};
|
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,22 +1,6 @@
|
|
|
1
|
-
$ vitest run
|
|
1
|
+
$ tsc -p tsconfig.test.json && vitest run
|
|
2
2
|
|
|
3
|
-
[1m[30m[46m RUN [49m[39m[22m [36mv4.1.
|
|
4
|
-
|
|
5
|
-
[90mstderr[2m | src/blocks-to-html.test.ts[2m > [22m[2mblocksToHtml - single markdown-block with string
|
|
6
|
-
[22m[39mmarked(): mangle parameter is enabled by default, but is deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-mangle, or disable by setting `{mangle: false}`.
|
|
7
|
-
marked(): headerIds and headerPrefix parameters enabled by default, but are deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-gfm-heading-id, or disable by setting `{headerIds: false}`.
|
|
8
|
-
|
|
9
|
-
[90mstderr[2m | src/blocks-to-html.test.ts[2m > [22m[2mblocksToHtml - single markdown-block with array
|
|
10
|
-
[22m[39mmarked(): mangle parameter is enabled by default, but is deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-mangle, or disable by setting `{mangle: false}`.
|
|
11
|
-
marked(): headerIds and headerPrefix parameters enabled by default, but are deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-gfm-heading-id, or disable by setting `{headerIds: false}`.
|
|
12
|
-
|
|
13
|
-
[90mstderr[2m | src/blocks-to-html.test.ts[2m > [22m[2mblocksToHtml - single markdown-block with empty string
|
|
14
|
-
[22m[39mmarked(): mangle parameter is enabled by default, but is deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-mangle, or disable by setting `{mangle: false}`.
|
|
15
|
-
marked(): headerIds and headerPrefix parameters enabled by default, but are deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-gfm-heading-id, or disable by setting `{headerIds: false}`.
|
|
16
|
-
|
|
17
|
-
[90mstderr[2m | src/blocks-to-html.test.ts[2m > [22m[2mblocksToHtml - single markdown-block with undefined md
|
|
18
|
-
[22m[39mmarked(): mangle parameter is enabled by default, but is deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-mangle, or disable by setting `{mangle: false}`.
|
|
19
|
-
marked(): headerIds and headerPrefix parameters enabled by default, but are deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-gfm-heading-id, or disable by setting `{headerIds: false}`.
|
|
3
|
+
[1m[30m[46m RUN [49m[39m[22m [36mv4.1.11 [39m[90m/home/runner/work/app-monorepo/app-monorepo/libs/rendering-utils[39m
|
|
20
4
|
|
|
21
5
|
[90mstderr[2m | src/blocks-to-html.test.ts[2m > [22m[2mblocksToHtml - text-editor with unknown TipTap node type does not throw
|
|
22
6
|
[22m[39m[blocks-to-html] TipTap render failed for block "test-1" (text-editor): RangeError: Unknown node type: this-node-type-does-not-exist
|
|
@@ -28,17 +12,13 @@ marked(): headerIds and headerPrefix parameters enabled by default, but are depr
|
|
|
28
12
|
at Node.fromJSON (file:///home/runner/work/app-monorepo/app-monorepo/node_modules/[4m.pnpm[24m/prosemirror-model@1.25.7/node_modules/[4mprosemirror-model[24m/dist/index.js:1529:32)
|
|
29
13
|
at generateHTML (file:///home/runner/work/app-monorepo/app-monorepo/node_modules/[4m.pnpm[24m/@tiptap+html@3.24.0_@tiptap+core@3.24.0_@tiptap+pm@3.24.0__@tiptap+pm@3.24.0_happy-dom@_5581d52037c54da583424e26a68fd3a3/node_modules/[4m@tiptap/html[24m/dist/server/index.js:54:28)
|
|
30
14
|
at convertTipTapJsonToHtml (/home/runner/work/app-monorepo/app-monorepo/libs/tiptap-utils/src/tiptap-utils.ts:27:22)
|
|
31
|
-
at tiptapToHtmlSafe [90m(/home/runner/work/app-monorepo/app-monorepo/libs/rendering-utils/[39msrc/blocks-to-html.ts:
|
|
32
|
-
at blockToHtml [90m(/home/runner/work/app-monorepo/app-monorepo/libs/rendering-utils/[39msrc/blocks-to-html.ts:
|
|
33
|
-
|
|
34
|
-
[90mstderr[2m | src/blocks-to-html.test.ts[2m > [22m[2mblocksToHtml - multiple different block types
|
|
35
|
-
[22m[39mmarked(): mangle parameter is enabled by default, but is deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-mangle, or disable by setting `{mangle: false}`.
|
|
36
|
-
marked(): headerIds and headerPrefix parameters enabled by default, but are deprecated since version 5.0.0, and will be removed in the future. To clear this warning, install https://www.npmjs.com/package/marked-gfm-heading-id, or disable by setting `{headerIds: false}`.
|
|
15
|
+
at tiptapToHtmlSafe [90m(/home/runner/work/app-monorepo/app-monorepo/libs/rendering-utils/[39msrc/blocks-to-html.ts:56:12[90m)[39m
|
|
16
|
+
at blockToHtml [90m(/home/runner/work/app-monorepo/app-monorepo/libs/rendering-utils/[39msrc/blocks-to-html.ts:78:14[90m)[39m
|
|
37
17
|
|
|
38
|
-
[32m✓[39m src/blocks-to-html.test.ts [2m([22m[
|
|
18
|
+
[32m✓[39m src/blocks-to-html.test.ts [2m([22m[2m38 tests[22m[2m)[22m[32m 179[2mms[22m[39m
|
|
39
19
|
|
|
40
20
|
[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
|
|
41
|
-
[2m Tests [22m [1m[
|
|
42
|
-
[2m Start at [22m
|
|
43
|
-
[2m Duration [22m 1.
|
|
21
|
+
[2m Tests [22m [1m[32m38 passed[39m[22m[90m (38)[39m
|
|
22
|
+
[2m Start at [22m 22:11:33
|
|
23
|
+
[2m Duration [22m 1.80s[2m (transform 281ms, setup 0ms, import 1.41s, tests 179ms, environment 0ms)[22m
|
|
44
24
|
|
package/dist/blocks-to-html.d.ts
CHANGED
|
@@ -4,5 +4,15 @@
|
|
|
4
4
|
* @description Convert Knapsack Blocks to html
|
|
5
5
|
*/
|
|
6
6
|
import { type BlockConfig } from '@knapsack/types';
|
|
7
|
+
/**
|
|
8
|
+
* Whether an empty render of this block means author content was lost.
|
|
9
|
+
*
|
|
10
|
+
* Many block types render nothing server-side by design (they render in the
|
|
11
|
+
* browser or embed a live source), so `''` from `blocksToHtml` is only a
|
|
12
|
+
* loss signal for TipTap-backed blocks that hold renderable content — the
|
|
13
|
+
* blocks where `tiptapToHtmlSafe` can swallow a render error into `''`.
|
|
14
|
+
* Every render-comparison tool judges empties by this one rule.
|
|
15
|
+
*/
|
|
16
|
+
export declare function mustRenderNonEmpty(block: BlockConfig): boolean;
|
|
7
17
|
export declare function blocksToHtml(blocks: BlockConfig[]): Promise<string>;
|
|
8
18
|
//# sourceMappingURL=blocks-to-html.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blocks-to-html.d.ts","sourceRoot":"","sources":["../src/blocks-to-html.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"blocks-to-html.d.ts","sourceRoot":"","sources":["../src/blocks-to-html.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAoLnD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAe9D;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAMzE"}
|
package/dist/blocks-to-html.js
CHANGED
|
@@ -9,7 +9,16 @@ import domPurify from 'isomorphic-dompurify';
|
|
|
9
9
|
const EOL = os.EOL || '\n';
|
|
10
10
|
async function mdToHtml(md) {
|
|
11
11
|
const { marked } = await import('marked');
|
|
12
|
-
|
|
12
|
+
// This output is both served (api-server's Block.html resolver) and
|
|
13
|
+
// hashed for render-parity comparisons. headerIds and mangle default to
|
|
14
|
+
// on in marked 6 and warn on every call. Disabling them DOES change what
|
|
15
|
+
// gets rendered here — headerIds stops emitting auto-generated heading id
|
|
16
|
+
// attributes, and nothing here consumes heading anchors or benefits from
|
|
17
|
+
// mangled mailto text, so that's an acceptable, deliberate change. It's
|
|
18
|
+
// still safe for i7-render-equivalence: gate.ts compares a before/after
|
|
19
|
+
// signature that both go through this same mdToHtml, so both sides drop
|
|
20
|
+
// the ids identically and the signatures move together, not apart.
|
|
21
|
+
return marked.parse(md, { headerIds: false, mangle: false });
|
|
13
22
|
}
|
|
14
23
|
// Utility to escape HTML attribute values
|
|
15
24
|
function escapeAttr(val = '') {
|
|
@@ -26,6 +35,11 @@ function escapeAttr(val = '') {
|
|
|
26
35
|
// guard below and degrade to empty content so the rest of the document
|
|
27
36
|
// still renders.
|
|
28
37
|
function tiptapToHtmlSafe(content, blockId, blockType) {
|
|
38
|
+
// Stored content with no root `type` (e.g. `{}` from an author never
|
|
39
|
+
// typing into the block) carries nothing to render — return empty without
|
|
40
|
+
// the error log, which is reserved for real schema drift.
|
|
41
|
+
if (!content?.type)
|
|
42
|
+
return '';
|
|
29
43
|
try {
|
|
30
44
|
return convertTipTapJsonToHtml(content);
|
|
31
45
|
}
|
|
@@ -139,6 +153,30 @@ async function blockToHtml(b) {
|
|
|
139
153
|
}
|
|
140
154
|
}
|
|
141
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Whether an empty render of this block means author content was lost.
|
|
158
|
+
*
|
|
159
|
+
* Many block types render nothing server-side by design (they render in the
|
|
160
|
+
* browser or embed a live source), so `''` from `blocksToHtml` is only a
|
|
161
|
+
* loss signal for TipTap-backed blocks that hold renderable content — the
|
|
162
|
+
* blocks where `tiptapToHtmlSafe` can swallow a render error into `''`.
|
|
163
|
+
* Every render-comparison tool judges empties by this one rule.
|
|
164
|
+
*/
|
|
165
|
+
export function mustRenderNonEmpty(block) {
|
|
166
|
+
if (!block.data)
|
|
167
|
+
return false;
|
|
168
|
+
switch (block.blockType) {
|
|
169
|
+
case 'text-editor':
|
|
170
|
+
case 'code-snippet':
|
|
171
|
+
case 'table':
|
|
172
|
+
case 'callout':
|
|
173
|
+
return (block.data.content?.content?.length ?? 0) > 0;
|
|
174
|
+
case 'guidelines':
|
|
175
|
+
return (block.data.guidelines ?? []).some((g) => (g.content?.content?.length ?? 0) > 0 || Boolean(g.image?.src));
|
|
176
|
+
default:
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
142
180
|
export async function blocksToHtml(blocks) {
|
|
143
181
|
// Sanitize each block's HTML output individually before joining
|
|
144
182
|
const htmls = await Promise.all(blocks.map(async (block) => domPurify.sanitize(await blockToHtml(block))));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blocks-to-html.js","sourceRoot":"","sources":["../src/blocks-to-html.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,SAAS,MAAM,sBAAsB,CAAC;AAE7C,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,IAAI,IAAI,CAAC;AAE3B,KAAK,UAAU,QAAQ,CAAC,EAAU;IAChC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"blocks-to-html.js","sourceRoot":"","sources":["../src/blocks-to-html.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knapsack/rendering-utils",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "4.102.1--canary.
|
|
4
|
+
"version": "4.102.1--canary.8157.a7ffa8f.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -22,23 +22,23 @@
|
|
|
22
22
|
"build": "tsc",
|
|
23
23
|
"clean": "rm -rf ./dist",
|
|
24
24
|
"lint": "eslint ./",
|
|
25
|
-
"test": "vitest run"
|
|
25
|
+
"test": "tsc -p tsconfig.test.json && vitest run"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@knapsack/tiptap-utils": "4.102.1--canary.
|
|
29
|
-
"@knapsack/utils": "4.102.1--canary.
|
|
28
|
+
"@knapsack/tiptap-utils": "4.102.1--canary.8157.a7ffa8f.0",
|
|
29
|
+
"@knapsack/utils": "4.102.1--canary.8157.a7ffa8f.0",
|
|
30
30
|
"isomorphic-dompurify": "^1.13.0",
|
|
31
31
|
"marked": "^6.0.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@knapsack/eslint-config-starter": "4.102.1--canary.
|
|
35
|
-
"@knapsack/prettier-config": "4.102.1--canary.
|
|
36
|
-
"@knapsack/types": "4.102.1--canary.
|
|
37
|
-
"@knapsack/typescript-config-starter": "4.102.1--canary.
|
|
34
|
+
"@knapsack/eslint-config-starter": "4.102.1--canary.8157.a7ffa8f.0",
|
|
35
|
+
"@knapsack/prettier-config": "4.102.1--canary.8157.a7ffa8f.0",
|
|
36
|
+
"@knapsack/types": "4.102.1--canary.8157.a7ffa8f.0",
|
|
37
|
+
"@knapsack/typescript-config-starter": "4.102.1--canary.8157.a7ffa8f.0",
|
|
38
38
|
"@types/node": "^24.13.2",
|
|
39
39
|
"eslint": "^9.20.0",
|
|
40
|
-
"typescript": "^
|
|
41
|
-
"vitest": "^4.1.
|
|
40
|
+
"typescript": "^6.0.3",
|
|
41
|
+
"vitest": "^4.1.11"
|
|
42
42
|
},
|
|
43
43
|
"license": "GPL-2.0-or-later",
|
|
44
44
|
"publishConfig": {
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"directory": "libs/rendering-utils",
|
|
50
50
|
"type": "git"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "a7ffa8fd21717341453999632af58d34192fb281"
|
|
53
53
|
}
|
package/src/blocks-to-html.ts
CHANGED
|
@@ -16,7 +16,16 @@ const EOL = os.EOL || '\n';
|
|
|
16
16
|
|
|
17
17
|
async function mdToHtml(md: string): Promise<string> {
|
|
18
18
|
const { marked } = await import('marked');
|
|
19
|
-
|
|
19
|
+
// This output is both served (api-server's Block.html resolver) and
|
|
20
|
+
// hashed for render-parity comparisons. headerIds and mangle default to
|
|
21
|
+
// on in marked 6 and warn on every call. Disabling them DOES change what
|
|
22
|
+
// gets rendered here — headerIds stops emitting auto-generated heading id
|
|
23
|
+
// attributes, and nothing here consumes heading anchors or benefits from
|
|
24
|
+
// mangled mailto text, so that's an acceptable, deliberate change. It's
|
|
25
|
+
// still safe for i7-render-equivalence: gate.ts compares a before/after
|
|
26
|
+
// signature that both go through this same mdToHtml, so both sides drop
|
|
27
|
+
// the ids identically and the signatures move together, not apart.
|
|
28
|
+
return marked.parse(md, { headerIds: false, mangle: false });
|
|
20
29
|
}
|
|
21
30
|
|
|
22
31
|
// Utility to escape HTML attribute values
|
|
@@ -39,6 +48,10 @@ function tiptapToHtmlSafe(
|
|
|
39
48
|
blockId: string,
|
|
40
49
|
blockType: string,
|
|
41
50
|
): string {
|
|
51
|
+
// Stored content with no root `type` (e.g. `{}` from an author never
|
|
52
|
+
// typing into the block) carries nothing to render — return empty without
|
|
53
|
+
// the error log, which is reserved for real schema drift.
|
|
54
|
+
if (!content?.type) return '';
|
|
42
55
|
try {
|
|
43
56
|
return convertTipTapJsonToHtml(content);
|
|
44
57
|
} catch (err) {
|
|
@@ -171,6 +184,32 @@ async function blockToHtml(b: BlockConfig): Promise<string> {
|
|
|
171
184
|
}
|
|
172
185
|
}
|
|
173
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Whether an empty render of this block means author content was lost.
|
|
189
|
+
*
|
|
190
|
+
* Many block types render nothing server-side by design (they render in the
|
|
191
|
+
* browser or embed a live source), so `''` from `blocksToHtml` is only a
|
|
192
|
+
* loss signal for TipTap-backed blocks that hold renderable content — the
|
|
193
|
+
* blocks where `tiptapToHtmlSafe` can swallow a render error into `''`.
|
|
194
|
+
* Every render-comparison tool judges empties by this one rule.
|
|
195
|
+
*/
|
|
196
|
+
export function mustRenderNonEmpty(block: BlockConfig): boolean {
|
|
197
|
+
if (!block.data) return false;
|
|
198
|
+
switch (block.blockType) {
|
|
199
|
+
case 'text-editor':
|
|
200
|
+
case 'code-snippet':
|
|
201
|
+
case 'table':
|
|
202
|
+
case 'callout':
|
|
203
|
+
return (block.data.content?.content?.length ?? 0) > 0;
|
|
204
|
+
case 'guidelines':
|
|
205
|
+
return (block.data.guidelines ?? []).some(
|
|
206
|
+
(g) => (g.content?.content?.length ?? 0) > 0 || Boolean(g.image?.src),
|
|
207
|
+
);
|
|
208
|
+
default:
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
174
213
|
export async function blocksToHtml(blocks: BlockConfig[]): Promise<string> {
|
|
175
214
|
// Sanitize each block's HTML output individually before joining
|
|
176
215
|
const htmls = await Promise.all(
|
package/tsconfig.json
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "@knapsack/typescript-config-starter/tsconfig.build.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
|
+
"rootDir": "./src",
|
|
4
5
|
"noImplicitAny": true,
|
|
5
6
|
"strict": true,
|
|
6
7
|
"outDir": "./dist"
|
|
7
8
|
},
|
|
8
|
-
"include": ["./src"]
|
|
9
|
+
"include": ["./src"],
|
|
10
|
+
"exclude": [
|
|
11
|
+
"src/**/*.test.ts",
|
|
12
|
+
"src/**/*.test.tsx",
|
|
13
|
+
"src/**/*.spec.ts",
|
|
14
|
+
"src/**/*.spec.tsx"
|
|
15
|
+
]
|
|
9
16
|
}
|