diff --git a/._MARKDOWN_EDITOR_REWRITE_PLAN.md b/._MARKDOWN_EDITOR_REWRITE_PLAN.md
new file mode 100755
index 00000000..3d095653
Binary files /dev/null and b/._MARKDOWN_EDITOR_REWRITE_PLAN.md differ
diff --git a/._MARKDOWN_EDITOR_UX_FINDINGS.md b/._MARKDOWN_EDITOR_UX_FINDINGS.md
new file mode 100755
index 00000000..3d095653
Binary files /dev/null and b/._MARKDOWN_EDITOR_UX_FINDINGS.md differ
diff --git a/._tailwind.config.js b/._tailwind.config.js
new file mode 100755
index 00000000..3d095653
Binary files /dev/null and b/._tailwind.config.js differ
diff --git a/MARKDOWN_EDITOR_REWRITE_PLAN.md b/MARKDOWN_EDITOR_REWRITE_PLAN.md
new file mode 100755
index 00000000..4201446b
--- /dev/null
+++ b/MARKDOWN_EDITOR_REWRITE_PLAN.md
@@ -0,0 +1,46 @@
+# Markdown Editor - Architecture Rewrite Plan
+
+## Context & Motivation
+The current Markdown Editor violates the core UX philosophy of the Dewe.Dev suite: `[input] program -> [process/edit] human -> [output] program`.
+
+Currently, users input Markdown and edit raw Markdown in a CodeMirror instance. To align with the rest of the suite (Object Editor, Table Editor, Invoice Editor), the tool must provide a **WYSIWYG (What You See Is What You Get) Rich Text Editor**. The user should interact with human-readable text visually, while the system seamlessly translates it back to raw Markdown/HTML for export.
+
+## Phase 1: Dependency Updates & Tiptap Integration
+To achieve a robust WYSIWYG experience that translates perfectly to/from Markdown, we will use **Tiptap** (a headless wrapper around ProseMirror).
+
+**Dependencies to Install:**
+* `@tiptap/react`
+* `@tiptap/starter-kit` (Core formatting)
+* `@tiptap/extension-link` (Hyperlinks)
+* `@tiptap/extension-image` (Image support)
+* `@tiptap/extension-table` (Table support)
+* `@tiptap/extension-task-list` & `@tiptap/extension-task-item`
+* `tiptap-markdown` (Crucial: Handles native parsing/serializing of markdown to the Tiptap state)
+
+**Dependencies to Remove:**
+* `marked` (Tiptap handles parsing now)
+* `dompurify` (Tiptap handles sanitization)
+* Custom CodeMirror Markdown implementations inside `MarkdownEditor.js` (We will keep CodeMirror only for the final "Export Code" view, if needed).
+
+## Phase 2: Component Restructuring
+Create a new component: `RichMarkdownEditor.js`.
+This component will replace the split-view CodeMirror setup.
+
+**Features of `RichMarkdownEditor.js`:**
+1. **Floating/Sticky Toolbar:** Similar to Google Docs or Notion. Bold, Italic, H1-H3, Lists, Blockquotes, Code Blocks.
+2. **Interactive Editor Content:** The actual prose area where users type naturally.
+3. **Two-way Binding:** When the Tiptap state updates, it immediately serializes the state to a hidden Markdown string, which is saved to `localStorage` (for data-loss prevention) and readied for export.
+
+## Phase 3: UX Flow Adjustments (Addressing Previous Findings)
+* **Input Flow:** User pastes Markdown -> Tiptap parses it via `tiptap-markdown` -> User sees rendered Rich Text immediately (Fixes UX Gap #3 from previous findings).
+* **View Modes:** Remove the complex "Split View" vs "Editor Only" logic. The primary view is *always* the Rich Text Editor.
+* **File Uploads:** Restrict the `` to only accept `.md` and `.txt` files. Remove UI mentions of `.html` or `.docx` until a dedicated parser (like mammoth.js) is explicitly implemented (Fixes UX Gap #2).
+
+## Phase 4: Export Engine
+The Export card will now feature:
+1. **Raw Markdown:** A read-only CodeMirror block displaying the exact Markdown output generated by Tiptap, with "Copy" and "Download" buttons.
+2. **HTML:** Tiptap's `editor.getHTML()` output.
+3. **PDF Export:** Retain `html2pdf.js`, but explicitly inject CSS print rules (`break-inside: avoid`, `white-space: pre-wrap`) targeting Tiptap's code block classes to prevent page overflow (Fixes UX Gap #4).
+
+## Summary
+By executing this rewrite, the Markdown Editor will transition from a basic code validator into a premium document translation hub, perfectly aligning with the product's overarching vision.
diff --git a/MARKDOWN_EDITOR_UX_FINDINGS.md b/MARKDOWN_EDITOR_UX_FINDINGS.md
new file mode 100755
index 00000000..d928799e
--- /dev/null
+++ b/MARKDOWN_EDITOR_UX_FINDINGS.md
@@ -0,0 +1,21 @@
+# Markdown Editor UX Findings & Proposed Improvements
+
+## 1. Core Goal Misalignment (The Primary UX Defect)
+**Current State:** The user inputs markdown (via paste, URL, file, or typing), and the primary editing experience happens in a raw text editor (CodeMirror) where they edit markdown syntax. The "rendered" version is read-only (Preview).
+**The Gap:** As a developer tool, the goal is often to translate system language (markdown) into human language (rich text) *and vice-versa*. Humans expect a WYSIWYG (What You See Is What You Get) document editor experience.
+**The Proposed Fix:** The "Preview" should actually be an interactive, editable Rich Text interface. A user should be able to input raw markdown, see the rich text, *edit the rich text visually like a Word document*, and then export the result back to raw markdown.
+
+## 2. File Import Format Limitations
+**Current State:** The UI implies users can open files.
+**The Gap:** `.html` and `.docx` imports require external libraries (`turndown`, `mammoth.js`) which are not yet fully implemented according to the Phase 2 roadmap.
+**The Proposed Fix:** Restrict the `` to `.md` and `.txt` until the conversion logic is built, preventing users from loading raw binary/HTML into the text editor.
+
+## 3. View Mode Toggles & Workflow
+**Current State:** Defaults to 'split' on desktop and 'editor' on mobile. After importing data, it jumps to the raw editor.
+**The Gap:** Similar to the Object Editor, jumping straight to raw code isn't ideal.
+**The Proposed Fix:** After data is provided, default to the (newly proposed) Rich Text / Preview mode first.
+
+## 4. PDF Export Styling
+**Current State:** Uses `html2pdf.js` for export.
+**The Gap:** Long code blocks in markdown often overflow the page boundaries when converted to PDF because CSS print media rules for `white-space: pre-wrap` or `break-inside` are missing.
+**The Proposed Fix:** Inject print-specific CSS rules before triggering the PDF export to ensure code blocks wrap gracefully.
diff --git a/package-lock.json b/package-lock.json
index cd14637e..0560e4a6 100755
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,9 +22,21 @@
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
+ "@tailwindcss/typography": "^0.5.20",
"@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
+ "@tiptap/extension-code-block-lowlight": "^3.26.1",
+ "@tiptap/extension-image": "^3.26.1",
+ "@tiptap/extension-link": "^3.26.1",
+ "@tiptap/extension-table": "^3.26.1",
+ "@tiptap/extension-table-cell": "^3.26.1",
+ "@tiptap/extension-table-header": "^3.26.1",
+ "@tiptap/extension-table-row": "^3.26.1",
+ "@tiptap/extension-task-item": "^3.26.1",
+ "@tiptap/extension-task-list": "^3.26.1",
+ "@tiptap/react": "^3.26.1",
+ "@tiptap/starter-kit": "^3.26.1",
"@uiw/react-codemirror": "^4.25.1",
"codemirror": "^6.0.2",
"diff-match-patch": "^1.0.5",
@@ -35,6 +47,7 @@
"js-beautify": "^1.15.4",
"jspdf": "^3.0.3",
"jspdf-autotable": "^5.0.2",
+ "lowlight": "^3.3.0",
"lucide-react": "^0.540.0",
"marked": "^16.4.1",
"marked-emoji": "^2.0.1",
@@ -48,6 +61,8 @@
"reactflow": "^11.11.4",
"serialize-javascript": "^6.0.0",
"serve": "^14.2.4",
+ "tailwindcss-typography": "^3.1.0",
+ "tiptap-markdown": "^0.9.0",
"turndown": "^7.2.1",
"web-vitals": "^2.1.4"
},
@@ -62,7 +77,6 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -2828,12 +2842,6 @@
"integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==",
"license": "MIT"
},
- "node_modules/@codemirror/view/node_modules/w3c-keyname": {
- "version": "2.2.8",
- "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
- "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
- "license": "MIT"
- },
"node_modules/@csstools/normalize.css": {
"version": "12.1.1",
"resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.1.1.tgz",
@@ -2926,6 +2934,34 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
+ "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.11"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.6",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
+ "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@floating-ui/core": "^1.7.5",
+ "@floating-ui/utils": "^0.2.11"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
+ "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/@humanwhocodes/module-importer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
@@ -5788,7 +5824,6 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
@@ -5802,7 +5837,6 @@
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
@@ -5816,7 +5850,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
@@ -5826,7 +5859,6 @@
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
"integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
- "dev": true,
"license": "ISC",
"dependencies": {
"reusify": "^1.0.4"
@@ -5836,7 +5868,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
- "dev": true,
"license": "MIT",
"engines": {
"iojs": ">=1.0.0",
@@ -5847,7 +5878,6 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -9175,6 +9205,18 @@
"node": ">= 6"
}
},
+ "node_modules/@tailwindcss/typography": {
+ "version": "0.5.20",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.20.tgz",
+ "integrity": "sha512-hwbzQuNUfcPvbegQFatVPl/MY/tcM9KLl963hQ5laJKPh81TEZ1+dNG9PirGvcaDBkp+BCshExAyKVPW91dozw==",
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "6.0.10"
+ },
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || >=4.0.0 || insiders"
+ }
+ },
"node_modules/@testing-library/dom": {
"version": "10.4.1",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz",
@@ -9238,16 +9280,6 @@
"dequal": "^2.0.3"
}
},
- "node_modules/@testing-library/dom/node_modules/dequal": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
- "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/@testing-library/dom/node_modules/dom-accessibility-api": {
"version": "0.5.16",
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
@@ -9395,6 +9427,544 @@
"@testing-library/dom": ">=7.21.4"
}
},
+ "node_modules/@tiptap/core": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.26.1.tgz",
+ "integrity": "sha512-TX9PyPqBoix0qDLjtok/bddtdSy54QhzLVha405C07V+WySOpH3s/pWYkywehZQY0SQtcrcY4MNSCeQjCbA28A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/pm": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-blockquote": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.26.1.tgz",
+ "integrity": "sha512-WaKjKmUaadgvZDDBk9JOn/oidlOFr6booqJIWHGL5S0aUUTKHS19oGfKQq/l9Z1y1niaRePk0Y4fy/jxCnfKPA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-bold": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.26.1.tgz",
+ "integrity": "sha512-VIlF2sAiV6K009pcIDotfY8mvsPaq90dxeG9Q0ZIqfMD958TUCqjHw4MGYZf0/FgP12xksBfmcR7W312xgUf9Q==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-bubble-menu": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.26.1.tgz",
+ "integrity": "sha512-Y3R9wFKP/U9M04JG+0PM/yW3OV+MSbUp6YBKQWZmUu8x6y7TbcNvDsaJ6QEFZt5aRMS6qH1ksYPTOz47JdjcfA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@floating-ui/dom": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1",
+ "@tiptap/pm": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-bullet-list": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.26.1.tgz",
+ "integrity": "sha512-JB6bEJJHxXNAXEXTIAN3/j70p1ARHdeMfhzshGZswWKUWtDibTCrspIp7p1VNeiuVtJ/HB6PpFkGi7yWtQ3RTg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-list": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-code": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.26.1.tgz",
+ "integrity": "sha512-t9/VR5k3rGPyhcGau9YvVgaAQ+nP9R9WzS996bQQ7GIrMOTSXb0FWwoQFBiYl83V6VA16Tlj/oScC7SFlA8lvA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-code-block": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.26.1.tgz",
+ "integrity": "sha512-NY7SYqcrqDVYTSWyaNGdSfCims6pOHoRQ2Rh4DEFb/rb8gLVkqbLZhcHzQCVfinlPqgV3xWF6cYMORwmnlBkXQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1",
+ "@tiptap/pm": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-code-block-lowlight": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-3.26.1.tgz",
+ "integrity": "sha512-DToQR8rJs/KeTU0KqCOdufkx8ujpFSWHZURUI8ajcX4z4nja8Q28OTvHflRQidsbF6i7Ps/3ga3odurXIpgyjw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1",
+ "@tiptap/extension-code-block": "3.26.1",
+ "@tiptap/pm": "3.26.1",
+ "highlight.js": "^11",
+ "lowlight": "^2 || ^3"
+ }
+ },
+ "node_modules/@tiptap/extension-document": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.26.1.tgz",
+ "integrity": "sha512-6W2vZjvi0Mv+4xEtwMDGhWwo7FotWR6eKfmntmduvehWevFpMxOKcTtyotjLigfZv738y50YWmvbaPuAPJG3BA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-dropcursor": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.26.1.tgz",
+ "integrity": "sha512-eVq3BvFIa3YD+pBIlj1i72vYEixlegGVKHnSYiVF2ovkQOSAH9sca7pkq6WgV1sMTCyWCU8e+WznTqtydvHUWA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extensions": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-floating-menu": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.26.1.tgz",
+ "integrity": "sha512-xn0g4m/q2bjG+hULPwp6Aqb/6wpzUtc65jOhgJsG/S3Ey3kLJGUvZBuhozwNFu8FcugxM1fMUpNhkJkodCCGFw==",
+ "license": "MIT",
+ "optional": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@floating-ui/dom": "^1.0.0",
+ "@tiptap/core": "3.26.1",
+ "@tiptap/pm": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-gapcursor": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.26.1.tgz",
+ "integrity": "sha512-BWW1yMQQA4TbEU0LLK+4cd9ebLTuZG5KjHwFMBRD/bGiRW9V1gTWFsCqThBbczcANoQiZK9pn5/4Ad/rGM3HUg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extensions": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-hard-break": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.26.1.tgz",
+ "integrity": "sha512-gzNb1e/fK6HN+ko1axsrasjK7F1q0Bnm0G4ZY/0eq7pV7s1wZuwoCiGbvUx/9LCFKRV6+94FTqlb0A3NbYN36g==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-heading": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.26.1.tgz",
+ "integrity": "sha512-eRlv9XxzUL8FobKAiF1WjP35CT2QpbcxxeyYFF7BmGEONvKI7r5g7JGwyGli4Cvclh70h8w6JuoXSmGUVEU65A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-horizontal-rule": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.26.1.tgz",
+ "integrity": "sha512-l9lPZYeSmY90y/2GkQcKaICFD5Atr8sx2SzJGkQzpNC9tRxZXyAHnfJE3OjBkspuGzjWIN0DimxBj4ibz58sKw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1",
+ "@tiptap/pm": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-image": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-image/-/extension-image-3.26.1.tgz",
+ "integrity": "sha512-IjoT+kRK4a1sTImvUz257yfk5l9kMxXxfxCfix5AUKdiWyn8SGUjJZapLICcZVY05UDqXmwsBvBK9lHkKX5ERg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-italic": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.26.1.tgz",
+ "integrity": "sha512-cLKYvOLToWEkJkAPspgIZ/PYDzAxacLm1VWcAq1tO1QDQCDe2Kw+y/zsGlyYEq/aKsAgpp4JNopBwAXRXxt2/A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-link": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.26.1.tgz",
+ "integrity": "sha512-aLLGLgikuhLFHRbjfUC6D4gRg+NUty4uhW7YkyVl8AxxPME47dPbCOX4H6uLCjEZcn3WnfNuCTr6HCTl0KEmGA==",
+ "license": "MIT",
+ "dependencies": {
+ "linkifyjs": "^4.3.3"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1",
+ "@tiptap/pm": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-list": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.26.1.tgz",
+ "integrity": "sha512-06nOjnyXpzMO8Ys5k3IbYsDsKib1mv2OtaxBYX1/1uvRyOKwUX5tqDLb/qigic0LIANNL73lkNC8Z8XPeG4Tkg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1",
+ "@tiptap/pm": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-list-item": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.26.1.tgz",
+ "integrity": "sha512-5gLXJUiP763NA6i4HgrtcwUDXPP8820hsaBQyF1Y1VsXNi02uW9FVLe3RZK8jF0NZUNh9CqD0gogYJCbKOUU8A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-list": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-list-keymap": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.26.1.tgz",
+ "integrity": "sha512-EReSayePO6SIxtRbxx+7KfBQreWHvoZmMb3O/RemfT8W6J0hCG5N/Rh8Z12+YZOnCDRXJ4RzFpAikYka3E54jQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-list": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-ordered-list": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.26.1.tgz",
+ "integrity": "sha512-LeFPeFwb7ylkQVuuaHj+niu7WhWHpjDOi1GKZJE/ohOa2lgt7P221HMqhUzPiDlXOExN72oWTNmXUlT0ymCTkw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-list": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-paragraph": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.26.1.tgz",
+ "integrity": "sha512-OkBeYUNM3eTzjm3z6IcC3NHryOX8g3eGNI86P/B+tFoFQSRuzLsKZU50ARCfIiLLg812NjcqujeJ1eX3BKDZrw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-strike": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.26.1.tgz",
+ "integrity": "sha512-7hmQ2mBsA+75GRrJIKYxb+10H23mblEQSGGsv9Ptl7JLaGmj+8sv2HGQGSUT9QBiBVprxaYTqyWFXQC9akfLWg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-table": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-table/-/extension-table-3.26.1.tgz",
+ "integrity": "sha512-epxUhc5ecxsH39lzNejc2WxFPXAXWGs9g2ofKDrIaoSlZlfFHf89/sEGSz048a46E5Sb+fYCtzUvRUUx+aG4xw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1",
+ "@tiptap/pm": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-table-cell": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-table-cell/-/extension-table-cell-3.26.1.tgz",
+ "integrity": "sha512-eCGgHrzIUPHZpz/z3F4O8yk+SM/HBcLVvAWTHl8P+4/GC2+6oVFH+9ixBDIMKiJugSOnuOY8uLm30+Ld/MtyTw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-table": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-table-header": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-table-header/-/extension-table-header-3.26.1.tgz",
+ "integrity": "sha512-idVDYdhVpTL4hnzuf/MbE74HHjqqqIRCVwzfbTy/d5JnTnJ1LXpJZKz2oFWNOk5NaAq0kPhkwkz5lSBUgd2DbQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-table": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-table-row": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-table-row/-/extension-table-row-3.26.1.tgz",
+ "integrity": "sha512-zAr7bQcUHoBpeysvbzxW8JchMduUn0wGwA2UeEgoE1K+gep74wRHs9LE8NRd70hARbZLzgUMRXcpT+W1pdoMMw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-table": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-task-item": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-task-item/-/extension-task-item-3.26.1.tgz",
+ "integrity": "sha512-VjwGkI7MJIswrfkArO4yWS9eAJq2KrCVsNIH96yUGkKve4cHrpDHfbCboLaj8453N98AGVtgY9GdVnAL6ypSAg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-list": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-task-list": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-task-list/-/extension-task-list-3.26.1.tgz",
+ "integrity": "sha512-d5eO6Ae6WqSZHd0lt16snD8u2PlZIjmKuvDQBjPYvzl5MUOmplcuOyaAsaphBJK5tr4u9pP9XDNVGB7Xjp0gHQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-list": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-text": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.26.1.tgz",
+ "integrity": "sha512-Gocui5WvcCCJJIX17gdOVCSdYi5H4fDwaR0qkMAUZPq5kJCdrfl+vNpt8BTt53Bk+/QumiUW21fhQ184w7RoeQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extension-underline": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.26.1.tgz",
+ "integrity": "sha512-HUHtQ+DRWDM0opW7Nk3YQwrLzw876hMU7cr1X/ZTG+8Bp+AKHihlwU+bqrPgG5St0mqASyUEhHQ/vK5PlnUYOQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/extensions": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.26.1.tgz",
+ "integrity": "sha512-PmRaoe6bebTgz/ZQrjmzwZMST1d9js9ZTiKnUXeXl3Fm+V5U/c3TbbKDfqmL63qPQdjtShDMHi9tYuv+c77OFQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1",
+ "@tiptap/pm": "3.26.1"
+ }
+ },
+ "node_modules/@tiptap/pm": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.26.1.tgz",
+ "integrity": "sha512-48cJQRbvr9Ux0+IgM1BR5vOLU5hkC+n+uerdQy2JjrIRKpYE/huU8fQFm6PoRppoKYfilklzb29elsQ+n2TA+g==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-changeset": "^2.3.0",
+ "prosemirror-commands": "^1.6.2",
+ "prosemirror-dropcursor": "^1.8.1",
+ "prosemirror-gapcursor": "^1.3.2",
+ "prosemirror-history": "^1.4.1",
+ "prosemirror-inputrules": "^1.4.0",
+ "prosemirror-keymap": "^1.2.3",
+ "prosemirror-model": "^1.25.7",
+ "prosemirror-schema-list": "^1.5.0",
+ "prosemirror-state": "^1.4.4",
+ "prosemirror-tables": "^1.8.0",
+ "prosemirror-transform": "^1.12.0",
+ "prosemirror-view": "^1.41.8"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ }
+ },
+ "node_modules/@tiptap/react": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-3.26.1.tgz",
+ "integrity": "sha512-Gl7AhTJM7pjQ2WFwdIwD736oQeqUcw3GVaXYmCKtwTSO3F9PszLgeKEp6DvM+CmctTNYhu/apRfzkH3vU0h0uA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/use-sync-external-store": "^0.0.6",
+ "fast-equals": "^5.3.3",
+ "use-sync-external-store": "^1.4.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "optionalDependencies": {
+ "@tiptap/extension-bubble-menu": "^3.26.1",
+ "@tiptap/extension-floating-menu": "^3.26.1"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.26.1",
+ "@tiptap/pm": "3.26.1",
+ "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@tiptap/starter-kit": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.26.1.tgz",
+ "integrity": "sha512-A0zsvwGU9exLND34F8e8KqUXFSfs835tNN+VC+ZT3yNeaO/WXnlh/Cgal1F6pHHbcxy7RV2CRwJU5S3cWLPxrA==",
+ "license": "MIT",
+ "dependencies": {
+ "@tiptap/core": "^3.26.1",
+ "@tiptap/extension-blockquote": "^3.26.1",
+ "@tiptap/extension-bold": "^3.26.1",
+ "@tiptap/extension-bullet-list": "^3.26.1",
+ "@tiptap/extension-code": "^3.26.1",
+ "@tiptap/extension-code-block": "^3.26.1",
+ "@tiptap/extension-document": "^3.26.1",
+ "@tiptap/extension-dropcursor": "^3.26.1",
+ "@tiptap/extension-gapcursor": "^3.26.1",
+ "@tiptap/extension-hard-break": "^3.26.1",
+ "@tiptap/extension-heading": "^3.26.1",
+ "@tiptap/extension-horizontal-rule": "^3.26.1",
+ "@tiptap/extension-italic": "^3.26.1",
+ "@tiptap/extension-link": "^3.26.1",
+ "@tiptap/extension-list": "^3.26.1",
+ "@tiptap/extension-list-item": "^3.26.1",
+ "@tiptap/extension-list-keymap": "^3.26.1",
+ "@tiptap/extension-ordered-list": "^3.26.1",
+ "@tiptap/extension-paragraph": "^3.26.1",
+ "@tiptap/extension-strike": "^3.26.1",
+ "@tiptap/extension-text": "^3.26.1",
+ "@tiptap/extension-underline": "^3.26.1",
+ "@tiptap/extensions": "^3.26.1",
+ "@tiptap/pm": "^3.26.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ }
+ },
"node_modules/@types/aria-query": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
@@ -9576,6 +10146,15 @@
"@types/send": "*"
}
},
+ "node_modules/@types/hast": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+ "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
"node_modules/@types/http-errors": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
@@ -9603,6 +10182,28 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/linkify-it": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz",
+ "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/markdown-it": {
+ "version": "13.0.9",
+ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.9.tgz",
+ "integrity": "sha512-1XPwR0+MgXLWfTn9gCsZ55AHOKW1WN+P9vr0PaQh5aerR9LLQXUbjfEAFhjmEmyoYFWAyuN2Mqkn40MZ4ukjBw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/linkify-it": "^3",
+ "@types/mdurl": "^1"
+ }
+ },
+ "node_modules/@types/mdurl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz",
+ "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==",
+ "license": "MIT"
+ },
"node_modules/@types/mime": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
@@ -9642,6 +10243,26 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/react": {
+ "version": "19.2.17",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz",
+ "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "license": "MIT",
+ "peer": true,
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
+ },
"node_modules/@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@@ -9719,6 +10340,18 @@
"devOptional": true,
"license": "MIT"
},
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "license": "MIT"
+ },
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
+ "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
+ "license": "MIT"
+ },
"node_modules/@types/ws": {
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
@@ -10207,7 +10840,6 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
- "dev": true,
"license": "MIT"
},
"node_modules/arch": {
@@ -10236,6 +10868,12 @@
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
"license": "MIT"
},
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
"node_modules/array.prototype.reduce": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.8.tgz",
@@ -13987,7 +14625,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
@@ -14246,17 +14883,10 @@
"node": ">= 6"
}
},
- "node_modules/cheerio/node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "license": "MIT"
- },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
@@ -14281,7 +14911,6 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
"license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
@@ -14295,7 +14924,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -14308,7 +14936,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
@@ -14321,7 +14948,6 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -14334,7 +14960,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
@@ -14347,7 +14972,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
@@ -14360,7 +14984,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -14370,7 +14993,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
@@ -14383,7 +15005,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -14393,7 +15014,6 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
@@ -14406,7 +15026,6 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
@@ -14419,7 +15038,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
@@ -14975,19 +15593,6 @@
"url": "https://github.com/sponsors/fb55"
}
},
- "node_modules/css-minimizer-webpack-plugin/node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/css-minimizer-webpack-plugin/node_modules/cssnano": {
"version": "5.1.15",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz",
@@ -15745,13 +16350,6 @@
"node": ">=10.13.0"
}
},
- "node_modules/css-minimizer-webpack-plugin/node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/css-minimizer-webpack-plugin/node_modules/yaml": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz",
@@ -15797,6 +16395,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/cssstyle": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
@@ -15817,6 +16427,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/d3-color": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
@@ -15887,6 +16504,15 @@
"node": ">= 10"
}
},
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
@@ -15900,11 +16526,23 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
- "dev": true,
"license": "Apache-2.0"
},
"node_modules/diff-match-patch": {
@@ -15917,7 +16555,6 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
- "dev": true,
"license": "MIT"
},
"node_modules/dns-packet": {
@@ -16140,6 +16777,18 @@
"url": "https://opencollective.com/webpack"
}
},
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
"node_modules/es-array-method-boxes-properly": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
@@ -19416,13 +20065,6 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
- "node_modules/eslint/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
- "license": "Python-2.0"
- },
"node_modules/eslint/node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -20744,11 +21386,19 @@
"node": ">= 0.8"
}
},
+ "node_modules/fast-equals": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz",
+ "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/fast-glob": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
@@ -20765,7 +21415,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
@@ -20775,7 +21424,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
@@ -20788,7 +21436,6 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -20801,7 +21448,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
@@ -20814,7 +21460,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -20824,7 +21469,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
@@ -20837,7 +21481,6 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
@@ -20847,7 +21490,6 @@
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"braces": "^3.0.3",
@@ -20861,7 +21503,6 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
@@ -20874,7 +21515,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
@@ -21181,7 +21821,6 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -21714,12 +22353,6 @@
"util-deprecate": "^1.0.2"
}
},
- "node_modules/highland/node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "license": "MIT"
- },
"node_modules/highlight.js": {
"version": "11.11.1",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
@@ -23437,7 +24070,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
@@ -27478,7 +28110,6 @@
"version": "1.21.7",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
- "dev": true,
"license": "MIT",
"bin": {
"jiti": "bin/jiti.js"
@@ -27750,6 +28381,31 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/linkify-it": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz",
+ "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/puzrin"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/markdown-it"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "uc.micro": "^2.0.0"
+ }
+ },
+ "node_modules/linkifyjs": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.3.tgz",
+ "integrity": "sha512-P8aEP5U/D1/IlTY2OeYsErdwh9bGuLE30NcXtKEjgdHcahveQoQwM2yZNsioQHsWFz0P7KKudisbrzCgR0sDHg==",
+ "license": "MIT"
+ },
"node_modules/loader-runner": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz",
@@ -27795,6 +28451,21 @@
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"license": "MIT"
},
+ "node_modules/lowlight": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-3.3.0.tgz",
+ "integrity": "sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "devlop": "^1.0.0",
+ "highlight.js": "~11.11.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/lucide-react": {
"version": "0.540.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.540.0.tgz",
@@ -27850,6 +28521,39 @@
"tmpl": "1.0.5"
}
},
+ "node_modules/markdown-it": {
+ "version": "14.2.0",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz",
+ "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/puzrin"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/markdown-it"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "^4.4.0",
+ "linkify-it": "^5.0.1",
+ "mdurl": "^2.0.0",
+ "punycode.js": "^2.3.1",
+ "uc.micro": "^2.1.0"
+ },
+ "bin": {
+ "markdown-it": "bin/markdown-it.mjs"
+ }
+ },
+ "node_modules/markdown-it-task-lists": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz",
+ "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==",
+ "license": "ISC"
+ },
"node_modules/marked": {
"version": "16.4.2",
"resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
@@ -27871,6 +28575,12 @@
"marked": ">=4 <19"
}
},
+ "node_modules/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
+ "license": "MIT"
+ },
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -28114,7 +28824,6 @@
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
- "dev": true,
"license": "MIT",
"dependencies": {
"any-promise": "^1.0.0",
@@ -28126,7 +28835,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -29466,7 +30174,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
@@ -30712,6 +31419,12 @@
"wrappy": "1"
}
},
+ "node_modules/orderedmap": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz",
+ "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==",
+ "license": "MIT"
+ },
"node_modules/p-retry": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
@@ -30751,7 +31464,6 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true,
"license": "MIT"
},
"node_modules/pend": {
@@ -30770,7 +31482,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -30780,7 +31491,6 @@
"version": "8.5.15",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
"integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -30819,7 +31529,6 @@
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
- "dev": true,
"license": "MIT",
"dependencies": {
"postcss-value-parser": "^4.0.0",
@@ -30837,7 +31546,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz",
"integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -31004,19 +31712,6 @@
"postcss": "^8.1.0"
}
},
- "node_modules/postcss-modules-local-by-default/node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/postcss-modules-local-by-default/node_modules/icss-utils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
@@ -31044,13 +31739,6 @@
"node": ">=4"
}
},
- "node_modules/postcss-modules-local-by-default/node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/postcss-modules-scope": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz",
@@ -31067,19 +31755,6 @@
"postcss": "^8.1.0"
}
},
- "node_modules/postcss-modules-scope/node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz",
@@ -31094,18 +31769,10 @@
"node": ">=4"
}
},
- "node_modules/postcss-modules-scope/node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/postcss-nested": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
"integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -31127,24 +31794,10 @@
"postcss": "^8.2.14"
}
},
- "node_modules/postcss-nested/node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/postcss-nested/node_modules/postcss-selector-parser": {
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz",
"integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
@@ -31154,13 +31807,6 @@
"node": ">=4"
}
},
- "node_modules/postcss-nested/node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/postcss-normalize": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz",
@@ -31628,19 +32274,6 @@
],
"license": "CC0-1.0"
},
- "node_modules/postcss-preset-env/node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/postcss-preset-env/node_modules/postcss-attribute-case-insensitive": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz",
@@ -32148,25 +32781,29 @@
"node": ">=4"
}
},
- "node_modules/postcss-preset-env/node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true,
- "license": "MIT"
+ "node_modules/postcss-selector-parser": {
+ "version": "6.0.10",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+ "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
},
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/postcss/node_modules/nanoid": {
"version": "3.3.12",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -32185,7 +32822,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -32270,6 +32906,178 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/prosemirror-changeset": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.4.1.tgz",
+ "integrity": "sha512-96WBLhOaYhJ+kPhLg3uW359Tz6I/MfcrQfL4EGv4SrcqKEMC1gmoGrXHecPE8eOwTVCJ4IwgfzM8fFad25wNfw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-transform": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-commands": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz",
+ "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.10.2"
+ }
+ },
+ "node_modules/prosemirror-dropcursor": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz",
+ "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.1.0",
+ "prosemirror-view": "^1.1.0"
+ }
+ },
+ "node_modules/prosemirror-gapcursor": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.1.tgz",
+ "integrity": "sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-keymap": "^1.0.0",
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-view": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-history": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.0.tgz",
+ "integrity": "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-state": "^1.2.2",
+ "prosemirror-transform": "^1.0.0",
+ "prosemirror-view": "^1.31.0",
+ "rope-sequence": "^1.3.0"
+ }
+ },
+ "node_modules/prosemirror-inputrules": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.1.tgz",
+ "integrity": "sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-keymap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz",
+ "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "w3c-keyname": "^2.2.0"
+ }
+ },
+ "node_modules/prosemirror-markdown": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.4.tgz",
+ "integrity": "sha512-D98dm4cQ3Hs6EmjK500TdAOew4Z03EV71ajEFiWra3Upr7diytJsjF4mPV2dW+eK5uNectiRj0xFxYI9NLXDbw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/markdown-it": "^14.0.0",
+ "markdown-it": "^14.0.0",
+ "prosemirror-model": "^1.25.0"
+ }
+ },
+ "node_modules/prosemirror-markdown/node_modules/@types/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
+ "license": "MIT"
+ },
+ "node_modules/prosemirror-markdown/node_modules/@types/markdown-it": {
+ "version": "14.1.2",
+ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
+ "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/linkify-it": "^5",
+ "@types/mdurl": "^2"
+ }
+ },
+ "node_modules/prosemirror-markdown/node_modules/@types/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
+ "license": "MIT"
+ },
+ "node_modules/prosemirror-model": {
+ "version": "1.25.8",
+ "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.8.tgz",
+ "integrity": "sha512-BswA4BLSFEiORV6Vjj/yZBXDbos1zTEnhyeSSgT8psGFhstQS7UJ8/WOLiDos9Byaee27+tml0/DuMNxYR84zg==",
+ "license": "MIT",
+ "dependencies": {
+ "orderedmap": "^2.0.0"
+ }
+ },
+ "node_modules/prosemirror-schema-list": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz",
+ "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.7.3"
+ }
+ },
+ "node_modules/prosemirror-state": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz",
+ "integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-transform": "^1.0.0",
+ "prosemirror-view": "^1.27.0"
+ }
+ },
+ "node_modules/prosemirror-tables": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.5.tgz",
+ "integrity": "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-keymap": "^1.2.3",
+ "prosemirror-model": "^1.25.4",
+ "prosemirror-state": "^1.4.4",
+ "prosemirror-transform": "^1.10.5",
+ "prosemirror-view": "^1.41.4"
+ }
+ },
+ "node_modules/prosemirror-transform": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.12.0.tgz",
+ "integrity": "sha512-GxboyN4AMIsoHNtz5uf2r2Ru551i5hWeCMD6E2Ib4Eogqoub0NflniaBPVQ4MrGE5yZ8JV9tUHg9qcZTTrcN4w==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-model": "^1.21.0"
+ }
+ },
+ "node_modules/prosemirror-view": {
+ "version": "1.41.9",
+ "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.9.tgz",
+ "integrity": "sha512-clTunTX+eaLbr87L1V1QPheRlEQJyTlL3gXe9x3jQIk3rL0RVWxviDGz8tFaydwIVm+hKhYCyr+R/zBtWr9s6A==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-model": "^1.25.8",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.1.0"
+ }
+ },
"node_modules/psl": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
@@ -32293,6 +33101,15 @@
"node": ">=6"
}
},
+ "node_modules/punycode.js": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/puppeteer": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.20.0.tgz",
@@ -32580,12 +33397,6 @@
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"license": "MIT"
},
- "node_modules/puppeteer/node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "license": "MIT"
- },
"node_modules/puppeteer/node_modules/ws": {
"version": "6.2.4",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.4.tgz",
@@ -32628,7 +33439,6 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -34164,7 +34974,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"pify": "^2.3.0"
@@ -35518,7 +36327,6 @@
"version": "1.22.12",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
"integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -35659,7 +36467,6 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -35669,7 +36476,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -35679,7 +36485,6 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -35692,7 +36497,6 @@
"version": "2.16.2",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
"integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"hasown": "^2.0.3"
@@ -35792,6 +36596,12 @@
"node": ">=8"
}
},
+ "node_modules/rope-sequence": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz",
+ "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==",
+ "license": "MIT"
+ },
"node_modules/sanitize.css": {
"dev": true
},
@@ -36991,13 +37801,6 @@
"safe-buffer": "~5.1.0"
}
},
- "node_modules/spdy-transport/node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/spdy/node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -37208,7 +38011,6 @@
"version": "3.35.1",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
"integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.2",
@@ -37231,7 +38033,6 @@
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -37242,7 +38043,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -37252,14 +38052,12 @@
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "dev": true,
"license": "MIT"
},
"node_modules/sucrase/node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@@ -37270,7 +38068,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
@@ -37280,14 +38077,12 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true,
"license": "MIT"
},
"node_modules/sucrase/node_modules/pirates": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
"integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
@@ -37324,7 +38119,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -37337,7 +38131,6 @@
"version": "3.4.19",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
"integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
@@ -37371,11 +38164,20 @@
"node": ">=14.0.0"
}
},
+ "node_modules/tailwindcss-typography": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/tailwindcss-typography/-/tailwindcss-typography-3.1.0.tgz",
+ "integrity": "sha512-uqovHMt9orPs1kl2U+bidlcO25tmUGJjjluQdI67yRnOy/IlqKe6tYcHHAsQPhehlk3r11/T3CE7Uc0PSUJcNg==",
+ "deprecated": "Use @tailwindcss/typography",
+ "license": "ISC",
+ "dependencies": {
+ "lodash": "^4.17.15"
+ }
+ },
"node_modules/tailwindcss/node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
@@ -37384,24 +38186,10 @@
"node": ">=8"
}
},
- "node_modules/tailwindcss/node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/tailwindcss/node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -37414,7 +38202,6 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.3"
@@ -37427,7 +38214,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -37437,7 +38223,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
@@ -37450,7 +38235,6 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
@@ -37463,7 +38247,6 @@
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"braces": "^3.0.3",
@@ -37477,7 +38260,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -37487,7 +38269,6 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
@@ -37500,7 +38281,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
"integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -37543,7 +38323,6 @@
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz",
"integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
@@ -37557,7 +38336,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
@@ -37566,18 +38344,10 @@
"node": ">=8.0"
}
},
- "node_modules/tailwindcss/node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/tailwindcss/node_modules/yaml": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
"integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
- "dev": true,
"license": "ISC",
"optional": true,
"peer": true,
@@ -37849,7 +38619,6 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"any-promise": "^1.0.0"
@@ -37859,7 +38628,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"thenify": ">= 3.1.0 < 4"
@@ -37879,7 +38647,6 @@
"version": "0.2.17",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
"integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
@@ -37896,7 +38663,6 @@
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=12.0.0"
@@ -37914,7 +38680,6 @@
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@@ -37923,6 +38688,24 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/tiptap-markdown": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/tiptap-markdown/-/tiptap-markdown-0.9.0.tgz",
+ "integrity": "sha512-dKLQ9iiuGNgrlGVjrNauF/UBzWu4LYOx5pkD0jNkmQt/GOwfCJsBuzZTsf1jZ204ANHOm572mZ9PYvGh1S7tpQ==",
+ "license": "MIT",
+ "workspaces": [
+ "example"
+ ],
+ "dependencies": {
+ "@types/markdown-it": "^13.0.7",
+ "markdown-it": "^14.1.0",
+ "markdown-it-task-lists": "^2.1.1",
+ "prosemirror-markdown": "^1.11.1"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^3.0.1"
+ }
+ },
"node_modules/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
@@ -37983,7 +38766,6 @@
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
- "dev": true,
"license": "Apache-2.0"
},
"node_modules/tslib": {
@@ -38039,9 +38821,9 @@
}
},
"node_modules/typescript": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
- "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
@@ -38050,9 +38832,15 @@
"tsserver": "bin/tsserver"
},
"engines": {
- "node": ">=14.17"
+ "node": ">=4.2.0"
}
},
+ "node_modules/uc.micro": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
+ "license": "MIT"
+ },
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
@@ -38164,6 +38952,12 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
"node_modules/util.promisify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz",
@@ -39430,6 +40224,12 @@
"node": ">= 12"
}
},
+ "node_modules/w3c-keyname": {
+ "version": "2.2.8",
+ "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
+ "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
+ "license": "MIT"
+ },
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
diff --git a/package.json b/package.json
index 13e3fa7c..1e3f60d0 100755
--- a/package.json
+++ b/package.json
@@ -18,9 +18,21 @@
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
+ "@tailwindcss/typography": "^0.5.20",
"@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
+ "@tiptap/extension-code-block-lowlight": "^3.26.1",
+ "@tiptap/extension-image": "^3.26.1",
+ "@tiptap/extension-link": "^3.26.1",
+ "@tiptap/extension-table": "^3.26.1",
+ "@tiptap/extension-table-cell": "^3.26.1",
+ "@tiptap/extension-table-header": "^3.26.1",
+ "@tiptap/extension-table-row": "^3.26.1",
+ "@tiptap/extension-task-item": "^3.26.1",
+ "@tiptap/extension-task-list": "^3.26.1",
+ "@tiptap/react": "^3.26.1",
+ "@tiptap/starter-kit": "^3.26.1",
"@uiw/react-codemirror": "^4.25.1",
"codemirror": "^6.0.2",
"diff-match-patch": "^1.0.5",
@@ -31,6 +43,7 @@
"js-beautify": "^1.15.4",
"jspdf": "^3.0.3",
"jspdf-autotable": "^5.0.2",
+ "lowlight": "^3.3.0",
"lucide-react": "^0.540.0",
"marked": "^16.4.1",
"marked-emoji": "^2.0.1",
@@ -44,6 +57,8 @@
"reactflow": "^11.11.4",
"serialize-javascript": "^6.0.0",
"serve": "^14.2.4",
+ "tailwindcss-typography": "^3.1.0",
+ "tiptap-markdown": "^0.9.0",
"turndown": "^7.2.1",
"web-vitals": "^2.1.4"
},
diff --git a/src/components/._CodeBlockComponent.js b/src/components/._CodeBlockComponent.js
new file mode 100755
index 00000000..3d095653
Binary files /dev/null and b/src/components/._CodeBlockComponent.js differ
diff --git a/src/components/._RichMarkdownEditor.js b/src/components/._RichMarkdownEditor.js
new file mode 100755
index 00000000..3d095653
Binary files /dev/null and b/src/components/._RichMarkdownEditor.js differ
diff --git a/src/components/CodeBlockComponent.js b/src/components/CodeBlockComponent.js
new file mode 100755
index 00000000..89e1d92d
--- /dev/null
+++ b/src/components/CodeBlockComponent.js
@@ -0,0 +1,41 @@
+import React from "react";
+import { NodeViewWrapper, NodeViewContent } from "@tiptap/react";
+import { Copy } from "lucide-react";
+
+const CodeBlockComponent = ({ node, updateAttributes, extension }) => {
+ const handleCopy = () => {
+ navigator.clipboard.writeText(node.textContent).then(() => {
+ // Optional: Add visual feedback for copy
+ });
+ };
+
+ return (
+
+
+
${highlightedCode}
- ${highlightedCode}
+ Error parsing markdown
'; + return "Error parsing markdown
"; } }; @@ -141,119 +153,49 @@ const MarkdownEditor = () => { } const words = markdownText.trim().split(/\s+/).length; const characters = markdownText.length; - const lines = markdownText.split('\n').length; + const lines = markdownText.split("\n").length; const readingTime = Math.ceil(words / 200); return { words, characters, lines, readingTime }; }; const stats = calculateStats(); - // Add event delegation for copy buttons and close dropdown on outside click useEffect(() => { const handleClick = (e) => { - // Handle copy button clicks - const button = e.target.closest('.code-block-copy'); + // Handle copy button clicks in Read mode + const button = e.target.closest(".code-block-copy"); if (button) { - const codeId = button.getAttribute('data-code-id'); + const codeId = button.getAttribute("data-code-id"); const codeElement = document.getElementById(codeId); - + if (codeElement) { const code = codeElement.textContent; - navigator.clipboard.writeText(code).then(() => { - const originalText = button.textContent; - button.textContent = 'Copied!'; - setTimeout(() => { - button.textContent = originalText; - }, 2000); - }).catch(err => { - // Failed to copy - }); + navigator.clipboard + .writeText(code) + .then(() => { + const originalText = button.innerHTML; + button.innerHTML = "Copied!"; + setTimeout(() => { + button.innerHTML = originalText; + }, 2000); + }) + .catch((err) => { + // Failed to copy + }); } return; } // Close heading dropdown if clicking outside - if (showHeadingDropdown && !e.target.closest('.relative')) { + if (showHeadingDropdown && !e.target.closest(".relative")) { setShowHeadingDropdown(false); } }; - document.addEventListener('click', handleClick); - return () => document.removeEventListener('click', handleClick); + document.addEventListener("click", handleClick); + return () => document.removeEventListener("click", handleClick); }, [showHeadingDropdown]); - // Toolbar formatting functions - proper CodeMirror integration with toggle support - const insertMarkdown = (before, after = '', placeholder = 'text', skipPlaceholder = false) => { - // Get CodeMirror view from the DOM - const editorElement = document.querySelector('.cm-editor'); - if (!editorElement) return; - - const view = editorElement.cmView?.view; - if (!view) return; - - const state = view.state; - const selection = state.selection.main; - - // Get selected text or use placeholder (unless skipPlaceholder is true) - const selectedText = state.doc.sliceString(selection.from, selection.to) || (skipPlaceholder ? '' : placeholder); - - // Check if text is already formatted (toggle support) - const beforeLen = before.length; - const afterLen = after.length; - const expandedFrom = Math.max(0, selection.from - beforeLen); - const expandedTo = Math.min(state.doc.length, selection.to + afterLen); - const expandedText = state.doc.sliceString(expandedFrom, expandedTo); - - // Check if already formatted - const isFormatted = expandedText.startsWith(before) && expandedText.endsWith(after); - - if (isFormatted && selectedText) { - // Remove formatting - view.dispatch({ - changes: { from: expandedFrom, to: expandedTo, insert: selectedText }, - selection: { - anchor: expandedFrom, - head: expandedFrom + selectedText.length - } - }); - } else { - // Add formatting - const formatted = `${before}${selectedText}${after}`; - view.dispatch({ - changes: { from: selection.from, to: selection.to, insert: formatted }, - selection: { - anchor: selection.from + before.length, - head: selection.from + before.length + selectedText.length - } - }); - } - - // Focus back to editor - view.focus(); - }; - - // Heading insertion helper - const insertHeading = (level) => { - const prefix = '#'.repeat(level) + ' '; - insertMarkdown(prefix, '', 'Heading'); - setShowHeadingDropdown(false); - }; - - const toolbarButtons = [ - { icon: Heading, label: 'Heading', action: () => setShowHeadingDropdown(!showHeadingDropdown), isDropdown: true, group: 'formatter' }, - { icon: Bold, label: 'Bold', action: () => insertMarkdown('**', '**', 'bold text'), group: 'formatter' }, - { icon: Italic, label: 'Italic', action: () => insertMarkdown('*', '*', 'italic text'), group: 'formatter' }, - { icon: Underline, label: 'Underline', action: () => insertMarkdown('__', '__', 'underlined text'), group: 'formatter' }, - { icon: Quote, label: 'Quote', action: () => insertMarkdown('> ', '', 'quote'), group: 'formatter' }, - { icon: Code, label: 'Code Block', action: () => insertMarkdown('\n```\n', '\n```\n', 'code'), group: 'formatter' }, - { icon: Link2, label: 'Link', action: () => insertMarkdown('[', '](url)', 'link text'), group: 'formatter' }, - { icon: List, label: 'Bullet List', action: () => insertMarkdown('- ', '', 'list item'), group: 'list' }, - { icon: ListOrdered, label: 'Numbered List', action: () => insertMarkdown('1. ', '', 'list item'), group: 'list' }, - { icon: CheckSquare, label: 'Task List', action: () => insertMarkdown('- [ ] ', '', 'task'), group: 'list' }, - { icon: Minus, label: 'Divider', action: () => insertMarkdown('\n---\n', '', '', true), group: 'element' }, - { icon: Table, label: 'Table', action: () => insertMarkdown('\n| Header 1 | Header 2 |\n|----------|----------|\n| Cell 1 | Cell 2 |', '', '', true), group: 'element' }, - ]; - // Sample markdown const sampleMarkdown = `# Welcome to Markdown Editor @@ -380,8 +322,8 @@ MIT License - see LICENSE file for details blog: `# Blog Post Title -**Published:** ${new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })} -**Author:** Your Name +**Published:** ${new Date().toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" })} +**Author:** Your Name **Tags:** #tag1 #tag2 #tag3 --- @@ -516,8 +458,8 @@ For support, email support@example.com or visit our [Help Center](https://help.e meeting: `# Meeting Notes -**Date:** ${new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })} -**Time:** [Start Time] - [End Time] +**Date:** ${new Date().toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" })} +**Time:** [Start Time] - [End Time] **Location:** [Location/Video Call Link] ## Attendees @@ -563,7 +505,7 @@ For support, email support@example.com or visit our [Help Center](https://help.e | Task 3 | Person C | 2025-01-10 | ✅ Complete | ## Next Meeting -**Date:** [Next Meeting Date] +**Date:** [Next Meeting Date] **Agenda Items:** - Follow up on action items - [Other topics] @@ -599,7 +541,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security - Security improvements -## [1.0.0] - ${new Date().toISOString().split('T')[0]} +## [1.0.0] - ${new Date().toISOString().split("T")[0]} ### Added - Initial release @@ -641,10 +583,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [Unreleased]: https://github.com/username/repo/compare/v1.0.0...HEAD [1.0.0]: https://github.com/username/repo/compare/v0.2.0...v1.0.0 [0.2.0]: https://github.com/username/repo/compare/v0.1.0...v0.2.0 -[0.1.0]: https://github.com/username/repo/releases/tag/v0.1.0` +[0.1.0]: https://github.com/username/repo/releases/tag/v0.1.0`, }; - const [selectedTemplate, setSelectedTemplate] = useState('sample'); + const [selectedTemplate, setSelectedTemplate] = useState("sample"); // Helper function to check if user has data that would be lost const hasUserData = () => { @@ -660,7 +602,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 // Handle tab change with confirmation if data exists const handleTabChange = (newTab) => { - if (newTab === 'create' && activeTab !== 'create') { + if (newTab === "create" && activeTab !== "create") { if (hasModifiedData()) { setPendingTabChange(newTab); setShowInputChangeModal(true); @@ -673,7 +615,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 setShowInputChangeModal(true); } else { setActiveTab(newTab); - if (newTab === 'create' && createNewCompleted) { + if (newTab === "create" && createNewCompleted) { setCreateNewCompleted(false); } } @@ -681,9 +623,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 // Clear all data function const clearAllData = () => { - setMarkdownText(''); - setInputText(''); - setError(''); + setMarkdownText(""); + setHtmlText(""); // Also clear HTML text to force re-render + setInputText(""); + setError(""); setCreateNewCompleted(false); setPasteCollapsed(false); setPasteDataSummary(null); @@ -693,22 +636,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 // Confirm input method change and clear data const confirmInputChange = () => { - if (pendingTabChange === 'create_empty') { + if (pendingTabChange === "create_empty") { clearAllData(); - setMarkdownText(''); + setMarkdownText(""); + setHtmlText(""); setCreateNewCompleted(true); - } else if (pendingTabChange === 'create_sample') { + } else if (pendingTabChange === "create_sample") { clearAllData(); setMarkdownText(templates[selectedTemplate]); + setHtmlText(""); setCreateNewCompleted(true); } else { clearAllData(); setActiveTab(pendingTabChange); - if (pendingTabChange === 'create') { + if (pendingTabChange === "create") { setCreateNewCompleted(false); } } - + setShowInputChangeModal(false); setPendingTabChange(null); }; @@ -722,18 +667,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 // Handle Parse Markdown button click const handleParseMarkdown = () => { if (!inputText.trim()) { - setError('Please enter some markdown text'); + setError("Please enter some markdown text"); setPasteCollapsed(false); return; } setMarkdownText(inputText); - setError(''); + setHtmlText(""); // Clear html text to force the fallback to parse the new markdown immediately + setError(""); setCreateNewCompleted(true); setPasteDataSummary({ - format: 'Markdown', + format: "Markdown", size: inputText.length, - lines: inputText.split('\n').length + lines: inputText.split("\n").length, }); setPasteCollapsed(true); }; @@ -747,10 +693,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 reader.onload = (e) => { let content = e.target.result; - let format = 'Markdown'; + let format = "Markdown"; // Detect file type and convert if needed - if (file.name.endsWith('.html') || file.name.endsWith('.htm')) { + if (file.name.endsWith(".html") || file.name.endsWith(".htm")) { // Extract content from HTML body if it's a full HTML document const bodyMatch = content.match(/]*>([\s\S]*)<\/body>/i); if (bodyMatch) { @@ -758,28 +704,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 } // Convert HTML to markdown (basic conversion) content = htmlToMarkdown(content); - format = 'HTML (converted)'; - } else if (file.name.endsWith('.txt')) { + format = "HTML (converted)"; + } else if (file.name.endsWith(".txt")) { // Plain text - treat as markdown-ready content - format = 'Plain Text'; + format = "Plain Text"; } setMarkdownText(content); - setActiveTab('open'); + setHtmlText(""); // Clear html text to force the fallback to parse the new markdown immediately + setActiveTab("open"); setCreateNewCompleted(true); - setError(''); + setError(""); // Update file data summary setFileDataSummary({ format: format, size: content.length, - lines: content.split('\n').length, - filename: file.name + lines: content.split("\n").length, + filename: file.name, }); }; reader.onerror = () => { - setError('Failed to read file'); + setError("Failed to read file"); }; reader.readAsText(file); @@ -788,21 +735,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 // Fetch markdown from URL const handleFetchFromURL = async () => { if (!fetchUrl.trim()) { - setError('Please enter a URL'); + setError("Please enter a URL"); return; } setFetching(true); - setError(''); + setError(""); try { let urlToFetch = fetchUrl.trim(); - + // Convert GitHub URLs to raw URLs - if (urlToFetch.includes('github.com') && !urlToFetch.includes('raw.githubusercontent.com')) { + if ( + urlToFetch.includes("github.com") && + !urlToFetch.includes("raw.githubusercontent.com") + ) { urlToFetch = urlToFetch - .replace('github.com', 'raw.githubusercontent.com') - .replace('/blob/', '/'); + .replace("github.com", "raw.githubusercontent.com") + .replace("/blob/", "/"); } // Try direct fetch first @@ -811,7 +761,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 response = await fetch(urlToFetch); } catch (corsError) { // If CORS error, try with CORS proxy - response = await fetch(`https://api.allorigins.win/raw?url=${encodeURIComponent(urlToFetch)}`); + response = await fetch( + `https://api.allorigins.win/raw?url=${encodeURIComponent(urlToFetch)}`, + ); } if (!response.ok) { @@ -819,33 +771,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 } const text = await response.text(); - + if (!text || text.trim().length === 0) { - throw new Error('URL returned empty content'); + throw new Error("URL returned empty content"); } // Detect format - let format = 'Markdown'; - if (urlToFetch.endsWith('.html') || urlToFetch.endsWith('.htm')) { - format = 'HTML (converted)'; + let format = "Markdown"; + if (urlToFetch.endsWith(".html") || urlToFetch.endsWith(".htm")) { + format = "HTML (converted)"; const converted = htmlToMarkdown(text); setMarkdownText(converted); + setHtmlText(""); // Clear html text to force the fallback to parse the new markdown immediately } else { setMarkdownText(text); + setHtmlText(""); // Clear html text to force the fallback to parse the new markdown immediately } - setActiveTab('url'); + setActiveTab("url"); setCreateNewCompleted(true); - setError(''); + setError(""); // Update URL data summary setUrlDataSummary({ format: format, size: text.length, - lines: text.split('\n').length, - url: urlToFetch + lines: text.split("\n").length, + url: urlToFetch, }); - } catch (err) { setError(`Failed to fetch from URL: ${err.message}`); } finally { @@ -856,146 +809,188 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 // HTML to Markdown converter - designed to reverse our exact export format const htmlToMarkdown = (html) => { // Create a temporary DOM element to parse HTML properly - const tempDiv = document.createElement('div'); + const tempDiv = document.createElement("div"); tempDiv.innerHTML = html; - + // Remove script and style tags - tempDiv.querySelectorAll('script, style').forEach(el => el.remove()); - + tempDiv.querySelectorAll("script, style").forEach((el) => el.remove()); + // Process our custom code-block-wrapper structure - tempDiv.querySelectorAll('.code-block-wrapper').forEach(wrapper => { - const langSpan = wrapper.querySelector('.code-block-language'); - const codeElement = wrapper.querySelector('code'); - + tempDiv.querySelectorAll(".code-block-wrapper").forEach((wrapper) => { + const langSpan = wrapper.querySelector(".code-block-language"); + const codeElement = wrapper.querySelector("code"); + if (codeElement) { - const language = langSpan ? langSpan.textContent.trim() : ''; + const language = langSpan ? langSpan.textContent.trim() : ""; // Get the text content directly (this preserves the actual code) let code = codeElement.textContent; - + // Create markdown code block - const codeBlock = document.createTextNode(`\n\`\`\`${language}\n${code}\n\`\`\`\n\n`); + const codeBlock = document.createTextNode( + `\n\`\`\`${language}\n${code}\n\`\`\`\n\n`, + ); wrapper.parentNode.replaceChild(codeBlock, wrapper); } }); - + // Handle regular code blocks (without our wrapper) - tempDiv.querySelectorAll('pre > code').forEach(codeElement => { + tempDiv.querySelectorAll("pre > code").forEach((codeElement) => { const pre = codeElement.parentElement; const classMatch = codeElement.className.match(/language-(\w+)/); - const language = classMatch ? classMatch[1] : ''; + const language = classMatch ? classMatch[1] : ""; let code = codeElement.textContent; - + // Create markdown code block - const codeBlock = document.createTextNode(`\n\`\`\`${language}\n${code}\n\`\`\`\n\n`); + const codeBlock = document.createTextNode( + `\n\`\`\`${language}\n${code}\n\`\`\`\n\n`, + ); pre.parentNode.replaceChild(codeBlock, pre); }); - + // Get the processed HTML let markdown = tempDiv.innerHTML; - + // Headers - markdown = markdown.replace(/]*>([\s\S]*?)<\/code>/gi, '`$1`');
-
+ markdown = markdown.replace(/]*>([\s\S]*?)<\/code>/gi, "`$1`");
+
// Tables
- markdown = markdown.replace(/]*>([\s\S]*?)<\/table>/gi, (match, content) => {
- let tableMarkdown = '\n';
- const rows = content.match(/]*>([\s\S]*?)<\/tr>/gi) || [];
-
- rows.forEach((row, index) => {
- const cells = row.match(/]*>([\s\S]*?)<\/t[hd]>/gi) || [];
- const cellContents = cells.map(cell => cell.replace(/<[^>]+>/g, '').trim());
- tableMarkdown += '| ' + cellContents.join(' | ') + ' |\n';
-
- // Add separator after header row
- if (index === 0) {
- tableMarkdown += '| ' + cellContents.map(() => '---').join(' | ') + ' |\n';
- }
- });
-
- return tableMarkdown + '\n';
- });
-
+ markdown = markdown.replace(
+ /]*>([\s\S]*?)<\/table>/gi,
+ (match, content) => {
+ let tableMarkdown = "\n";
+ const rows = content.match(/]*>([\s\S]*?)<\/tr>/gi) || [];
+
+ rows.forEach((row, index) => {
+ const cells = row.match(/]*>([\s\S]*?)<\/t[hd]>/gi) || [];
+ const cellContents = cells.map((cell) =>
+ cell.replace(/<[^>]+>/g, "").trim(),
+ );
+ tableMarkdown += "| " + cellContents.join(" | ") + " |\n";
+
+ // Add separator after header row
+ if (index === 0) {
+ tableMarkdown +=
+ "| " + cellContents.map(() => "---").join(" | ") + " |\n";
+ }
+ });
+
+ return tableMarkdown + "\n";
+ },
+ );
+
// Lists - handle nested lists
- markdown = markdown.replace(/]*>([\s\S]*?)<\/li>/gi, (match, content) => {
- content = content.trim();
- return '- ' + content + '\n';
- });
- markdown = markdown.replace(/]*>([\s\S]*?)<\/ul>/gi, '$1\n');
- markdown = markdown.replace(/]*>([\s\S]*?)<\/ol>/gi, '$1\n');
-
+ markdown = markdown.replace(
+ /- ]*>([\s\S]*?)<\/li>/gi,
+ (match, content) => {
+ content = content.trim();
+ return "- " + content + "\n";
+ },
+ );
+ markdown = markdown.replace(/
]*>([\s\S]*?)<\/ul>/gi, "$1\n");
+ markdown = markdown.replace(/]*>([\s\S]*?)<\/ol>/gi, "$1\n");
+
// Blockquotes
- markdown = markdown.replace(/]*>([\s\S]*?)<\/blockquote>/gi, (match, content) => {
- // Remove HTML tags from content first
- content = content.replace(/<[^>]+>/g, '');
- return '\n' + content.split('\n').filter(line => line.trim()).map(line => '> ' + line.trim()).join('\n') + '\n\n';
- });
-
+ markdown = markdown.replace(
+ /]*>([\s\S]*?)<\/blockquote>/gi,
+ (match, content) => {
+ // Remove HTML tags from content first
+ content = content.replace(/<[^>]+>/g, "");
+ return (
+ "\n" +
+ content
+ .split("\n")
+ .filter((line) => line.trim())
+ .map((line) => "> " + line.trim())
+ .join("\n") +
+ "\n\n"
+ );
+ },
+ );
+
// Paragraphs and breaks
- markdown = markdown.replace(/]*>([\s\S]*?)<\/p>/gi, (match, content) => {
- content = content.trim();
- return content + '\n\n';
- });
- markdown = markdown.replace(/
/gi, '\n');
- markdown = markdown.replace(/
/gi, '\n---\n\n');
-
+ markdown = markdown.replace(
+ /]*>([\s\S]*?)<\/p>/gi,
+ (match, content) => {
+ content = content.trim();
+ return content + "\n\n";
+ },
+ );
+ markdown = markdown.replace(/
/gi, "\n");
+ markdown = markdown.replace(/
/gi, "\n---\n\n");
+
// Remove remaining HTML tags
- markdown = markdown.replace(/<[^>]+>/g, '');
-
+ markdown = markdown.replace(/<[^>]+>/g, "");
+
// Decode HTML entities (that might still be in non-code content)
- markdown = markdown.replace(/</g, '<');
- markdown = markdown.replace(/>/g, '>');
- markdown = markdown.replace(/&/g, '&');
+ markdown = markdown.replace(/</g, "<");
+ markdown = markdown.replace(/>/g, ">");
+ markdown = markdown.replace(/&/g, "&");
markdown = markdown.replace(/"/g, '"');
markdown = markdown.replace(/'/g, "'");
- markdown = markdown.replace(/ /g, ' ');
-
+ markdown = markdown.replace(/ /g, " ");
+
// Clean up extra whitespace gently
// Remove multiple consecutive blank lines (3+ becomes 2)
- markdown = markdown.replace(/\n{3,}/g, '\n\n');
-
+ markdown = markdown.replace(/\n{3,}/g, "\n\n");
+
// Remove leading spaces from each line (but preserve code block indentation)
let inCodeBlock = false;
- markdown = markdown.split('\n').map(line => {
- // Check if this line starts or ends a code block
- if (line.trim().startsWith('```')) {
- inCodeBlock = !inCodeBlock;
- return line.trimStart(); // Trim the ``` line itself
- }
-
- // If we're inside a code block, preserve indentation
- if (inCodeBlock) {
- return line;
- }
-
- // Outside code blocks, remove leading spaces
- return line.trimStart();
- }).join('\n');
-
+ markdown = markdown
+ .split("\n")
+ .map((line) => {
+ // Check if this line starts or ends a code block
+ if (line.trim().startsWith("```")) {
+ inCodeBlock = !inCodeBlock;
+ return line.trimStart(); // Trim the ``` line itself
+ }
+
+ // If we're inside a code block, preserve indentation
+ if (inCodeBlock) {
+ return line;
+ }
+
+ // Outside code blocks, remove leading spaces
+ return line.trimStart();
+ })
+ .join("\n");
+
// Remove leading/trailing whitespace from the entire document
markdown = markdown.trim();
-
+
return markdown;
};
@@ -1015,18 +1010,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
// Export handlers
const handleExportMarkdown = () => {
if (!markdownText.trim()) {
- setError('No content to export');
+ setError("No content to export");
return;
}
- downloadFile(markdownText, 'document.md', 'text/markdown');
+ downloadFile(markdownText, "document.md", "text/markdown");
};
const handleExportHTML = () => {
if (!markdownText.trim()) {
- setError('No content to export');
+ setError("No content to export");
return;
}
- const html = parseMarkdown(markdownText);
+
+ // Determine HTML to use: if htmlText is empty, fall back to marked
+ const html = htmlText || parseMarkdownFallback(markdownText);
const fullHTML = `
@@ -1036,15 +1033,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
-${html}
+ ${html}
`;
- downloadFile(fullHTML, 'document.html', 'text/html');
+ downloadFile(fullHTML, "document.html", "text/html");
};
const handleExportHTMLContent = () => {
if (!markdownText.trim()) {
- setError('No content to export');
+ setError("No content to export");
return;
}
- let html = parseMarkdown(markdownText);
-
- // Clean up the HTML content by removing code-block wrappers
- const tempDiv = document.createElement('div');
+ const html = htmlText || parseMarkdownFallback(markdownText);
+
+ // Clean up the HTML content by removing code-block wrappers and headers
+ const tempDiv = document.createElement("div");
tempDiv.innerHTML = html;
-
- // Remove code-block-header and code-block-wrapper elements
- tempDiv.querySelectorAll('.code-block-header').forEach(el => el.remove());
- tempDiv.querySelectorAll('.code-block-wrapper').forEach(wrapper => {
+
+ // Remove code-block-header
+ tempDiv.querySelectorAll(".code-block-header").forEach((el) => el.remove());
+
+ // Unwrap code-block-wrapper
+ tempDiv.querySelectorAll(".code-block-wrapper").forEach((wrapper) => {
while (wrapper.firstChild) {
wrapper.parentNode.insertBefore(wrapper.firstChild, wrapper);
}
wrapper.remove();
});
-
- html = tempDiv.innerHTML;
- downloadFile(html, 'content.html', 'text/html');
+
+ // Remove React-specific classes and styles from pre tags to keep it generic
+ tempDiv.querySelectorAll("pre").forEach((pre) => {
+ pre.removeAttribute("class");
+ pre.removeAttribute("style");
+ });
+
+ const cleanHtml = tempDiv.innerHTML;
+ downloadFile(cleanHtml, "content.html", "text/html");
};
const handleExportPlainText = () => {
if (!markdownText.trim()) {
- setError('No content to export');
+ setError("No content to export");
return;
}
- // Export as markdown-ready plain text (keep markdown syntax)
- // This allows users to copy/paste and re-import without losing formatting
- downloadFile(markdownText, 'document.txt', 'text/plain');
+
+ // Strip markdown formatting using a simple regex to get plain text
+ const plainText = markdownText
+ .replace(/[#*`_~>[\]]/g, "") // remove markdown characters
+ .replace(/!\[.*?\]\([^)]+\)/g, "") // remove images
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1") // remove links but keep text
+ .trim();
+
+ downloadFile(plainText, "document.txt", "text/plain");
};
const handleCopyToClipboard = () => {
if (!markdownText.trim()) {
- setError('No content to copy');
+ setError("No content to copy");
return;
}
- navigator.clipboard.writeText(markdownText).then(() => {
- // Show success feedback (you can add a toast notification here)
- setError(''); // Clear any errors
- }).catch(() => {
- setError('Failed to copy to clipboard');
- });
+
+ // Attempt to copy the markdown text
+ if (navigator.clipboard && window.isSecureContext) {
+ navigator.clipboard
+ .writeText(markdownText)
+ .then(() => {
+ // Provide visual feedback by temporarily changing the button state
+ const copyBtn = document.getElementById("copy-export-btn");
+ if (copyBtn) {
+ const originalText = copyBtn.innerHTML;
+ copyBtn.innerHTML = `Copied!To clipboard`;
+ setTimeout(() => {
+ copyBtn.innerHTML = originalText;
+ }, 2000);
+ }
+ setError("");
+ })
+ .catch((err) => {
+ console.error("Clipboard API failed:", err);
+ fallbackCopyTextToClipboard(markdownText);
+ });
+ } else {
+ fallbackCopyTextToClipboard(markdownText);
+ }
+ };
+
+ // Fallback copy mechanism
+ const fallbackCopyTextToClipboard = (text) => {
+ const textArea = document.createElement("textarea");
+ textArea.value = text;
+
+ // Avoid scrolling to bottom
+ textArea.style.top = "0";
+ textArea.style.left = "0";
+ textArea.style.position = "fixed";
+
+ document.body.appendChild(textArea);
+ textArea.focus();
+ textArea.select();
+
+ try {
+ document.execCommand("copy");
+ const copyBtn = document.getElementById("copy-export-btn");
+ if (copyBtn) {
+ const originalText = copyBtn.innerHTML;
+ copyBtn.innerHTML = `Copied!To clipboard`;
+ setTimeout(() => {
+ copyBtn.innerHTML = originalText;
+ }, 2000);
+ }
+ setError("");
+ } catch (err) {
+ setError("Failed to copy to clipboard");
+ }
+
+ document.body.removeChild(textArea);
};
const handleExportPDF = () => {
if (!markdownText.trim()) {
- setError('No content to export');
+ setError("No content to export");
return;
}
- // Create the content element with rendered markdown
- const element = document.createElement('div');
- element.innerHTML = parseMarkdown(markdownText);
-
- // Remove code block headers (language + copy button)
- const codeHeaders = element.querySelectorAll('.code-block-header');
- codeHeaders.forEach(header => header.remove());
-
- // Remove copy buttons from code blocks
- const copyButtons = element.querySelectorAll('button[title="Copy code"]');
- copyButtons.forEach(btn => btn.remove());
-
+ // Determine HTML to use: if htmlText is empty, fall back to marked
+ const sourceHtml = htmlText || parseMarkdownFallback(markdownText);
+
+ // Create the content element with rendered html
+ const element = document.createElement("div");
+ element.innerHTML = sourceHtml;
+
// Add comprehensive PDF styles inline
- const styleEl = document.createElement('style');
+ const styleEl = document.createElement("style");
styleEl.textContent = `
.pdf-content {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
@@ -1454,44 +1475,49 @@ ${html}
margin-right: 8px;
}
`;
-
- element.className = 'pdf-content';
-
+
+ element.className = "pdf-content";
+
// Create wrapper with styles
- const wrapper = document.createElement('div');
+ const wrapper = document.createElement("div");
wrapper.appendChild(styleEl);
wrapper.appendChild(element);
const opt = {
margin: [15, 15, 15, 15],
- filename: 'document.pdf',
- image: { type: 'jpeg', quality: 0.98 },
- html2canvas: {
- scale: 2,
+ filename: "document.pdf",
+ image: { type: "jpeg", quality: 0.98 },
+ html2canvas: {
+ scale: 2,
useCORS: true,
logging: false,
letterRendering: true,
- backgroundColor: '#ffffff'
+ backgroundColor: "#ffffff",
},
- jsPDF: {
- unit: 'mm',
- format: 'a4',
- orientation: 'portrait',
- compress: true
+ jsPDF: {
+ unit: "mm",
+ format: "a4",
+ orientation: "portrait",
+ compress: true,
},
- pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
+ pagebreak: { mode: ["avoid-all", "css", "legacy"] },
};
- html2pdf().set(opt).from(wrapper).save().then(() => {
- setError('');
- }).catch((err) => {
- setError('Failed to generate PDF');
- });
+ html2pdf()
+ .set(opt)
+ .from(wrapper)
+ .save()
+ .then(() => {
+ setError("");
+ })
+ .catch((err) => {
+ setError("Failed to generate PDF");
+ });
};
return (
<>
-
- {/* Input Section - Always visible */}
-
-
- Get Started
-
+ {/* Input Section - Always visible */}
+
+
+
+ Get Started
+
+
{/* Tab Navigation */}
{/* Tab Content */}
- {(activeTab !== 'create' || !createNewCompleted) && (
+ {(activeTab !== "create" || !createNewCompleted) && (
{/* Create New Tab Content */}
- {activeTab === 'create' && (
+ {activeTab === "create" && (
<>
{!createNewCompleted ? (
@@ -1575,16 +1603,16 @@ ${html}
Choose how you'd like to begin writing
-
+
-
+
-
+
- 💡 Tip: You can always import markdown later using the URL, Paste, or Open tabs.
+ 💡 Tip: You can always import
+ markdown later using the URL, Paste, or Open tabs.
@@ -1649,9 +1690,12 @@ ${html}
- ✓ Document ready: {markdownText ? `${stats.words} words, ${stats.characters} characters, ${stats.lines} lines` : 'Empty document'}
+ ✓ Document ready:{" "}
+ {markdownText
+ ? `${stats.words} words, ${stats.characters} characters, ${stats.lines} lines`
+ : "Empty document"}
-
- {/* Input Method Change Confirmation Modal */}
- {showInputChangeModal && (
-
- )}
+ {/* Input Method Change Confirmation Modal */}
+ {showInputChangeModal && (
+
+ )}
- {/* Editor Section */}
- {(activeTab !== 'create' || createNewCompleted) && (
-
- {/* Editor Header - Sticky */}
-
-
-
-
-
- Markdown Editor
-
-
- {/* Statistics */}
-
- {stats.words} words
- •
- {stats.characters} chars
- •
- {stats.lines} lines
- •
- {stats.readingTime} min read
+ {/* Editor Section */}
+ {(activeTab !== "create" || createNewCompleted) && (
+
+ {/* Editor Header - Sticky */}
+
+
+
+
+
+ Markdown Editor
+
+
+ {/* Statistics */}
+
+ {stats.words} words
+ •
+ {stats.characters} chars
+ •
+ {stats.lines} lines
+ •
+ {stats.readingTime} min read
+
-
-
- {/* View Mode Controls */}
-
-
+
+ {/* View Mode Controls */}
+
+
+ setViewMode("preview")}
+ className={`flex items-center gap-2 px-3 py-1.5 text-sm font-medium transition-colors ${
+ viewMode === "preview"
+ ? "bg-green-50 dark:bg-green-900/20 text-green-700 dark:text-green-300"
+ : "text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700"
+ }`}
+ title="Read Mode"
+ >
+
+ Read
+
+ setViewMode("editor")}
+ className={`flex items-center gap-2 px-3 py-1.5 text-sm font-medium transition-colors border-l border-gray-200 dark:border-gray-700 ${
+ viewMode === "editor"
+ ? "bg-orange-50 dark:bg-orange-900/20 text-orange-700 dark:text-orange-300"
+ : "text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700"
+ }`}
+ title="Rich Text Edit"
+ >
+
+ Edit
+
+ setViewMode("markdown")}
+ className={`flex items-center gap-2 px-3 py-1.5 text-sm font-medium transition-colors border-l border-gray-200 dark:border-gray-700 ${
+ viewMode === "markdown"
+ ? "bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300"
+ : "text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700"
+ }`}
+ title="Raw Markdown"
+ >
+
+ Markdown
+
+
setViewMode('editor')}
- className={`flex items-center gap-2 px-3 py-2 text-sm font-medium transition-colors ${
- viewMode === 'editor'
- ? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
- : 'text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700'
- }`}
- title="Editor Only"
+ onClick={() => setIsFullscreen(!isFullscreen)}
+ className="p-2 text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
+ title={isFullscreen ? "Exit Fullscreen" : "Fullscreen"}
>
-
- Editor
-
- {/* Hide split button on mobile (< lg) */}
- setViewMode('split')}
- className={`hidden lg:flex items-center gap-2 px-3 py-2 text-sm font-medium transition-colors border-l border-gray-200 dark:border-gray-700 ${
- viewMode === 'split'
- ? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
- : 'text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700'
- }`}
- title="Split View"
- >
-
- Split
-
- setViewMode('preview')}
- className={`flex items-center gap-2 px-3 py-2 text-sm font-medium transition-colors border-l border-gray-200 dark:border-gray-700 ${
- viewMode === 'preview'
- ? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
- : 'text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700'
- }`}
- title="Preview Only"
- >
-
- Preview
+ {isFullscreen ? (
+
+ ) : (
+
+ )}
-
- setIsFullscreen(!isFullscreen)}
- className="p-2 text-gray-600 dark:text-gray-600 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
- title={isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'}
- >
- {isFullscreen ? : }
-
-
- {/* Markdown Toolbar */}
- {(viewMode === 'editor' || viewMode === 'split') && (
-
-
- {toolbarButtons.map((btn, idx) => {
- const Icon = btn.icon;
- const prevGroup = idx > 0 ? toolbarButtons[idx - 1].group : null;
- const showSeparator = idx > 0 && btn.group !== prevGroup;
-
- return (
-
- {/* Group Separator */}
- {showSeparator && (
-
- )}
-
-
-
-
-
- {/* Tooltip */}
-
- {btn.label}
-
-
- {/* Heading Dropdown */}
- {btn.isDropdown && showHeadingDropdown && (
-
- {[1, 2, 3, 4, 5, 6].map(level => (
- insertHeading(level)}
- className="w-full px-3 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300 text-sm"
- >
- H{level} - {'#'.repeat(level)} Heading {level}
-
- ))}
-
- )}
-
-
- );
- })}
-
-
- )}
-
- {/* Editor Content */}
-
- {/* Markdown Editor */}
- {(viewMode === 'editor' || viewMode === 'split') && (
-
-
-
-
-
- )}
-
- {/* Preview */}
- {(viewMode === 'preview' || viewMode === 'split') && (
-
-
- {markdownText ? (
-
- ) : (
-
-
-
- Preview will appear here
-
+ {/* Editor Content */}
+
+
+ {viewMode === "preview" ? (
+
+
+
- )}
-
+
+ ) : viewMode === "editor" ? (
+
+ ) : (
+
+ {
+ setMarkdownText(newMarkdown);
+ setHtmlText(""); // Clear html text so switching to preview re-renders it accurately
+ }}
+ language="markdown"
+ placeholder="Write markdown here..."
+ maxLines={999}
+ showToggle={false}
+ height={isFullscreen ? "calc(100vh - 60px)" : "600px"}
+ className="w-full h-full"
+ />
+
+ )}
- )}
-
-
- )}
-
- {/* Export Section */}
- {markdownText && (
-
-
-
-
- Export Options
-
-
- Download your markdown in different formats
-
-
-
-
-
- {/* Export as Markdown */}
-
-
- Markdown
- .md file
-
-
- {/* Export as PDF */}
-
-
- PDF
- .pdf file
-
-
- {/* Export as Full HTML */}
-
-
- Full HTML
- .html page
-
-
- {/* Export as HTML Content Only */}
-
-
- HTML Content
- Body only
-
-
- {/* Export as Plain Text */}
-
-
- Plain Text
- .txt file
-
-
- {/* Copy to Clipboard */}
-
-
- Copy
- To clipboard
-
-
-
- {/* Export Info */}
-
-
-
-
- Export Information
-
- - Markdown: Original markdown with all formatting (.md file)
- - PDF: Professional PDF document with formatted content - perfect for sharing and printing!
- - Full HTML: Complete standalone HTML page with GitHub Dark theme, syntax highlighting (Highlight.js), and working copy buttons - ready to use!
- - HTML Content: Body content only, ready to paste into web pages
- - Plain Text: Markdown-ready text file, keeps all syntax (.txt file)
- - Copy: Copy markdown to clipboard for pasting
-
-
-
-
-
-
- )}
-
- {/* Usage Tips */}
-
- setUsageTipsExpanded(!usageTipsExpanded)}
- className="px-4 py-3 cursor-pointer hover:bg-blue-100 dark:hover:bg-blue-900/30 transition-colors flex items-center justify-between"
- >
-
- 💡 Usage Tips
-
- {usageTipsExpanded ? : }
-
-
- {usageTipsExpanded && (
-
- {/* Input Methods */}
-
- 📝 Input Methods:
-
- - Create New: Start with empty editor or load sample markdown
- - URL: Fetch markdown from GitHub, Gist, or any public URL
- - Paste: Paste markdown, HTML (auto-converts), or plain text
- - Open: Load .md, .txt, or .html files from your computer
-
-
-
- {/* Editing Features */}
-
- ✏️ Editing Features
-
- - Live Preview: See your markdown rendered in real-time
- - Syntax Highlighting: Code blocks with automatic language detection
- - View Modes: Switch between Split, Editor Only, Preview Only, or Fullscreen
- - Toolbar: Quick formatting buttons for headers, bold, italic, links, code, and more
- - Statistics: Track word count, character count, lines, and reading time
- - GitHub Flavored Markdown: Full GFM support including tables and task lists
-
-
-
- {/* Markdown Syntax */}
-
- 📖 Markdown Syntax
-
- - Headers: # H1, ## H2, ### H3, etc.
- - Bold: **bold text** or __bold text__
- - Italic: *italic text* or _italic text_
- - Underline: __underlined text__ (custom syntax)
- - Code: `inline code` or ```language for code blocks
- - Links: [text](url)
- - Images: 
- - Lists: - or * for unordered, 1. for ordered
- - Tables: {'|'} Header {'|'} Header {'|'} with {'|'} --- {'|'} --- {'|'} separator
- - Blockquotes: {'>'} quoted text
-
-
-
- {/* Export Options */}
-
- 📤 Export Options
-
- - Markdown (.md): Standard markdown format
- - Full HTML: Standalone page with styling and working copy buttons
- - HTML Content: Just the body content for embedding
- - Plain Text (.txt): Markdown-ready text file
- - Copy: Copy to clipboard for quick sharing
-
-
-
- {/* Data Privacy */}
-
- 💾 Data Privacy
-
- - 100% Client-Side: All processing happens in your browser
- - No Server Upload: Your markdown never leaves your device
- - No Tracking: We don't store or track your content
- - Privacy-First: Safe for confidential documents
-
)}
-
- {/* Related Tools */}
-
-
+ {/* Export Section */}
+ {markdownText && (
+
+
+
+
+ Export Options
+
+
+ Download your markdown in different formats
+
+
+
+
+
+ {/* Export as Markdown */}
+
+
+
+ Markdown
+
+
+ .md file
+
+
+
+ {/* Export as PDF */}
+
+
+
+ PDF
+
+
+ .pdf file
+
+
+
+ {/* Export as Full HTML */}
+
+
+
+ Full HTML
+
+
+ .html page
+
+
+
+ {/* Export as HTML Content Only */}
+
+
+
+ HTML Content
+
+
+ Body only
+
+
+
+ {/* Export as Plain Text */}
+
+
+
+ Plain Text
+
+
+ .txt file
+
+
+
+ {/* Copy to Clipboard */}
+
+
+
+ Copy
+
+
+ To clipboard
+
+
+
+
+ {/* Export Info */}
+
+
+
+
+ Export Information
+
+ -
+ Markdown: Original markdown with all
+ formatting (.md file)
+
+ -
+ PDF: Professional PDF document with
+ formatted content - perfect for sharing and printing!
+
+ -
+ Full HTML: Complete standalone HTML
+ page with GitHub Dark theme, syntax highlighting
+ (Highlight.js), and working copy buttons - ready to use!
+
+ -
+ HTML Content: Body content only, ready
+ to paste into web pages
+
+ -
+ Plain Text: Markdown-ready text file,
+ keeps all syntax (.txt file)
+
+ -
+ Copy: Copy markdown to clipboard for
+ pasting
+
+
+
+
+
+
+
+ )}
+
+ {/* Usage Tips */}
+
+ setUsageTipsExpanded(!usageTipsExpanded)}
+ className="px-4 py-3 cursor-pointer hover:bg-blue-100 dark:hover:bg-blue-900/30 transition-colors flex items-center justify-between"
+ >
+
+ 💡 Usage Tips
+
+ {usageTipsExpanded ? (
+
+ ) : (
+
+ )}
+
+
+ {usageTipsExpanded && (
+
+ {/* Input Methods */}
+
+ 📝 Input Methods:
+
+ -
+ Create New: Start with empty editor or load
+ sample markdown
+
+ -
+ URL: Fetch markdown from GitHub, Gist, or
+ any public URL
+
+ -
+ Paste: Paste markdown, HTML
+ (auto-converts), or plain text
+
+ -
+ Open: Load .md, .txt, or .html files from
+ your computer
+
+
+
+
+ {/* Editing Features */}
+
+
+ ✏️ Editing Features
+
+
+ -
+ Live Preview: See your markdown rendered in
+ real-time
+
+ -
+ Syntax Highlighting: Code blocks with
+ automatic language detection
+
+ -
+ View Modes: Switch between Split, Editor
+ Only, Preview Only, or Fullscreen
+
+ -
+ Toolbar: Quick formatting buttons for
+ headers, bold, italic, links, code, and more
+
+ -
+ Statistics: Track word count, character
+ count, lines, and reading time
+
+ -
+ GitHub Flavored Markdown: Full GFM support
+ including tables and task lists
+
+
+
+
+ {/* Markdown Syntax */}
+
+
+ 📖 Markdown Syntax
+
+
+ -
+ Headers: # H1, ## H2, ### H3, etc.
+
+ -
+ Bold: **bold text** or __bold text__
+
+ -
+ Italic: *italic text* or _italic text_
+
+ -
+ Underline: __underlined text__ (custom
+ syntax)
+
+ -
+ Code: `inline code` or ```language for code
+ blocks
+
+ -
+ Links: [text](url)
+
+ -
+ Images: 
+
+ -
+ Lists: - or * for unordered, 1. for ordered
+
+ -
+ Tables: {"|"} Header {"|"} Header {"|"}{" "}
+ with {"|"} --- {"|"} --- {"|"} separator
+
+ -
+ Blockquotes: {">"} quoted text
+
+
+
+
+ {/* Export Options */}
+
+
+ 📤 Export Options
+
+
+ -
+ Markdown (.md): Standard markdown format
+
+ -
+ Full HTML: Standalone page with styling and
+ working copy buttons
+
+ -
+ HTML Content: Just the body content for
+ embedding
+
+ -
+ Plain Text (.txt): Markdown-ready text file
+
+ -
+ Copy: Copy to clipboard for quick sharing
+
+
+
+
+ {/* Data Privacy */}
+
+
+ 💾 Data Privacy
+
+
+ -
+ 100% Client-Side: All processing happens in
+ your browser
+
+ -
+ No Server Upload: Your markdown never
+ leaves your device
+
+ -
+ No Tracking: We don't store or track your
+ content
+
+ -
+ Privacy-First: Safe for confidential
+ documents
+
+
+
+
+ )}
+
+
+ {/* Related Tools */}
+
+
>
);
};
// Input Method Change Confirmation Modal Component
-const InputChangeConfirmationModal = ({ markdownText, stats, currentMethod, newMethod, onConfirm, onCancel }) => {
+const InputChangeConfirmationModal = ({
+ markdownText,
+ stats,
+ currentMethod,
+ newMethod,
+ onConfirm,
+ onCancel,
+}) => {
const getMethodName = (method) => {
switch (method) {
- case 'create': return 'Create New';
- case 'create_empty': return 'Start Empty';
- case 'create_sample': return 'Load Sample';
- case 'url': return 'URL Import';
- case 'paste': return 'Paste Data';
- case 'open': return 'File Upload';
- default: return method;
+ case "create":
+ return "Create New";
+ case "create_empty":
+ return "Start Empty";
+ case "create_sample":
+ return "Load Sample";
+ case "url":
+ return "URL Import";
+ case "paste":
+ return "Paste Data";
+ case "open":
+ return "File Upload";
+ default:
+ return method;
}
};
@@ -2213,13 +2369,20 @@ const InputChangeConfirmationModal = ({ markdownText, stats, currentMethod, newM
{/* Content */}
- {(newMethod === 'create_empty' || newMethod === 'create_sample') ? (
- <>Using {getMethodName(newMethod)} will clear all current markdown.>
+ {newMethod === "create_empty" || newMethod === "create_sample" ? (
+ <>
+ Using {getMethodName(newMethod)} will clear all
+ current markdown.
+ >
) : (
- <>Switching from {getMethodName(currentMethod)} to {getMethodName(newMethod)} will clear all current markdown.>
+ <>
+ Switching from {getMethodName(currentMethod)}{" "}
+ to {getMethodName(newMethod)} will clear all
+ current markdown.
+ >
)}
-
+
This will permanently delete:
@@ -2235,7 +2398,8 @@ const InputChangeConfirmationModal = ({ markdownText, stats, currentMethod, newM
- Tip: Consider downloading your current markdown before switching methods to avoid losing your work.
+ Tip: Consider downloading your current markdown
+ before switching methods to avoid losing your work.
diff --git a/src/styles/._markdown-preview.css b/src/styles/._markdown-preview.css
new file mode 100755
index 00000000..3d095653
Binary files /dev/null and b/src/styles/._markdown-preview.css differ
diff --git a/src/styles/markdown-preview.css b/src/styles/markdown-preview.css
index 2a4fd5ba..4d22df9c 100755
--- a/src/styles/markdown-preview.css
+++ b/src/styles/markdown-preview.css
@@ -1,23 +1,25 @@
/* GitHub-style Markdown Preview Styling */
.markdown-preview {
- color: #24292f;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif;
- font-size: 16px;
- line-height: 1.6;
- word-wrap: break-word;
- overflow-wrap: break-word;
- max-width: 100%;
- word-break: break-word;
+ color: #24292f;
+ font-family:
+ -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica,
+ Arial, sans-serif;
+ font-size: 16px;
+ line-height: 1.6;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ max-width: 100%;
+ word-break: break-word;
}
/* Ensure all child elements respect container width */
.markdown-preview * {
- max-width: 100%;
- box-sizing: border-box;
+ max-width: 100%;
+ box-sizing: border-box;
}
.dark .markdown-preview {
- color: #c9d1d9;
+ color: #c9d1d9;
}
.markdown-preview h1,
@@ -26,254 +28,256 @@
.markdown-preview h4,
.markdown-preview h5,
.markdown-preview h6 {
- margin-top: 24px;
- margin-bottom: 16px;
- font-weight: 600;
- line-height: 1.25;
+ margin-top: 24px;
+ margin-bottom: 16px;
+ font-weight: 600;
+ line-height: 1.25;
}
.markdown-preview h1 {
- font-size: 2em;
- border-bottom: 1px solid #d0d7de;
- padding-bottom: 0.3em;
+ font-size: 2em;
+ border-bottom: 1px solid #d0d7de;
+ padding-bottom: 0.3em;
}
.dark .markdown-preview h1 {
- border-bottom-color: #21262d;
+ border-bottom-color: #21262d;
}
.markdown-preview h2 {
- font-size: 1.5em;
- border-bottom: 1px solid #d0d7de;
- padding-bottom: 0.3em;
+ font-size: 1.5em;
+ border-bottom: 1px solid #d0d7de;
+ padding-bottom: 0.3em;
}
.dark .markdown-preview h2 {
- border-bottom-color: #21262d;
+ border-bottom-color: #21262d;
}
.markdown-preview h3 {
- font-size: 1.25em;
+ font-size: 1.25em;
}
.markdown-preview h4 {
- font-size: 1em;
+ font-size: 1em;
}
.markdown-preview h5 {
- font-size: 0.875em;
+ font-size: 0.875em;
}
.markdown-preview h6 {
- font-size: 0.85em;
- color: #57606a;
+ font-size: 0.85em;
+ color: #57606a;
}
.dark .markdown-preview h6 {
- color: #8b949e;
+ color: #8b949e;
}
.markdown-preview p {
- margin-top: 0;
- margin-bottom: 16px;
+ margin-top: 0;
+ margin-bottom: 16px;
}
/* Inline code - with background */
.markdown-preview code {
- padding: 0.2em 0.4em;
- margin: 0;
- font-size: 85%;
- background-color: rgba(175, 184, 193, 0.2);
- border-radius: 6px;
- font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
+ padding: 0.2em 0.4em;
+ margin: 0;
+ font-size: 85%;
+ background-color: rgba(175, 184, 193, 0.2);
+ border-radius: 6px;
+ font-family:
+ ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
+ "Liberation Mono", monospace;
}
.dark .markdown-preview code {
- background-color: rgba(110, 118, 129, 0.4);
+ background-color: rgba(110, 118, 129, 0.4);
}
/* Code block wrapper with header */
.markdown-preview .code-block-wrapper {
- margin-bottom: 16px;
- border-radius: 8px;
- overflow: hidden;
- border: 1px solid #d0d7de;
- background-color: #f6f8fa;
+ margin-bottom: 16px;
+ border-radius: 8px;
+ overflow: hidden;
+ border: 1px solid #d0d7de;
+ background-color: #f6f8fa;
}
.dark .markdown-preview .code-block-wrapper {
- border-color: #30363d;
- background-color: #0d1117;
+ border-color: #30363d;
+ background-color: #0d1117;
}
/* Code block header */
.markdown-preview .code-block-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 4px 10px;
- background-color: #f6f8fa;
- border-bottom: 1px solid #d0d7de;
- font-size: 12px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 4px 10px;
+ background-color: #f6f8fa;
+ border-bottom: 1px solid #d0d7de;
+ font-size: 12px;
}
.dark .markdown-preview .code-block-header {
- background-color: #161b22;
- border-bottom-color: #30363d;
+ background-color: #161b22;
+ border-bottom-color: #30363d;
}
/* Language label */
.markdown-preview .code-block-language {
- font-weight: 600;
- color: #57606a;
- text-transform: uppercase;
- font-size: 10px;
- letter-spacing: 0.5px;
+ font-weight: 600;
+ color: #57606a;
+ text-transform: uppercase;
+ font-size: 10px;
+ letter-spacing: 0.5px;
}
.dark .markdown-preview .code-block-language {
- color: #8b949e;
+ color: #8b949e;
}
/* Copy button */
.markdown-preview .code-block-copy {
- padding: 2px 6px;
- background-color: transparent;
- border: 1px solid #d0d7de;
- border-radius: 6px;
- color: #24292f;
- font-size: 10px;
- cursor: pointer;
- transition: all 0.2s;
- font-weight: 500;
+ padding: 2px 6px;
+ background-color: transparent;
+ border: 1px solid #d0d7de;
+ border-radius: 6px;
+ color: #24292f;
+ font-size: 10px;
+ cursor: pointer;
+ transition: all 0.2s;
+ font-weight: 500;
}
.markdown-preview .code-block-copy:hover {
- background-color: #f3f4f6;
- border-color: #1f2328;
+ background-color: #f3f4f6;
+ border-color: #1f2328;
}
.dark .markdown-preview .code-block-copy {
- color: #c9d1d9;
- border-color: #30363d;
+ color: #c9d1d9;
+ border-color: #30363d;
}
.dark .markdown-preview .code-block-copy:hover {
- background-color: #21262d;
- border-color: #8b949e;
+ background-color: #21262d;
+ border-color: #8b949e;
}
/* Code blocks - with background */
.markdown-preview .code-block-wrapper pre {
- padding: 16px;
- overflow: auto;
- font-size: 85%;
- line-height: 1.45;
- background-color: #0d1117;
- margin: 0;
- border-radius: 0;
+ padding: 16px;
+ overflow: auto;
+ font-size: 85%;
+ line-height: 1.45;
+ background-color: #0d1117;
+ margin: 0;
+ border-radius: 0;
}
/* Legacy pre blocks (without wrapper) */
.markdown-preview pre:not(.code-block-wrapper pre) {
- padding: 16px;
- overflow: auto;
- font-size: 85%;
- line-height: 1.45;
- background-color: #afb8c133;
- border-radius: 6px;
- margin-bottom: 16px;
+ padding: 16px;
+ overflow: auto;
+ font-size: 85%;
+ line-height: 1.45;
+ background-color: #afb8c133;
+ border-radius: 6px;
+ margin-bottom: 16px;
}
.dark .markdown-preview pre:not(.code-block-wrapper pre) {
- background-color: rgba(110, 118, 129, 0.4);
+ background-color: rgba(110, 118, 129, 0.4);
}
/* Code inside pre blocks - NO background (transparent) */
.markdown-preview pre code {
- display: inline;
- max-width: auto;
- padding: 0;
- margin: 0;
- overflow: visible;
- line-height: inherit;
- word-wrap: normal;
- background-color: transparent !important;
- border: 0;
- border-radius: 0;
+ display: inline;
+ max-width: auto;
+ padding: 0;
+ margin: 0;
+ overflow: visible;
+ line-height: inherit;
+ word-wrap: normal;
+ background-color: transparent !important;
+ border: 0;
+ border-radius: 0;
}
/* Preserve highlight.js syntax highlighting colors */
.markdown-preview pre code.hljs {
- background: transparent !important;
- padding: 0 !important;
+ background: transparent !important;
+ padding: 0 !important;
}
.markdown-preview table {
- border-spacing: 0;
- border-collapse: collapse;
- display: block;
- width: 100%;
- max-width: 100%;
- overflow-x: auto;
- margin-bottom: 16px;
+ border-spacing: 0;
+ border-collapse: collapse;
+ display: block;
+ width: 100%;
+ max-width: 100%;
+ overflow-x: auto;
+ margin-bottom: 16px;
}
.markdown-preview table tr {
- background-color: #ffffff;
- border-top: 1px solid #d0d7de;
+ background-color: #ffffff;
+ border-top: 1px solid #d0d7de;
}
.dark .markdown-preview table tr {
- background-color: #0d1117;
- border-top-color: #21262d;
+ background-color: #0d1117;
+ border-top-color: #21262d;
}
.markdown-preview table tr:nth-child(2n) {
- background-color: #f6f8fa;
+ background-color: #f6f8fa;
}
.dark .markdown-preview table tr:nth-child(2n) {
- background-color: #161b22;
+ background-color: #161b22;
}
.markdown-preview table th,
.markdown-preview table td {
- padding: 6px 13px;
- border: 1px solid #d0d7de;
+ padding: 6px 13px;
+ border: 1px solid #d0d7de;
}
.dark .markdown-preview table th,
.dark .markdown-preview table td {
- border-color: #21262d;
+ border-color: #21262d;
}
.markdown-preview table th {
- font-weight: 600;
- background-color: #f6f8fa;
+ font-weight: 600;
+ background-color: #f6f8fa;
}
.dark .markdown-preview table th {
- background-color: #161b22;
+ background-color: #161b22;
}
.markdown-preview blockquote {
- padding: 0 1em;
- color: #57606a;
- border-left: 0.25em solid #d0d7de;
- margin: 0 0 16px 0;
+ padding: 0 1em;
+ color: #57606a;
+ border-left: 0.25em solid #d0d7de;
+ margin: 0 0 16px 0;
}
.dark .markdown-preview blockquote {
- color: #8b949e;
- border-left-color: #3b434b;
+ color: #8b949e;
+ border-left-color: #3b434b;
}
.markdown-preview ul,
.markdown-preview ol {
- padding-left: 2em;
- margin-top: 0;
- margin-bottom: 16px;
+ padding-left: 2em;
+ margin-top: 0;
+ margin-bottom: 16px;
}
/* Nested lists */
@@ -281,100 +285,192 @@
.markdown-preview ul ol,
.markdown-preview ol ul,
.markdown-preview ol ol {
- margin-top: 0.25em;
- margin-bottom: 0.25em;
+ margin-top: 0.25em;
+ margin-bottom: 0.25em;
}
/* List items */
.markdown-preview li {
- margin-bottom: 0.25em;
- line-height: 1.6;
+ margin-bottom: 0.25em;
+ line-height: 1.6;
}
.markdown-preview li + li {
- margin-top: 0.25em;
+ margin-top: 0.25em;
}
/* Better bullet points */
.markdown-preview ul > li {
- list-style-type: disc;
+ list-style-type: disc;
}
.markdown-preview ul ul > li {
- list-style-type: circle;
+ list-style-type: circle;
}
.markdown-preview ul ul ul > li {
- list-style-type: square;
+ list-style-type: square;
}
/* Ordered list styling */
.markdown-preview ol > li {
- list-style-type: decimal;
+ list-style-type: decimal;
}
.markdown-preview ol ol > li {
- list-style-type: lower-alpha;
+ list-style-type: lower-alpha;
}
.markdown-preview ol ol ol > li {
- list-style-type: lower-roman;
+ list-style-type: lower-roman;
}
/* List item content spacing */
.markdown-preview li > p {
- margin-top: 0.5em;
- margin-bottom: 0.5em;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
}
.markdown-preview li > p:first-child {
- margin-top: 0;
+ margin-top: 0;
}
.markdown-preview li > p:last-child {
- margin-bottom: 0;
+ margin-bottom: 0;
}
.markdown-preview hr {
- height: 0.25em;
- padding: 0;
- margin: 24px 0;
- background-color: #d0d7de;
- border: 0;
+ height: 0.25em;
+ padding: 0;
+ margin: 24px 0;
+ background-color: #d0d7de;
+ border: 0;
}
.dark .markdown-preview hr {
- background-color: #21262d;
+ background-color: #21262d;
}
.markdown-preview a {
- color: #0969da;
- text-decoration: none;
+ color: #0969da;
+ text-decoration: none;
}
.dark .markdown-preview a {
- color: #58a6ff;
+ color: #58a6ff;
}
.markdown-preview a:hover {
- text-decoration: underline;
+ text-decoration: underline;
}
.markdown-preview strong {
- font-weight: 600;
+ font-weight: 600;
}
.markdown-preview em {
- font-style: italic;
+ font-style: italic;
}
.markdown-preview u {
- text-decoration: underline;
+ text-decoration: underline;
}
.markdown-preview img {
- max-width: 100%;
- height: auto;
- border-radius: 6px;
- margin: 16px 0;
+ max-width: 100%;
+ height: auto;
+ border-radius: 6px;
+ margin: 16px 0;
+}
+
+/* Tiptap specific styling overrides to match prose */
+.tiptap p.is-editor-empty:first-child::before {
+ color: #adb5bd;
+ content: attr(data-placeholder);
+ float: left;
+ height: 0;
+ pointer-events: none;
+}
+
+.tiptap {
+ outline: none;
+}
+
+.tiptap ul[data-type="taskList"] {
+ list-style: none;
+ padding: 0;
+}
+
+.tiptap ul[data-type="taskList"] li {
+ display: flex;
+ align-items: flex-start;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+.tiptap ul[data-type="taskList"] li > label {
+ flex: 0 0 auto;
+ margin-right: 0.5rem;
+ user-select: none;
+ margin-top: 0.2rem;
+}
+
+.tiptap ul[data-type="taskList"] li > div {
+ flex: 1 1 auto;
+ margin: 0;
+}
+
+.tiptap ul[data-type="taskList"] li > div > p {
+ margin: 0;
+}
+
+.tiptap p {
+ margin-top: 0;
+ margin-bottom: 0.65em;
+}
+
+/* Printing logic for PDF export */
+@media print {
+ .tiptap pre,
+ .markdown-preview pre {
+ white-space: pre-wrap !important;
+ word-wrap: break-word !important;
+ break-inside: avoid !important;
+ }
+
+ .code-block-header {
+ display: none !important;
+ }
+}
+
+/* Custom Node Views (Code Block) */
+.tiptap .code-block-wrapper {
+ margin-bottom: 0.65em;
+ border-radius: 6px;
+ background-color: #0d1117;
+ overflow: hidden;
+}
+
+.tiptap .code-block-wrapper pre {
+ margin: 0 !important;
+ padding: 1rem;
+ border-radius: 0 0 6px 6px;
+ background: transparent;
+}
+
+/* Markdown Content Wrapper Padding Strategies */
+.markdown-content-wrapper.is-normal.is-read-mode > .prose {
+ padding-bottom: 3rem; /* 48px */
+}
+
+.markdown-content-wrapper.is-fullscreen.is-read-mode > .prose {
+ padding-bottom: 4rem; /* 128px */
+}
+
+.markdown-content-wrapper.is-normal.is-edit-mode > div {
+ padding-bottom: 3rem; /* 48px */
+}
+
+.markdown-content-wrapper.is-fullscreen.is-edit-mode > div {
+ padding-bottom: 6rem; /* 128px */
}
diff --git a/tailwind.config.js b/tailwind.config.js
index 9fd42706..94651e61 100755
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,34 +1,165 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
- content: [
- "./src/**/*.{js,jsx,ts,tsx}",
- ],
- darkMode: 'class', // Enable manual dark mode control via class
+ content: ["./src/**/*.{js,jsx,ts,tsx}"],
+ darkMode: "class", // Enable manual dark mode control via class
theme: {
extend: {
colors: {
primary: {
- 50: '#f0f9ff',
- 100: '#e0f2fe',
- 200: '#bae6fd',
- 300: '#7dd3fc',
- 400: '#38bdf8',
- 500: '#0ea5e9',
- 600: '#0284c7',
- 700: '#0369a1',
- 800: '#075985',
- 900: '#0c4a6e',
- }
+ 50: "#f0f9ff",
+ 100: "#e0f2fe",
+ 200: "#bae6fd",
+ 300: "#7dd3fc",
+ 400: "#38bdf8",
+ 500: "#0ea5e9",
+ 600: "#0284c7",
+ 700: "#0369a1",
+ 800: "#075985",
+ 900: "#0c4a6e",
+ },
},
fontFamily: {
- mono: ['JetBrains Mono', 'Monaco', 'Cascadia Code', 'Segoe UI Mono', 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro', 'Fira Code', 'Droid Sans Mono', 'Courier New', 'monospace'],
+ mono: [
+ "JetBrains Mono",
+ "Monaco",
+ "Cascadia Code",
+ "Segoe UI Mono",
+ "Roboto Mono",
+ "Oxygen Mono",
+ "Ubuntu Monospace",
+ "Source Code Pro",
+ "Fira Code",
+ "Droid Sans Mono",
+ "Courier New",
+ "monospace",
+ ],
},
- maxWidth: {
- '1/4': '25%',
- '1/2': '50%',
- '3/4': '75%',
- }
+ typography: (theme) => ({
+ DEFAULT: {
+ css: {
+ "--tw-prose-body": "#24292f",
+ "--tw-prose-headings": "#24292f",
+ "--tw-prose-lead": "#57606a",
+ "--tw-prose-links": "#0969da",
+ "--tw-prose-bold": "#24292f",
+ "--tw-prose-counters": "#57606a",
+ "--tw-prose-bullets": "#d0d7de",
+ "--tw-prose-hr": "#d0d7de",
+ "--tw-prose-quotes": "#57606a",
+ "--tw-prose-quote-borders": "#d0d7de",
+ "--tw-prose-captions": "#57606a",
+ "--tw-prose-code": "#24292f",
+ "--tw-prose-pre-code": "#24292f",
+ "--tw-prose-pre-bg": "#f6f8fa",
+ "--tw-prose-th-borders": "#d0d7de",
+ "--tw-prose-td-borders": "#d0d7de",
+
+ // Invert colors for dark mode
+ "--tw-prose-invert-body": "#c9d1d9",
+ "--tw-prose-invert-headings": "#c9d1d9",
+ "--tw-prose-invert-lead": "#8b949e",
+ "--tw-prose-invert-links": "#58a6ff",
+ "--tw-prose-invert-bold": "#c9d1d9",
+ "--tw-prose-invert-counters": "#8b949e",
+ "--tw-prose-invert-bullets": "#30363d",
+ "--tw-prose-invert-hr": "#21262d",
+ "--tw-prose-invert-quotes": "#8b949e",
+ "--tw-prose-invert-quote-borders": "#30363d",
+ "--tw-prose-invert-captions": "#8b949e",
+ "--tw-prose-invert-code": "#c9d1d9",
+ "--tw-prose-invert-pre-code": "#c9d1d9",
+ "--tw-prose-invert-pre-bg": "#161b22",
+ "--tw-prose-invert-th-borders": "#30363d",
+ "--tw-prose-invert-td-borders": "#30363d",
+
+ // Adjust margins and sizes (Standardizing to GitHub Markdown / Modern defaults)
+ maxWidth: "none",
+ lineHeight: "1.4",
+ p: {
+ marginTop: "0",
+ marginBottom: "0.65em",
+ },
+ "h1, h2, h3, h4, h5, h6": {
+ marginTop: "1em",
+ marginBottom: "0.65em",
+ fontWeight: "600",
+ lineHeight: "1.2",
+ },
+ h1: {
+ fontSize: "2em",
+ paddingBottom: "0.2em",
+ borderBottomWidth: "1px",
+ },
+ h2: {
+ fontSize: "1.5em",
+ paddingBottom: "0.2em",
+ borderBottomWidth: "1px",
+ },
+ h3: { fontSize: "1.25em" },
+ h4: { fontSize: "1em" },
+ h5: { fontSize: "0.875em" },
+ h6: { fontSize: "0.85em", color: "var(--tw-prose-lead)" },
+ "ul, ol": {
+ marginTop: "0",
+ marginBottom: "0.65em",
+ paddingLeft: "1.5em",
+ },
+ li: {
+ marginTop: "0.15em",
+ marginBottom: "0.15em",
+ },
+ "li > p": {
+ marginTop: "0",
+ marginBottom: "0",
+ },
+ blockquote: {
+ marginTop: "0",
+ marginBottom: "0.65em",
+ paddingLeft: "1em",
+ fontStyle: "normal",
+ borderLeftWidth: "4px",
+ },
+ pre: {
+ marginTop: "0",
+ marginBottom: "0.65em",
+ padding: "0.75em",
+ borderRadius: "6px",
+ },
+ code: {
+ backgroundColor: "rgba(175, 184, 193, 0.2)",
+ padding: "0.2em 0.4em",
+ borderRadius: "6px",
+ fontWeight: "inherit",
+ },
+ "code::before": { content: '""' },
+ "code::after": { content: '""' },
+ "pre code": {
+ backgroundColor: "transparent",
+ padding: "0",
+ },
+ table: {
+ marginTop: "0",
+ marginBottom: "0.65em",
+ },
+ "thead th": {
+ padding: "0.4em 0.75em",
+ borderWidth: "1px",
+ },
+ "tbody td": {
+ padding: "0.4em 0.75em",
+ borderWidth: "1px",
+ },
+ hr: {
+ marginTop: "1em",
+ marginBottom: "1em",
+ height: "0.25em",
+ borderWidth: "0",
+ backgroundColor: "var(--tw-prose-hr)",
+ },
+ },
+ },
+ }),
},
},
- plugins: [],
-}
+ plugins: [require("@tailwindcss/typography")],
+};