@jackuait/blok-cli 0.10.0-beta.15
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/bin/blok-cli.mjs +10 -0
- package/dist/cli.mjs +51 -0
- package/dist/convert-html-CnpK6ocW.mjs +603 -0
- package/package.json +36 -0
package/bin/blok-cli.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { run } from '../dist/cli.mjs';
|
|
5
|
+
|
|
6
|
+
const version = process.env.npm_package_version
|
|
7
|
+
|| JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8')).version;
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
|
|
10
|
+
run(args, version);
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as e from "node:fs";
|
|
2
|
+
//#region src/cli/commands/migrationContent.ts
|
|
3
|
+
var t = "# Migrating from EditorJS to Blok\n\nThis guide covers the breaking changes when migrating from EditorJS to Blok.\n\n## Table of Contents\n\n- [Core Changes](#core-changes)\n- [Data Attributes](#data-attributes)\n- [CSS Classes](#css-classes)\n- [Bundled Tools](#bundled-tools)\n - [Tool Configuration](#tool-configuration)\n - [Lifecycle Hooks](#lifecycle-hooks)\n - [Delimiter → Divider](#delimiter--divider)\n- [Configuration Defaults](#configuration-defaults)\n- [New API Methods](#new-api-methods)\n- [DOM Selectors](#dom-selectors)\n- [E2E Test Selectors](#e2e-test-selectors)\n\n---\n\n## Core Changes\n\n### Class Name\n\n```diff\n- import EditorJS from '@editorjs/editorjs';\n+ import Blok from '@jackuait/blok';\n\n- const editor = new EditorJS({ ... });\n+ const editor = new Blok({ ... });\n```\n\n### Default Holder\n\nThe default holder ID changed from `editorjs` to `blok`:\n\n```diff\n- <div id=\"editorjs\"></div>\n+ <div id=\"blok\"></div>\n```\n\nOr specify explicitly:\n\n```javascript\nconst editor = new Blok({\n holder: 'my-editor', // works the same as before\n});\n```\n\n### TypeScript Types\n\n```diff\n- import type { EditorConfig, OutputData } from '@editorjs/editorjs';\n+ import type { BlokConfig, OutputData } from '@jackuait/blok';\n```\n\n---\n\n## Data Attributes\n\nBlok uses `data-blok-*` attributes instead of EditorJS's mixed naming conventions.\n\n| EditorJS | Blok |\n|----------|------|\n| `data-id` | `data-blok-id` |\n| `data-item-name` | `data-blok-item-name` |\n| `data-empty` | `data-blok-empty` |\n| `.ce-block--selected` (class) | `data-blok-selected=\"true\"` |\n| — | `data-blok-component` (tool name) |\n| — | `data-blok-interface` (element type) |\n| — | `data-blok-testid` (testing) |\n| — | `data-blok-opened` (toolbar state) |\n| — | `data-blok-placeholder` |\n| — | `data-blok-stretched` |\n| — | `data-blok-focused` |\n| — | `data-blok-popover-opened` |\n| — | `data-blok-tool` (tool name on rendered element) |\n| — | `data-blok-dragging` (block being dragged) |\n| — | `data-blok-hidden` (hidden state) |\n| — | `data-blok-rtl` (RTL mode) |\n| — | `data-blok-drag-handle` (drag handle element) |\n| — | `data-blok-overlay` (selection overlay) |\n| — | `data-blok-overlay-rectangle` (selection rectangle) |\n\n### Querying Blocks\n\n```diff\n- document.querySelector('[data-id=\"abc123\"]');\n+ document.querySelector('[data-blok-id=\"abc123\"]');\n\n- document.querySelector('[data-item-name=\"bold\"]');\n+ document.querySelector('[data-blok-item-name=\"bold\"]');\n```\n\n---\n\n## CSS Classes\n\nBlok replaces BEM class names with data attributes for selection.\n\n### Editor Wrapper\n\n| EditorJS | Blok |\n|----------|------|\n| `.codex-editor` | `[data-blok-editor]` |\n| `.codex-editor__redactor` | `[data-blok-redactor]` |\n| `.codex-editor--rtl` | `[data-blok-rtl=\"true\"]` |\n\n### Block Elements\n\n| EditorJS | Blok |\n|----------|------|\n| `.ce-block` | `[data-blok-element]` |\n| `.ce-block--selected` | `[data-blok-selected=\"true\"]` |\n| `.ce-block--stretched` | `[data-blok-stretched=\"true\"]` |\n| `.ce-block--focused` | `[data-blok-focused=\"true\"]` |\n| `.ce-block__content` | `[data-blok-element-content]` |\n\n### Toolbar\n\n| EditorJS | Blok |\n|----------|------|\n| `.ce-toolbar` | `[data-blok-toolbar]` |\n| `.ce-toolbar__plus` | `[data-blok-testid=\"plus-button\"]` |\n| `.ce-toolbar__settings-btn` | `[data-blok-settings-toggler]` |\n| `.ce-toolbar__actions` | `[data-blok-testid=\"toolbar-actions\"]` |\n| `.ce-toolbox` | `[data-blok-toolbox]` |\n| `.ce-toolbox--opened` | `[data-blok-toolbox][data-blok-opened=\"true\"]` |\n\n### Inline Toolbar\n\n| EditorJS | Blok |\n|----------|------|\n| `.ce-inline-toolbar` | `[data-blok-testid=\"inline-toolbar\"]` |\n| `.ce-inline-tool` | `[data-blok-testid=\"inline-tool\"]` |\n| `.ce-inline-tool--link` | `[data-blok-testid=\"inline-tool-link\"]` |\n| `.ce-inline-tool--bold` | `[data-blok-testid=\"inline-tool-bold\"]` |\n| `.ce-inline-tool--italic` | `[data-blok-testid=\"inline-tool-italic\"]` |\n\n### Popover\n\n| EditorJS | Blok |\n|----------|------|\n| `.ce-popover` | `[data-blok-popover]` |\n| `.ce-popover--opened` | `[data-blok-popover][data-blok-opened=\"true\"]` |\n| `.ce-popover__container` | `[data-blok-popover-container]` |\n| `.ce-popover-item` | `[data-blok-testid=\"popover-item\"]` |\n| `.ce-popover-item--focused` | `[data-blok-focused=\"true\"]` |\n| `.ce-popover-item--confirmation` | `[data-blok-confirmation=\"true\"]` |\n| `.ce-popover-item__icon` | `[data-blok-testid=\"popover-item-icon\"]` |\n| `.ce-popover-item__icon--tool` | `[data-blok-testid=\"popover-item-icon-tool\"]` |\n\n### Tool-Specific Classes\n\n| EditorJS | Blok |\n|----------|------|\n| `.ce-paragraph` | `[data-blok-tool=\"paragraph\"]` |\n| `.ce-header` | `[data-blok-tool=\"header\"]` |\n\n### Conversion Toolbar & Settings\n\n| EditorJS | Blok |\n|----------|------|\n| `.ce-conversion-toolbar` | `[data-blok-testid=\"conversion-toolbar\"]` |\n| `.ce-conversion-tool` | `[data-blok-testid=\"conversion-tool\"]` |\n| `.ce-settings` | `[data-blok-testid=\"block-settings\"]` |\n| `.ce-tune` | `[data-blok-testid=\"block-tune\"]` |\n\n### Other Elements\n\n| EditorJS | Blok |\n|----------|------|\n| `.ce-stub` | `[data-blok-stub]` |\n| `.ce-drag-handle` | `[data-blok-drag-handle]` |\n| `.ce-ragged-right` | `[data-blok-ragged-right=\"true\"]` |\n\n### CDX List Classes\n\n| EditorJS | Blok |\n|----------|------|\n| `.cdx-list` | `[data-blok-list]` |\n| `.cdx-list__item` | `[data-blok-list-item]` |\n| `.cdx-list--ordered` | `[data-blok-list=\"ordered\"]` |\n| `.cdx-list--unordered` | `[data-blok-list=\"unordered\"]` |\n\n### CDX Utility Classes\n\n| EditorJS | Blok |\n|----------|------|\n| `.cdx-button` | `[data-blok-button]` |\n| `.cdx-input` | `[data-blok-input]` |\n| `.cdx-loader` | `[data-blok-loader]` |\n| `.cdx-search-field` | `[data-blok-search-field]` |\n\n---\n\n## Bundled Tools\n\nBlok includes Header and Paragraph tools. No external packages needed:\n\n```diff\n- import Header from '@editorjs/header';\n- import Paragraph from '@editorjs/paragraph';\n\n+ import Blok from '@jackuait/blok';\n\nconst editor = new Blok({\n tools: {\n- header: Header,\n- paragraph: Paragraph,\n+ header: Blok.Header,\n+ paragraph: Blok.Paragraph, // optional, it's the default\n },\n});\n```\n\n### Tool Configuration\n\nBoth bundled tools accept configuration options:\n\n#### HeaderConfig\n\n```typescript\nimport type { HeaderConfig } from '@jackuait/blok';\n\nconst editor = new Blok({\n tools: {\n header: {\n class: Blok.Header,\n config: {\n placeholder: 'Enter a heading',\n levels: [2, 3, 4], // Restrict to H2-H4 only\n defaultLevel: 2, // Default to H2\n } as HeaderConfig,\n },\n },\n});\n```\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `placeholder` | `string` | `''` | Placeholder text for empty header |\n| `levels` | `number[]` | `[1,2,3,4,5,6]` | Available heading levels (1-6) |\n| `defaultLevel` | `number` | `2` | Default heading level |\n\n#### ParagraphConfig\n\n```typescript\nimport type { ParagraphConfig } from '@jackuait/blok';\n\nconst editor = new Blok({\n tools: {\n paragraph: {\n class: Blok.Paragraph,\n config: {\n placeholder: 'Start typing...',\n preserveBlank: true,\n } as ParagraphConfig,\n },\n },\n});\n```\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `placeholder` | `string` | `''` | Placeholder text for empty paragraph |\n| `preserveBlank` | `boolean` | `false` | Keep empty paragraphs when saving |\n\n### Delimiter → Divider\n\nEditor.js's `@editorjs/delimiter` is replaced by Blok's built-in `divider` tool:\n\n```diff\n- import Delimiter from '@editorjs/delimiter';\n\nconst editor = new Blok({\n tools: {\n- delimiter: Delimiter,\n+ divider: Blok.Divider,\n },\n});\n```\n\n**Saved data migration:** The block type name changed from `\"delimiter\"` to `\"divider\"`. The data format is identical (empty `{}`):\n\n```diff\n {\n- \"type\": \"delimiter\",\n+ \"type\": \"divider\",\n \"data\": {}\n }\n```\n\n> **Note:** Blok automatically recognizes `\"delimiter\"` blocks and renders them as dividers, so existing articles work without data migration. However, renaming the type in your database is recommended for consistency.\n\n---\n\n## Configuration Defaults\n\n| Option | EditorJS | Blok |\n|--------|----------|------|\n| `holder` | `\"editorjs\"` | `\"blok\"` |\n| `defaultBlock` | `\"paragraph\"` | `\"paragraph\"` |\n\n---\n\n## New API Methods\n\nBlok exposes shorthand methods directly on the instance:\n\n```javascript\nconst editor = new Blok({ ... });\n\n// Shorthand methods\nawait editor.save(); // Same as editor.saver.save()\neditor.clear(); // Same as editor.blocks.clear()\nawait editor.render(data);// Same as editor.blocks.render(data)\neditor.focus(); // Same as editor.caret.focus()\n\n// Event methods\neditor.on('change', handler); // Same as editor.events.on()\neditor.off('change', handler); // Same as editor.events.off()\neditor.emit('custom', data); // Same as editor.events.emit()\n```\n\n---\n\n## DOM Selectors\n\nBlok uses consistent `data-blok-interface` attributes for major UI components:\n\n```javascript\n// Find the editor wrapper\nconst editorWrapper = document.querySelector('[data-blok-interface=\"blok\"]');\n\n// Find inline toolbar\nconst inlineToolbar = document.querySelector('[data-blok-interface=\"inline-toolbar\"]');\n\n// Find tooltip\nconst tooltip = document.querySelector('[data-blok-interface=\"tooltip\"]');\n```\n\nThese selectors are stable and recommended for programmatic access to Blok's UI components.\n\n### Key Changes\n\n1. **Prefix custom classes** with `blok-` instead of `ce-` or `cdx-`\n2. **Use `data-blok-*`** attributes instead of `data-*`\n\n---\n\n## E2E Test Selectors\n\nUpdate your test selectors to use Blok's `data-blok-testid` attributes:\n\n| EditorJS | Blok |\n|----------|------|\n| `[data-cy=editorjs]` | `[data-blok-testid=\"blok-editor\"]` |\n| `.ce-block` | `[data-blok-element]` |\n| `.ce-block__content` | `[data-blok-element-content]` |\n| `.ce-toolbar` | `[data-blok-toolbar]` |\n| `.ce-toolbar__plus` | `[data-blok-testid=\"plus-button\"]` |\n| `.ce-toolbar__settings-btn` | `[data-blok-settings-toggler]` |\n| `.ce-toolbar__actions` | `[data-blok-testid=\"toolbar-actions\"]` |\n| `.ce-toolbox` | `[data-blok-toolbox]` |\n| `.ce-inline-toolbar` | `[data-blok-testid=\"inline-toolbar\"]` |\n| `.ce-popover` | `[data-blok-popover]` |\n| `.ce-popover-item` | `[data-blok-testid=\"popover-item\"]` |\n| `[data-item-name=\"...\"]` | `[data-blok-item-name=\"...\"]` |\n\n### Playwright Example\n\n```diff\n// EditorJS\n- await page.locator('[data-cy=editorjs] .ce-block').click();\n- await page.locator('.ce-toolbar__settings-btn').click();\n- await page.locator('[data-item-name=\"delete\"]').click();\n\n// Blok\n+ await page.locator('[data-blok-element]').click();\n+ await page.locator('[data-blok-settings-toggler]').click();\n+ await page.locator('[data-blok-item-name=\"delete\"]').click();\n```\n\n### Additional Test Selectors\n\n| Element | Selector |\n|---------|----------|\n| Block tunes popover | `[data-blok-testid=\"block-tunes-popover\"]` |\n| Popover search input | `[data-blok-testid=\"popover-search-input\"]` |\n| Popover item title | `[data-blok-testid=\"popover-item-title\"]` |\n| Popover overlay | `[data-blok-testid=\"popover-overlay\"]` |\n| Inline tool input | `[data-blok-testid=\"inline-tool-input\"]` |\n| Tooltip | `[data-blok-testid=\"tooltip\"]` |\n| Redactor | `[data-blok-testid=\"redactor\"]` |\n| Toolbox | `[data-blok-testid=\"toolbox\"]` |\n| Toolbox popover | `[data-blok-testid=\"toolbox-popover\"]` |\n| Selection overlay | `[data-blok-testid=\"overlay\"]` |\n| Selection rectangle | `[data-blok-testid=\"overlay-rectangle\"]` |\n\n---\n\n### State Selectors\n\n| State | Selector |\n|-------|----------|\n| Toolbar opened | `[data-blok-opened=\"true\"]` |\n| Block selected | `[data-blok-selected=\"true\"]` |\n| Popover opened | `[data-blok-popover-opened=\"true\"]` |\n| Item focused | `[data-blok-focused=\"true\"]` |\n| Item disabled | `[data-blok-disabled=\"true\"]` |\n| Nested popover | `[data-blok-nested=\"true\"]` |\n| Toolbox opened | `[data-blok-toolbox-opened=\"true\"]` |\n| Block dragging | `[data-blok-dragging=\"true\"]` |\n| Element hidden | `[data-blok-hidden=\"true\"]` |\n| RTL mode | `[data-blok-rtl=\"true\"]` |\n\n---\n\n## Quick Checklist\n\n- [ ] Replace `new EditorJS` with `new Blok`\n- [ ] Update imports from `@editorjs/*` to `@jackuait/blok`\n- [ ] Change holder from `editorjs` to `blok` (or specify explicitly)\n- [ ] Use bundled tools: `Blok.Header`, `Blok.Paragraph`\n- [ ] Replace `@editorjs/delimiter` with built-in `Blok.Divider`\n- [ ] Update `EditorConfig` type to `BlokConfig`\n- [ ] Replace `data-id` with `data-blok-id` in queries\n- [ ] Replace `data-item-name` with `data-blok-item-name`\n- [ ] Replace `.ce-*` selectors with `[data-blok-*]` attributes\n- [ ] Replace `.cdx-*` selectors with `[data-blok-*]` attributes\n- [ ] Update E2E test selectors\n", n = (e) => [
|
|
4
|
+
"# Blok Migration Guide (for LLM-assisted migration)",
|
|
5
|
+
"",
|
|
6
|
+
"> This document contains everything needed to migrate a project from EditorJS to Blok.",
|
|
7
|
+
"> Apply these changes systematically to the user's codebase.",
|
|
8
|
+
`> Current Blok version: ${e}`,
|
|
9
|
+
"",
|
|
10
|
+
"---",
|
|
11
|
+
""
|
|
12
|
+
].join("\n") + t, r = (t, n) => {
|
|
13
|
+
n ? (e.writeFileSync(n, t, "utf-8"), process.stderr.write(`Written to ${n}\n`)) : process.stdout.write(t);
|
|
14
|
+
}, i = "Usage: blok-cli [options]\n\nOptions:\n --convert-html Convert legacy HTML from stdin to Blok JSON (stdout)\n --migration Output the EditorJS to Blok migration guide (LLM-friendly)\n --output <file> Write output to a file instead of stdout\n --help Show this help message\n\nExamples:\n npx @jackuait/blok-cli --convert-html < article.html\n npx @jackuait/blok-cli --convert-html < article.html --output article.json\n npx @jackuait/blok-cli --migration\n npx @jackuait/blok-cli --migration | pbcopy\n npx @jackuait/blok-cli --migration --output migration-guide.md\n", a = (e) => {
|
|
15
|
+
if (e.includes("--help")) return { command: "help" };
|
|
16
|
+
if (e.includes("--convert-html")) {
|
|
17
|
+
let t = e.indexOf("--output");
|
|
18
|
+
return {
|
|
19
|
+
command: "convert-html",
|
|
20
|
+
output: t === -1 ? void 0 : e[t + 1]
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (e.includes("--migration")) {
|
|
24
|
+
let t = e.indexOf("--output");
|
|
25
|
+
return {
|
|
26
|
+
command: "migration",
|
|
27
|
+
output: t === -1 ? void 0 : e[t + 1]
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return { command: null };
|
|
31
|
+
}, o = async (e, t) => {
|
|
32
|
+
let { command: o, output: s } = a(e);
|
|
33
|
+
switch (o) {
|
|
34
|
+
case "convert-html": {
|
|
35
|
+
let e = new (await (import("jsdom"))).JSDOM("");
|
|
36
|
+
globalThis.DOMParser = e.window.DOMParser, globalThis.Node = e.window.Node;
|
|
37
|
+
let { convertHtml: t } = await import("./convert-html-CnpK6ocW.mjs");
|
|
38
|
+
r(t((await import("node:fs")).readFileSync("/dev/stdin", "utf-8")), s);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case "migration":
|
|
42
|
+
r(n(t), s);
|
|
43
|
+
break;
|
|
44
|
+
case "help":
|
|
45
|
+
case null:
|
|
46
|
+
process.stdout.write(i);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
export { o as run };
|
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
//#region src/cli/commands/convert-html/preprocessor.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
t(e), r(e), s(e), c(e), l(e), d(e);
|
|
4
|
+
}
|
|
5
|
+
function t(e) {
|
|
6
|
+
let t = e.ownerDocument;
|
|
7
|
+
for (let n of Array.from(e.querySelectorAll("div[style]"))) {
|
|
8
|
+
if (n.closest("table")) continue;
|
|
9
|
+
let e = o(n);
|
|
10
|
+
if (!e || i(e)) continue;
|
|
11
|
+
let r = t.createElement("aside");
|
|
12
|
+
r.style.backgroundColor = e, r.append(...Array.from(n.childNodes));
|
|
13
|
+
let a;
|
|
14
|
+
for (; (a = Array.from(r.querySelectorAll(":scope > div")).filter((e) => !e.getAttribute("style") && !e.getAttribute("class"))).length > 0;) for (let e of a) e.replaceWith(...Array.from(e.childNodes));
|
|
15
|
+
for (let e of Array.from(r.querySelectorAll("p"))) {
|
|
16
|
+
let t = e.lastElementChild;
|
|
17
|
+
t?.tagName === "BR" && t.remove();
|
|
18
|
+
}
|
|
19
|
+
n.replaceWith(r);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
var n = 250;
|
|
23
|
+
function r(e) {
|
|
24
|
+
let t = e.querySelectorAll("[style*=\"background-color\"]");
|
|
25
|
+
for (let e of Array.from(t)) i(e.style.backgroundColor) && (e.style.removeProperty("background-color"), e.getAttribute("style")?.trim() === "" && e.removeAttribute("style"), a(e) && e.replaceWith(...Array.from(e.childNodes)));
|
|
26
|
+
}
|
|
27
|
+
function i(e) {
|
|
28
|
+
if (!e) return !1;
|
|
29
|
+
let t = e.replace(/\s/g, "").toLowerCase();
|
|
30
|
+
if (t === "transparent") return !0;
|
|
31
|
+
let r = t.match(/^rgba?\((\d+),(\d+),(\d+)(?:,([^)]+))?\)$/);
|
|
32
|
+
if (!r) return !1;
|
|
33
|
+
if ((r[4] === void 0 ? 1 : parseFloat(r[4])) === 0) return !0;
|
|
34
|
+
let i = parseInt(r[1], 10), a = parseInt(r[2], 10), o = parseInt(r[3], 10);
|
|
35
|
+
return i >= n && a >= n && o >= n;
|
|
36
|
+
}
|
|
37
|
+
function a(e) {
|
|
38
|
+
return e.attributes.length > 0 ? !1 : (e.textContent ?? "").replace(/[\s\u00A0]/g, "").length === 0;
|
|
39
|
+
}
|
|
40
|
+
function o(e) {
|
|
41
|
+
if (e.style.backgroundColor) return e.style.backgroundColor;
|
|
42
|
+
let t = (e.getAttribute("style") ?? "").match(/background:\s*([^;]+)/i);
|
|
43
|
+
if (t) {
|
|
44
|
+
let e = t[1].trim().match(/^(rgb[a]?\([^)]+\)|#[0-9a-fA-F]{3,8}|[a-z]+)$/i);
|
|
45
|
+
if (e) return e[1];
|
|
46
|
+
}
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
function s(e) {
|
|
50
|
+
let t = e.ownerDocument;
|
|
51
|
+
for (let n of Array.from(e.querySelectorAll("td, th"))) {
|
|
52
|
+
let e = n.querySelectorAll("p");
|
|
53
|
+
if (e.length !== 0) {
|
|
54
|
+
for (let n of Array.from(e)) {
|
|
55
|
+
if (n.innerHTML.trim() === "" || n.innerHTML.trim() === " ") {
|
|
56
|
+
n.remove();
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
let e = t.createDocumentFragment();
|
|
60
|
+
e.append(...Array.from(n.childNodes)), e.append(t.createElement("br")), n.replaceWith(e);
|
|
61
|
+
}
|
|
62
|
+
f(n);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function c(e) {
|
|
67
|
+
for (let t of Array.from(e.querySelectorAll("p"))) t.closest("td") || t.closest("th") || (t.textContent ?? "").replace(/[\s\u00A0]/g, "").length === 0 && t.remove();
|
|
68
|
+
}
|
|
69
|
+
function l(e) {
|
|
70
|
+
let t = e.ownerDocument;
|
|
71
|
+
for (let n of Array.from(e.querySelectorAll("del, strike"))) {
|
|
72
|
+
let e = t.createElement("s");
|
|
73
|
+
e.append(...Array.from(n.childNodes)), n.replaceWith(e);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
var u = /^[\u2022\u00B7][\s\u00A0]*|^-\s/;
|
|
77
|
+
function d(e) {
|
|
78
|
+
let t = e.ownerDocument, n = Array.from(e.childNodes), r = null;
|
|
79
|
+
for (let e of n) {
|
|
80
|
+
if (e.nodeType !== Node.ELEMENT_NODE) continue;
|
|
81
|
+
let n = e;
|
|
82
|
+
if (n.tagName !== "P") {
|
|
83
|
+
r = null;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
let i = n.textContent ?? "";
|
|
87
|
+
if (!u.test(i)) {
|
|
88
|
+
r = null;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
r || (r = t.createElement("ul"), n.before(r));
|
|
92
|
+
let a = t.createElement("li"), o = p(n);
|
|
93
|
+
o && (o.textContent = (o.textContent ?? "").replace(u, "")), a.append(...Array.from(n.childNodes)), r.appendChild(a), n.remove();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function f(e) {
|
|
97
|
+
let t = e.lastChild;
|
|
98
|
+
for (; t;) if (t.nodeType === Node.ELEMENT_NODE && t.tagName === "BR") {
|
|
99
|
+
let e = t.previousSibling;
|
|
100
|
+
t.remove(), t = e;
|
|
101
|
+
} else if (t.nodeType === Node.TEXT_NODE && t.textContent?.trim() === "") {
|
|
102
|
+
let e = t.previousSibling;
|
|
103
|
+
t.remove(), t = e;
|
|
104
|
+
} else break;
|
|
105
|
+
}
|
|
106
|
+
function p(e) {
|
|
107
|
+
if (e.nodeType === Node.TEXT_NODE) return e;
|
|
108
|
+
for (let t of Array.from(e.childNodes)) {
|
|
109
|
+
let e = p(t);
|
|
110
|
+
if (e) return e;
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/cli/commands/convert-html/sanitizer.ts
|
|
116
|
+
var m = {
|
|
117
|
+
B: !0,
|
|
118
|
+
STRONG: !0,
|
|
119
|
+
I: !0,
|
|
120
|
+
EM: !0,
|
|
121
|
+
A: new Set(["href"]),
|
|
122
|
+
S: !0,
|
|
123
|
+
U: !0,
|
|
124
|
+
CODE: !0,
|
|
125
|
+
MARK: new Set(["style"]),
|
|
126
|
+
BR: !0,
|
|
127
|
+
P: !0,
|
|
128
|
+
H1: !0,
|
|
129
|
+
H2: !0,
|
|
130
|
+
H3: !0,
|
|
131
|
+
H4: !0,
|
|
132
|
+
H5: !0,
|
|
133
|
+
H6: !0,
|
|
134
|
+
UL: !0,
|
|
135
|
+
OL: !0,
|
|
136
|
+
LI: new Set(["aria-level"]),
|
|
137
|
+
TABLE: !0,
|
|
138
|
+
THEAD: !0,
|
|
139
|
+
TBODY: !0,
|
|
140
|
+
TR: !0,
|
|
141
|
+
TD: new Set(["style"]),
|
|
142
|
+
TH: new Set(["style"]),
|
|
143
|
+
BLOCKQUOTE: !0,
|
|
144
|
+
PRE: !0,
|
|
145
|
+
HR: !0,
|
|
146
|
+
ASIDE: new Set(["style"]),
|
|
147
|
+
DETAILS: !0,
|
|
148
|
+
SUMMARY: !0,
|
|
149
|
+
IMG: new Set(["src", "style"])
|
|
150
|
+
};
|
|
151
|
+
function h(e) {
|
|
152
|
+
g(e);
|
|
153
|
+
}
|
|
154
|
+
function g(e) {
|
|
155
|
+
let t = Array.from(e.childNodes);
|
|
156
|
+
for (let e of t) {
|
|
157
|
+
if (e.nodeType !== e.ELEMENT_NODE) continue;
|
|
158
|
+
let n = e, r = m[n.tagName];
|
|
159
|
+
if (r === void 0) {
|
|
160
|
+
let e = Array.from(n.childNodes);
|
|
161
|
+
for (let t of e) n.before(t);
|
|
162
|
+
n.remove();
|
|
163
|
+
for (let n of e) n.nodeType === n.ELEMENT_NODE && t.push(n);
|
|
164
|
+
} else {
|
|
165
|
+
if (r !== !0) for (let e of Array.from(n.attributes)) r.has(e.name) || n.removeAttribute(e.name);
|
|
166
|
+
else for (let e of Array.from(n.attributes)) n.removeAttribute(e.name);
|
|
167
|
+
g(n);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region src/cli/commands/convert-html/id-generator.ts
|
|
173
|
+
function _() {
|
|
174
|
+
let e = /* @__PURE__ */ new Map();
|
|
175
|
+
return (t) => {
|
|
176
|
+
let n = (e.get(t) ?? 0) + 1;
|
|
177
|
+
return e.set(t, n), `${t}-${n}`;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/components/shared/color-presets.ts
|
|
182
|
+
var v = [
|
|
183
|
+
{
|
|
184
|
+
name: "gray",
|
|
185
|
+
text: "#787774",
|
|
186
|
+
bg: "#f1f1ef"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: "brown",
|
|
190
|
+
text: "#9f6b53",
|
|
191
|
+
bg: "#f4eeee"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
name: "orange",
|
|
195
|
+
text: "#d9730d",
|
|
196
|
+
bg: "#fbecdd"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: "yellow",
|
|
200
|
+
text: "#cb9b00",
|
|
201
|
+
bg: "#fbf3db"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: "green",
|
|
205
|
+
text: "#448361",
|
|
206
|
+
bg: "#edf3ec"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: "blue",
|
|
210
|
+
text: "#337ea9",
|
|
211
|
+
bg: "#e7f3f8"
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: "purple",
|
|
215
|
+
text: "#9065b0",
|
|
216
|
+
bg: "#f6f3f9"
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: "pink",
|
|
220
|
+
text: "#c14c8a",
|
|
221
|
+
bg: "#f9f0f5"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
name: "red",
|
|
225
|
+
text: "#d44c47",
|
|
226
|
+
bg: "#fdebec"
|
|
227
|
+
}
|
|
228
|
+
], y = [
|
|
229
|
+
{
|
|
230
|
+
name: "gray",
|
|
231
|
+
text: "#9b9b9b",
|
|
232
|
+
bg: "#2f2f2f"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: "brown",
|
|
236
|
+
text: "#c59177",
|
|
237
|
+
bg: "#452a1c"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: "orange",
|
|
241
|
+
text: "#dc8c47",
|
|
242
|
+
bg: "#4d2f14"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
name: "yellow",
|
|
246
|
+
text: "#d4ab49",
|
|
247
|
+
bg: "#544012"
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: "green",
|
|
251
|
+
text: "#5db184",
|
|
252
|
+
bg: "#1e432f"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: "blue",
|
|
256
|
+
text: "#5c9fcc",
|
|
257
|
+
bg: "#123a54"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: "purple",
|
|
261
|
+
text: "#a67dca",
|
|
262
|
+
bg: "#341d49"
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "pink",
|
|
266
|
+
text: "#d45e99",
|
|
267
|
+
bg: "#4b1b33"
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
name: "red",
|
|
271
|
+
text: "#dd5e5a",
|
|
272
|
+
bg: "#4e1a18"
|
|
273
|
+
}
|
|
274
|
+
];
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region src/components/utils/color-mapping.ts
|
|
277
|
+
function b(e, t, n) {
|
|
278
|
+
let r = t / 100, i = n / 100;
|
|
279
|
+
if (r === 0) {
|
|
280
|
+
let e = Math.round(i * 255);
|
|
281
|
+
return [
|
|
282
|
+
e,
|
|
283
|
+
e,
|
|
284
|
+
e
|
|
285
|
+
];
|
|
286
|
+
}
|
|
287
|
+
let a = (e) => e < 0 ? e + 1 : e > 1 ? e - 1 : e, o = (e, t, n) => {
|
|
288
|
+
let r = a(n);
|
|
289
|
+
return r < 1 / 6 ? e + (t - e) * 6 * r : r < 1 / 2 ? t : r < 2 / 3 ? e + (t - e) * (2 / 3 - r) * 6 : e;
|
|
290
|
+
}, s = i < .5 ? i * (1 + r) : i + r - i * r, c = 2 * i - s, l = e / 360;
|
|
291
|
+
return [
|
|
292
|
+
Math.round(o(c, s, l + 1 / 3) * 255),
|
|
293
|
+
Math.round(o(c, s, l) * 255),
|
|
294
|
+
Math.round(o(c, s, l - 1 / 3) * 255)
|
|
295
|
+
];
|
|
296
|
+
}
|
|
297
|
+
function x(e) {
|
|
298
|
+
let t = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(e);
|
|
299
|
+
if (t) return [
|
|
300
|
+
parseInt(t[1], 16),
|
|
301
|
+
parseInt(t[2], 16),
|
|
302
|
+
parseInt(t[3], 16)
|
|
303
|
+
];
|
|
304
|
+
let n = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})[0-9a-f]{2}$/i.exec(e);
|
|
305
|
+
if (n) return [
|
|
306
|
+
parseInt(n[1], 16),
|
|
307
|
+
parseInt(n[2], 16),
|
|
308
|
+
parseInt(n[3], 16)
|
|
309
|
+
];
|
|
310
|
+
let r = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(e);
|
|
311
|
+
if (r) return [
|
|
312
|
+
parseInt(r[1] + r[1], 16),
|
|
313
|
+
parseInt(r[2] + r[2], 16),
|
|
314
|
+
parseInt(r[3] + r[3], 16)
|
|
315
|
+
];
|
|
316
|
+
let i = /^#([0-9a-f])([0-9a-f])([0-9a-f])[0-9a-f]$/i.exec(e);
|
|
317
|
+
if (i) return [
|
|
318
|
+
parseInt(i[1] + i[1], 16),
|
|
319
|
+
parseInt(i[2] + i[2], 16),
|
|
320
|
+
parseInt(i[3] + i[3], 16)
|
|
321
|
+
];
|
|
322
|
+
let a = /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*[\d.]+\s*)?\)$/i.exec(e);
|
|
323
|
+
if (a) return [
|
|
324
|
+
Number(a[1]),
|
|
325
|
+
Number(a[2]),
|
|
326
|
+
Number(a[3])
|
|
327
|
+
];
|
|
328
|
+
let o = /^hsla?\(\s*([\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*(?:,\s*[\d.]+\s*)?\)$/i.exec(e);
|
|
329
|
+
return o ? b(Number(o[1]), Number(o[2]), Number(o[3])) : null;
|
|
330
|
+
}
|
|
331
|
+
var S = .1;
|
|
332
|
+
function C(e) {
|
|
333
|
+
let t = e[0] / 255, n = e[1] / 255, r = e[2] / 255, i = Math.max(t, n, r), a = Math.min(t, n, r), o = (i + a) / 2;
|
|
334
|
+
if (i === a) return [
|
|
335
|
+
0,
|
|
336
|
+
0,
|
|
337
|
+
o
|
|
338
|
+
];
|
|
339
|
+
let s = i - a, c = o > .5 ? s / (2 - i - a) : s / (i + a);
|
|
340
|
+
return [
|
|
341
|
+
((e) => e === t ? ((n - r) / s + (n < r ? 6 : 0)) / 6 : e === n ? ((r - t) / s + 2) / 6 : ((t - n) / s + 4) / 6)(i) * 360,
|
|
342
|
+
c,
|
|
343
|
+
o
|
|
344
|
+
];
|
|
345
|
+
}
|
|
346
|
+
function w(e, t) {
|
|
347
|
+
let n = e[1] < S, r = t[1] < S;
|
|
348
|
+
if (n && r) {
|
|
349
|
+
let n = Math.abs(e[2] - t[2]);
|
|
350
|
+
return n * n;
|
|
351
|
+
}
|
|
352
|
+
if (n !== r) return 1e3;
|
|
353
|
+
let i = Math.abs(e[0] - t[0]), a = Math.min(i, 360 - i) / 180, o = Math.abs(e[1] - t[1]), s = Math.abs(e[2] - t[2]);
|
|
354
|
+
return 8 * a * a + 1 * o * o + 1 * s * s;
|
|
355
|
+
}
|
|
356
|
+
function T(e, t) {
|
|
357
|
+
let n = x(e);
|
|
358
|
+
if (n === null) return null;
|
|
359
|
+
let r = C(n);
|
|
360
|
+
return [...v, ...y].reduce((e, n) => {
|
|
361
|
+
let i = x(n[t]);
|
|
362
|
+
if (i === null) return e;
|
|
363
|
+
let a = w(r, C(i));
|
|
364
|
+
return e === null || a < e.distance ? {
|
|
365
|
+
name: n.name,
|
|
366
|
+
distance: a
|
|
367
|
+
} : e;
|
|
368
|
+
}, null)?.name ?? null;
|
|
369
|
+
}
|
|
370
|
+
//#endregion
|
|
371
|
+
//#region src/cli/commands/convert-html/block-builder.ts
|
|
372
|
+
function E(e) {
|
|
373
|
+
let t = _(), n = [];
|
|
374
|
+
for (let r of Array.from(e.childNodes)) D(r, n, t);
|
|
375
|
+
return n;
|
|
376
|
+
}
|
|
377
|
+
function D(e, t, n) {
|
|
378
|
+
if (e.nodeType === Node.TEXT_NODE) {
|
|
379
|
+
let r = e.textContent?.trim() ?? "";
|
|
380
|
+
r && t.push({
|
|
381
|
+
id: n("paragraph"),
|
|
382
|
+
type: "paragraph",
|
|
383
|
+
data: { text: r }
|
|
384
|
+
});
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (e.nodeType !== Node.ELEMENT_NODE) return;
|
|
388
|
+
let r = e, i = r.tagName;
|
|
389
|
+
if (i === "P") {
|
|
390
|
+
t.push({
|
|
391
|
+
id: n("paragraph"),
|
|
392
|
+
type: "paragraph",
|
|
393
|
+
data: { text: r.innerHTML }
|
|
394
|
+
});
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
if (/^H[1-6]$/.test(i)) {
|
|
398
|
+
let e = Number(i[1]);
|
|
399
|
+
t.push({
|
|
400
|
+
id: n("header"),
|
|
401
|
+
type: "header",
|
|
402
|
+
data: {
|
|
403
|
+
text: r.innerHTML,
|
|
404
|
+
level: e
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (i === "BLOCKQUOTE") {
|
|
410
|
+
t.push({
|
|
411
|
+
id: n("quote"),
|
|
412
|
+
type: "quote",
|
|
413
|
+
data: {
|
|
414
|
+
text: r.innerHTML,
|
|
415
|
+
size: "default"
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
if (i === "PRE") {
|
|
421
|
+
t.push({
|
|
422
|
+
id: n("code"),
|
|
423
|
+
type: "code",
|
|
424
|
+
data: {
|
|
425
|
+
code: r.textContent ?? "",
|
|
426
|
+
language: "plain-text"
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
if (i === "HR") {
|
|
432
|
+
t.push({
|
|
433
|
+
id: n("divider"),
|
|
434
|
+
type: "divider",
|
|
435
|
+
data: {}
|
|
436
|
+
});
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if (i === "IMG") {
|
|
440
|
+
let e = r.getAttribute("src") ?? "", i = j(r, "width"), a = null;
|
|
441
|
+
if (i) {
|
|
442
|
+
let e = parseInt(i, 10);
|
|
443
|
+
isNaN(e) || (a = e);
|
|
444
|
+
}
|
|
445
|
+
t.push({
|
|
446
|
+
id: n("image"),
|
|
447
|
+
type: "image",
|
|
448
|
+
data: { url: e },
|
|
449
|
+
stretched: null,
|
|
450
|
+
key: null,
|
|
451
|
+
width: a
|
|
452
|
+
});
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
if (i === "DETAILS") {
|
|
456
|
+
let e = r.querySelector("summary"), i = e ? e.innerHTML : r.innerHTML;
|
|
457
|
+
t.push({
|
|
458
|
+
id: n("toggle"),
|
|
459
|
+
type: "toggle",
|
|
460
|
+
data: { text: i }
|
|
461
|
+
});
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (i === "UL" || i === "OL") {
|
|
465
|
+
O(r, i === "OL" ? "ordered" : "unordered", 0, t, n);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
if (i === "TABLE") {
|
|
469
|
+
k(r, t, n);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
if (i === "ASIDE") {
|
|
473
|
+
A(r, t, n);
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
t.push({
|
|
477
|
+
id: n("paragraph"),
|
|
478
|
+
type: "paragraph",
|
|
479
|
+
data: { text: r.innerHTML }
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
function O(e, t, n, r, i) {
|
|
483
|
+
let a = e.getAttribute("start"), o = a ? Number(a) : null, s = !0;
|
|
484
|
+
for (let a of Array.from(e.children)) {
|
|
485
|
+
if (a.tagName !== "LI") continue;
|
|
486
|
+
let e = a.cloneNode(!0), c = [];
|
|
487
|
+
for (let t of Array.from(e.querySelectorAll("ul, ol"))) c.push(t.cloneNode(!0)), t.remove();
|
|
488
|
+
let l = e.innerHTML.trim(), u = a.getAttribute("aria-level"), d = n;
|
|
489
|
+
u && (d = Math.max(0, parseInt(u, 10) - 1)), r.push({
|
|
490
|
+
id: i("list"),
|
|
491
|
+
type: "list",
|
|
492
|
+
data: {
|
|
493
|
+
text: l,
|
|
494
|
+
style: t,
|
|
495
|
+
depth: d === 0 ? null : d,
|
|
496
|
+
checked: null,
|
|
497
|
+
start: s && o !== null ? o : null
|
|
498
|
+
}
|
|
499
|
+
}), s = !1;
|
|
500
|
+
for (let e of c) O(e, e.tagName === "OL" ? "ordered" : "unordered", n + 1, r, i);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
function k(e, t, n) {
|
|
504
|
+
let r = n("table"), i = Array.from(e.querySelectorAll("tr")), a = !1, o = [];
|
|
505
|
+
for (let e = 0; e < i.length; e++) {
|
|
506
|
+
let s = i[e], c = Array.from(s.querySelectorAll("td, th"));
|
|
507
|
+
e === 0 && c.some((e) => e.tagName === "TH") && (a = !0);
|
|
508
|
+
let l = [];
|
|
509
|
+
for (let e of c) {
|
|
510
|
+
let i = e, a = i.innerHTML.trim();
|
|
511
|
+
if (a) {
|
|
512
|
+
let e = n("paragraph");
|
|
513
|
+
t.push({
|
|
514
|
+
id: e,
|
|
515
|
+
type: "paragraph",
|
|
516
|
+
parent: r,
|
|
517
|
+
data: { text: a }
|
|
518
|
+
});
|
|
519
|
+
let o = j(i, "background-color"), s = j(i, "color");
|
|
520
|
+
l.push({
|
|
521
|
+
blocks: [e],
|
|
522
|
+
color: o ? T(o, "bg") : null,
|
|
523
|
+
textColor: s ? T(s, "text") : null
|
|
524
|
+
});
|
|
525
|
+
} else l.push({
|
|
526
|
+
blocks: [],
|
|
527
|
+
color: null,
|
|
528
|
+
textColor: null
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
o.push(l);
|
|
532
|
+
}
|
|
533
|
+
let s = (i[0] ? Array.from(i[0].querySelectorAll("td, th")) : []).map((e) => {
|
|
534
|
+
let t = j(e, "width");
|
|
535
|
+
if (t) {
|
|
536
|
+
let e = parseInt(t, 10);
|
|
537
|
+
return isNaN(e) ? null : e;
|
|
538
|
+
}
|
|
539
|
+
return null;
|
|
540
|
+
}), c = s.some((e) => e !== null), l = {
|
|
541
|
+
id: r,
|
|
542
|
+
type: "table",
|
|
543
|
+
data: {
|
|
544
|
+
withHeadings: a,
|
|
545
|
+
withHeadingColumn: !1,
|
|
546
|
+
content: o,
|
|
547
|
+
...c ? { colWidths: s } : {}
|
|
548
|
+
}
|
|
549
|
+
}, u = t.findIndex((e) => e.parent === r);
|
|
550
|
+
u >= 0 ? t.splice(u, 0, l) : t.push(l);
|
|
551
|
+
}
|
|
552
|
+
function A(e, t, n) {
|
|
553
|
+
let r = n("callout"), i = j(e, "background-color"), a = i ? T(i, "bg") : null, o = [];
|
|
554
|
+
for (let i of Array.from(e.childNodes)) if (i.nodeType === Node.ELEMENT_NODE) {
|
|
555
|
+
let e = i, a = n("paragraph");
|
|
556
|
+
t.push({
|
|
557
|
+
id: a,
|
|
558
|
+
type: "paragraph",
|
|
559
|
+
parent: r,
|
|
560
|
+
data: { text: e.innerHTML }
|
|
561
|
+
}), o.push(a);
|
|
562
|
+
} else if (i.nodeType === Node.TEXT_NODE) {
|
|
563
|
+
let e = i.textContent?.trim() ?? "";
|
|
564
|
+
if (e) {
|
|
565
|
+
let i = n("paragraph");
|
|
566
|
+
t.push({
|
|
567
|
+
id: i,
|
|
568
|
+
type: "paragraph",
|
|
569
|
+
parent: r,
|
|
570
|
+
data: { text: e }
|
|
571
|
+
}), o.push(i);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
let s = t.findIndex((e) => e.parent === r), c = {
|
|
575
|
+
id: r,
|
|
576
|
+
type: "callout",
|
|
577
|
+
data: {
|
|
578
|
+
emoji: "💡",
|
|
579
|
+
backgroundColor: a ?? "gray"
|
|
580
|
+
},
|
|
581
|
+
content: o
|
|
582
|
+
};
|
|
583
|
+
s >= 0 ? t.splice(s, 0, c) : t.push(c);
|
|
584
|
+
}
|
|
585
|
+
function j(e, t) {
|
|
586
|
+
let n = e.getAttribute("style");
|
|
587
|
+
if (!n) return null;
|
|
588
|
+
let r = RegExp(`(?<![\\-a-z])${t}\\s*:\\s*([^;]+)`).exec(n);
|
|
589
|
+
return r ? r[1].trim() : null;
|
|
590
|
+
}
|
|
591
|
+
//#endregion
|
|
592
|
+
//#region src/cli/commands/convert-html/index.ts
|
|
593
|
+
function M(t) {
|
|
594
|
+
let n = new DOMParser().parseFromString(t, "text/html").body;
|
|
595
|
+
e(n), h(n);
|
|
596
|
+
let r = {
|
|
597
|
+
version: "2.31.0",
|
|
598
|
+
blocks: E(n)
|
|
599
|
+
};
|
|
600
|
+
return JSON.stringify(r);
|
|
601
|
+
}
|
|
602
|
+
//#endregion
|
|
603
|
+
export { M as convertHtml };
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jackuait/blok-cli",
|
|
3
|
+
"version": "0.10.0-beta.15",
|
|
4
|
+
"description": "CLI tools for Blok — convert HTML to Blok JSON, generate migration guides",
|
|
5
|
+
"bin": {
|
|
6
|
+
"blok-cli": "bin/blok-cli.mjs"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin",
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=20.19.0"
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"blok",
|
|
20
|
+
"cli",
|
|
21
|
+
"html-to-json",
|
|
22
|
+
"editorjs",
|
|
23
|
+
"migration",
|
|
24
|
+
"rich-text"
|
|
25
|
+
],
|
|
26
|
+
"author": "JackUait",
|
|
27
|
+
"license": "Apache-2.0",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/JackUait/blok.git",
|
|
31
|
+
"directory": "packages/cli"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"jsdom": "28.1.0"
|
|
35
|
+
}
|
|
36
|
+
}
|