From d99b683a29ceff3c2707adfeab86b9f5a5a7cccb Mon Sep 17 00:00:00 2001 From: Tacx <12997062+tacxou@users.noreply.github.com> Date: Mon, 19 Oct 2026 09:37:17 +0200 Subject: [PATCH 1/3] feat(advanced): store WYSIWYG content as Markdown Accept `options.contentType: 'markdown'` on string controls: UEditor serializes the document through TipTap's Markdown extension, source mode edits the raw Markdown and the builder inspector offers the format. Images and tables round-trip; resized image widths have no Markdown equivalent and are dropped. Prepare the 2.1.0 changelog, which also covers the unreleased rich WYSIWYG features and AI assistant. --- CHANGELOG.md | 17 ++++++++++ README.md | 4 +-- changelog/2.1.0.md | 22 +++++++++++++ docs/en/guide/options/string.md | 18 ++++++++++- docs/guide/options/string.md | 19 ++++++++++- package.json | 2 ++ playground/examples/items/nuxt-wysiwyg.ts | 23 +++++++++++++ src/advanced/wysiwyg/WysiwygSourceEditor.vue | 17 +++++++--- src/advanced/wysiwyg/source.ts | 14 +++++--- src/advanced/wysiwygOptions.ts | 7 ++-- src/builder/BuilderInspector.vue | 7 ++-- tests/advanced/wysiwygFeatures.test.ts | 34 ++++++++++++++++++++ tests/advanced/wysiwygOptions.test.ts | 3 ++ yarn.lock | 4 +-- 14 files changed, 170 insertions(+), 21 deletions(-) create mode 100644 changelog/2.1.0.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e0ff28..ffe5715 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,23 @@ versioning follows [SemVer](https://semver.org/). +## [2.1.0](https://github.com/FicSysFR/jsonforms_builder/compare/2.0.2...2.1.0) - 2026-10-19 + +### ✹ Features + +- WYSIWYG renderer: tables, task lists, alignment, colors, highlights, link panel, find & replace, + source mode, preview, an opt-in text bubble and an opt-in slash palette (`0de8d92`). +- Optional AI writing assistant over a host AI SDK endpoint (UI message stream, text stream or + JSON); results stay in a detached panel until accepted, requests are abortable and the feature + is inert unless `ai.enabled` is `true` (`0de8d92`). +- `options.contentType: 'markdown'` stores the WYSIWYG value as a Markdown string through TipTap's + Markdown extension; source mode edits the raw Markdown and the builder inspector offers the + Markdown format (`string` schema). + +### 📝 Documentation + +- WYSIWYG & AI guide, Markdown storage options and playground example (FR/EN). + ## [2.0.2](https://github.com/FicSysFR/jsonforms_builder/compare/2.0.1...2.0.2) - 2026-09-08 ### ⚠ Breaking Changes diff --git a/README.md b/README.md index 53260a9..8d27dc0 100644 --- a/README.md +++ b/README.md @@ -74,14 +74,14 @@ Palette, drag-and-drop reorderable tree, property inspector, live preview, and J | `string` | `UInput` | | `string` + `options.multi` | `UTextarea` | | `string` + `format: password` | `UInput` + visibility toggle | -| `object` / `string` + `options.wysiwyg` | `UEditor` (JSON or HTML via `contentType`) | +| `object` / `string` + `options.wysiwyg` | `UEditor` (JSON, HTML or Markdown via `contentType`) | | WYSIWYG images | upload dropzone, drag-resize, bubble replace/delete | WYSIWYG options (`options.wysiwyg: true`): | Option | Role | |---|---| -| `contentType` | `'json'` \| `'html'` (else inferred from schema) | +| `contentType` | `'json'` \| `'html'` \| `'markdown'` (else inferred from schema) | | `toolbar` | Nuxt UI toolbar groups, or `false` to hide | | `density` | `'compact'` \| `'comfortable'` \| `'prose'` | | `minHeight` / `padding` / `blockSpacing` / `editorClass` | spacing overrides | diff --git a/changelog/2.1.0.md b/changelog/2.1.0.md new file mode 100644 index 0000000..ae032ab --- /dev/null +++ b/changelog/2.1.0.md @@ -0,0 +1,22 @@ +--- +version: 2.1.0 +date: 2026-10-19 +title: Rich WYSIWYG, AI assistant and Markdown content +previous: 2.0.2 +prerelease: false +--- + +### ✹ Features + +- WYSIWYG renderer: tables, task lists, alignment, colors, highlights, link panel, find & replace, + source mode, preview, an opt-in text bubble and an opt-in slash palette (`0de8d92`). +- Optional AI writing assistant over a host AI SDK endpoint (UI message stream, text stream or + JSON); results stay in a detached panel until accepted, requests are abortable and the feature + is inert unless `ai.enabled` is `true` (`0de8d92`). +- `options.contentType: 'markdown'` stores the WYSIWYG value as a Markdown string through TipTap's + Markdown extension; source mode edits the raw Markdown and the builder inspector offers the + Markdown format (`string` schema). + +### 📝 Documentation + +- WYSIWYG & AI guide, Markdown storage options and playground example (FR/EN). diff --git a/docs/en/guide/options/string.md b/docs/en/guide/options/string.md index 5b78822..2912a58 100644 --- a/docs/en/guide/options/string.md +++ b/docs/en/guide/options/string.md @@ -286,7 +286,7 @@ Requires `allRenderers` (not just `nuxtUiRenderers`). | Name | Type | Default | Description | |---|---|---|---| | `wysiwyg` | `Boolean` | — | **Required** (`true`) to enable the editor. | -| `contentType` | `"json"` \| `"html"` | inferred | Stored format: ProseMirror object (`json`) or HTML string (`html`). | +| `contentType` | `"json"` \| `"html"` \| `"markdown"` | inferred | Stored format: ProseMirror object (`json`), HTML string (`html`) or Markdown string (`markdown`, `string` schema). | | `toolbar` | `Array` \| `false` | built-in toolbar | Replaces the toolbar (`EditorToolbarItem[][]`) or hides it. | | `placeholder` | `String` | — | Editor placeholder. | | `features` | `false` \| `Object` | all on | Tables, task lists, alignment, colors, highlight, link, find & replace, source, preview. | @@ -320,6 +320,22 @@ Editing features, the AI assistant and an AI SDK backend are detailed in } ``` +```json +{ + "type": "Control", + "scope": "#/properties/article", + "options": { + "wysiwyg": true, + "contentType": "markdown", + "density": "prose" + } +} +``` + +With `markdown`, the value is serialized by TipTap's Markdown extension (loaded by `UEditor`): +headings, lists, links, code, tables and images (`![alt](src)`) round-trip; the width of a resized +image has no Markdown equivalent and is not kept. Source mode then edits the raw Markdown. + ## Playground - [String & Textarea](/en/playground#/?section=docs&example=nuxt-string) diff --git a/docs/guide/options/string.md b/docs/guide/options/string.md index 8228371..f7ad4af 100644 --- a/docs/guide/options/string.md +++ b/docs/guide/options/string.md @@ -286,7 +286,7 @@ NĂ©cessite `allRenderers` (pas seulement `nuxtUiRenderers`). | Name | Type | Default | Description | |---|---|---|---| | `wysiwyg` | `Boolean` | — | **Requis** (`true`) pour activer l’éditeur. | -| `contentType` | `"json"` \| `"html"` | infĂ©rĂ© | Format stockĂ© : objet ProseMirror (`json`) ou chaĂźne HTML (`html`). | +| `contentType` | `"json"` \| `"html"` \| `"markdown"` | infĂ©rĂ© | Format stockĂ© : objet ProseMirror (`json`), chaĂźne HTML (`html`) ou chaĂźne Markdown (`markdown`, schema `string`). | | `toolbar` | `Array` \| `false` | barre intĂ©grĂ©e | Remplace la barre d’outils (`EditorToolbarItem[][]`) ou la masque. | | `placeholder` | `String` | — | Placeholder de l’éditeur. | | `features` | `false` \| `Object` | tout activĂ© | Tableaux, listes de tĂąches, alignement, couleurs, surlignage, lien, rechercher/remplacer, source, aperçu. | @@ -320,6 +320,23 @@ DĂ©tail des fonctions d’édition, de l’assistant IA et d’un backend AI SDK } ``` +```json +{ + "type": "Control", + "scope": "#/properties/article", + "options": { + "wysiwyg": true, + "contentType": "markdown", + "density": "prose" + } +} +``` + +En `markdown`, la valeur est sĂ©rialisĂ©e par l'extension Markdown de TipTap (chargĂ©e par `UEditor`) : +titres, listes, liens, code, tableaux et images (`![alt](src)`) font l'aller-retour ; la largeur +d'une image redimensionnĂ©e n'a pas d'Ă©quivalent Markdown et n'est pas conservĂ©e. Le mode source +Ă©dite alors le Markdown brut. + ## Playground - [String & Textarea](/playground#/?section=docs&example=nuxt-string) diff --git a/package.json b/package.json index 4260d09..e1a54fe 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,8 @@ "@jsonforms/core": "^3.6.0", "@jsonforms/vue": "^3.6.0", "@nuxt/ui": "^4.8.1", + "@tiptap/extension-image": "^3.29.2", + "@tiptap/markdown": "^3.29.2", "@types/express": "^5.0.6", "@types/multer": "^2.0.0", "@types/node": "^22.10.0", diff --git a/playground/examples/items/nuxt-wysiwyg.ts b/playground/examples/items/nuxt-wysiwyg.ts index 741941c..223934f 100644 --- a/playground/examples/items/nuxt-wysiwyg.ts +++ b/playground/examples/items/nuxt-wysiwyg.ts @@ -11,6 +11,14 @@ export const data = { ], }, notesHtml: '

Notes HTML libres


', + article: [ + '## ProcĂ©dure', + '', + '1. Ouvrir le portail', + '2. Cliquer sur **Nouvelle demande**', + '', + '> Astuce : joignez une capture.', + ].join('\n'), } export const schema = { @@ -26,6 +34,11 @@ export const schema = { title: 'Notes (HTML)', description: 'contentType: "html" stocke une chaĂźne HTML.', }, + article: { + type: 'string', + title: 'Article (Markdown)', + description: 'contentType: "markdown" stocke une chaĂźne Markdown.', + }, }, } @@ -52,6 +65,16 @@ export const uischema = { showUnfocusedDescription: true, }, }, + { + type: 'Control', + scope: '#/properties/article', + options: { + wysiwyg: true, + contentType: 'markdown', + density: 'prose', + showUnfocusedDescription: true, + }, + }, ], } diff --git a/src/advanced/wysiwyg/WysiwygSourceEditor.vue b/src/advanced/wysiwyg/WysiwygSourceEditor.vue index b6ce81b..264ddd8 100644 --- a/src/advanced/wysiwyg/WysiwygSourceEditor.vue +++ b/src/advanced/wysiwyg/WysiwygSourceEditor.vue @@ -6,7 +6,7 @@ autoresize :maxrows="30" :readonly="!editable" - :aria-label="contentType === 'json' ? 'Source JSON' : 'Source HTML'" + :aria-label="sourceLabel" :ui="{ base: 'font-mono text-xs' }" ) u-alert(v-if="error" color="error" variant="subtle" icon="i-lucide-circle-alert" :description="error") @@ -16,15 +16,16 @@ diff --git a/src/advanced/wysiwyg/source.ts b/src/advanced/wysiwyg/source.ts index 8539671..11b236e 100644 --- a/src/advanced/wysiwyg/source.ts +++ b/src/advanced/wysiwyg/source.ts @@ -1,18 +1,22 @@ import type { Editor, JSONContent } from '@tiptap/core' +import type { WysiwygContentType } from '../wysiwygOptions' export type WysiwygSourceParseResult = | { ok: true; content: string | JSONContent } | { ok: false; error: string } -export const serializeWysiwygSource = (editor: Editor, contentType: 'html' | 'json'): string => - contentType === 'json' ? JSON.stringify(editor.getJSON(), null, 2) : editor.getHTML() +export const serializeWysiwygSource = (editor: Editor, contentType: WysiwygContentType): string => { + if (contentType === 'json') return JSON.stringify(editor.getJSON(), null, 2) + if (contentType === 'markdown') return editor.getMarkdown() + return editor.getHTML() +} -/** Validates source-mode input; JSON must be a Tiptap `doc` node. */ +/** Validates source-mode input; JSON must be a Tiptap `doc` node, HTML and Markdown pass through. */ export const parseWysiwygSource = ( source: string, - contentType: 'html' | 'json', + contentType: WysiwygContentType, ): WysiwygSourceParseResult => { - if (contentType === 'html') return { ok: true, content: source } + if (contentType !== 'json') return { ok: true, content: source } let parsed: unknown try { parsed = JSON.parse(source) diff --git a/src/advanced/wysiwygOptions.ts b/src/advanced/wysiwygOptions.ts index ef00530..86b7a34 100644 --- a/src/advanced/wysiwygOptions.ts +++ b/src/advanced/wysiwygOptions.ts @@ -12,7 +12,10 @@ import { } from './wysiwyg/features' import { buildWysiwygToolbar } from './wysiwyg/toolbar' -export type WysiwygContentType = 'html' | 'json' +/** Stored value format: TipTap JSON (object), HTML or Markdown (strings). */ +export type WysiwygContentType = 'html' | 'json' | 'markdown' + +const CONTENT_TYPES: readonly WysiwygContentType[] = ['html', 'json', 'markdown'] export type WysiwygDensity = 'compact' | 'comfortable' | 'prose' @@ -163,7 +166,7 @@ export const resolveWysiwygOptions = ( const explicitContent = opts.contentType const contentType: WysiwygContentType = - explicitContent === 'html' || explicitContent === 'json' + explicitContent && CONTENT_TYPES.includes(explicitContent) ? explicitContent : schemaType === 'string' ? 'html' diff --git a/src/builder/BuilderInspector.vue b/src/builder/BuilderInspector.vue index ae81a32..0d8e5d3 100644 --- a/src/builder/BuilderInspector.vue +++ b/src/builder/BuilderInspector.vue @@ -476,7 +476,7 @@ p.text-xs.font-semibold.uppercase.tracking-wide.text-dimmed Options — texte riche u-form-field(label="Format stockĂ©" help="options.contentType — adapte aussi le type du schema") u-select( - :model-value="options.contentType === 'html' ? 'html' : 'json'" + :model-value="options.contentType === 'html' || options.contentType === 'markdown' ? options.contentType : 'json'" :items="wysiwygContentItems" value-key="value" class="w-full" @@ -699,6 +699,7 @@ export default defineComponent({ const wysiwygContentItems = [ { label: 'JSON (ProseMirror)', value: 'json' }, { label: 'HTML', value: 'html' }, + { label: 'Markdown', value: 'markdown' }, ] const asNumber = (value: unknown): number | undefined => @@ -799,10 +800,10 @@ export default defineComponent({ /** contentType drives both the option and the schema `type` (object vs string). */ const patchWysiwygContentType = (value: unknown) => { - const contentType = value === 'html' ? 'html' : 'json' + const contentType = value === 'html' || value === 'markdown' ? value : 'json' emit('update:control', { element: { options: { ...options.value, contentType } }, - property: { type: contentType === 'html' ? 'string' : 'object' }, + property: { type: contentType === 'json' ? 'object' : 'string' }, }) } diff --git a/tests/advanced/wysiwygFeatures.test.ts b/tests/advanced/wysiwygFeatures.test.ts index 8170483..6d5cf4b 100644 --- a/tests/advanced/wysiwygFeatures.test.ts +++ b/tests/advanced/wysiwygFeatures.test.ts @@ -1,7 +1,9 @@ // @vitest-environment jsdom import { Extension, type Editor } from '@tiptap/core' +import Image from '@tiptap/extension-image' import { TableKit } from '@tiptap/extension-table' +import { Markdown } from '@tiptap/markdown' import { afterEach, describe, expect, it, vi } from 'vitest' import { computed, reactive, ref } from 'vue' import { isSafeWysiwygUrl, sanitizeWysiwygAiHtml } from '../../src/advanced/wysiwyg/ai/sanitize' @@ -350,6 +352,38 @@ describe('source mode helpers', () => { expect(parseWysiwygSource('[]', 'json')).toMatchObject({ ok: false }) expect(parseWysiwygSource('{"type":"paragraph"}', 'json')).toMatchObject({ ok: false }) }) + + it('serializes and re-applies Markdown sources, images and tables included', () => { + const editor = createTestEditor('', [Markdown, Image, TableKit]) + editors.push(editor) + const source = [ + '## Title', + '', + 'Some **bold** text and a [link](https://example.com).', + '', + '- one', + '- two', + '', + '![Screenshot](https://example.com/shot.png)', + '', + '| A | B |', + '| --- | --- |', + '| 1 | 2 |', + ].join('\n') + + const parsed = parseWysiwygSource(source, 'markdown') + expect(parsed).toEqual({ ok: true, content: source }) + editor.commands.setContent(source, { contentType: 'markdown' }) + + expect(editor.getHTML()).toContain('

Title

') + expect(editor.getHTML()).toContain('src="https://example.com/shot.png"') + const markdown = serializeWysiwygSource(editor, 'markdown') + expect(markdown).toContain('## Title') + expect(markdown).toContain('**bold**') + expect(markdown).toContain('[link](https://example.com)') + expect(markdown).toContain('![Screenshot](https://example.com/shot.png)') + expect(markdown).toMatch(/\|\s*A\s*\|\s*B\s*\|/) + }) }) describe('AI output safety', () => { diff --git a/tests/advanced/wysiwygOptions.test.ts b/tests/advanced/wysiwygOptions.test.ts index 879cd94..847dc29 100644 --- a/tests/advanced/wysiwygOptions.test.ts +++ b/tests/advanced/wysiwygOptions.test.ts @@ -66,6 +66,9 @@ describe('resolveWysiwygOptions', () => { contentType: 'html', debounce: 300, }) + expect(resolveWysiwygOptions({ contentType: 'markdown' }, 'string').contentType).toBe( + 'markdown', + ) expect(resolveWysiwygOptions({ toolbar: false }, 'object').toolbar).toBe(false) }) diff --git a/yarn.lock b/yarn.lock index 3004e2d..873200a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1770,7 +1770,7 @@ resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.29.2.tgz#a2afe200c29f9355fa1a79c96fc73bef016bbbd2" integrity sha512-8/ZPzbB9X85Mc9/7xVLZupQKBr2UVcQTGr512xtqMW+XkCQRHCph46tRo828YE13IMWI5fWn/FaNCqXG9cULSw== -"@tiptap/extension-image@^3.27.3": +"@tiptap/extension-image@^3.27.3", "@tiptap/extension-image@^3.29.2": version "3.29.2" resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-3.29.2.tgz#3c2295362d24b7a6be4f5d2cdffefd2424fe0a0b" integrity sha512-F+S4iru247mNVZdkNwNDZHeb281DkjsBJinaOGsOyJTvXY+KU5Uq7vY1LQTn493dTfU48Z0yMBUXwJffCT92Mg== @@ -1862,7 +1862,7 @@ resolved "https://registry.yarnpkg.com/@tiptap/extensions/-/extensions-3.29.2.tgz#207c6ed79db1a5baec13f3fd8653b437fca2c8b6" integrity sha512-BCz+FCAChSYtUe4BFj97HEO+nSK+J7GxbJgZG4Hg7DT/gI+hRyeNndU8efiQAx3WGdzsFi3UxRpcF1tTQM7iMQ== -"@tiptap/markdown@^3.27.3": +"@tiptap/markdown@^3.27.3", "@tiptap/markdown@^3.29.2": version "3.29.2" resolved "https://registry.yarnpkg.com/@tiptap/markdown/-/markdown-3.29.2.tgz#4a5fe4fb796e6a3c03c59de2c5a2fb840d2489ac" integrity sha512-Knf9YqG3fxOyFuS3pe3eapDz0ya9eqPGzmyMSd5PuHNmR9/Ir6i5qk5+Md6bCPgDNjYskztNm7DoBXPfbXbO/w== From a4ad9482f130e43a494f327e3fd4be3b3a903f14 Mon Sep 17 00:00:00 2001 From: Tacx <12997062+tacxou@users.noreply.github.com> Date: Mon, 19 Oct 2026 10:16:03 +0200 Subject: [PATCH 2/3] fix(deps): require Nuxt UI 4.10 as peer dependency The rating control imports UInputRating, which first shipped in Nuxt UI 4.10.0: hosts on 4.8 or 4.9 satisfied the declared ^4.8 range but failed to build. Align the peer and development ranges on ^4.10. --- CHANGELOG.md | 5 +++++ changelog/2.1.0.md | 5 +++++ package.json | 4 ++-- project-context.md | 2 +- yarn.lock | 2 +- 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffe5715..39b70e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,11 @@ versioning follows [SemVer](https://semver.org/). Markdown extension; source mode edits the raw Markdown and the builder inspector offers the Markdown format (`string` schema). +### 🐛 Fixes + +- The `@nuxt/ui` peer dependency now requires `^4.10`: the rating control imports `UInputRating`, + which first shipped in Nuxt UI 4.10.0, so hosts on 4.8 or 4.9 failed to build. + ### 📝 Documentation - WYSIWYG & AI guide, Markdown storage options and playground example (FR/EN). diff --git a/changelog/2.1.0.md b/changelog/2.1.0.md index ae032ab..c0817a8 100644 --- a/changelog/2.1.0.md +++ b/changelog/2.1.0.md @@ -17,6 +17,11 @@ prerelease: false Markdown extension; source mode edits the raw Markdown and the builder inspector offers the Markdown format (`string` schema). +### 🐛 Fixes + +- The `@nuxt/ui` peer dependency now requires `^4.10`: the rating control imports `UInputRating`, + which first shipped in Nuxt UI 4.10.0, so hosts on 4.8 or 4.9 failed to build. + ### 📝 Documentation - WYSIWYG & AI guide, Markdown storage options and playground example (FR/EN). diff --git a/package.json b/package.json index e1a54fe..987003c 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "@iconify-json/lucide": "^1.2.111", "@jsonforms/core": "^3.6.0", "@jsonforms/vue": "^3.6.0", - "@nuxt/ui": "^4.8.1", + "@nuxt/ui": "^4.10.0", "@tiptap/extension-image": "^3.29.2", "@tiptap/markdown": "^3.29.2", "@types/express": "^5.0.6", @@ -120,7 +120,7 @@ "peerDependencies": { "@jsonforms/core": "^3.6", "@jsonforms/vue": "^3.6", - "@nuxt/ui": "^4.8", + "@nuxt/ui": "^4.10", "typescript": "^5", "vue": "^3.5" }, diff --git a/project-context.md b/project-context.md index 747a9e5..aad3804 100644 --- a/project-context.md +++ b/project-context.md @@ -25,7 +25,7 @@ Termes canoniques du mĂ©tier, un par entrĂ©e, affĂ»tĂ©s par le skill ## DĂ©veloppement -- Runtime et versions : Node.js 22 ou supĂ©rieur ; TypeScript 5 ; Vue 3.5 ; JSON Forms 3.6 ; Nuxt UI 4.8. +- Runtime et versions : Node.js 22 ou supĂ©rieur ; TypeScript 5 ; Vue 3.5 ; JSON Forms 3.6 ; Nuxt UI 4.10. - Package manager : Yarn Classic 1.22.22, avec un lockfile Ă  la racine et un lockfile sĂ©parĂ© dans `mcp/`. - Commande d'installation : `yarn install --frozen-lockfile` ; pour le paquet MCP, `yarn --cwd mcp install --frozen-lockfile`. - Commande de dĂ©veloppement : `yarn start:dev` pour le playground sur le port 5174 ; `yarn docs:dev` pour VitePress sur le port 5173. diff --git a/yarn.lock b/yarn.lock index 873200a..86448ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1181,7 +1181,7 @@ pkg-types "^2.3.1" std-env "^4.2.0" -"@nuxt/ui@^4.8.1": +"@nuxt/ui@^4.10.0": version "4.10.0" resolved "https://registry.yarnpkg.com/@nuxt/ui/-/ui-4.10.0.tgz#a18ccd40bf50a95e3e4b3902a6aa20aa8c82c596" integrity sha512-f6eFtHZ958XIVnbpGz7OeVRjuEXdmQWgNKWBppNlh/lP790KDi8IXTZ6lndJ72lpp7hC8Wo2BbSL9zo9fwywWQ== From c3e169650fbe9adf0122a30aba22714acadf1161 Mon Sep 17 00:00:00 2001 From: Tacx <12997062+tacxou@users.noreply.github.com> Date: Mon, 19 Oct 2026 16:18:58 +0200 Subject: [PATCH 3/3] chore(release): raise unpacked size budget to 3.5 MB The rich WYSIWYG editor and AI assistant take the library tarball from 2.59 MB (2.0.2) to 3.20 MB unpacked; the packed size stays under its 750 kB budget. --- scripts/package.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/package.mjs b/scripts/package.mjs index c49432b..a5c16e8 100644 --- a/scripts/package.mjs +++ b/scripts/package.mjs @@ -39,7 +39,7 @@ export const PACKAGE_SPECS = [ /(?:^|\/)\.env(?:\.|$)/, ], maximumPackedSize: 750_000, - maximumUnpackedSize: 3_000_000, + maximumUnpackedSize: 3_500_000, }, { directory: join(root, 'mcp'),