@cubud/wen 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 cubud
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,53 @@
1
+ # 🤖 Agentic & LLM Contributor Guidelines for Wen (ƿen) Editor
2
+
3
+ Hello, fellow LLM or AI Assistant! If you have been asked to help extend, debug, or refactor the Wen Editor, please read this document first. It outlines the strict architectural philosophy and boundaries of this project.
4
+
5
+ ## 1. The Core Philosophy
6
+ Wen is a vanilla JavaScript, dependency-light, ESM-native rich text editor built on top of TipTap and ProseMirror.
7
+ * **Zero Build Tools:** We do not use Node.js, Webpack, Vite, or npm. We use a simple bash script (`build.sh`) that concatenates files using `cat`.
8
+ * **ESM Only:** All third-party libraries must be imported directly from CDNs (like `https://esm.sh/`).
9
+ * **Joyful Minimalism:** The editor is named after the Anglo-Saxon rune ƿ (wynn), meaning "joy". Keep the UI polished, the codebase tiny, and the dependencies strictly limited.
10
+
11
+ ## 2. The "Dumb Router" Architecture
12
+ Wen bridges the gap between raw Markdown and rich visual interfaces without destroying the underlying Markdown AST. **Do not create custom TipTap nodes for everything.** Instead, we use a "Dumb Router" pattern:
13
+ 1. All complex data (YAML, Components, Mermaid, Charts) is stored in the Markdown as standard fenced code blocks (e.g., ````yaml`).
14
+ 2. The core extension (`WenSmartBlocks` in `wen-core.js`) intercepts these standard code blocks based on their language tag.
15
+ 3. It routes the rendering to independent `NodeView` classes (e.g., `WenYamlView`, `WenMermaidView`).
16
+
17
+ **If the user asks you to add a new block type (like a Kanban board or a Math renderer):**
18
+ * Do NOT rewrite the TipTap schema.
19
+ * DO create a new class that intercepts a specific code block language.
20
+ * DO ensure the raw text remains pure and standard Markdown.
21
+
22
+ ## 3. The View Class Pattern
23
+ Every custom block view MUST implement the following structure:
24
+ * **Visual vs. Raw Toggle:** The UI must provide a way to flip between the beautiful visual rendering and the raw text/JSON/XML code.
25
+ * **State Synchronization:** You must implement a `updateTipTapState(newContent)` function that safely updates the ProseMirror transaction without crashing the editor cursor.
26
+ * **The `update()` Hook:** You must implement TipTap's `update(updatedNode)` method to listen for external changes (e.g., if the user edits the code via a split-pane Monaco editor) and re-render the visual state dynamically.
27
+
28
+ ## 4. Modal and Recursion Rules
29
+ Wen supports deep UI recursion (e.g., a component containing markdown, which contains another component).
30
+ * Do not attempt to render inline WYSIWYG editors inside of custom NodeViews; the DOM cannot handle the event-bubbling and horizontal space constraints.
31
+ * Instead, use the `editor.wenEditorInstance.showRichModal()` method. This spawns a full-screen overlay containing a fresh, recursive instance of Wen Editor to handle inner content.
32
+ * Always assign high `z-index` values (`99999`) to utility modals (like Link/Image prompts) so they don't get trapped beneath the recursive rich modals.
33
+
34
+ ## 5. CSS and Styling Strictness
35
+ * **Encapsulation:** Prefix all classes with `.wen-`. Do not pollute the global CSS namespace.
36
+ * **Box-Sizing:** Always apply `box-sizing: border-box` to custom block wrappers to prevent horizontal blowout when paddings are applied to 100% width textareas.
37
+ * **Variables:** Use the provided CSS variables (e.g., `var(--wen-bg)`, `var(--wen-border)`) to ensure dark-mode/light-mode portability.
38
+
39
+ ## 6. Security: Safe by Default
40
+ ƿen renders untrusted document content, so it is **safe by default** with a deliberate opt-out (`unsafe: true` in the editor config). Preserve this contract:
41
+ * **Never** interpolate document data straight into `innerHTML` or into an HTML attribute. Use `escapeHtml()` from `src/wen-utils.js` for values and attributes — this is baseline correctness and applies in both modes.
42
+ * For rich HTML you must inject (e.g. `marked` output), pass it through `sanitizeHtml()` from `src/wen-utils.js`, gated on `this.editor.wenEditorInstance?.unsafe`.
43
+ * Third-party renderers must run in their safe mode by default (e.g. Mermaid `securityLevel: 'strict'`), loosening only when `unsafe` is set.
44
+ * `WenEditor` propagates `unsafe` into recursive modal editors — keep that wiring intact when touching `showRichModal`.
45
+
46
+ ## 7. Development Workflow
47
+ If you are instructed to create a new module (e.g., `src/wen-math.js`):
48
+ 1. Write the JS file and its accompanying `src/wen-math.css` file.
49
+ 2. Instruct the user to add the CSS file to the concatenation list in `build.sh`.
50
+ 3. Instruct the user to add the JS export to the temporary entry point in `build.sh`.
51
+ 4. Instruct the user to map the language tag to the new class in the `blockViews` configuration inside `index.html`.
52
+
53
+ Stick to these patterns, avoid unnecessary abstractions, and help us keep the editor a joy to use and maintain.
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # ƿen (AKA wen / wynn / "joy") editor
2
+
3
+ **Sponsored by [Cubud](https://cubud.com)**
4
+
5
+ **ƿen** (pronounced *wen*) takes its name from the Anglo-Saxon runic alphabet. The rune **ƿ** (wynn) translates directly to "joy." Because it was historically transliterated as "w" (wen) but visually masquerades as the letter "p" (pen), it felt like the perfect namesake for a text editor: a tool designed to bring a little more joy to the act of writing.
6
+
7
+ ### 🤝 The Philosophy: A Shared Language
8
+
9
+ ƿen was built to bridge a historical divide.
10
+
11
+ For years, developers have loved the clean, portable predictability of formats like Markdown, YAML, and XML components. Meanwhile, content editors and real humans have understandably preferred the immediate visual feedback of WYSIWYG (What You See Is What You Get) interfaces.
12
+
13
+ We didn't build ƿen to wage war on modern, heavy web frameworks. Instead, it is offered as a lightweight, unifying *alternative*. We've chosen to avoid a complex toolchain (no Node.js, no Webpack, no `npm install`) to build incredibly rich, extensible browser experiences _but_ acknowledge that we're only able to do this by leveraging robust and mature open source libraries like TipTap, Frappe, Lowlight, Mermaid and others.
14
+
15
+ By taking abstract technical formats and wrapping them in friendly, interactive user interfaces, ƿen helps demystify developer tools for everyday writers. The ultimate goal is to encourage the wider adoption of these brilliant, plain-text concepts. When a content team gets comfortable editing YAML configurations and Markdown tables visually in ƿen, it becomes second nature to start using those same Markdown shortcuts to format a WhatsApp message, or structure a quick note on their phone.
16
+
17
+ It is about bringing developers and editors together into the same workflow, speaking the exact same language.
18
+
19
+ ### ✨ Core Features
20
+
21
+ ƿen is an ESM-native, vanilla JavaScript editor built on top of TipTap and ProseMirror. It introduces a unique "Dumb Router" architecture that keeps your underlying data perfectly pure while providing a massively upgraded Writer Experience (WX).
22
+
23
+ * **Zero-Build Extensibility:** No build step required. Just import the ESM modules directly from CDNs and stitch them together with a simple bash script.
24
+ * **Visual YAML Frontmatter:** Writers can edit complex, nested page metadata through a clean, interactive form UI, which seamlessly serializes back to strict YAML.
25
+ * **Recursive Component IDE:** Drop XML/React-style components right into the editor. ƿen renders them as visual wireframes with editable attribute pills. Need to edit the Markdown *inside* a component? Click "Edit in WYSIWYG" to spawn a recursive, infinite-depth rich modal.
26
+ * **Smart Block Routing:** Type a code block, and ƿen instantly routes it to a custom UI.
27
+ * ```` ```mermaid ```` renders live, scalable state diagrams.
28
+ * ```` ```chart ```` turns simple CSV data into beautiful, on-brand Frappe Charts.
29
+ * ```` ```javascript ```` gracefully falls back to GitHub-dark syntax highlighting.
30
+ * **Native Markdown Superpowers:** Full visual support for Markdown Tables, interactive Checklists, and dynamic GitHub-flavored Alerts (`[!WARNING]`), all perfectly translating back to standard text.
31
+
32
+ ### 📄 Optional Frontmatter
33
+ ƿen natively supports YAML frontmatter, treating it as a highly structured interactive form.
34
+
35
+ By default, the editor intercepts blocks at the top of the file bracketed by `---`. It temporarily translates this into a standard ````yaml` code block so TipTap can safely route it to the visual `WenYamlView` UI without destroying the key/value pairs. When you export the document, ƿen seamlessly translates it back into strict `---` frontmatter.
36
+
37
+ *(To disable this translation if you are using the editor for fragments rather than full pages, simply pass `useFrontmatter: false` in the configuration object).*
38
+
39
+ ### 🧩 Inline Component Support
40
+ You can author custom HTML or React/JSX-style components directly in the Markdown stream:
41
+
42
+ ```xml
43
+ <Hero banner="/img/bg.jpg" align="center">
44
+ # Hello World
45
+ </Hero>
46
+ ```
47
+
48
+ When useNativeComponents is enabled, ƿen uses a lightweight AST translation layer. It temporarily wraps these XML nodes in ````component` code blocks, allowing the "Dumb Router" to intercept them. They are rendered as interactive wireframes where attributes become editable text inputs.
49
+
50
+ Because of this encapsulation, writers can safely edit the Markdown inside the component via a spawned modal without accidentally deleting the XML tags. On export, the wrapper is stripped away, leaving your pristine <Hero> tags exactly where they belong.
51
+
52
+ ## Installation & Usage
53
+
54
+ No `npm install`. ƿen is published to npm as [`@cubud/wen`](https://www.npmjs.com/package/@cubud/wen) and served for free over the jsDelivr CDN. Just load the styles and import the modules:
55
+
56
+ ```html
57
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@cubud/wen@1/dist/wen-full.min.css">
58
+ <script type="module">
59
+ import {
60
+ WenEditor, WenYamlView, WenComponentView, WenMermaidView, WenChartView
61
+ } from 'https://cdn.jsdelivr.net/npm/@cubud/wen@1/dist/wen-full.min.js';
62
+
63
+ const editor = new WenEditor({
64
+ element: document.getElementById('my-editor'),
65
+ // Dependency Injection: Route the code blocks to the visual engines
66
+ blockViews: {
67
+ 'yaml': WenYamlView,
68
+ 'component': WenComponentView,
69
+ 'mermaid': WenMermaidView,
70
+ 'chart': WenChartView
71
+ },
72
+ initialMarkdown: '# Welcome to ƿen.'
73
+ });
74
+ </script>
75
+ ```
76
+
77
+ > Prefer ESM-native imports with automatic dependency resolution? `https://esm.sh/@cubud/wen@1` works too.
78
+
79
+ ## API
80
+
81
+ `editor.exportMarkdown()`
82
+
83
+ Serializes the current state of the editor back into a clean, strictly formatted Markdown string (including perfectly indented YAML data blocks and XML components).
84
+
85
+ ## Security
86
+
87
+ ƿen turns Markdown, YAML, components and Mermaid diagrams into live HTML. By default it is **safe**: interpolated values are escaped, component previews are sanitized with [DOMPurify](https://github.com/cure53/DOMPurify), and Mermaid runs in `strict` mode (no inline HTML or click handlers).
88
+
89
+ If you fully trust your content and want raw HTML and interactive diagrams rendered verbatim, opt in explicitly:
90
+
91
+ ```js
92
+ const editor = new WenEditor({ /* ... */, unsafe: true });
93
+ ```
94
+
95
+ ƿen is open source and dependency-light by design, so you're free to adapt this behaviour — but the default keeps an untrusted document from executing script in your page.
96
+
97
+ ## License
98
+
99
+ MIT License. Build great things.