@pantoken/scaffold 1.6.2 → 1.7.1

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.
@@ -19,21 +19,24 @@ const SCAFFOLDS = {
19
19
  },
20
20
  "canvas-theme-editor": {
21
21
  ".gitignore": "node_modules\ndist\n",
22
- "README.md": "# {{projectName}}\n\nUpload-ready assets for Canvas LMS's **Theme Editor**, plus a local preview for authoring Rich\nContent Editor (RCE) page templates styled with\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## What's here\n\n- `theme.css` / `theme.js` — upload these two files under **Theme Editor → Advanced** in Canvas.\n They're built for the CDN provider/theme/mode you chose when scaffolding (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light by default) and include a loader for\n `@pantoken/interactions` (wires up component behaviors like modal, tooltip, and drilldown).\n- `index.html` / `src/main.ts` — a local, TinyMCE-based editor (`npm run dev`) that mirrors Canvas's\n RCE so you can author page templates against pantoken's classes before copying them into Canvas.\n The page itself is built with pantoken's `wrapper` layout: click **Edit theme** to open a tray\n with **Config** / **CSS** / **JS** tabs (CDN provider/theme/mode selects, and blank CSS/JS\n editors for custom overrides that get appended to `theme.css`/`theme.js`), and the **?** button\n for full instructions. Use the **Layouts** toolbar button to start from one of pantoken's bundled\n starter page layouts (course home, header, footer, about me, syllabus, hero, callout, two-column,\n rubric note, testimonial), sourced from\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\nThis opens a Vite dev server with:\n\n- An **editor** pane on top (TinyMCE, matching the version/config\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) itself uses — see below),\n styled live with the real CDN CSS for the chosen provider/theme/mode, so WYSIWYG editing looks\n like the page will once uploaded to Canvas. Use the **Layouts** button to load one of the bundled\n starter layouts (this replaces the whole document, after a confirm, rather than inserting at the\n cursor), the **Accessibility** button to check common image, heading, table, link, and list\n issues, and the **Source code** toggle to hand-edit the raw HTML in a syntax-highlighted\n (CodeMirror) view alongside the editor, with the preview pane updating live as you type — unlike\n TinyMCE's stock `code` plugin, which edits in a one-shot modal dialog with no live preview.\n Also enabled: **Image** (URL-only — the Upload tab is hidden, so images are always linked, never\n embedded as base64), **Fullscreen**, **Find and replace**, **Quickbars** (a contextual formatting\n toolbar on text selection, an insert toolbar for images/tables/media/placeholders, and an\n alignment/edit toolbar on selected images), **Word count** (status bar), **Autosave** (drafts\n persist to the browser's `localStorage`), and **Presets** (explicit named snapshots).\n- A **preview** pane underneath, showing the editor's content with the current CSS/JS tab's\n stylesheet/script applied plus CDN `<link>` tags or inlined styles for picker-inserted\n icon/component assets, wrapped to match Canvas's own content-area background and max width — a faithful \"what\n this will look like once uploaded to Canvas\" check, updated live as you type or edit the theme.\n Use the preview footer's pop-out button to move the live preview into its own fullscreen window\n while keeping only the editor in the original window. The popup's minimize button or browser\n close button returns the preview to its previous row, column, or fullscreen position.\n- The **Edit theme** tray's **Config** tab holds the CDN provider/theme/mode selects and\n **Download theme.css** / **Download theme.js** links; its **CSS**/**JS** tabs start blank —\n anything you add there is appended to the generated `theme.css`/`theme.js`, both in the live\n preview and in the downloaded files, so custom overrides survive Config select changes instead\n of being regenerated away.\n- **Download HTML** saves the current normalized Canvas RCE fragment as `index.html`. **Download\n package** saves `canvas-theme.zip`, containing that same `index.html` plus the current\n `theme.css` and `theme.js`, including anything added in the CSS and JS tabs.\n\n### Named presets\n\nThe TinyMCE **Presets** menu provides **Save**, **Save as...**, **Open...**, and **Delete...**. A\npreset captures the editor HTML together with the active theme, color scheme, light/adaptive mode,\nCDN provider, custom CSS, and custom JavaScript. Names are unique without regard to case; **Save\nas...** asks before replacing an existing name, and **Open...** asks before discarding changes made\nsince the last open or save. Deleting a preset does not clear the current working document.\n\nPresets and Autosave serve different purposes and use separate localStorage keys. Autosave remains\nshort-lived draft recovery; presets open only when selected and never replace an Autosave draft on\nreload. Both are local to this browser origin and are not uploaded or synchronized to Canvas.\nPrivate browsing, disabled storage, or storage quota limits can prevent a preset from being saved.\nPreset HTML, CSS, and JavaScript are trusted author input and are restored without sanitization.\n\n## Workflow\n\n1. Upload `theme.css` and `theme.js` to Canvas's Theme Editor (**Advanced → CSS / JavaScript**) so\n pantoken's classes are available on every page. Download them individually from **Edit theme**,\n or use **Download package** to get both files together with the page HTML.\n2. Run `npm run dev`, use **Layouts** to start from a bundled starter, and edit it like you\n would in Canvas's own RCE.\n3. Click **Copy HTML** and paste the result into a Canvas page's RCE (switch to the HTML editor\n view first), or use **Download HTML** to save the same fragment as `index.html`. Canvas sanitizes\n pasted HTML server-side — this scaffold doesn't attempt to replicate that, so always verify the\n pasted result in Canvas (see \"Notes on Canvas's RCE\" below).\n\nCopied HTML has one outer `<div data-pantoken-color=\"navy\">` wrapper. The color picker updates that\neditable attribute, and you can change it directly in the HTML source view to any supported color\nnamespace, such as `sea`. Keep the page content inside the wrapper so the uploaded `theme.css` can\nscope the selected color to that Canvas page.\n\nPick **Custom** to enter your own brand hex. The editor derives a full color scale from it, anchored\nat the step with the closest lightness, and writes that\nscale into the downloaded `theme.css`. A `theme.css` carries only one custom color, so every\n`data-pantoken-color=\"custom\"` wrapper on the account uses it.\n\nUse the **Placeholder image** button to insert a PNG from\n[`placehold.co`](https://placehold.co/) with custom dimensions, colors, visible text, and alt text.\nThe preview and the resulting Canvas page need network access to `https://placehold.co` to render\nthese images. The existing **Image** button remains available for other remote image URLs.\n\n### Class-aware editing commands\n\nThe editor enables `@pantoken/tinymce`'s content-classes plugin. Stock TinyMCE actions add the\nmatching pantoken classes to paragraphs, headings, inline links, images, alignment, lists, and\ntables. Existing classes are preserved, and repeated edits don't duplicate them. Placeholder and\nproduct-logo images also include `instui-img` directly.\n\nHosts that build their own Canvas-style toolbar can import `PANTOKEN_COMMANDS` from\n`@pantoken/tinymce` and pass those command names to their buttons. The aliases cover paragraph and\nH2-H6 formats, semantic `xs` through `xl` font sizes, inline formatting, colors, links, images,\nalignment, lists, and tables. Underline, arbitrary font/highlight colors, superscript, and\nsubscript retain TinyMCE's semantic elements or inline styles because pantoken doesn't define\nequivalent component modifiers.\n\n## Notes on Canvas's RCE\n\nThe Canvas Rich Content Editor runs TinyMCE and sanitizes submitted HTML on the server against an\nallowlist (`gems/canvas_sanitize` in canvas-lms, kept in sync with TinyMCE's own\n`valid_elements`/`extended_valid_elements`). What that allowlist means for templates built here:\n\n- `class`, `id`, `style`, `title`, `role`, and `aria-*` attributes are allowed on every element —\n pantoken's `class=\"instui-*\"` styling hooks (and inline `style`, e.g. for CSS anchor positioning)\n **do** survive being pasted and saved, contrary to older guidance in this file. `<script>` tags\n are always stripped.\n- **RCE-safe pantoken components**: static/display components — alert, view, heading, text, table,\n a button-as-`<a>` (not a real `<button>`), blockquote. Stick to semantic HTML pantoken already\n supports (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- **RCE-unsafe**: anything from `@pantoken/interactions`'s behavior set — modal, tooltip,\n drilldown, close-button, or any other component driven by the native `popover`/`popovertarget`/\n `command`/`commandfor` attributes. Those attributes aren't in Canvas's sanitizer allowlist, so\n the markup survives but the interactive behavior silently breaks the first time the page is\n saved in Canvas, even with `theme.js`'s `@pantoken/interactions` loader present. Real form\n elements (`input`, `form`, `button`, `select`, `textarea`, `label`) and inline `<svg>` are\n stripped outright — none of the bundled starter templates use them.\n\n`theme.js` loads `@pantoken/interactions` from the CDN, which runs in Canvas's global page scope —\nuseful for interactions on pages you build directly in Canvas's RCE with raw HTML edits, but (per\nabove) any `popover`/`command`-attribute-driven markup pasted from the RCE preview here won't stay\ninteractive once saved.\n\n### Canvas-specific plugins intentionally left out\n\nCanvas's own RCE also ships an accessibility checker\n([`tinymce-a11y-checker`](https://github.com/instructure/canvas-lms/tree/master/packages/canvas-rce/src/rce/plugins/tinymce-a11y-checker))\nand a LaTeX equation editor\n([`instructure_equation`](https://github.com/instructure/canvas-lms/tree/master/packages/canvas-rce/src/rce/plugins/instructure_equation)).\nThe Canvas implementations are not included here because they are deeply coupled to canvas-rce's\ninternals (React, roughly a dozen `@instructure/ui-*` packages, Redux, the mathlive/KaTeX math\neditor, and canvas-rce's own `Bridge` singleton). This scaffold does include pantoken's standalone,\nReact-free accessibility checker as the **Accessibility** toolbar button; it checks common image,\nheading, table, link, and list issues without depending on Canvas's RCE internals. Follow the linked\nsource if you need Canvas's full tray UI or equation editor.\n",
22
+ "README.md": "# {{projectName}}\n\nUpload-ready assets for Canvas LMS's **Theme Editor**, plus a local preview for authoring Rich\nContent Editor (RCE) page templates styled with\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## What's here\n\n- `theme.css` / `theme.js` — upload these two files under **Theme Editor → Advanced** in Canvas.\n They're built for the CDN provider/theme/mode you chose when scaffolding (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light by default) and include a loader for\n `@pantoken/interactions` (wires up component behaviors like modal, tooltip, and drilldown).\n- `index.html` / `src/main.ts` — a local, TinyMCE-based editor (`npm run dev`) that mirrors Canvas's\n RCE so you can author page templates against pantoken's classes before copying them into Canvas.\n The page itself is built with pantoken's `wrapper` layout: click **Edit theme** to open a tray\n with **Config** / **CSS** / **JS** tabs (CDN provider/theme/mode selects, and blank CSS/JS\n editors for custom overrides that get appended to `theme.css`/`theme.js`), and the **?** button\n for full instructions. Use the **Layouts** toolbar button to start from one of pantoken's bundled\n starter page layouts (course home, header, footer, about me, syllabus, hero, callout, two-column,\n rubric note, testimonial), sourced from\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\nThis opens a Vite dev server with:\n\n- An **editor** pane on top (TinyMCE, matching the version/config\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) itself uses — see below),\n styled live with the real CDN CSS for the chosen provider/theme/mode, so WYSIWYG editing looks\n like the page will once uploaded to Canvas. Use the **Layouts** button to load one of the bundled\n starter layouts (this replaces the whole document, after a confirm, rather than inserting at the\n cursor), the **Accessibility** button to check common image, heading, table, link, and list\n issues, and the **Source code** toggle to hand-edit the raw HTML in a syntax-highlighted\n (CodeMirror) view alongside the editor, with the preview pane updating live as you type — unlike\n TinyMCE's stock `code` plugin, which edits in a one-shot modal dialog with no live preview.\n Also enabled: **Image** (URL-only — the Upload tab is hidden, so images are always linked, never\n embedded as base64), **Fullscreen**, **Find and replace**, **Quickbars** (a contextual formatting\n toolbar on text selection, an insert toolbar for images/tables/media/placeholders, and an\n alignment/edit toolbar on selected images), **Word count** (status bar), **Autosave** (drafts\n persist to the browser's `localStorage`), and **Presets** (explicit named snapshots).\n- A **preview** pane underneath, showing the editor's content with the current CSS/JS tab's\n stylesheet/script applied plus CDN `<link>` tags or inlined styles for picker-inserted\n icon/component assets, wrapped to match Canvas's own content-area background and max width — a faithful \"what\n this will look like once uploaded to Canvas\" check, updated live as you type or edit the theme.\n Use the preview footer's pop-out button to move the live preview into its own fullscreen window\n while keeping only the editor in the original window. The popup's minimize button or browser\n close button returns the preview to its previous row, column, or fullscreen position.\n- The **Edit theme** tray's **Config** tab holds the CDN provider/theme/mode selects and\n **Download theme.css** / **Download theme.js** links; its **CSS**/**JS** tabs start blank —\n anything you add there is appended to the generated `theme.css`/`theme.js`, both in the live\n preview and in the downloaded files, so custom overrides survive Config select changes instead\n of being regenerated away.\n- **Download HTML** saves the current normalized Canvas RCE fragment as `index.html`. **Download\n package** saves `canvas-theme.zip`, containing that same `index.html` plus the current\n `theme.css` and `theme.js`, including anything added in the CSS and JS tabs.\n\n### Provider and behavior options\n\n**None** embeds component CSS in `theme.css`. **Inline** uses `@pantoken/inline-styles` to add\nelement styles to the editor HTML, including source view and copied/downloaded content. Switching\nback preserves component classes, structure, and edits while removing generated inline declarations.\nInline exports resolved, light-only element styles and real static glyph markup. It doesn't need\n`theme.css` or `theme.js`; the preview deliberately loads neither. Include dark mode and Include\ninteractions are turned off and disabled in Inline, with their prior choices restored when leaving\nit. Packaged glyphs become PNG images, and missing custom fonts use the declared system fallbacks.\nCanvas can still filter HTML, data images, and CSS properties, so verify the saved page there.\n\n**Include interactions** defaults on. Turning it off omits Pantoken's behavior JavaScript from the\npreview and downloads and hides new component insertions that require it. Existing content remains.\nThe list uses the CDN picker's tiers: no-JS and JS-enhancement components remain available; only\nJS-requirement components are hidden.\nThe switch does not disable the editor's controls, custom JavaScript, or native browser behavior.\nInline is an exception: its portable preview and downloads omit custom JavaScript too, while the\nJS tab's authored text is preserved for other providers. CSS overrides participate in conversion.\n\n### Named presets\n\nThe TinyMCE **Presets** menu provides **Save**, **Save as...**, **Open...**, and **Delete...**. A\npreset captures the editor HTML together with the active theme, color scheme, light/adaptive mode,\nCDN provider, custom CSS, and custom JavaScript. Names are unique without regard to case; **Save\nas...** asks before replacing an existing name, and **Open...** asks before discarding changes made\nsince the last open or save. Deleting a preset does not clear the current working document.\n\nPresets and Autosave serve different purposes and use separate localStorage keys. Autosave remains\nshort-lived draft recovery; presets open only when selected and never replace an Autosave draft on\nreload. Both are local to this browser origin and are not uploaded or synchronized to Canvas.\nPrivate browsing, disabled storage, or storage quota limits can prevent a preset from being saved.\nPreset HTML, CSS, and JavaScript are trusted author input and are restored without sanitization.\n\n## Workflow\n\n1. Upload `theme.css` and `theme.js` to Canvas's Theme Editor (**Advanced → CSS / JavaScript**) so\n pantoken's classes are available on every page. Download them individually from **Edit theme**,\n or use **Download package** to get both files together with the page HTML.\n2. Run `npm run dev`, use **Layouts** to start from a bundled starter, and edit it like you\n would in Canvas's own RCE.\n3. Click **Copy HTML** and paste the result into a Canvas page's RCE (switch to the HTML editor\n view first), or use **Download HTML** to save the same fragment as `index.html`. Canvas sanitizes\n pasted HTML server-side — this scaffold doesn't attempt to replicate that, so always verify the\n pasted result in Canvas (see \"Notes on Canvas's RCE\" below).\n\nCopied HTML has one outer `<div data-pantoken-color=\"navy\">` wrapper. The color picker updates that\neditable attribute, and you can change it directly in the HTML source view to any supported color\nnamespace, such as `sea`. Keep the page content inside the wrapper so the uploaded `theme.css` can\nscope the selected color to that Canvas page.\n\nPick **Custom** to enter your own brand hex. The editor derives a full color scale from it, anchored\nat the step with the closest lightness, and writes that\nscale into the downloaded `theme.css`. A `theme.css` carries only one custom color, so every\n`data-pantoken-color=\"custom\"` wrapper on the account uses it.\n\nUse the **Placeholder image** button to insert a PNG from\n[`placehold.co`](https://placehold.co/) with custom dimensions, colors, visible text, and alt text.\nThe preview and the resulting Canvas page need network access to `https://placehold.co` to render\nthese images. The existing **Image** button remains available for other remote image URLs.\n\n### Class-aware editing commands\n\nThe editor enables `@pantoken/tinymce`'s content-classes plugin. Stock TinyMCE actions add the\nmatching pantoken classes to paragraphs, headings, inline links, images, alignment, lists, and\ntables. Existing classes are preserved, and repeated edits don't duplicate them. Placeholder and\nproduct-logo images also include `instui-img` directly.\n\nHosts that build their own Canvas-style toolbar can import `PANTOKEN_COMMANDS` from\n`@pantoken/tinymce` and pass those command names to their buttons. The aliases cover paragraph and\nH2-H6 formats, semantic `xs` through `xl` font sizes, inline formatting, colors, links, images,\nalignment, lists, and tables. Underline, arbitrary font/highlight colors, superscript, and\nsubscript retain TinyMCE's semantic elements or inline styles because pantoken doesn't define\nequivalent component modifiers.\n\n## Notes on Canvas's RCE\n\nThe Canvas Rich Content Editor runs TinyMCE and sanitizes submitted HTML on the server against an\nallowlist (`gems/canvas_sanitize` in canvas-lms, kept in sync with TinyMCE's own\n`valid_elements`/`extended_valid_elements`). What that allowlist means for templates built here:\n\n- `class`, `id`, `style`, `title`, `role`, and `aria-*` attributes are allowed on every element —\n pantoken's `class=\"instui-*\"` styling hooks (and inline `style`, e.g. for CSS anchor positioning)\n **do** survive being pasted and saved, contrary to older guidance in this file. `<script>` tags\n are always stripped.\n- **RCE-safe pantoken components**: static/display components — alert, view, heading, text, table,\n a button-as-`<a>` (not a real `<button>`), blockquote. Stick to semantic HTML pantoken already\n supports (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- **RCE-unsafe**: anything from `@pantoken/interactions`'s behavior set — modal, tooltip,\n drilldown, close-button, or any other component driven by the native `popover`/`popovertarget`/\n `command`/`commandfor` attributes. Those attributes aren't in Canvas's sanitizer allowlist, so\n the markup survives but the interactive behavior silently breaks the first time the page is\n saved in Canvas, even with `theme.js`'s `@pantoken/interactions` loader present. Real form\n elements (`input`, `form`, `button`, `select`, `textarea`, `label`) and inline `<svg>` are\n stripped outright — none of the bundled starter templates use them.\n\n`theme.js` loads `@pantoken/interactions` from the CDN, which runs in Canvas's global page scope —\nuseful for interactions on pages you build directly in Canvas's RCE with raw HTML edits, but (per\nabove) any `popover`/`command`-attribute-driven markup pasted from the RCE preview here won't stay\ninteractive once saved.\n\n### Canvas-specific plugins intentionally left out\n\nCanvas's own RCE also ships an accessibility checker\n([`tinymce-a11y-checker`](https://github.com/instructure/canvas-lms/tree/master/packages/canvas-rce/src/rce/plugins/tinymce-a11y-checker))\nand a LaTeX equation editor\n([`instructure_equation`](https://github.com/instructure/canvas-lms/tree/master/packages/canvas-rce/src/rce/plugins/instructure_equation)).\nThe Canvas implementations are not included here because they are deeply coupled to canvas-rce's\ninternals (React, roughly a dozen `@instructure/ui-*` packages, Redux, the mathlive/KaTeX math\neditor, and canvas-rce's own `Bridge` singleton). This scaffold does include pantoken's standalone,\nReact-free accessibility checker as the **Accessibility** toolbar button; it checks common image,\nheading, table, link, and list issues without depending on Canvas's RCE internals. Follow the linked\nsource if you need Canvas's full tray UI or equation editor.\n",
23
23
  "index.html": "<!doctype html>\n<html lang=\"{{locale}}\" dir=\"{{dir}}\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <meta name=\"theme-color\" content=\"#f5f5f5\" />\n <meta name=\"color-scheme\" content=\"light dark\" />\n <meta name=\"application-name\" content=\"Canvas Theme Editor\" />\n <link rel=\"icon\" href=\"/icon.svg\" type=\"image/svg+xml\" data-pantoken-themed-icon />\n <link rel=\"manifest\" href=\"/manifest.webmanifest\" />\n <title>Canvas Theme Editor</title>\n </head>\n <body class=\"instui-display-flex\">\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/src/main.ts\"><\/script>\n </body>\n</html>\n",
24
- "package.json": "{\n \"name\": \"{{projectName}}\",\n \"version\": \"0.0.0\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"vite build\",\n \"preview\": \"vite preview\"\n },\n \"dependencies\": {\n \"@pantoken/canvas-theme-editor\": \"latest\",\n \"@pantoken/cdn\": \"latest\",\n \"@pantoken/components\": \"latest\",\n \"@pantoken/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/plugin-custom-components\": \"latest\",\n \"@pantoken/plugin-custom-icons\": \"latest\",\n \"@pantoken/plugin-custom-theme-colors\": \"latest\",\n \"@pantoken/plugin-layouts\": \"latest\",\n \"@pantoken/plugin-logos\": \"latest\",\n \"@pantoken/plugin-lucide-lab\": \"latest\",\n \"@pantoken/plugin-simple-icons\": \"latest\",\n \"@pantoken/tinymce\": \"latest\",\n \"@pantoken/tinymce-a11y\": \"latest\",\n \"@pantoken/tinymce-codemirror\": \"latest\",\n \"@pantoken/tinymce-placehold\": \"latest\",\n \"@pantoken/tinymce-save\": \"latest\",\n \"fflate\": \"catalog:\",\n \"lucide\": \"latest\"\n },\n \"devDependencies\": {\n \"@codemirror/lang-css\": \"catalog:\",\n \"@codemirror/lang-html\": \"catalog:\",\n \"@codemirror/lang-javascript\": \"catalog:\",\n \"codemirror\": \"catalog:\",\n \"tinymce\": \"catalog:\",\n \"tinymce-i18n\": \"26.9.21\",\n \"typescript\": \"^7.0.2\",\n \"vite\": \"^8.2.2\"\n },\n \"allowScripts\": {\n \"core-js\": true,\n \"fsevents\": true,\n \"ttf2woff2\": true\n },\n \"trustedDependencies\": [\n \"core-js\",\n \"fsevents\",\n \"ttf2woff2\"\n ]\n}\n",
24
+ "package.json": "{\n \"name\": \"{{projectName}}\",\n \"version\": \"0.0.0\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"vite build\",\n \"preview\": \"vite preview\"\n },\n \"dependencies\": {\n \"@pantoken/canvas-theme-editor\": \"latest\",\n \"@pantoken/cdn\": \"latest\",\n \"@pantoken/components\": \"latest\",\n \"@pantoken/css\": \"latest\",\n \"@pantoken/inline-styles\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/plugin-custom-components\": \"latest\",\n \"@pantoken/plugin-custom-icons\": \"latest\",\n \"@pantoken/plugin-custom-theme-colors\": \"latest\",\n \"@pantoken/plugin-layouts\": \"latest\",\n \"@pantoken/plugin-logos\": \"latest\",\n \"@pantoken/plugin-lucide-lab\": \"latest\",\n \"@pantoken/plugin-simple-icons\": \"latest\",\n \"@pantoken/tinymce\": \"latest\",\n \"@pantoken/tinymce-a11y\": \"latest\",\n \"@pantoken/tinymce-codemirror\": \"latest\",\n \"@pantoken/tinymce-placehold\": \"latest\",\n \"@pantoken/tinymce-save\": \"latest\",\n \"fflate\": \"catalog:\",\n \"lucide\": \"latest\"\n },\n \"devDependencies\": {\n \"@codemirror/lang-css\": \"catalog:\",\n \"@codemirror/lang-html\": \"catalog:\",\n \"@codemirror/lang-javascript\": \"catalog:\",\n \"codemirror\": \"catalog:\",\n \"tinymce\": \"catalog:\",\n \"tinymce-i18n\": \"26.9.21\",\n \"typescript\": \"^7.0.2\",\n \"vite\": \"^8.2.2\"\n },\n \"allowScripts\": {\n \"core-js\": true,\n \"fsevents\": true,\n \"ttf2woff2\": true\n },\n \"trustedDependencies\": [\n \"core-js\",\n \"fsevents\",\n \"ttf2woff2\"\n ]\n}\n",
25
25
  "pnpm-workspace.yaml": "# core-js/fsevents/ttf2woff2 arrive transitively; pre-approve their install scripts\n# so `pnpm install` doesn't fail/warn under pnpm's default strictDepBuilds gate.\nallowBuilds:\n core-js: true\n fsevents: true\n ttf2woff2: true\n# @pantoken/tokens pulls in a git-resolved upstream dependency several levels deep; pnpm's default\n# blockExoticSubdeps gate otherwise fails the install with ERR_PNPM_EXOTIC_SUBDEP.\nblockExoticSubdeps: false\n",
26
26
  "tsconfig.json": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"module\": \"ESNext\",\n \"moduleResolution\": \"Bundler\",\n \"types\": [\"vite/client\"],\n \"strict\": true,\n \"skipLibCheck\": true,\n \"noEmit\": true\n },\n \"include\": [\"src\"]\n}\n",
27
27
  "vite.config.ts": "import { defineConfig } from \"vite\";\n\nexport default defineConfig({});\n",
28
28
  "public/icon.svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 128 128\" role=\"img\" aria-label=\"Canvas Theme Editor icon\">\n <defs>\n <linearGradient id=\"g\" x1=\"0\" x2=\"1\" y1=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#1d4ed8\"/>\n <stop offset=\"100%\" stop-color=\"#0f172a\"/>\n </linearGradient>\n </defs>\n <rect width=\"128\" height=\"128\" rx=\"28\" fill=\"url(#g)\"/>\n <rect x=\"24\" y=\"28\" width=\"80\" height=\"16\" rx=\"7\" fill=\"#e2e8f0\" opacity=\"0.9\"/>\n <rect x=\"24\" y=\"56\" width=\"56\" height=\"14\" rx=\"7\" fill=\"#bfdbfe\" opacity=\"0.9\"/>\n <rect x=\"24\" y=\"80\" width=\"68\" height=\"14\" rx=\"7\" fill=\"#cbd5e1\" opacity=\"0.85\"/>\n <circle cx=\"92\" cy=\"90\" r=\"12\" fill=\"#f8fafc\" opacity=\"0.92\"/>\n <path d=\"M86 90l4 4 8-10\" fill=\"none\" stroke=\"#0f172a\" stroke-width=\"6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>\n",
29
29
  "public/manifest.webmanifest": "{\n \"name\": \"Canvas Theme Editor\",\n \"short_name\": \"Canvas Theme Editor\",\n \"description\": \"Create and preview Canvas Rich Content Editor themes and starter content.\",\n \"start_url\": \".\",\n \"scope\": \".\",\n \"display\": \"standalone\",\n \"background_color\": \"#f5f5f5\",\n \"theme_color\": \"#0d1b2a\",\n \"orientation\": \"portrait-primary\",\n \"lang\": \"en\",\n \"icons\": [\n {\n \"src\": \"/icon.svg\",\n \"sizes\": \"any\",\n \"type\": \"image/svg+xml\",\n \"purpose\": \"any\"\n }\n ]\n}\n",
30
- "src/app.css": "/* Layout for this scaffold's own authoring UI (not part of any Canvas-pasted RCE content). */\n\n:root {\n color-scheme: light dark;\n overflow-x: hidden;\n}\n\n:where(html) {\n background-color: light-dark(\n var(--instui-color-background-container),\n var(--instui-color-background-page)\n );\n}\n\n:where(body) {\n min-height: 100vh;\n margin: 0;\n background: light-dark(\n var(--instui-color-background-container),\n var(--instui-color-background-page)\n );\n color: var(--instui-color-text-base, inherit);\n}\n\nbody:not(.canvas-rce-shell-enabled) {\n padding: 1.5rem 3rem 3rem;\n}\n\n/* Overrides the scaffold-base wrapper layout's app-shell ROW class (side nav + content) — this\n shell is a top header, not a side nav, so the body needs to stack it above #app instead. */\n\nhtml:has(body.canvas-rce-shell-enabled) {\n background-color: var(--instui-color-background-page);\n}\n\nbody.canvas-rce-shell-enabled {\n display: flex;\n flex-direction: column;\n padding: 0;\n background-color: var(--instui-color-background-page);\n}\n\n#app {\n margin: 0 auto;\n width: 100%;\n}\n\nbody.canvas-rce-shell-enabled #app {\n padding: 1rem 3rem 3rem;\n}\n\n@media (max-width: 64em) {\n body.canvas-rce-shell-enabled #app {\n padding: 1rem 1.5rem 1.5rem;\n }\n}\n\n/* Redundant with the shell's own brand mark once it's showing. */\nbody.canvas-rce-shell-enabled .title,\nbody.canvas-rce-shell-enabled .description,\nbody.canvas-rce-shell-enabled #app-mode {\n display: none;\n}\n\n.canvas-rce-shell {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n padding: 0.75rem 1.5rem;\n border-block-end: 1px solid var(--instui-color-stroke-base, rgba(0, 0, 0, 0.12));\n background: color-mix(in srgb, var(--instui-color-background-container) 92%, transparent);\n backdrop-filter: blur(12px);\n position: relative;\n inset-block-start: 0;\n /* backdrop-filter makes this a stacking context, so the panel's z-index is capped at this one:\n it must clear the .controls tooltips (30/40) but stay below the fullscreen preview (100). */\n z-index: 50;\n}\n\n.canvas-rce-shell__brand {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n min-width: 0;\n}\n\n.canvas-rce-shell__brand-mark {\n flex-shrink: 0;\n}\n\n/* Navy primitives here are remapped to the chrome's active color; the glyph reads as a cutout. */\n.canvas-rce-shell__brand-mark.instui-button.-color-primary {\n background: light-dark(\n var(--instui-primitive-color-navy-navy100),\n var(--instui-primitive-color-navy-navy90)\n );\n border-color: light-dark(\n var(--instui-primitive-color-navy-navy100),\n var(--instui-primitive-color-navy-navy90)\n );\n color: light-dark(var(--instui-color-background-container), var(--instui-color-background-page));\n}\n\n.canvas-rce-shell__brand-mark.instui-button.-color-primary:hover {\n background: light-dark(\n var(--instui-primitive-color-navy-navy110),\n var(--instui-primitive-color-navy-navy80)\n );\n border-color: light-dark(\n var(--instui-primitive-color-navy-navy110),\n var(--instui-primitive-color-navy-navy80)\n );\n}\n\n.canvas-rce-shell__brand-mark.instui-button.-color-primary:active {\n background: light-dark(\n var(--instui-primitive-color-navy-navy120),\n var(--instui-primitive-color-navy-navy70)\n );\n border-color: light-dark(\n var(--instui-primitive-color-navy-navy120),\n var(--instui-primitive-color-navy-navy70)\n );\n}\n\n.canvas-rce-shell__eyebrow {\n display: block;\n font-size: 0.625rem;\n line-height: 1;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n opacity: 0.7;\n}\n\n.canvas-rce-shell__brand strong {\n display: block;\n font-size: 1rem;\n line-height: 1.2;\n}\n\n@media (max-width: 48em) {\n .canvas-rce-shell__brand strong {\n font-size: 0.8rem;\n }\n}\n\n.canvas-rce-shell__actions {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n}\n\n.canvas-rce-shell__menu {\n position: relative;\n}\n\n.canvas-rce-shell__menu summary {\n list-style: none;\n}\n\n.canvas-rce-shell__menu summary::-webkit-details-marker {\n display: none;\n}\n\n.canvas-rce-shell__summary .canvas-rce-shell__icon {\n width: 1rem;\n height: 1rem;\n}\n\n.canvas-rce-shell__label {\n white-space: nowrap;\n}\n\n.canvas-rce-shell__panel {\n position: absolute;\n inset-block-start: calc(100% + 0.5rem);\n inset-inline-end: 0;\n width: max-content;\n min-width: 12rem;\n max-width: calc(100vw - 2rem);\n overflow: hidden;\n border: 1px solid var(--instui-color-stroke-base, rgba(0, 0, 0, 0.12));\n border-radius: 0.75rem;\n background: light-dark(\n var(--instui-color-background-container),\n var(--instui-color-background-page)\n );\n box-shadow: 0 0.75rem 2rem rgba(0, 0, 0, 0.15);\n z-index: 60;\n}\n\n.canvas-rce-shell__panel-scroll {\n max-height: min(70vh, 24rem);\n display: grid;\n gap: 0.5rem;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 0.75rem;\n}\n\n.canvas-rce-shell__group {\n display: grid;\n gap: 0.375rem;\n}\n\n.canvas-rce-shell__group-title {\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n opacity: 0.7;\n}\n\n.canvas-rce-shell__option {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n width: 100%;\n white-space: nowrap;\n padding: 0.5rem 0.625rem;\n border: 1px solid transparent;\n border-radius: 0.5rem;\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n\n.canvas-rce-shell__option:hover,\n.canvas-rce-shell__option:focus-visible {\n border-color: var(--instui-color-stroke-base, rgba(0, 0, 0, 0.12));\n background: var(--instui-color-background-secondary, rgba(0, 0, 0, 0.02));\n}\n\n.canvas-rce-shell__option.is-selected {\n border-color: var(--instui-color-stroke-base, rgba(0, 0, 0, 0.12));\n background: var(--instui-color-background-secondary, rgba(0, 0, 0, 0.02));\n}\n\n.canvas-rce-shell__option .canvas-rce-shell__mark {\n width: 1rem;\n height: 1rem;\n opacity: 0;\n}\n\n.canvas-rce-shell__option.is-selected .canvas-rce-shell__mark {\n opacity: 1;\n}\n\n.theme-picker__custom.canvas-rce-shell__custom {\n max-width: none;\n padding: 0.25rem 0.625rem 0;\n}\n\n.wrapper {\n margin: var(--instui-spacing-padding-container-lg) var(--instui-spacing-padding-container-lg);\n}\n\n.header {\n display: flex;\n flex-direction: column;\n}\n\n.utilities {\n display: flex;\n justify-content: flex-end;\n gap: var(--instui-component-shared-tokens-spacing-gap-buttons);\n}\n\n.controls .instui-tooltip,\n.preview-pane .instui-tooltip {\n z-index: 30;\n}\n\n.controls .instui-tooltip > .tip,\n.preview-pane .instui-tooltip > .tip {\n z-index: 40;\n}\n\n/* The open/close chevrons point at the tray's edge, so RTL needs the mirror-image glyph, not a flip. */\n:dir(rtl) .instui-button.-icon-panel-right-open {\n --pantoken-glyph: var(--instui-icon-panel-left-open);\n}\n\n:dir(rtl) .instui-button.-icon-panel-right-close {\n --pantoken-glyph: var(--instui-icon-panel-left-close);\n}\n\n.instui-tray .instui-tabs {\n position: relative;\n}\n\n.instui-tray .list {\n display: flex;\n gap: 0.5rem;\n padding-inline-end: var(--instui-component-base-button-small-height);\n}\n\n.theme-tray__close {\n position: absolute;\n inset-block-start: 0;\n inset-inline-end: 0;\n}\n\n.instui-tray .panel[hidden] {\n display: none;\n}\n\n.config-section {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n margin-block-end: 1rem;\n}\n\n.theme-picker {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.theme-picker__colors {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n gap: 0.25rem;\n max-width: 14rem;\n}\n\n.theme-picker__color-item {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n border-radius: 50%;\n border: 2px solid transparent;\n background: transparent;\n cursor: pointer;\n}\n\n.theme-picker__color-item[aria-checked=\"true\"] {\n border-color: currentcolor;\n}\n\n.theme-picker__swatch {\n width: 1rem;\n height: 1rem;\n border-radius: 50%;\n display: block;\n box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);\n}\n\n.theme-picker__swatch[data-swatch=\"navy\"] {\n background-color: var(--instui-primitive-color-navy-navy70);\n}\n\n.theme-picker__swatch[data-swatch=\"blue\"] {\n background-color: var(--instui-primitive-color-blue-blue70);\n}\n\n.theme-picker__swatch[data-swatch=\"green\"] {\n background-color: var(--instui-primitive-color-green-green70);\n}\n\n.theme-picker__swatch[data-swatch=\"red\"] {\n background-color: var(--instui-primitive-color-red-red70);\n}\n\n.theme-picker__swatch[data-swatch=\"orange\"] {\n background-color: var(--instui-primitive-color-orange-orange70);\n}\n\n.theme-picker__swatch[data-swatch=\"grey\"] {\n background-color: var(--instui-primitive-color-grey-grey70);\n}\n\n.theme-picker__swatch[data-swatch=\"plum\"] {\n background-color: var(--instui-primitive-color-plum-plum70);\n}\n\n.theme-picker__swatch[data-swatch=\"violet\"] {\n background-color: var(--instui-primitive-color-violet-violet70);\n}\n\n.theme-picker__swatch[data-swatch=\"stone\"] {\n background-color: var(--instui-primitive-color-stone-stone70);\n}\n\n.theme-picker__swatch[data-swatch=\"sky\"] {\n background-color: var(--instui-primitive-color-sky-sky70);\n}\n\n.theme-picker__swatch[data-swatch=\"honey\"] {\n background-color: var(--instui-primitive-color-honey-honey70);\n}\n\n.theme-picker__swatch[data-swatch=\"sea\"] {\n background-color: var(--instui-primitive-color-sea-sea70);\n}\n\n.theme-picker__swatch[data-swatch=\"aurora\"] {\n background-color: var(--instui-primitive-color-aurora-aurora70);\n}\n\n/* A rainbow ring sets Custom apart from the palettes; the center shows the picked hex, if any. */\n.theme-picker__swatch[data-swatch=\"custom\"] {\n background:\n radial-gradient(closest-side, var(--custom-swatch-fill, Canvas) 55%, transparent 60%),\n conic-gradient(red, yellow, lime, cyan, blue, magenta, red);\n}\n\n.theme-picker__custom {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n max-width: 14rem;\n}\n\n.theme-picker__custom[hidden] {\n display: none;\n}\n\n.theme-picker__custom-inputs {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.theme-picker__custom-inputs input[type=\"color\"] {\n flex: none;\n inline-size: 2rem;\n block-size: 2rem;\n padding: 0;\n border: 0;\n background: none;\n cursor: pointer;\n}\n\n.code-editor {\n border: var(--instui-component-tray-border-width, 1px) solid\n var(--instui-component-tray-border-color, #ccc);\n min-height: 20rem;\n}\n\n.controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n}\n\n/* Named distinctly from the generic scaffold-base wrapper layout's `.container .content` — that\n shared selector otherwise wins on specificity and silently forces `flex-direction: row` here\n without ever setting `data-layout`, so the row-only sizing rules below never activate. */\n.panes {\n display: flex;\n flex-direction: column;\n gap: var(--instui-spacing-gap-cards-lg);\n}\n\n.pane {\n display: flex;\n flex-direction: column;\n}\n\n/* min-height (not height) so TinyMCE's own resize handle can grow the editor, not just shrink it.\n flex:0 1 auto so it stays content-sized in stacked layout — flex:1 1 0 here would give it a\n flex-basis of 0 with no free space to grow into (the column has no fixed height), capping how\n tall TinyMCE's own resize handle can make it. Row layout restores equal-width sharing below. */\n.editor-pane {\n flex: 0 1 auto;\n min-height: 25rem;\n min-width: 0;\n\n .tox.tox {\n border-width: var(--instui-border-width-sm);\n box-shadow: var(--instui-elevation-resting);\n border-color: var(--instui-component-view-border-color-secondary);\n border-radius: var(--instui-border-radius-container-md);\n background-color: var(--instui-color-background-container);\n\n .tox-edit-area.tox-edit-area::before {\n border: 2px solid var(--instui-focus-outline-color);\n border-radius: 0;\n }\n\n &:not(.tox-tinymce-inline) .tox-editor-header.tox-editor-header {\n box-shadow: none;\n border-bottom: 1px solid var(--instui-component-view-border-color-secondary);\n }\n\n &:is(\n :not(.tox-tinymce-inline) .tox-editor-header,\n .tox-toolbar-overlord,\n .tox-toolbar,\n .tox-toolbar__primary,\n .tox-toolbar__overflow\n ) {\n background-color: var(--instui-color-background-container);\n }\n\n .tox-statusbar {\n height: 33px;\n border-top: var(--instui-border-width-sm) solid\n var(--instui-component-view-border-color-secondary);\n }\n }\n}\n\n:root[data-pantoken-scheme=\"dark\"] {\n .editor-pane {\n .tox.tox {\n border: var(--instui-border-width-sm) solid\n var(--instui-component-view-border-color-secondary);\n\n .tox-edit-area.tox-edit-area::before {\n border: 2px solid var(--instui-focus-outline-color);\n border-radius: 0;\n }\n\n &:not(.tox-tinymce-inline) .tox-editor-header.tox-editor-header {\n box-shadow: none;\n border-bottom: 1px solid var(--instui-component-view-border-color-secondary);\n }\n\n .tox-statusbar {\n height: 33px;\n border-top: var(--instui-border-width-sm) solid\n var(--instui-component-view-border-color-secondary);\n }\n }\n }\n}\n\n/* The iframe reports its rendered content height to the host, so this pane stays content-sized in\n the stacked layout. The row rule below restores equal width sharing without stretching height. */\n.preview-pane {\n flex: 0 1 auto;\n align-items: center;\n gap: 0;\n min-width: 0;\n min-height: 0;\n border-width: var(--instui-border-width-sm);\n box-shadow: var(--instui-elevation-resting);\n border-color: var(--instui-component-view-border-color-secondary);\n border-radius: var(--instui-border-radius-container-md);\n background-color: var(--instui-color-background-container);\n border-style: solid;\n}\n\n.panes[data-layout=\"row\"] .editor-pane {\n flex: 1 1 0;\n}\n\n.panes[data-layout=\"row\"] .preview-pane {\n flex: 1 1 0;\n align-self: flex-start;\n}\n\n.preview-width-picker {\n display: flex;\n align-items: center;\n align-self: flex-start;\n gap: 0.125rem;\n}\n\n.preview-width-value {\n min-inline-size: 3ch;\n padding-inline: var(--instui-spacing-space2xs);\n text-align: end;\n font-variant-numeric: tabular-nums;\n}\n\n.preview-width-unit {\n color: var(--instui-color-text-secondary);\n font-size: var(--instui-font-size-small);\n}\n\n/* Overlays the current window/iframe viewport — not the OS-level Fullscreen API — matching\n TinyMCE's own fullscreen plugin. !important overrides the width picker's inline flex/width. */\n.preview-pane.-fullscreen {\n position: fixed !important;\n inset: 0 !important;\n z-index: 100;\n flex: initial !important;\n width: 100vw !important;\n height: 100vh !important;\n margin: 0 !important;\n padding: 0;\n background: light-dark(\n var(--instui-color-background-container),\n var(--instui-color-background-page)\n );\n overflow: hidden;\n border: 0 none;\n border-radius: 0;\n}\n\n/* The page behind the overlay keeps its full content height, so without this the document still\n scrolls under a pane that's pinned to the viewport. */\nhtml:has(.preview-pane.-fullscreen),\nhtml:has(.preview-pane.-fullscreen) body {\n overflow: hidden;\n}\n\n#editor,\n#css-editor,\n#js-editor {\n flex: 1 1 auto;\n min-height: 0;\n width: 100%;\n}\n\n/* Width is set inline (large/medium/small); height grows with content — see updatePreview(). */\n#preview {\n border: 0 none;\n overflow: hidden;\n width: 100%;\n margin-inline: auto;\n}\n\n/* Fullscreen swaps the content-height sizing (see resizePreviewFrame) for filling the pane, so long\n content scrolls inside the frame instead of growing a scrollbar on the overlay. */\n.preview-pane.-fullscreen #preview {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n border-radius: 0;\n}\n\n.preview-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n border-bottom: var(--instui-border-width-sm) solid\n var(--instui-component-view-border-color-secondary);\n width: 100%;\n padding: 0.5rem 1rem;\n}\n\n.preview-footer {\n display: flex;\n justify-content: flex-end;\n gap: 0.125rem;\n border-top: var(--instui-border-width-sm) solid\n var(--instui-component-view-border-color-secondary);\n width: 100%;\n padding: 0 0.25rem;\n}\n\nbody.preview-popup {\n min-height: 100vh;\n margin: 0;\n overflow: hidden;\n}\n\nbody.preview-popup #preview-popup-toggle {\n display: none;\n}\n",
31
- "src/app.html": "<div class=\"container\">\n <div class=\"header\">\n <div class=\"title\">\n <span class=\"instui-heading -level-h1\">{{pageTitle}}</span>\n </div>\n </div>\n <div class=\"description\">{{pageDescription}}</div>\n\n <div class=\"controls --my-lg\">\n <div class=\"control-group instui-button-set -color-primary\">\n <button\n type=\"button\"\n id=\"download-package\"\n class=\"instui-button instui-tooltip -icon-file-archive\"\n aria-label=\"{{downloadPackageLabel}}\"\n aria-describedby=\"download-package-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{downloadPackageLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"download-package-tip\" role=\"tooltip\"\n >{{downloadPackageLabel}}</span\n >\n </button>\n <button\n type=\"button\"\n id=\"download-html\"\n class=\"instui-button instui-tooltip -icon-download\"\n aria-label=\"{{downloadHtmlLabel}}\"\n aria-describedby=\"download-html-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{downloadHtmlLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"download-html-tip\" role=\"tooltip\"\n >{{downloadHtmlLabel}}</span\n >\n </button>\n <button\n type=\"button\"\n id=\"copy-html\"\n class=\"instui-button instui-tooltip -icon-copy\"\n aria-label=\"{{copyHtmlLabel}}\"\n aria-describedby=\"copy-html-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{copyHtmlLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"copy-html-tip\" role=\"tooltip\"\n >{{copyHtmlLabel}}</span\n >\n </button>\n </div>\n <div class=\"utilities\">\n <a\n href=\"/tools/canvas-rce/\"\n target=\"_blank\"\n id=\"app-mode\"\n class=\"instui-button instui-tooltip -color-secondary -icon-app-window-mac\"\n aria-describedby=\"app-mode-tip\"\n ><span class=\"instui-screen-reader-content\">{{appModeLabel}}</span\n ><span class=\"tip -placement-bottom\" id=\"app-mode-tip\" role=\"tooltip\"\n >{{appModeLabel}}</span\n ></a\n >\n <button\n type=\"button\"\n id=\"layout-direction-toggle\"\n class=\"instui-button instui-tooltip -color-secondary -icon-columns-2\"\n aria-pressed=\"false\"\n aria-label=\"{{layoutDirectionLabel}}\"\n aria-describedby=\"layout-direction-toggle-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{layoutDirectionLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"layout-direction-toggle-tip\" role=\"tooltip\"\n >{{layoutDirectionLabel}}</span\n >\n </button>\n <button\n class=\"instui-button instui-tooltip -color-secondary -icon-circle-question-mark\"\n type=\"button\"\n command=\"show-modal\"\n commandfor=\"help-modal\"\n aria-label=\"{{helpAriaLabel}}\"\n aria-describedby=\"help-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{helpAriaLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"help-tip\" role=\"tooltip\">{{helpAriaLabel}}</span>\n </button>\n <button\n class=\"instui-button instui-tooltip -color-secondary -icon-sliders-horizontal\"\n type=\"button\"\n popovertarget=\"theme-tray\"\n aria-label=\"{{editThemeLabel}}\"\n aria-describedby=\"edit-theme-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{editThemeLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"edit-theme-tip\" role=\"tooltip\"\n >{{editThemeLabel}}</span\n >\n </button>\n </div>\n </div>\n <div class=\"panes\">\n <div class=\"pane editor-pane\">\n <textarea id=\"editor\"><div data-pantoken-color=\"navy\"><p></p></div></textarea>\n </div>\n <div class=\"pane preview-pane\">\n <div class=\"preview-header\">\n <div class=\"preview-width-picker\" role=\"group\" aria-label=\"{{previewWidthGroupLabel}}\">\n <button\n type=\"button\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -toggle -icon-monitor -without-background -without-border\"\n aria-pressed=\"true\"\n aria-label=\"{{previewWidthLargeLabel}}\"\n aria-describedby=\"preview-width-large-tip\"\n data-preview-width=\"large\"\n >\n <span class=\"instui-screen-reader-content\">{{previewWidthLargeLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"preview-width-large-tip\" role=\"tooltip\"\n >{{previewWidthLargeLabel}}</span\n >\n </button>\n <button\n type=\"button\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -toggle -icon-tablet -without-background -without-border\"\n aria-pressed=\"false\"\n aria-label=\"{{previewWidthMediumLabel}}\"\n aria-describedby=\"preview-width-medium-tip\"\n data-preview-width=\"medium\"\n >\n <span class=\"instui-screen-reader-content\">{{previewWidthMediumLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"preview-width-medium-tip\" role=\"tooltip\"\n >{{previewWidthMediumLabel}}</span\n >\n </button>\n <button\n type=\"button\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -toggle -icon-smartphone -without-background -without-border\"\n aria-pressed=\"false\"\n aria-label=\"{{previewWidthSmallLabel}}\"\n aria-describedby=\"preview-width-small-tip\"\n data-preview-width=\"small\"\n >\n <span class=\"instui-screen-reader-content\">{{previewWidthSmallLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"preview-width-small-tip\" role=\"tooltip\"\n >{{previewWidthSmallLabel}}</span\n >\n </button>\n <span\n id=\"preview-width-value\"\n class=\"instui-in-place-edit preview-width-value\"\n contenteditable=\"true\"\n role=\"textbox\"\n aria-label=\"{{previewWidthValueLabel}}\"\n data-input-type=\"number\"\n >1</span\n >\n <span class=\"preview-width-unit\" aria-hidden=\"true\">px</span>\n </div>\n <button\n type=\"button\"\n id=\"preview-scheme-toggle\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -toggle -icon-moon -without-background -without-border\"\n aria-pressed=\"false\"\n aria-label=\"{{previewSchemeToggleLabel}}\"\n aria-describedby=\"preview-scheme-toggle-tip\"\n disabled\n >\n <span class=\"instui-screen-reader-content\">{{previewSchemeToggleLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"preview-scheme-toggle-tip\" role=\"tooltip\"\n >{{previewSchemeToggleLabel}}</span\n >\n </button>\n </div>\n <iframe id=\"preview\" title=\"{{previewFrameTitle}}\"></iframe>\n <div class=\"preview-footer\">\n <button\n type=\"button\"\n id=\"preview-popup-toggle\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -icon-app-window -without-background -without-border\"\n aria-label=\"{{previewPopupLabel}}\"\n aria-describedby=\"preview-popup-toggle-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{previewPopupLabel}}</span>\n <span class=\"tip\" id=\"preview-popup-toggle-tip\" role=\"tooltip\"\n >{{previewPopupLabel}}</span\n >\n <span id=\"preview-popup-title\" hidden>{{previewPopupTitle}}</span>\n <span id=\"preview-popup-blocked-message\" hidden>{{previewPopupBlockedMessage}}</span>\n </button>\n <button\n type=\"button\"\n id=\"preview-fullscreen-toggle\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -toggle -icon-maximize -without-background -without-border\"\n aria-pressed=\"false\"\n aria-label=\"{{previewFullscreenLabel}}\"\n aria-describedby=\"preview-fullscreen-toggle-tip\"\n >\n <span id=\"preview-fullscreen-label\" class=\"instui-screen-reader-content\"\n >{{previewFullscreenLabel}}</span\n >\n <span class=\"tip\" id=\"preview-fullscreen-toggle-tip\" role=\"tooltip\"\n >{{previewFullscreenLabel}}</span\n >\n <span id=\"preview-popup-return-label\" class=\"instui-screen-reader-content\" hidden\n >{{previewPopupReturnLabel}}</span\n >\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<div\n class=\"instui-tray -placement-end -size-md\"\n popover\n id=\"theme-tray\"\n aria-label=\"{{themeTrayAriaLabel}}\"\n>\n <div class=\"instui-tabs\">\n <div class=\"list\" role=\"tablist\" aria-label=\"{{themeTrayAriaLabel}}\">\n <button\n class=\"tab -selected\"\n role=\"tab\"\n aria-selected=\"true\"\n id=\"tab-config\"\n aria-controls=\"panel-config\"\n type=\"button\"\n >\n {{tabConfigLabel}}\n </button>\n <button\n class=\"tab\"\n role=\"tab\"\n aria-selected=\"false\"\n id=\"tab-css\"\n aria-controls=\"panel-css\"\n type=\"button\"\n >\n {{tabCssLabel}}\n </button>\n <button\n class=\"tab\"\n role=\"tab\"\n aria-selected=\"false\"\n id=\"tab-js\"\n aria-controls=\"panel-js\"\n type=\"button\"\n >\n {{tabJsLabel}}\n </button>\n </div>\n <button\n class=\"instui-close-button -size-sm theme-tray__close\"\n type=\"button\"\n popovertarget=\"theme-tray\"\n popovertargetaction=\"hide\"\n aria-label=\"{{closeLabel}}\"\n ></button>\n <div class=\"panel\" role=\"tabpanel\" id=\"panel-config\" aria-labelledby=\"tab-config\">\n <div class=\"config-section\">\n <span class=\"instui-heading -level-h3\">{{themeLabel}}</span>\n <div class=\"theme-picker\" role=\"group\" aria-label=\"{{themeLabel}}\">\n <button\n type=\"button\"\n class=\"instui-button -size-sm -color-secondary -toggle\"\n aria-pressed=\"true\"\n data-theme=\"rebrand\"\n >\n {{themeRebrandLabel}}\n </button>\n <button\n type=\"button\"\n class=\"instui-button -size-sm -color-secondary -toggle\"\n aria-pressed=\"false\"\n data-theme=\"canvas\"\n >\n {{themeCanvasLabel}}\n </button>\n <button\n type=\"button\"\n class=\"instui-button -size-sm -color-secondary -toggle\"\n aria-pressed=\"false\"\n data-theme=\"canvasHighContrast\"\n >\n {{themeCanvasHighContrastLabel}}\n </button>\n </div>\n <div class=\"theme-picker__colors\" role=\"group\" aria-label=\"{{colorLabel}}\">\n <button\n type=\"button\"\n class=\"theme-picker__color-item -selected\"\n role=\"menuitemradio\"\n aria-checked=\"true\"\n data-color=\"navy\"\n aria-label=\"{{colorNavyLabel}}\"\n title=\"{{colorNavyLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"navy\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"blue\"\n aria-label=\"{{colorBlueLabel}}\"\n title=\"{{colorBlueLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"blue\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"green\"\n aria-label=\"{{colorGreenLabel}}\"\n title=\"{{colorGreenLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"green\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"red\"\n aria-label=\"{{colorRedLabel}}\"\n title=\"{{colorRedLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"red\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"orange\"\n aria-label=\"{{colorOrangeLabel}}\"\n title=\"{{colorOrangeLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"orange\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"grey\"\n aria-label=\"{{colorGreyLabel}}\"\n title=\"{{colorGreyLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"grey\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"plum\"\n aria-label=\"{{colorPlumLabel}}\"\n title=\"{{colorPlumLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"plum\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"violet\"\n aria-label=\"{{colorVioletLabel}}\"\n title=\"{{colorVioletLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"violet\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"stone\"\n aria-label=\"{{colorStoneLabel}}\"\n title=\"{{colorStoneLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"stone\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"sky\"\n aria-label=\"{{colorSkyLabel}}\"\n title=\"{{colorSkyLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"sky\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"honey\"\n aria-label=\"{{colorHoneyLabel}}\"\n title=\"{{colorHoneyLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"honey\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"sea\"\n aria-label=\"{{colorSeaLabel}}\"\n title=\"{{colorSeaLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"sea\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"aurora\"\n aria-label=\"{{colorAuroraLabel}}\"\n title=\"{{colorAuroraLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"aurora\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"custom\"\n aria-label=\"{{colorCustomLabel}}\"\n title=\"{{colorCustomLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"custom\"></span>\n </button>\n </div>\n <div class=\"theme-picker__custom\" id=\"custom-color-row\" hidden>\n <label for=\"custom-color-hex\">{{customColorInputLabel}}</label>\n <div class=\"theme-picker__custom-inputs\">\n <input\n type=\"color\"\n id=\"custom-color-picker\"\n aria-label=\"{{customColorInputLabel}}\"\n value=\"#4c79aa\"\n />\n <input\n type=\"text\"\n class=\"instui-text-input -size-sm\"\n id=\"custom-color-hex\"\n value=\"#4c79aa\"\n pattern=\"#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\"\n maxlength=\"7\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n />\n </div>\n </div>\n <label class=\"instui-checkbox -variant-toggle\" id=\"include-dark-mode-row\">\n <input type=\"checkbox\" id=\"include-dark-mode\" />\n {{includeDarkModeLabel}}\n </label>\n </div>\n <div class=\"config-section\">\n <span class=\"instui-heading -level-h3\">{{cdnSectionLabel}}</span>\n <label for=\"cdn-provider\">\n {{cdnProviderLabel}}\n <select class=\"instui-simple-select\" id=\"cdn-provider\"></select>\n </label>\n </div>\n </div>\n <div class=\"panel\" role=\"tabpanel\" id=\"panel-css\" hidden aria-labelledby=\"tab-css\">\n <p>{{cssPanelHintLabel}}</p>\n <div id=\"css-editor\" class=\"code-editor\"></div>\n <p><a id=\"download-theme-css\" download=\"theme.css\">{{downloadCssLabel}}</a></p>\n </div>\n <div class=\"panel\" role=\"tabpanel\" id=\"panel-js\" hidden aria-labelledby=\"tab-js\">\n <p>{{jsPanelHintLabel}}</p>\n <div id=\"js-editor\" class=\"code-editor\"></div>\n <p><a id=\"download-theme-js\" download=\"theme.js\">{{downloadJsLabel}}</a></p>\n </div>\n </div>\n</div>\n<dialog class=\"instui-modal\" id=\"help-modal\" aria-labelledby=\"help-modal-title\">\n <div class=\"header\"><strong id=\"help-modal-title\">{{helpModalTitle}}</strong></div>\n <div class=\"body\">\n <p>{{helpModalBody1}}</p>\n <p>{{helpModalBody2}}</p>\n </div>\n <div class=\"footer\">\n <button class=\"instui-button\" type=\"button\" command=\"close\" commandfor=\"help-modal\">\n {{closeLabel}}\n </button>\n </div>\n</dialog>\n",
30
+ "src/app.css": "/* Layout for this scaffold's own authoring UI (not part of any Canvas-pasted RCE content). */\n\n:root {\n color-scheme: light dark;\n overflow-x: hidden;\n}\n\n#preview-scheme-toggle {\n margin-inline-start: auto;\n}\n\n:where(html) {\n background-color: light-dark(\n var(--instui-color-background-container),\n var(--instui-color-background-page)\n );\n}\n\n:where(body) {\n min-height: 100vh;\n margin: 0;\n background: light-dark(\n var(--instui-color-background-container),\n var(--instui-color-background-page)\n );\n color: var(--instui-color-text-base, inherit);\n}\n\nbody:not(.canvas-rce-shell-enabled) {\n padding: 1.5rem 3rem 3rem;\n}\n\n/* Overrides the scaffold-base wrapper layout's app-shell ROW class (side nav + content) — this\n shell is a top header, not a side nav, so the body needs to stack it above #app instead. */\n\nhtml:has(body.canvas-rce-shell-enabled) {\n background-color: var(--instui-color-background-page);\n}\n\nbody.canvas-rce-shell-enabled {\n display: flex;\n flex-direction: column;\n padding: 0;\n background-color: var(--instui-color-background-page);\n}\n\n#app {\n margin: 0 auto;\n width: 100%;\n}\n\nbody.canvas-rce-shell-enabled #app {\n padding: 1rem 3rem 3rem;\n}\n\n@media (max-width: 64em) {\n body.canvas-rce-shell-enabled #app {\n padding: 1rem 1.5rem 1.5rem;\n }\n}\n\n/* Redundant with the shell's own brand mark once it's showing. */\nbody.canvas-rce-shell-enabled .title,\nbody.canvas-rce-shell-enabled .description,\nbody.canvas-rce-shell-enabled #app-mode {\n display: none;\n}\n\n.canvas-rce-shell {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n padding: 0.75rem 1.5rem;\n border-block-end: 1px solid var(--instui-color-stroke-base, rgba(0, 0, 0, 0.12));\n background: color-mix(in srgb, var(--instui-color-background-container) 92%, transparent);\n backdrop-filter: blur(12px);\n position: relative;\n inset-block-start: 0;\n /* backdrop-filter makes this a stacking context, so the panel's z-index is capped at this one:\n it must clear the .controls tooltips (30/40) but stay below the fullscreen preview (100). */\n z-index: 50;\n}\n\n.canvas-rce-shell__brand {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n min-width: 0;\n}\n\n.canvas-rce-shell__brand-mark {\n flex-shrink: 0;\n}\n\n/* Navy primitives here are remapped to the chrome's active color; the glyph reads as a cutout. */\n.canvas-rce-shell__brand-mark.instui-button.-color-primary {\n background: light-dark(\n var(--instui-primitive-color-navy-navy100),\n var(--instui-primitive-color-navy-navy90)\n );\n border-color: light-dark(\n var(--instui-primitive-color-navy-navy100),\n var(--instui-primitive-color-navy-navy90)\n );\n color: light-dark(var(--instui-color-background-container), var(--instui-color-background-page));\n}\n\n.canvas-rce-shell__brand-mark.instui-button.-color-primary:hover {\n background: light-dark(\n var(--instui-primitive-color-navy-navy110),\n var(--instui-primitive-color-navy-navy80)\n );\n border-color: light-dark(\n var(--instui-primitive-color-navy-navy110),\n var(--instui-primitive-color-navy-navy80)\n );\n}\n\n.canvas-rce-shell__brand-mark.instui-button.-color-primary:active {\n background: light-dark(\n var(--instui-primitive-color-navy-navy120),\n var(--instui-primitive-color-navy-navy70)\n );\n border-color: light-dark(\n var(--instui-primitive-color-navy-navy120),\n var(--instui-primitive-color-navy-navy70)\n );\n}\n\n.canvas-rce-shell__eyebrow {\n display: block;\n font-size: 0.625rem;\n line-height: 1;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n opacity: 0.7;\n}\n\n.canvas-rce-shell__brand strong {\n display: block;\n font-size: 1rem;\n line-height: 1.2;\n}\n\n@media (max-width: 48em) {\n .canvas-rce-shell__brand strong {\n font-size: 0.8rem;\n }\n}\n\n.canvas-rce-shell__actions {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n}\n\n.canvas-rce-shell__menu {\n position: relative;\n}\n\n.canvas-rce-shell__menu summary {\n list-style: none;\n}\n\n.canvas-rce-shell__menu summary::-webkit-details-marker {\n display: none;\n}\n\n.canvas-rce-shell__summary .canvas-rce-shell__icon {\n width: 1rem;\n height: 1rem;\n}\n\n.canvas-rce-shell__label {\n white-space: nowrap;\n}\n\n.canvas-rce-shell__panel {\n position: absolute;\n inset-block-start: calc(100% + 0.5rem);\n inset-inline-end: 0;\n width: max-content;\n min-width: 12rem;\n max-width: calc(100vw - 2rem);\n overflow: hidden;\n border: 1px solid var(--instui-color-stroke-base, rgba(0, 0, 0, 0.12));\n border-radius: 0.75rem;\n background: light-dark(\n var(--instui-color-background-container),\n var(--instui-color-background-page)\n );\n box-shadow: 0 0.75rem 2rem rgba(0, 0, 0, 0.15);\n z-index: 60;\n}\n\n.canvas-rce-shell__panel-scroll {\n max-height: min(70vh, 24rem);\n display: grid;\n gap: 0.5rem;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 0.75rem;\n}\n\n.canvas-rce-shell__group {\n display: grid;\n gap: 0.375rem;\n}\n\n.canvas-rce-shell__group-title {\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n opacity: 0.7;\n}\n\n.canvas-rce-shell__option {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n width: 100%;\n white-space: nowrap;\n padding: 0.5rem 0.625rem;\n border: 1px solid transparent;\n border-radius: 0.5rem;\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n\n.canvas-rce-shell__option:hover,\n.canvas-rce-shell__option:focus-visible {\n border-color: var(--instui-color-stroke-base, rgba(0, 0, 0, 0.12));\n background: var(--instui-color-background-secondary, rgba(0, 0, 0, 0.02));\n}\n\n.canvas-rce-shell__option.is-selected {\n border-color: var(--instui-color-stroke-base, rgba(0, 0, 0, 0.12));\n background: var(--instui-color-background-secondary, rgba(0, 0, 0, 0.02));\n}\n\n.canvas-rce-shell__option .canvas-rce-shell__mark {\n width: 1rem;\n height: 1rem;\n opacity: 0;\n}\n\n.canvas-rce-shell__option.is-selected .canvas-rce-shell__mark {\n opacity: 1;\n}\n\n.theme-picker__custom.canvas-rce-shell__custom {\n max-width: none;\n padding: 0.25rem 0.625rem 0;\n}\n\n.wrapper {\n margin: var(--instui-spacing-padding-container-lg) var(--instui-spacing-padding-container-lg);\n}\n\n.header {\n display: flex;\n flex-direction: column;\n}\n\n.utilities {\n display: flex;\n justify-content: flex-end;\n gap: var(--instui-component-shared-tokens-spacing-gap-buttons);\n}\n\n.controls .instui-tooltip,\n.preview-pane .instui-tooltip {\n z-index: 30;\n}\n\n.controls .instui-tooltip > .tip,\n.preview-pane .instui-tooltip > .tip {\n z-index: 40;\n}\n\n/* The open/close chevrons point at the tray's edge, so RTL needs the mirror-image glyph, not a flip. */\n:dir(rtl) .instui-button.-icon-panel-right-open {\n --pantoken-glyph: var(--instui-icon-panel-left-open);\n}\n\n:dir(rtl) .instui-button.-icon-panel-right-close {\n --pantoken-glyph: var(--instui-icon-panel-left-close);\n}\n\n.instui-tray .instui-tabs {\n position: relative;\n}\n\n.instui-tray .list {\n display: flex;\n gap: 0.5rem;\n padding-inline-end: var(--instui-component-base-button-small-height);\n}\n\n.theme-tray__close {\n position: absolute;\n inset-block-start: 0;\n inset-inline-end: 0;\n}\n\n.instui-tray .panel[hidden] {\n display: none;\n}\n\n.config-section {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n margin-block-end: 1rem;\n}\n\n.theme-picker {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.theme-picker__colors {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n gap: 0.25rem;\n max-width: 14rem;\n}\n\n.theme-picker__color-item {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n border-radius: 50%;\n border: 2px solid transparent;\n background: transparent;\n cursor: pointer;\n}\n\n.theme-picker__color-item[aria-checked=\"true\"] {\n border-color: currentcolor;\n}\n\n.theme-picker__swatch {\n width: 1rem;\n height: 1rem;\n border-radius: 50%;\n display: block;\n box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);\n}\n\n.theme-picker__swatch[data-swatch=\"navy\"] {\n background-color: var(--instui-primitive-color-navy-navy70);\n}\n\n.theme-picker__swatch[data-swatch=\"blue\"] {\n background-color: var(--instui-primitive-color-blue-blue70);\n}\n\n.theme-picker__swatch[data-swatch=\"green\"] {\n background-color: var(--instui-primitive-color-green-green70);\n}\n\n.theme-picker__swatch[data-swatch=\"red\"] {\n background-color: var(--instui-primitive-color-red-red70);\n}\n\n.theme-picker__swatch[data-swatch=\"orange\"] {\n background-color: var(--instui-primitive-color-orange-orange70);\n}\n\n.theme-picker__swatch[data-swatch=\"grey\"] {\n background-color: var(--instui-primitive-color-grey-grey70);\n}\n\n.theme-picker__swatch[data-swatch=\"plum\"] {\n background-color: var(--instui-primitive-color-plum-plum70);\n}\n\n.theme-picker__swatch[data-swatch=\"violet\"] {\n background-color: var(--instui-primitive-color-violet-violet70);\n}\n\n.theme-picker__swatch[data-swatch=\"stone\"] {\n background-color: var(--instui-primitive-color-stone-stone70);\n}\n\n.theme-picker__swatch[data-swatch=\"sky\"] {\n background-color: var(--instui-primitive-color-sky-sky70);\n}\n\n.theme-picker__swatch[data-swatch=\"honey\"] {\n background-color: var(--instui-primitive-color-honey-honey70);\n}\n\n.theme-picker__swatch[data-swatch=\"sea\"] {\n background-color: var(--instui-primitive-color-sea-sea70);\n}\n\n.theme-picker__swatch[data-swatch=\"aurora\"] {\n background-color: var(--instui-primitive-color-aurora-aurora70);\n}\n\n/* A rainbow ring sets Custom apart from the palettes; the center shows the picked hex, if any. */\n.theme-picker__swatch[data-swatch=\"custom\"] {\n background:\n radial-gradient(closest-side, var(--custom-swatch-fill, Canvas) 55%, transparent 60%),\n conic-gradient(red, yellow, lime, cyan, blue, magenta, red);\n}\n\n.theme-picker__custom {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n max-width: 14rem;\n}\n\n.theme-picker__custom[hidden] {\n display: none;\n}\n\n.theme-picker__custom-inputs {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.theme-picker__custom-inputs input[type=\"color\"] {\n flex: none;\n inline-size: 2rem;\n block-size: 2rem;\n padding: 0;\n border: 0;\n background: none;\n cursor: pointer;\n}\n\n.code-editor {\n border: var(--instui-component-tray-border-width, 1px) solid\n var(--instui-component-tray-border-color, #ccc);\n min-height: 20rem;\n}\n\n.controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n}\n\n/* Named distinctly from the generic scaffold-base wrapper layout's `.container .content` — that\n shared selector otherwise wins on specificity and silently forces `flex-direction: row` here\n without ever setting `data-layout`, so the row-only sizing rules below never activate. */\n.panes {\n display: flex;\n flex-direction: column;\n gap: var(--instui-spacing-gap-cards-lg);\n}\n\n.pane {\n display: flex;\n flex-direction: column;\n}\n\n/* min-height (not height) so TinyMCE's own resize handle can grow the editor, not just shrink it.\n flex:0 1 auto so it stays content-sized in stacked layout — flex:1 1 0 here would give it a\n flex-basis of 0 with no free space to grow into (the column has no fixed height), capping how\n tall TinyMCE's own resize handle can make it. Row layout restores equal-width sharing below. */\n.editor-pane {\n flex: 0 1 auto;\n min-height: 25rem;\n min-width: 0;\n\n .tox.tox {\n border-width: var(--instui-border-width-sm);\n box-shadow: var(--instui-elevation-resting);\n border-color: var(--instui-component-view-border-color-secondary);\n border-radius: var(--instui-border-radius-container-md);\n background-color: var(--instui-color-background-container);\n\n .tox-edit-area.tox-edit-area::before {\n border: 2px solid var(--instui-focus-outline-color);\n border-radius: 0;\n }\n\n &:not(.tox-tinymce-inline) .tox-editor-header.tox-editor-header {\n box-shadow: none;\n border-bottom: 1px solid var(--instui-component-view-border-color-secondary);\n }\n\n &:is(\n :not(.tox-tinymce-inline) .tox-editor-header,\n .tox-toolbar-overlord,\n .tox-toolbar,\n .tox-toolbar__primary,\n .tox-toolbar__overflow\n ) {\n background-color: var(--instui-color-background-container);\n }\n\n .tox-statusbar {\n height: 33px;\n border-top: var(--instui-border-width-sm) solid\n var(--instui-component-view-border-color-secondary);\n }\n }\n}\n\n:root[data-pantoken-scheme=\"dark\"] {\n .editor-pane {\n .tox.tox {\n border: var(--instui-border-width-sm) solid\n var(--instui-component-view-border-color-secondary);\n\n .tox-edit-area.tox-edit-area::before {\n border: 2px solid var(--instui-focus-outline-color);\n border-radius: 0;\n }\n\n &:not(.tox-tinymce-inline) .tox-editor-header.tox-editor-header {\n box-shadow: none;\n border-bottom: 1px solid var(--instui-component-view-border-color-secondary);\n }\n\n .tox-statusbar {\n height: 33px;\n border-top: var(--instui-border-width-sm) solid\n var(--instui-component-view-border-color-secondary);\n }\n }\n }\n}\n\n/* The iframe reports its rendered content height to the host, so this pane stays content-sized in\n the stacked layout. The row rule below restores equal width sharing without stretching height. */\n.preview-pane {\n flex: 0 1 auto;\n align-items: center;\n gap: 0;\n min-width: 0;\n min-height: 0;\n border-width: var(--instui-border-width-sm);\n box-shadow: var(--instui-elevation-resting);\n border-color: var(--instui-component-view-border-color-secondary);\n border-radius: var(--instui-border-radius-container-md);\n background-color: var(--instui-color-background-container);\n border-style: solid;\n}\n\n.panes[data-layout=\"row\"] .editor-pane {\n flex: 1 1 0;\n}\n\n.panes[data-layout=\"row\"] .preview-pane {\n flex: 1 1 0;\n align-self: flex-start;\n}\n\n.preview-width-picker {\n display: flex;\n align-items: center;\n align-self: flex-start;\n gap: 0.125rem;\n}\n\n.preview-width-value {\n min-inline-size: 3ch;\n padding-inline: var(--instui-spacing-space2xs);\n text-align: end;\n font-variant-numeric: tabular-nums;\n}\n\n.preview-width-unit {\n color: var(--instui-color-text-secondary);\n font-size: var(--instui-font-size-small);\n}\n\n/* Overlays the current window/iframe viewport — not the OS-level Fullscreen API — matching\n TinyMCE's own fullscreen plugin. !important overrides the width picker's inline flex/width. */\n.preview-pane.-fullscreen {\n position: fixed !important;\n inset: 0 !important;\n z-index: 100;\n flex: initial !important;\n width: 100vw !important;\n height: 100vh !important;\n margin: 0 !important;\n padding: 0;\n background: light-dark(\n var(--instui-color-background-container),\n var(--instui-color-background-page)\n );\n overflow: hidden;\n border: 0 none;\n border-radius: 0;\n}\n\n/* The page behind the overlay keeps its full content height, so without this the document still\n scrolls under a pane that's pinned to the viewport. */\nhtml:has(.preview-pane.-fullscreen),\nhtml:has(.preview-pane.-fullscreen) body {\n overflow: hidden;\n}\n\n#editor,\n#css-editor,\n#js-editor {\n flex: 1 1 auto;\n min-height: 0;\n width: 100%;\n}\n\n/* Width is set inline (large/medium/small); height grows with content — see updatePreview(). */\n#preview {\n border: 0 none;\n overflow: hidden;\n width: 100%;\n margin-inline: auto;\n}\n\n/* Fullscreen swaps the content-height sizing (see resizePreviewFrame) for filling the pane, so long\n content scrolls inside the frame instead of growing a scrollbar on the overlay. */\n.preview-pane.-fullscreen #preview {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n border-radius: 0;\n}\n\n.preview-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n border-bottom: var(--instui-border-width-sm) solid\n var(--instui-component-view-border-color-secondary);\n width: 100%;\n padding: 0.5rem 1rem;\n}\n\n.preview-footer {\n display: flex;\n justify-content: flex-end;\n gap: 0.125rem;\n border-top: var(--instui-border-width-sm) solid\n var(--instui-component-view-border-color-secondary);\n width: 100%;\n padding: 0 0.25rem;\n}\n\nbody.preview-popup {\n min-height: 100vh;\n margin: 0;\n overflow: hidden;\n}\n\nbody.preview-popup #preview-popup-toggle {\n display: none;\n}\n",
31
+ "src/app.html": "<div class=\"container\">\n <div class=\"header\">\n <div class=\"title\">\n <span class=\"instui-heading -level-h1\">{{pageTitle}}</span>\n </div>\n </div>\n <div class=\"description\">{{pageDescription}}</div>\n\n <div class=\"controls --my-lg\">\n <div class=\"control-group instui-button-set -color-primary\">\n <button\n type=\"button\"\n id=\"download-package\"\n class=\"instui-button instui-tooltip -icon-file-archive\"\n aria-label=\"{{downloadPackageLabel}}\"\n aria-describedby=\"download-package-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{downloadPackageLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"download-package-tip\" role=\"tooltip\"\n >{{downloadPackageLabel}}</span\n >\n </button>\n <button\n type=\"button\"\n id=\"download-html\"\n class=\"instui-button instui-tooltip -icon-download\"\n aria-label=\"{{downloadHtmlLabel}}\"\n aria-describedby=\"download-html-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{downloadHtmlLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"download-html-tip\" role=\"tooltip\"\n >{{downloadHtmlLabel}}</span\n >\n </button>\n <button\n type=\"button\"\n id=\"copy-html\"\n class=\"instui-button instui-tooltip -icon-copy\"\n aria-label=\"{{copyHtmlLabel}}\"\n aria-describedby=\"copy-html-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{copyHtmlLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"copy-html-tip\" role=\"tooltip\"\n >{{copyHtmlLabel}}</span\n >\n </button>\n </div>\n <div class=\"utilities\">\n <a\n href=\"/tools/canvas-rce/\"\n target=\"_blank\"\n id=\"app-mode\"\n class=\"instui-button instui-tooltip -color-secondary -icon-app-window-mac\"\n aria-describedby=\"app-mode-tip\"\n ><span class=\"instui-screen-reader-content\">{{appModeLabel}}</span\n ><span class=\"tip -placement-bottom\" id=\"app-mode-tip\" role=\"tooltip\"\n >{{appModeLabel}}</span\n ></a\n >\n <button\n type=\"button\"\n id=\"layout-direction-toggle\"\n class=\"instui-button instui-tooltip -color-secondary -icon-columns-2\"\n aria-pressed=\"false\"\n aria-label=\"{{layoutDirectionLabel}}\"\n aria-describedby=\"layout-direction-toggle-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{layoutDirectionLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"layout-direction-toggle-tip\" role=\"tooltip\"\n >{{layoutDirectionLabel}}</span\n >\n </button>\n <button\n class=\"instui-button instui-tooltip -color-secondary -icon-circle-question-mark\"\n type=\"button\"\n command=\"show-modal\"\n commandfor=\"help-modal\"\n aria-label=\"{{helpAriaLabel}}\"\n aria-describedby=\"help-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{helpAriaLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"help-tip\" role=\"tooltip\">{{helpAriaLabel}}</span>\n </button>\n <button\n class=\"instui-button instui-tooltip -color-secondary -icon-sliders-horizontal\"\n type=\"button\"\n popovertarget=\"theme-tray\"\n aria-label=\"{{editThemeLabel}}\"\n aria-describedby=\"edit-theme-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{editThemeLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"edit-theme-tip\" role=\"tooltip\"\n >{{editThemeLabel}}</span\n >\n </button>\n </div>\n </div>\n <div class=\"panes\">\n <div class=\"pane editor-pane\">\n <textarea id=\"editor\"><div data-pantoken-color=\"navy\"><p></p></div></textarea>\n </div>\n <div class=\"pane preview-pane\">\n <div class=\"preview-header\">\n <div class=\"preview-width-picker\" role=\"group\" aria-label=\"{{previewWidthGroupLabel}}\">\n <button\n type=\"button\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -toggle -icon-monitor -without-background -without-border\"\n aria-pressed=\"true\"\n aria-label=\"{{previewWidthLargeLabel}}\"\n aria-describedby=\"preview-width-large-tip\"\n data-preview-width=\"large\"\n >\n <span class=\"instui-screen-reader-content\">{{previewWidthLargeLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"preview-width-large-tip\" role=\"tooltip\"\n >{{previewWidthLargeLabel}}</span\n >\n </button>\n <button\n type=\"button\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -toggle -icon-tablet -without-background -without-border\"\n aria-pressed=\"false\"\n aria-label=\"{{previewWidthMediumLabel}}\"\n aria-describedby=\"preview-width-medium-tip\"\n data-preview-width=\"medium\"\n >\n <span class=\"instui-screen-reader-content\">{{previewWidthMediumLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"preview-width-medium-tip\" role=\"tooltip\"\n >{{previewWidthMediumLabel}}</span\n >\n </button>\n <button\n type=\"button\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -toggle -icon-smartphone -without-background -without-border\"\n aria-pressed=\"false\"\n aria-label=\"{{previewWidthSmallLabel}}\"\n aria-describedby=\"preview-width-small-tip\"\n data-preview-width=\"small\"\n >\n <span class=\"instui-screen-reader-content\">{{previewWidthSmallLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"preview-width-small-tip\" role=\"tooltip\"\n >{{previewWidthSmallLabel}}</span\n >\n </button>\n <span\n id=\"preview-width-value\"\n class=\"instui-in-place-edit preview-width-value\"\n contenteditable=\"true\"\n role=\"textbox\"\n aria-label=\"{{previewWidthValueLabel}}\"\n data-input-type=\"number\"\n >1</span\n >\n <span class=\"preview-width-unit\" aria-hidden=\"true\">px</span>\n </div>\n <button\n type=\"button\"\n id=\"preview-scheme-toggle\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -toggle -icon-moon -without-background -without-border\"\n aria-pressed=\"false\"\n aria-label=\"{{previewSchemeToggleLabel}}\"\n aria-describedby=\"preview-scheme-toggle-tip\"\n disabled\n >\n <span class=\"instui-screen-reader-content\">{{previewSchemeToggleLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"preview-scheme-toggle-tip\" role=\"tooltip\"\n >{{previewSchemeToggleLabel}}</span\n >\n </button>\n <button\n type=\"button\"\n id=\"preview-reset\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -icon-rotate-ccw -without-background -without-border\"\n aria-label=\"{{previewResetLabel}}\"\n aria-describedby=\"preview-reset-tip\"\n disabled\n >\n <span class=\"instui-screen-reader-content\">{{previewResetLabel}}</span>\n <span class=\"tip -placement-bottom\" id=\"preview-reset-tip\" role=\"tooltip\"\n >{{previewResetLabel}}</span\n >\n </button>\n </div>\n <iframe id=\"preview\" title=\"{{previewFrameTitle}}\"></iframe>\n <div class=\"preview-footer\">\n <button\n type=\"button\"\n id=\"preview-popup-toggle\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -icon-app-window -without-background -without-border\"\n aria-label=\"{{previewPopupLabel}}\"\n aria-describedby=\"preview-popup-toggle-tip\"\n >\n <span class=\"instui-screen-reader-content\">{{previewPopupLabel}}</span>\n <span class=\"tip\" id=\"preview-popup-toggle-tip\" role=\"tooltip\"\n >{{previewPopupLabel}}</span\n >\n <span id=\"preview-popup-title\" hidden>{{previewPopupTitle}}</span>\n <span id=\"preview-popup-blocked-message\" hidden>{{previewPopupBlockedMessage}}</span>\n </button>\n <button\n type=\"button\"\n id=\"preview-fullscreen-toggle\"\n class=\"instui-button instui-tooltip -size-sm -color-tertiary -toggle -icon-maximize -without-background -without-border\"\n aria-pressed=\"false\"\n aria-label=\"{{previewFullscreenLabel}}\"\n aria-describedby=\"preview-fullscreen-toggle-tip\"\n >\n <span id=\"preview-fullscreen-label\" class=\"instui-screen-reader-content\"\n >{{previewFullscreenLabel}}</span\n >\n <span class=\"tip\" id=\"preview-fullscreen-toggle-tip\" role=\"tooltip\"\n >{{previewFullscreenLabel}}</span\n >\n <span id=\"preview-popup-return-label\" class=\"instui-screen-reader-content\" hidden\n >{{previewPopupReturnLabel}}</span\n >\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<div\n class=\"instui-tray -placement-end -size-md\"\n popover\n id=\"theme-tray\"\n aria-label=\"{{themeTrayAriaLabel}}\"\n>\n <div class=\"instui-tabs\">\n <div class=\"list\" role=\"tablist\" aria-label=\"{{themeTrayAriaLabel}}\">\n <button\n class=\"tab -selected\"\n role=\"tab\"\n aria-selected=\"true\"\n id=\"tab-config\"\n aria-controls=\"panel-config\"\n type=\"button\"\n >\n {{tabConfigLabel}}\n </button>\n <button\n class=\"tab\"\n role=\"tab\"\n aria-selected=\"false\"\n id=\"tab-css\"\n aria-controls=\"panel-css\"\n type=\"button\"\n >\n {{tabCssLabel}}\n </button>\n <button\n class=\"tab\"\n role=\"tab\"\n aria-selected=\"false\"\n id=\"tab-js\"\n aria-controls=\"panel-js\"\n type=\"button\"\n >\n {{tabJsLabel}}\n </button>\n </div>\n <button\n class=\"instui-close-button -size-sm theme-tray__close\"\n type=\"button\"\n popovertarget=\"theme-tray\"\n popovertargetaction=\"hide\"\n aria-label=\"{{closeLabel}}\"\n ></button>\n <div class=\"panel\" role=\"tabpanel\" id=\"panel-config\" aria-labelledby=\"tab-config\">\n <div class=\"config-section\">\n <span class=\"instui-heading -level-h3\">{{themeLabel}}</span>\n <div class=\"theme-picker\" role=\"group\" aria-label=\"{{themeLabel}}\">\n <button\n type=\"button\"\n class=\"instui-button -size-sm -color-secondary -toggle\"\n aria-pressed=\"true\"\n data-theme=\"rebrand\"\n >\n {{themeRebrandLabel}}\n </button>\n <button\n type=\"button\"\n class=\"instui-button -size-sm -color-secondary -toggle\"\n aria-pressed=\"false\"\n data-theme=\"canvas\"\n >\n {{themeCanvasLabel}}\n </button>\n <button\n type=\"button\"\n class=\"instui-button -size-sm -color-secondary -toggle\"\n aria-pressed=\"false\"\n data-theme=\"canvasHighContrast\"\n >\n {{themeCanvasHighContrastLabel}}\n </button>\n </div>\n <div class=\"theme-picker__colors\" role=\"group\" aria-label=\"{{colorLabel}}\">\n <button\n type=\"button\"\n class=\"theme-picker__color-item -selected\"\n role=\"menuitemradio\"\n aria-checked=\"true\"\n data-color=\"navy\"\n aria-label=\"{{colorNavyLabel}}\"\n title=\"{{colorNavyLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"navy\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"blue\"\n aria-label=\"{{colorBlueLabel}}\"\n title=\"{{colorBlueLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"blue\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"green\"\n aria-label=\"{{colorGreenLabel}}\"\n title=\"{{colorGreenLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"green\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"red\"\n aria-label=\"{{colorRedLabel}}\"\n title=\"{{colorRedLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"red\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"orange\"\n aria-label=\"{{colorOrangeLabel}}\"\n title=\"{{colorOrangeLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"orange\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"grey\"\n aria-label=\"{{colorGreyLabel}}\"\n title=\"{{colorGreyLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"grey\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"plum\"\n aria-label=\"{{colorPlumLabel}}\"\n title=\"{{colorPlumLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"plum\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"violet\"\n aria-label=\"{{colorVioletLabel}}\"\n title=\"{{colorVioletLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"violet\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"stone\"\n aria-label=\"{{colorStoneLabel}}\"\n title=\"{{colorStoneLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"stone\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"sky\"\n aria-label=\"{{colorSkyLabel}}\"\n title=\"{{colorSkyLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"sky\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"honey\"\n aria-label=\"{{colorHoneyLabel}}\"\n title=\"{{colorHoneyLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"honey\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"sea\"\n aria-label=\"{{colorSeaLabel}}\"\n title=\"{{colorSeaLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"sea\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"aurora\"\n aria-label=\"{{colorAuroraLabel}}\"\n title=\"{{colorAuroraLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"aurora\"></span>\n </button>\n <button\n type=\"button\"\n class=\"theme-picker__color-item\"\n role=\"menuitemradio\"\n aria-checked=\"false\"\n data-color=\"custom\"\n aria-label=\"{{colorCustomLabel}}\"\n title=\"{{colorCustomLabel}}\"\n >\n <span class=\"theme-picker__swatch\" data-swatch=\"custom\"></span>\n </button>\n </div>\n <div class=\"theme-picker__custom\" id=\"custom-color-row\" hidden>\n <label for=\"custom-color-hex\">{{customColorInputLabel}}</label>\n <div class=\"theme-picker__custom-inputs\">\n <input\n type=\"color\"\n id=\"custom-color-picker\"\n aria-label=\"{{customColorInputLabel}}\"\n value=\"#4c79aa\"\n />\n <input\n type=\"text\"\n class=\"instui-text-input -size-sm\"\n id=\"custom-color-hex\"\n value=\"#4c79aa\"\n pattern=\"#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\"\n maxlength=\"7\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n />\n </div>\n </div>\n <label class=\"instui-checkbox -variant-toggle\" id=\"include-dark-mode-row\">\n <input type=\"checkbox\" id=\"include-dark-mode\" />\n {{includeDarkModeLabel}}\n </label>\n <label class=\"instui-checkbox -variant-toggle\">\n <input type=\"checkbox\" id=\"include-interactions\" checked />\n {{includeInteractionsLabel}}\n </label>\n </div>\n <div class=\"config-section\">\n <span class=\"instui-heading -level-h3\">{{cdnSectionLabel}}</span>\n <label for=\"cdn-provider\">\n {{cdnProviderLabel}}\n <select class=\"instui-simple-select\" id=\"cdn-provider\"></select>\n </label>\n </div>\n </div>\n <div class=\"panel\" role=\"tabpanel\" id=\"panel-css\" hidden aria-labelledby=\"tab-css\">\n <p>{{cssPanelHintLabel}}</p>\n <div id=\"css-editor\" class=\"code-editor\"></div>\n <p>\n <a\n id=\"download-theme-css\"\n role=\"link\"\n aria-disabled=\"true\"\n tabindex=\"-1\"\n download=\"theme.css\"\n >{{downloadCssLabel}}</a\n >\n </p>\n </div>\n <div class=\"panel\" role=\"tabpanel\" id=\"panel-js\" hidden aria-labelledby=\"tab-js\">\n <p>{{jsPanelHintLabel}}</p>\n <div id=\"js-editor\" class=\"code-editor\"></div>\n <p>\n <a id=\"download-theme-js\" role=\"link\" aria-disabled=\"true\" tabindex=\"-1\" download=\"theme.js\"\n >{{downloadJsLabel}}</a\n >\n </p>\n </div>\n </div>\n</div>\n<dialog class=\"instui-modal\" id=\"help-modal\" aria-labelledby=\"help-modal-title\">\n <div class=\"header\"><strong id=\"help-modal-title\">{{helpModalTitle}}</strong></div>\n <div class=\"body\">\n <p>{{helpModalBody1}}</p>\n <p>{{helpModalBody2}}</p>\n </div>\n <div class=\"footer\">\n <button class=\"instui-button\" type=\"button\" command=\"close\" commandfor=\"help-modal\">\n {{closeLabel}}\n </button>\n </div>\n</dialog>\n",
32
+ "src/component-availability.ts": "interface ComponentEntry {\n name: string;\n}\n\ninterface Capability {\n name: string;\n type: string;\n}\n\n/** Match the CDN picker: css-only is none, both is enhancement, and js-only is requirement. */\nexport function componentNeedsInteractions(\n entry: ComponentEntry,\n capabilities: readonly Capability[],\n): boolean {\n return capabilities.some(\n (capability) => capability.name === entry.name && capability.type === \"js-only\",\n );\n}\n",
33
+ "src/inline-document.ts": "interface StyleSnapshot {\n authored: string;\n generated: string;\n}\n\nconst INLINE_ID = \"data-pantoken-inline-id\";\n\n/** Tracks generated declarations separately from authored HTML during provider changes. */\nexport class InlineDocument {\n private snapshots = new Map<string, StyleSnapshot>();\n private nextId = 0;\n\n /** Recover authored styles while preserving edits made to the rendered document. */\n canonical(html: string): string {\n const fragment = document.createElement(\"template\");\n fragment.innerHTML = html;\n for (const element of fragment.content.querySelectorAll(\"[data-pantoken-inline-generated]\"))\n element.remove();\n for (const element of fragment.content.querySelectorAll<HTMLElement>(`[${INLINE_ID}]`)) {\n const snapshot = this.snapshots.get(element.getAttribute(INLINE_ID)!);\n if (snapshot) {\n const authored = document.createElement(\"span\").style;\n const generated = document.createElement(\"span\").style;\n authored.cssText = snapshot.authored;\n generated.cssText = snapshot.generated;\n for (const property of Array.from(generated)) {\n if (\n element.style.getPropertyValue(property) !== generated.getPropertyValue(property) ||\n element.style.getPropertyPriority(property) !== generated.getPropertyPriority(property)\n )\n continue;\n if (authored.getPropertyValue(property)) {\n element.style.setProperty(\n property,\n authored.getPropertyValue(property),\n authored.getPropertyPriority(property),\n );\n } else element.style.removeProperty(property);\n }\n if (!element.style.cssText) element.removeAttribute(\"style\");\n element.removeAttribute(\"data-mce-style\");\n }\n element.removeAttribute(INLINE_ID);\n }\n return fragment.innerHTML;\n }\n\n /** Render canonical HTML using the shared inliner, recording only generated styles. */\n render(html: string, css: string, inline: (html: string, css: string) => string): string {\n const prepared = this.prepare(html);\n return this.capture(inline(prepared.html, css), prepared.snapshots);\n }\n\n /** Render a static browser snapshot without losing canonical authored styles or structure. */\n async renderAsync(\n html: string,\n css: string,\n inline: (html: string, css: string) => Promise<string>,\n ): Promise<string> {\n const prepared = this.prepare(html);\n return this.capture(await inline(prepared.html, css), prepared.snapshots);\n }\n\n private prepare(html: string): { html: string; snapshots: Map<string, StyleSnapshot> } {\n const fragment = document.createElement(\"template\");\n fragment.innerHTML = this.canonical(html);\n const snapshots = new Map(this.snapshots);\n for (const element of fragment.content.querySelectorAll<HTMLElement>(\"*\")) {\n const id = String(++this.nextId);\n element.setAttribute(INLINE_ID, id);\n snapshots.set(id, { authored: element.getAttribute(\"style\") ?? \"\", generated: \"\" });\n }\n return { html: fragment.innerHTML, snapshots };\n }\n\n private capture(html: string, snapshots: Map<string, StyleSnapshot>): string {\n const result = document.createElement(\"template\");\n result.innerHTML = html;\n for (const style of result.content.querySelectorAll(\"style\")) style.remove();\n for (const element of result.content.querySelectorAll<HTMLElement>(`[${INLINE_ID}]`)) {\n const snapshot = snapshots.get(element.getAttribute(INLINE_ID)!);\n if (snapshot) snapshot.generated = element.getAttribute(\"style\") ?? \"\";\n }\n this.snapshots = snapshots;\n return result.innerHTML;\n }\n\n /** Strip editor-only tracking attributes from copied or exported HTML. */\n export(html: string): string {\n const fragment = document.createElement(\"template\");\n fragment.innerHTML = html;\n for (const element of fragment.content.querySelectorAll(`[${INLINE_ID}]`))\n element.removeAttribute(INLINE_ID);\n for (const element of fragment.content.querySelectorAll(\"[data-pantoken-inline-generated]\"))\n element.removeAttribute(\"data-pantoken-inline-generated\");\n return fragment.innerHTML;\n }\n}\n",
32
34
  "src/locale.ts": "/** Resolve an editor locale without letting an embedded frame inherit standalone preferences. */\nexport function selectEditorLocale(\n embedded: boolean,\n queryLocale: string | null,\n storedLocale: string | null,\n initialLocale: string,\n supported: Record<string, \"ltr\" | \"rtl\">,\n): string {\n if (embedded) {\n return queryLocale && Object.hasOwn(supported, queryLocale) ? queryLocale : \"en\";\n }\n if (storedLocale && Object.hasOwn(supported, storedLocale)) return storedLocale;\n return Object.hasOwn(supported, initialLocale) ? initialLocale : \"en\";\n}\n",
33
- "src/main.ts": "// @ts-nocheck\n/**\n * Authors starter page templates against pantoken's classes: TinyMCE for editing (pinned/\n * configured to match instructure/canvas-lms's own RCE — see README), a custom \"Insert template\"\n * plugin for the bundled starters, and a live styled preview pane fed by the chosen CDN\n * provider/theme/mode. The page shell itself is built with pantoken (wrapper layout, tray, modal,\n * tabs) so this authoring tool dogfoods the same library it's previewing.\n */\nimport \"@pantoken/components/components.css\";\nimport \"@pantoken/components/utilities.css\";\nimport \"@pantoken/components/base.css\";\nimport \"@pantoken/components/icons/copy.css\";\nimport \"@pantoken/components/icons/app-window-mac.css\";\nimport \"@pantoken/components/icons/x.css\";\nimport \"@pantoken/components/icons/check.css\";\nimport \"@pantoken/components/icons/download.css\";\nimport \"@pantoken/components/icons/file-archive.css\";\nimport \"@pantoken/components/icons/sliders-horizontal.css\"; // app.html's -icon-sliders-horizontal button modifier\nimport \"@pantoken/components/icons/circle-question-mark.css\"; // app.html's -icon-circle-question-mark button modifier\nimport \"@pantoken/components/icons/rows-2.css\"; // app.html's layout-direction toggle, row state\nimport \"@pantoken/components/icons/columns-2.css\"; // app.html's layout-direction toggle, column state\nimport \"@pantoken/components/icons/monitor.css\"; // app.html's preview-width-picker, large\nimport \"@pantoken/components/icons/tablet.css\"; // app.html's preview-width-picker, medium\nimport \"@pantoken/components/icons/smartphone.css\"; // app.html's preview-width-picker, small\nimport \"@pantoken/components/icons/app-window.css\"; // app.html's preview popup button\nimport \"@pantoken/components/icons/maximize.css\"; // app.html's preview-fullscreen-toggle, off state\nimport \"@pantoken/components/icons/minimize.css\"; // app.html's preview-fullscreen-toggle, on state\nimport \"@pantoken/components/icons/moon.css\"; // app.html's preview-scheme-toggle, light state\nimport \"@pantoken/components/icons/sun.css\"; // app.html's preview-scheme-toggle, dark state\nimport adaptiveTokensCss from \"@pantoken/css/style.lean.css?inline\";\nimport rebrandLightTokensCss from \"@pantoken/css/style.rebrand.light.lean.css?inline\";\nimport canvasTokensCss from \"@pantoken/css/style.canvas.lean.css?inline\";\nimport canvasHighContrastTokensCss from \"@pantoken/css/style.canvas-high-contrast.lean.css?inline\";\nimport baseCss from \"@pantoken/components/base.css?inline\";\nimport componentIconsCss from \"@pantoken/components/component-icons.css?inline\";\nimport componentsCss from \"@pantoken/components/components.css?inline\";\nimport utilitiesCss from \"@pantoken/components/utilities.css?inline\";\nimport fontsCss from \"@pantoken/components/fonts.css?inline\";\nimport logoPainterCss from \"@pantoken/plugin-custom-components/logo.css?inline\";\nconst fontAssetUrls = import.meta.glob<string>(\n \"/node_modules/@pantoken/components/assets/fonts/**/*.woff2\",\n { eager: true, query: \"?url\", import: \"default\" },\n);\nconst localFontsCss = fontsCss.replace(/\\.\\.\\/assets\\/fonts\\/([^\"\\s)]+\\.woff2)/gu, (_, path: string) => {\n const url = fontAssetUrls[`/node_modules/@pantoken/components/assets/fonts/${path}`];\n if (!url) throw new Error(`Missing local font asset: ${path}`);\n return url;\n});\nimport localInteractionsJs from \"@pantoken/interactions/interactions.iife.js?raw\";\n// A resolved asset URL for a real <script> tag — a dynamic import() of a pure side-effect module\n// from a \"sideEffects\": false package can get tree-shaken out of a production bundle.\nimport interactionsIifeUrl from \"@pantoken/interactions/interactions.iife.js?url\";\n\nimport \"@pantoken/plugin-custom-components/custom-components.css\";\nimport \"@pantoken/plugin-layouts/layouts.css\";\nimport \"./app.css\";\nimport appHtml from \"./app.html?raw\";\nimport { STRINGS } from \"./strings.ts\";\nimport { LOCALE_STRINGS } from \"./locale-strings.ts\";\nimport { LOCALE_DIRS } from \"./locale-dirs.ts\";\nimport { TINYMCE_LOCALE_STRINGS } from \"./tinymce-locale-strings.ts\";\nimport { selectEditorLocale } from \"./locale.ts\";\nimport tinymce from \"tinymce\";\nimport \"tinymce/models/dom/model\";\nimport \"tinymce/themes/silver/theme\";\nimport \"tinymce/icons/default\";\nimport \"tinymce/plugins/image\";\nimport \"tinymce/plugins/link\";\nimport \"tinymce/plugins/lists\";\nimport \"tinymce/plugins/autosave\";\nimport \"tinymce/plugins/fullscreen\";\nimport \"tinymce/plugins/quickbars\";\nimport \"tinymce/plugins/searchreplace\";\nimport \"tinymce/plugins/wordcount\";\nimport \"tinymce/plugins/table\";\nimport \"tinymce/plugins/media\";\nimport \"tinymce/plugins/visualblocks\";\nimport nextGenSkinCss from \"@pantoken/tinymce/skins/next-gen/skin.css?inline\";\nimport nextGenContentCss from \"@pantoken/tinymce/skins/next-gen/content.css?inline\";\nimport canvasSkinCss from \"@pantoken/tinymce/skins/canvas/skin.css?inline\";\nimport canvasContentCss from \"@pantoken/tinymce/skins/canvas/content.css?inline\";\nimport canvasHighContrastSkinCss from \"@pantoken/tinymce/skins/canvas-high-contrast/skin.css?inline\";\nimport canvasHighContrastContentCss from \"@pantoken/tinymce/skins/canvas-high-contrast/content.css?inline\";\nimport {\n buildTheme,\n CDN_PROVIDERS,\n DEFAULT_CDN_PROVIDER_ID,\n defaultThemeCssAssets,\n type ThemeMode,\n type ThemeVariant,\n} from \"@pantoken/canvas-theme-editor\";\nimport { Check, ChevronDown, createElement, Languages, MoonStar, Palette, SunMedium } from \"lucide\";\n// Inlined (not CDN-fetched) so the live preview's color swap never depends on a network round trip.\nimport {\n COLOR_KEYS,\n CUSTOM_COLOR_KEY,\n customColorCss,\n customThemeColorsCss,\n isHexColor,\n parseHexColor,\n type PantokenColorNamespace,\n} from \"@pantoken/plugin-custom-theme-colors\";\nimport type { Editor } from \"tinymce\";\nimport { basicSetup, EditorView } from \"codemirror\";\nimport { css } from \"@codemirror/lang-css\";\nimport { html } from \"@codemirror/lang-html\";\nimport { javascript } from \"@codemirror/lang-javascript\";\nimport { strToU8, zipSync } from \"fflate\";\nimport { buildFileUrl, type CdnFile } from \"@pantoken/cdn\";\nimport {\n CONTENT_CLASSES_PLUGIN_NAME,\n createContentClassesPlugin,\n createFullscreenFooterPlugin,\n createPantokenPlugin,\n createSearchReplaceFooterPlugin,\n createSupSubPlugin,\n createVisualBlocksFooterPlugin,\n FULLSCREEN_FOOTER_PLUGIN_NAME,\n getIconCdnFile,\n getUsedIconCdnFiles,\n getLogoCdnFile,\n getUsedLogoCdnFiles,\n listComponents,\n listUtilities,\n loadAllIcons,\n logos,\n PANTOKEN_ICON,\n PANTOKEN_ICON_PACK_NAME,\n products,\n registerPantokenIconPack,\n retargetContentStylesheets,\n pantokenHtmlLinter,\n pantokenHtmlCompletion,\n SEARCHREPLACE_FOOTER_PLUGIN_NAME,\n SUP_SUB_PLUGIN_NAME,\n SUP_SUB_TOOLBAR_NAME,\n VISUALBLOCKS_FOOTER_PLUGIN_NAME,\n type TaggedIcon,\n} from \"@pantoken/tinymce\";\nimport {\n createSourceTogglePlugin,\n SOURCE_TOGGLE_PLUGIN_NAME,\n type SourceTogglePluginApi,\n} from \"@pantoken/tinymce-codemirror\";\nimport {\n buildPlaceholdImage,\n createPlaceholdPlugin,\n PLACEHOLD_PLUGIN_NAME,\n} from \"@pantoken/tinymce-placehold\";\nimport {\n A11Y_PLUGIN_NAME,\n createA11yPlugin,\n type A11yCheckConfig,\n type A11yColorScheme,\n} from \"@pantoken/tinymce-a11y\";\nimport {\n createSavePlugin,\n SAVE_PLUGIN_NAME,\n SAVE_TOOLBAR_NAME,\n slugifyExportName,\n type SavePluginApi,\n} from \"@pantoken/tinymce-save\";\nimport { loadPreferences, savePreferences } from \"./preferences.ts\";\n\n// Shared with the toolbar's source-view editor so both stay the same size.\nconst EDITOR_HEIGHT_PX = 400;\n// This app's pantoken instance, and the one it accepts theme messages from. Two pantoken instances\n// can share a page (this editor embedded in the docs site being the case that forced the issue), so\n// both sides tag their messages and ignore anything addressed elsewhere.\nconst EDITOR_INSTANCE = \"canvas-theme-editor\";\nconst HOST_INSTANCE = \"docs\";\n// Canvas's content area caps out at this width — the preview mirrors that constraint.\nconst CANVAS_CONTENT_MAX_WIDTH = \"59.25rem\";\n// All 13 `[data-pantoken-color=\"…\"]` color-remap rules, computed once — editable Canvas content,\n// the shell, and the preview can each own an independent color scope. `resetSelector`\n// pins the theme tray's own subtree (buttons, swatches) and the standalone shell's menus (its\n// color swatches) back to true colors, immune to whatever color the chrome currently has active —\n// the shell's brand mark stays outside it so it follows the chrome color. See\n// plugins/pantoken/custom-theme-colors.\nconst CUSTOM_THEME_COLORS_CSS = customThemeColorsCss(undefined, {\n selector: \"\",\n resetSelector: \"#theme-tray, #canvas-rce-shell .canvas-rce-shell__actions\",\n});\n// The scaffold's own chrome (toolbar, buttons outside the tray) mirrors the embedding docs page's\n// active theme and color — entirely independent of the preview and the tray, which drive their own\n// theme/color separately below. The color remaps follow this theme block in the cascade so a parent\n// color change overrides the theme's root token declarations.\nconst chromeThemeStyle = document.createElement(\"style\");\ndocument.head.append(chromeThemeStyle);\nconst customThemeColorsStyle = document.createElement(\"style\");\ncustomThemeColorsStyle.textContent = CUSTOM_THEME_COLORS_CSS;\ndocument.head.append(customThemeColorsStyle);\n// The chrome's own `custom` scale, independent of the tray's; empty unless the chrome is on custom.\nconst chromeCustomColorStyle = document.createElement(\"style\");\ndocument.head.append(chromeCustomColorStyle);\n// Seeded with navy100 so switching to Custom starts from the default brand color.\nconst DEFAULT_CUSTOM_COLOR = \"#4c79aa\";\nlet chromeCustomColor = DEFAULT_CUSTOM_COLOR;\nlet syncShellCustomColor: (() => void) | undefined;\n\n/** Fill the Custom swatch's center with a picked hex; the untouched default leaves it empty. */\nfunction syncCustomSwatch(swatch: HTMLElement, hex: string): void {\n if (hex === DEFAULT_CUSTOM_COLOR) swatch.style.removeProperty(\"--custom-swatch-fill\");\n else swatch.style.setProperty(\"--custom-swatch-fill\", hex);\n}\nconst preferences = loadPreferences();\nlet previewPopup: Window | null = null;\nlet previewPopupCloseTimer: number | undefined;\nlet previewPopupStylePairs: Array<{\n source: HTMLStyleElement;\n clone: HTMLStyleElement;\n}> = [];\nconst LOCAL_PROVIDER_ID = \"none\";\n// `import.meta.env.DEV` is baked in at build time, so it's `false` for any `vite build` output —\n// including docs' Canvas RCE preview, which is always built for production yet only ever served on\n// localhost. Fall back to a hostname check so a local, non-CDN preview is detected either way.\nconst isLocalPreview =\n import.meta.env.DEV || [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(window.location.hostname);\nconst LOCAL_COMPONENT_CSS = [\n baseCss,\n componentIconsCss,\n componentsCss,\n utilitiesCss,\n logoPainterCss,\n CUSTOM_THEME_COLORS_CSS,\n localFontsCss,\n].join(\"\\n\");\n// pantoken's token sheets express dark mode as `light-dark()`, which lightningcss (this bundle's\n// minifier) downlevels to two OS-preference-gated control variables — fine for theme.css (a real\n// Canvas page can't force a scheme anyway), but it means `color-scheme`/`data-pantoken-scheme`\n// alone can't force the *preview's* scheme against the visitor's own OS setting. This block\n// re-derives those two control variables from `data-pantoken-scheme` so the preview's light/dark\n// toggle actually overrides it. `--lightningcss-light`/`-dark` are lightningcss's fixed,\n// undocumented-but-stable names for this downlevel — see the vendored `--lightningcss-*` custom\n// properties in @pantoken/css's built output.\nconst PREVIEW_SCHEME_FORCE_CSS = `\n[data-pantoken-scheme=\"light\"] { --lightningcss-light: initial; --lightningcss-dark: ; }\n[data-pantoken-scheme=\"dark\"] { --lightningcss-light: ; --lightningcss-dark: initial; }\n`;\n\n/** Minimal `{{key}}` substitution — every key must exist in `strings`, values are inserted raw. */\nfunction render(template: string, strings: Record<string, string>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key: string) => strings[key] ?? match);\n}\n\nfunction syncPreviewPopupChrome(): void {\n if (!previewPopup || previewPopup.closed) return;\n const popupDocument = previewPopup.document;\n for (const { source, clone } of previewPopupStylePairs) clone.textContent = source.textContent;\n for (const attribute of [\n \"lang\",\n \"dir\",\n \"data-pantoken-instance\",\n \"data-pantoken-theme\",\n \"data-pantoken-scheme\",\n \"data-pantoken-color\",\n ]) {\n const value = document.documentElement.getAttribute(attribute);\n if (value === null) popupDocument.documentElement.removeAttribute(attribute);\n else popupDocument.documentElement.setAttribute(attribute, value);\n }\n popupDocument.documentElement.style.colorScheme = document.documentElement.style.colorScheme;\n}\n\nfunction createShellIcon(icon: Parameters<typeof createElement>[0]): SVGSVGElement {\n const svg = createElement(icon, { width: 16, height: 16, \"stroke-width\": 2 });\n svg.classList.add(\"canvas-rce-shell__icon\");\n return svg;\n}\n\nfunction syncBrowserMetadata(): void {\n const themeColorMeta =\n document.querySelector<HTMLMetaElement>('meta[name=\"theme-color\"]') ??\n document.createElement(\"meta\");\n themeColorMeta.name = \"theme-color\";\n const backgroundColor = getComputedStyle(document.documentElement).backgroundColor;\n if (backgroundColor) themeColorMeta.content = backgroundColor;\n if (!themeColorMeta.parentElement) document.head.append(themeColorMeta);\n\n const favicon = document.querySelector<HTMLLinkElement>(\n 'link[rel=\"icon\"][data-pantoken-themed-icon]',\n );\n if (!favicon) return;\n const accentColor = getComputedStyle(document.documentElement)\n .getPropertyValue(\"--instui-primitive-color-navy-navy100\")\n .trim();\n if (!accentColor) return;\n const mark = PANTOKEN_ICON.replace(\n \"<svg \",\n '<svg x=\"32\" y=\"32\" width=\"64\" height=\"64\" ',\n ).replaceAll(/fill=\"[^\"]+\"/gu, 'fill=\"#fff\"');\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 128 128\"><rect width=\"128\" height=\"128\" rx=\"24\" fill=\"${accentColor}\"/>${mark}</svg>`;\n favicon.href = `data:image/svg+xml,${encodeURIComponent(svg)}`;\n}\n\nfunction setupStandaloneAppShell(): void {\n if (window.self !== window.top || document.getElementById(\"canvas-rce-shell\")) return;\n\n document.body.classList.add(\"canvas-rce-shell-enabled\");\n document.title =\n document.querySelector<HTMLMetaElement>('meta[name=\"application-name\"]')?.content ||\n \"Canvas Theme Editor\";\n\n const shell = document.createElement(\"header\");\n shell.id = \"canvas-rce-shell\";\n shell.className = \"canvas-rce-shell\";\n\n const brand = document.createElement(\"div\");\n brand.className = \"canvas-rce-shell__brand\";\n\n const brandMark = document.createElement(\"a\");\n brandMark.className = \"instui-button -color-primary -shape-square canvas-rce-shell__brand-mark\";\n brandMark.href = \"https://pantoken.app/\";\n brandMark.target = \"_blank\";\n brandMark.rel = \"noopener noreferrer\";\n brandMark.setAttribute(\"aria-label\", \"Pantoken (opens pantoken.app in a new tab)\");\n brandMark.innerHTML = PANTOKEN_ICON;\n\n const brandText = document.createElement(\"div\");\n brandText.className = \"canvas-rce-shell__brand-text instui-hidden-max-sm\";\n const eyebrow = document.createElement(\"span\");\n eyebrow.className = \"canvas-rce-shell__eyebrow\";\n eyebrow.textContent = \"Pantoken\";\n const title = document.createElement(\"strong\");\n title.textContent = \"Canvas Theme Editor\";\n brandText.append(eyebrow, title);\n brand.append(brandMark, brandText);\n\n const actions = document.createElement(\"div\");\n actions.className = \"canvas-rce-shell__actions\";\n\n const localeMenu = document.createElement(\"details\");\n localeMenu.className = \"canvas-rce-shell__menu\";\n const localeSummary = document.createElement(\"summary\");\n localeSummary.className = \"canvas-rce-shell__summary instui-button -color-tertiary\";\n localeSummary.append(createShellIcon(Languages));\n const localeLabel = document.createElement(\"span\");\n localeLabel.className = \"canvas-rce-shell__label instui-hidden-max-md\";\n const localeLocale = (\n document.documentElement.lang || navigator.languages?.[0] || navigator.language || \"en-US\"\n ).trim();\n let localeText = \"English\";\n try {\n // Names itself, in its own script (matching the picker's own option labels below).\n localeText = new Intl.DisplayNames([localeLocale], { type: \"language\" }).of(localeLocale) ?? localeText;\n } catch {\n localeText = localeLocale.split(\"-\")[0].toUpperCase();\n }\n localeLabel.textContent = localeText;\n localeSummary.setAttribute(\"aria-label\", localeText);\n localeSummary.append(localeLabel, createShellIcon(ChevronDown));\n\n const localePanel = document.createElement(\"div\");\n localePanel.className = \"canvas-rce-shell__panel\";\n const localePanelScroll = document.createElement(\"div\");\n localePanelScroll.className = \"canvas-rce-shell__panel-scroll\";\n const availableLocales = [\"en\", ...Object.keys(LOCALE_STRINGS).sort()];\n const localeDisplayNames = new Intl.DisplayNames(availableLocales, { type: \"language\" });\n for (const locale of availableLocales) {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.className = \"canvas-rce-shell__option\";\n option.dataset.locale = locale;\n const optionLabel = document.createElement(\"span\");\n // Each locale names itself, in its own script — matching the summary's own display name.\n optionLabel.textContent =\n new Intl.DisplayNames([locale], { type: \"language\" }).of(locale) ??\n localeDisplayNames.of(locale) ??\n locale;\n const optionMark = document.createElement(\"span\");\n optionMark.className = \"canvas-rce-shell__mark\";\n optionMark.append(createShellIcon(Check));\n option.append(optionLabel, optionMark);\n if (document.documentElement.lang === locale || (!document.documentElement.lang && locale === \"en\")) {\n option.classList.add(\"is-selected\");\n }\n option.addEventListener(\"click\", () => {\n if (locale === document.documentElement.lang) {\n localeMenu.removeAttribute(\"open\");\n return;\n }\n try {\n localStorage.setItem(LOCALE_STORAGE_KEY, locale);\n } catch {\n // Private mode / storage disabled — the reload below still applies it for this load.\n }\n // The app's own strings are only ever resolved once, at the initial `render()` call — a\n // reload re-runs that with the newly persisted locale instead of trying to re-render (and\n // re-initialize TinyMCE, the popup, etc.) in place.\n window.location.reload();\n });\n localePanelScroll.append(option);\n }\n localePanel.append(localePanelScroll);\n localeMenu.append(localeSummary, localePanel);\n\n const themeMenu = document.createElement(\"details\");\n themeMenu.className = \"canvas-rce-shell__menu\";\n const themeSummary = document.createElement(\"summary\");\n themeSummary.className = \"canvas-rce-shell__summary instui-button -color-tertiary\";\n themeSummary.append(createShellIcon(Palette));\n const themeLabel = document.createElement(\"span\");\n themeLabel.className = \"canvas-rce-shell__label instui-hidden-max-md\";\n themeLabel.textContent = activeStrings.themeLabel;\n themeSummary.setAttribute(\"aria-label\", activeStrings.themeLabel);\n themeSummary.append(themeLabel, createShellIcon(ChevronDown));\n\n const themePanel = document.createElement(\"div\");\n themePanel.className = \"canvas-rce-shell__panel\";\n const themePanelScroll = document.createElement(\"div\");\n themePanelScroll.className = \"canvas-rce-shell__panel-scroll\";\n\n const appearanceGroup = document.createElement(\"div\");\n appearanceGroup.className = \"canvas-rce-shell__group\";\n const appearanceTitle = document.createElement(\"span\");\n appearanceTitle.className = \"canvas-rce-shell__group-title\";\n appearanceTitle.textContent = activeStrings.appearanceLabel;\n appearanceGroup.append(appearanceTitle);\n // Shared by the click handler below and the initial application at the end of this function.\n const applyAppearance = (appearance: \"light\" | \"dark\"): void => {\n document.body.dataset.appearanceMode = appearance;\n document.documentElement.style.colorScheme = appearance;\n document.documentElement.dataset.pantokenScheme = appearance;\n if (typeof applyChromeTheme === \"function\") {\n applyChromeTheme(selectedTheme ?? \"rebrand\", appearance);\n }\n for (const candidate of themePanel.querySelectorAll<HTMLButtonElement>(\"[data-appearance]\")) {\n candidate.classList.toggle(\"is-selected\", candidate.dataset.appearance === appearance);\n }\n };\n for (const [appearance, label, icon] of [\n [\"light\", activeStrings.appearanceLightLabel, SunMedium],\n [\"dark\", activeStrings.appearanceDarkLabel, MoonStar],\n ] as const) {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.className = \"canvas-rce-shell__option\";\n option.dataset.appearance = appearance;\n const text = document.createElement(\"span\");\n text.textContent = label;\n const mark = document.createElement(\"span\");\n mark.className = \"canvas-rce-shell__mark\";\n mark.append(createShellIcon(icon));\n option.append(text, mark);\n if (appearance === \"light\") option.classList.add(\"is-selected\");\n option.addEventListener(\"click\", () => {\n applyAppearance(appearance);\n // The editor content and the live preview both default to following the app's own\n // appearance — only guide mode (via `applyParentTheme`) did this before; tools mode's own\n // shell toggle left both stuck on their prior scheme until a tray/preview control changed.\n applyEditorTheme(activeEditor);\n syncPreviewSchemeToAppearance(appearance);\n void refreshAll();\n themeMenu.removeAttribute(\"open\");\n });\n appearanceGroup.append(option);\n }\n\n const colorGroup = document.createElement(\"div\");\n colorGroup.className = \"canvas-rce-shell__group\";\n const colorTitle = document.createElement(\"span\");\n colorTitle.className = \"canvas-rce-shell__group-title\";\n colorTitle.textContent = activeStrings.colorLabel;\n colorGroup.append(colorTitle);\n for (const color of [...COLOR_KEYS, CUSTOM_COLOR_KEY]) {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.className = \"canvas-rce-shell__option\";\n option.dataset.color = color;\n const swatch = document.createElement(\"span\");\n swatch.className = \"theme-picker__swatch\";\n swatch.dataset.swatch = color;\n const text = document.createElement(\"span\");\n const colorKey = `color${color.charAt(0).toUpperCase()}${color.slice(1)}Label`;\n text.textContent = activeStrings[colorKey] ?? color.charAt(0).toUpperCase() + color.slice(1);\n const mark = document.createElement(\"span\");\n mark.className = \"canvas-rce-shell__mark\";\n mark.append(createShellIcon(Check));\n option.append(swatch, text, mark);\n // \"navy\" is the app's actual default (see `selectedColor`/`applyChromeColor(\"navy\")` below) —\n // without this the picker showed no color as selected until the user picked one explicitly.\n if (color === \"navy\") option.classList.add(\"is-selected\");\n option.addEventListener(\"click\", () => {\n applyChromeColor(color);\n // Custom stays open so the hex field below is reachable.\n if (color !== CUSTOM_COLOR_KEY) themeMenu.removeAttribute(\"open\");\n });\n colorGroup.append(option);\n }\n\n const customRow = document.createElement(\"div\");\n customRow.className = \"theme-picker__custom canvas-rce-shell__custom\";\n customRow.hidden = true;\n const customLabel = document.createElement(\"label\");\n customLabel.htmlFor = \"canvas-rce-shell-custom-hex\";\n customLabel.textContent = activeStrings.customColorInputLabel;\n const customInputs = document.createElement(\"div\");\n customInputs.className = \"theme-picker__custom-inputs\";\n const customPicker = document.createElement(\"input\");\n customPicker.type = \"color\";\n customPicker.setAttribute(\"aria-label\", activeStrings.customColorInputLabel);\n const customHex = document.createElement(\"input\");\n customHex.type = \"text\";\n customHex.id = \"canvas-rce-shell-custom-hex\";\n customHex.className = \"instui-text-input -size-sm\";\n customHex.maxLength = 7;\n customHex.spellcheck = false;\n customHex.autocomplete = \"off\";\n customInputs.append(customPicker, customHex);\n customRow.append(customLabel, customInputs);\n colorGroup.append(customRow);\n\n const onShellCustomInput = (value: string): void => {\n const valid = isHexColor(value);\n customHex.classList.toggle(\"-invalid\", !valid);\n customHex.toggleAttribute(\"aria-invalid\", !valid);\n if (valid) applyChromeColor(CUSTOM_COLOR_KEY, value);\n };\n customPicker.addEventListener(\"input\", () => onShellCustomInput(customPicker.value));\n customHex.addEventListener(\"input\", () => onShellCustomInput(customHex.value));\n\n syncShellCustomColor = () => {\n const color = document.documentElement.dataset.pantokenColor;\n for (const candidate of themePanel.querySelectorAll<HTMLButtonElement>(\"[data-color]\")) {\n candidate.classList.toggle(\"is-selected\", candidate.dataset.color === color);\n }\n customRow.hidden = color !== CUSTOM_COLOR_KEY;\n customPicker.value = chromeCustomColor;\n if (!isHexColor(customHex.value) || parseHexColor(customHex.value) !== chromeCustomColor) {\n customHex.value = chromeCustomColor;\n }\n syncCustomSwatch(colorGroup.querySelector('[data-swatch=\"custom\"]')!, chromeCustomColor);\n };\n syncShellCustomColor();\n\n themePanelScroll.append(appearanceGroup, colorGroup);\n themePanel.append(themePanelScroll);\n themeMenu.append(themeSummary, themePanel);\n actions.append(localeMenu, themeMenu);\n shell.append(brand, actions);\n document.body.prepend(shell);\n\n // Native <details> doesn't close on its own for either of these — without this a click\n // elsewhere on the page, or Escape, leaves the panel open.\n const shellMenus = [localeMenu, themeMenu];\n document.addEventListener(\"click\", (event) => {\n for (const menu of shellMenus) {\n if (menu.open && !menu.contains(event.target as Node)) menu.removeAttribute(\"open\");\n }\n });\n document.addEventListener(\"keydown\", (event) => {\n if (event.key !== \"Escape\") return;\n for (const menu of shellMenus) {\n if (!menu.open) continue;\n menu.removeAttribute(\"open\");\n menu.querySelector<HTMLElement>(\"summary\")?.focus();\n }\n });\n\n applyAppearance(\"light\");\n}\n\n/** Persists the shell's own locale choice — never the authored content's own `lang`/`dir`. */\nconst LOCALE_STORAGE_KEY = \"pantoken-canvas-theme-editor-locale\";\nconst SESSION_DRAFT_KEY = \"pantoken-canvas-theme-editor-session-draft\";\n\n/** Reads the docs locale when embedded, otherwise the standalone shell's saved choice. */\nfunction loadLocale(): string {\n const embedded = window.self !== window.top;\n const queryLocale = embedded ? new URLSearchParams(window.location.search).get(\"locale\") : null;\n let storedLocale: string | null = null;\n try {\n if (!embedded) storedLocale = localStorage.getItem(LOCALE_STORAGE_KEY);\n } catch {\n // Storage can be disabled; the scaffold's initial HTML locale is still available.\n }\n return selectEditorLocale(\n embedded,\n queryLocale,\n storedLocale,\n document.documentElement.lang,\n LOCALE_DIRS,\n );\n}\n\nconst activeLocale = loadLocale();\nconst tinymceStrings = TINYMCE_LOCALE_STRINGS[activeLocale] ?? {};\nconst tinymceLanguages: Record<string, [string, () => Promise<unknown>]> = {\n ar: [\"ar\", () => import(\"tinymce-i18n/langs8/ar.js\")],\n hy: [\"hy\", () => import(\"tinymce-i18n/langs8/hy.js\")],\n ca: [\"ca\", () => import(\"tinymce-i18n/langs8/ca.js\")],\n da: [\"da\", () => import(\"tinymce-i18n/langs8/da.js\")],\n nl: [\"nl\", () => import(\"tinymce-i18n/langs8/nl.js\")],\n fi: [\"fi\", () => import(\"tinymce-i18n/langs8/fi.js\")],\n fr: [\"fr-FR\", () => import(\"tinymce-i18n/langs8/fr-FR.js\")],\n \"fr-CA\": [\"fr-FR\", () => import(\"tinymce-i18n/langs8/fr-FR.js\")],\n de: [\"de\", () => import(\"tinymce-i18n/langs8/de.js\")],\n el: [\"el\", () => import(\"tinymce-i18n/langs8/el.js\")],\n he: [\"he-IL\", () => import(\"tinymce-i18n/langs8/he-IL.js\")],\n hu: [\"hu-HU\", () => import(\"tinymce-i18n/langs8/hu-HU.js\")],\n is: [\"is-IS\", () => import(\"tinymce-i18n/langs8/is-IS.js\")],\n id: [\"id\", () => import(\"tinymce-i18n/langs8/id.js\")],\n it: [\"it\", () => import(\"tinymce-i18n/langs8/it.js\")],\n ja: [\"ja\", () => import(\"tinymce-i18n/langs8/ja.js\")],\n ko: [\"ko-KR\", () => import(\"tinymce-i18n/langs8/ko-KR.js\")],\n nb: [\"nb-NO\", () => import(\"tinymce-i18n/langs8/nb-NO.js\")],\n fa: [\"fa\", () => import(\"tinymce-i18n/langs8/fa.js\")],\n pl: [\"pl\", () => import(\"tinymce-i18n/langs8/pl.js\")],\n pt: [\"pt-PT\", () => import(\"tinymce-i18n/langs8/pt-PT.js\")],\n \"pt-BR\": [\"pt-BR\", () => import(\"tinymce-i18n/langs8/pt-BR.js\")],\n ru: [\"ru\", () => import(\"tinymce-i18n/langs8/ru.js\")],\n \"zh-Hans\": [\"zh-CN\", () => import(\"tinymce-i18n/langs8/zh-CN.js\")],\n sl: [\"sl-SI\", () => import(\"tinymce-i18n/langs8/sl-SI.js\")],\n es: [\"es\", () => import(\"tinymce-i18n/langs8/es.js\")],\n sv: [\"sv-SE\", () => import(\"tinymce-i18n/langs8/sv-SE.js\")],\n th: [\"th-TH\", () => import(\"tinymce-i18n/langs8/th-TH.js\")],\n \"zh-Hant\": [\"zh-TW\", () => import(\"tinymce-i18n/langs8/zh-TW.js\")],\n tr: [\"tr\", () => import(\"tinymce-i18n/langs8/tr.js\")],\n uk: [\"uk\", () => import(\"tinymce-i18n/langs8/uk.js\")],\n vi: [\"vi\", () => import(\"tinymce-i18n/langs8/vi.js\")],\n cy: [\"cy\", () => import(\"tinymce-i18n/langs8/cy.js\")],\n};\n// A missing key/locale in `LOCALE_STRINGS` falls back to English — see generate.ts's own comment.\nconst activeStrings: Record<string, string> = { ...STRINGS, ...LOCALE_STRINGS[activeLocale] };\ndocument.documentElement.lang = activeLocale;\ndocument.documentElement.dir = LOCALE_DIRS[activeLocale] ?? \"ltr\";\n\ndocument.querySelector<HTMLDivElement>(\"#app\")!.innerHTML = render(appHtml, activeStrings);\nconst interactionsScript = document.createElement(\"script\");\ninteractionsScript.src = interactionsIifeUrl;\ndocument.head.append(interactionsScript);\n\n// Shared CSS assets array — tracks stylesheets for dynamic injection and generated theme CSS.\nconst currentAssets: CdnFile[] = [];\nconst onMissingAsset = () => void refreshAll();\nlet availableIcons: TaggedIcon[] = [];\nconst inlineAssetContents = new Map<string, string>();\nlet refreshGeneration = 0;\n// Covers `plugin-logos`, the core component icons (both real dependencies for any scaffolded\n// project), and the icon packages `build-canvas-rce.ts` vendors into `node_modules` purely so this\n// docs-hosted preview's \"None (inline)\" provider doesn't have to hit a CDN for any glyph.\nconst localAssetUrls = import.meta.glob<string>(\n [\n \"/node_modules/@pantoken/components/dist/icons/*.css\",\n \"/node_modules/@pantoken/plugin-{logos,simple-icons,lucide-lab,custom-icons}/dist/**/*.css\",\n ],\n { eager: true, import: \"default\", query: \"?url\" },\n);\n\nfunction buildSelectedAssetUrl(file: CdnFile): string {\n if (providerSelect.value !== LOCAL_PROVIDER_ID) {\n return buildFileUrl(file, providerSelect.value);\n }\n const localUrl = localAssetUrls[`/node_modules/${file.package}/${file.path}`];\n return localUrl ?? buildFileUrl(file);\n}\n\nconst editorThemeCss: Record<\n ThemeVariant,\n { skin: string; content: string }\n> = {\n rebrand: { skin: nextGenSkinCss, content: nextGenContentCss },\n canvas: { skin: canvasSkinCss, content: canvasContentCss },\n canvasHighContrast: {\n skin: canvasHighContrastSkinCss,\n content: canvasHighContrastContentCss,\n },\n};\n\nconst editorSkinStyle = document.createElement(\"style\");\ndocument.head.append(editorSkinStyle);\nlet editorContentStyle: HTMLStyleElement | undefined;\n\nfunction isThemeColor(color: unknown): color is PantokenColorNamespace {\n return color === CUSTOM_COLOR_KEY || isShippedColor(color);\n}\n\n/** The docs host only ever offers the 13 shipped scales, so the chrome never takes `custom`. */\nfunction isShippedColor(color: unknown): color is (typeof COLOR_KEYS)[number] {\n return typeof color === \"string\" && (COLOR_KEYS as readonly string[]).includes(color);\n}\n\n/** Applies the selected static skin to TinyMCE's chrome and iframe document. */\nfunction applyEditorTheme(editor: Editor | undefined): void {\n const css = editorThemeCss[selectedTheme];\n editorSkinStyle.textContent = css.skin;\n\n if (!editor) return;\n const editorDocument = editor.getDoc();\n if (!editorContentStyle || editorContentStyle.ownerDocument !== editorDocument) {\n editorContentStyle?.remove();\n editorContentStyle = editorDocument.createElement(\"style\");\n editorDocument.head.append(editorContentStyle);\n }\n editorContentStyle.textContent = [css.content, PREVIEW_SCHEME_FORCE_CSS].join(\"\\n\");\n // The content CSS's dark rules key off this attribute on the iframe's own root, which doesn't\n // inherit it from the host document.\n editorDocument.documentElement.dataset.pantokenScheme =\n document.documentElement.dataset.pantokenScheme;\n}\n\n/** Temporarily overrides the editing iframe's scheme so the a11y checker can test contrast under\n * both light and dark; the next `applyEditorTheme` call restores the chrome-mirrored value. */\nfunction forceEditorColorScheme(scheme: A11yColorScheme): void {\n if (!activeEditor) return;\n activeEditor.getDoc().documentElement.dataset.pantokenScheme = scheme;\n}\n\nfunction getEditorColorScheme(): A11yColorScheme {\n return activeEditor?.getDoc().documentElement.dataset.pantokenScheme === \"dark\"\n ? \"dark\"\n : \"light\";\n}\n\n/** Only \"rebrand\" ships a dark scheme (`syncDarkModeAvailability` hides/disables the checkbox for\n * the others), so the a11y checker only ever tests both schemes for it. */\nconst a11yRuntimeConfig: A11yCheckConfig = {\n setColorScheme: forceEditorColorScheme,\n getColorScheme: getEditorColorScheme,\n get colorSchemes(): readonly A11yColorScheme[] {\n return selectedTheme === \"rebrand\" && includeDarkModeCheckbox.checked\n ? [\"light\", \"dark\"]\n : [\"light\"];\n },\n};\n\n/** Re-themes the chrome's token variant + light/dark scheme — the tray and shell are regular app\n * chrome and inherit this too; only the preview `srcdoc` has its own independent theme/scheme. */\nfunction applyChromeTheme(theme: ThemeVariant, mode: \"light\" | \"dark\"): void {\n const tokensCss =\n theme === \"canvas\"\n ? canvasTokensCss\n : theme === \"canvasHighContrast\"\n ? canvasHighContrastTokensCss\n : adaptiveTokensCss;\n // Without `PREVIEW_SCHEME_FORCE_CSS`, the chrome's own buttons/text stay pinned to the OS\n // `prefers-color-scheme` (see that constant's comment) even though `colorScheme` below is set\n // explicitly — only the native-CSS background rules that key off `color-scheme` directly would\n // follow the toggle, leaving everything else stuck on the OS default.\n chromeThemeStyle.textContent = [tokensCss, PREVIEW_SCHEME_FORCE_CSS].join(\"\\n\");\n // Pins `light-dark()` resolution to the docs page's explicit mode instead of the OS preference —\n // single-scheme themes (canvas/canvasHighContrast) only ever render light.\n const scheme = theme === \"rebrand\" ? mode : \"light\";\n document.documentElement.dataset.pantokenTheme = theme;\n document.documentElement.dataset.pantokenScheme = scheme;\n document.documentElement.style.colorScheme = scheme;\n syncBrowserMetadata();\n syncPreviewPopupChrome();\n}\n\n/** Re-colors the chrome only — the tray's `#theme-tray` reset scope keeps it (and the preview,\n * which reads `selectedColor` directly) immune to this. */\nfunction applyChromeColor(color: PantokenColorNamespace, customHex?: string): void {\n if (customHex !== undefined) chromeCustomColor = parseHexColor(customHex);\n chromeCustomColorStyle.textContent =\n color === CUSTOM_COLOR_KEY ? customColorCss(chromeCustomColor) : \"\";\n document.documentElement.dataset.pantokenColor = color;\n syncShellCustomColor?.();\n syncBrowserMetadata();\n syncPreviewPopupChrome();\n}\n\n/** A host color message: a shipped scale, or `custom` with a valid hex. */\nfunction applyHostColor(color: unknown, customHex: unknown): void {\n if (isShippedColor(color)) applyChromeColor(color);\n else if (color === CUSTOM_COLOR_KEY && isHexColor(customHex)) applyChromeColor(color, customHex);\n}\n\nfunction applyParentTheme(theme: ThemeVariant, mode: \"light\" | \"dark\"): void {\n selectedTheme = theme;\n // The docs page's own light/dark mode re-themes the chrome only — \"include dark mode\" is an\n // independent authoring choice about what ships with the exported theme, not a mirror of it.\n document.documentElement.dataset.pantokenScheme = mode;\n const themeButton = [...themeButtons].find((button) => button.dataset.theme === theme);\n if (themeButton) selectToggleButton(themeButtons, themeButton);\n syncDarkModeAvailability();\n syncPreviewSchemeToAppearance(mode);\n applyEditorTheme(activeEditor);\n void refreshAll();\n syncPreviewPopupChrome();\n}\n\n// This app is its own pantoken instance. Claiming the root stops an embedding page's scope from\n// being mistaken for ours, and stops our own preview/tray scopes from being re-themed by it.\ndocument.documentElement.dataset.pantokenInstance = EDITOR_INSTANCE;\napplyChromeTheme(\"rebrand\", \"light\");\napplyChromeColor(\"navy\");\n\nwindow.addEventListener(\"message\", (event) => {\n if (event.source !== window.parent || event.origin !== window.location.origin) return;\n const data = event.data as {\n type?: unknown;\n theme?: unknown;\n mode?: unknown;\n color?: unknown;\n customColor?: unknown;\n instanceId?: unknown;\n };\n // A message tagged for a different instance belongs to another pantoken on the host page.\n if (typeof data?.instanceId === \"string\" && data.instanceId !== HOST_INSTANCE) return;\n if (data?.type === \"pantoken-demo-color\") {\n applyHostColor(data.color, data.customColor);\n return;\n }\n if (data?.type !== \"pantoken-demo-theme\") return;\n if (\n (data.theme !== \"rebrand\" &&\n data.theme !== \"canvas\" &&\n data.theme !== \"canvasHighContrast\") ||\n (data.mode !== \"light\" && data.mode !== \"dark\")\n ) {\n return;\n }\n applyChromeTheme(data.theme, data.mode);\n applyParentTheme(data.theme, data.mode);\n applyHostColor(data.color, data.customColor);\n});\n\nwindow.parent.postMessage({ type: \"pantoken-demo-request-theme\" }, window.location.origin);\n\n/** Creates a CodeMirror editor for the given language, wired to call `onChange` on user edits. */\nfunction createEditor(\n container: HTMLElement,\n lang: \"html\" | \"css\" | \"javascript\",\n value: string,\n onChange: () => void,\n): EditorView {\n const langExtension = lang === \"css\" ? css() : lang === \"javascript\" ? javascript() : html();\n const extensions: any[] = [\n basicSetup,\n langExtension,\n EditorView.lineWrapping,\n EditorView.updateListener.of((update: any): void => {\n if (update.docChanged) onChange();\n }),\n ];\n \n // Add pantoken linter + autocomplete for HTML editor only.\n if (lang === \"html\") {\n extensions.push(\n pantokenHtmlLinter({ model: [...listComponents(), ...listUtilities()] as any }),\n pantokenHtmlCompletion({ model: [...listComponents(), ...listUtilities()] as any })\n );\n }\n \n return new EditorView({\n doc: value,\n extensions,\n parent: container,\n });\n}\n\n// Register one pantoken plugin that composes components, icons, logos, layouts, and templates\n// behind a single toolbar menu. tinymce.init() waits until the icon catalog is available.\nconst registerPantokenPlugin = (async () => {\n const componentModel = [...listComponents(), ...listUtilities()];\n const allIcons = await loadAllIcons();\n availableIcons = allIcons;\n\n tinymce.PluginManager.add(\n \"pantoken\",\n createPantokenPlugin({\n strings: tinymceStrings,\n components: {\n model: componentModel as any,\n currentAssets,\n onMissingAsset,\n },\n icons: {\n icons: allIcons,\n currentAssets,\n onMissingAsset,\n buildAssetUrl: buildSelectedAssetUrl,\n },\n logos: {\n // pantoken's own marks aren't Canvas content; pasted ones still render via glyph sync.\n logos: logos.filter((logo) => logo.product !== \"pantoken\"),\n products: products.filter((product) => product !== \"pantoken\"),\n currentAssets,\n onMissingAsset,\n buildAssetUrl: buildSelectedAssetUrl,\n },\n layouts: {\n locale: activeLocale,\n resolveImage: (placeholder) => {\n const image = buildPlaceholdImage({\n width: placeholder.width,\n height: placeholder.height,\n backgroundColor: \"#eeeeee\",\n textColor: \"#31343c\",\n text: placeholder.text,\n });\n return {\n src: image.url,\n alt: placeholder.altText ?? \"\",\n width: image.width,\n height: image.height,\n };\n },\n onInsert: () => {\n applyThemeColor(selectedColor, false);\n void refreshAll();\n },\n },\n }),\n );\n})();\n\ntinymce.PluginManager.add(\n PLACEHOLD_PLUGIN_NAME,\n createPlaceholdPlugin({ strings: tinymceStrings, onInsert: () => void refreshAll() }),\n);\ntinymce.PluginManager.add(CONTENT_CLASSES_PLUGIN_NAME, createContentClassesPlugin());\ntinymce.PluginManager.add(\n A11Y_PLUGIN_NAME,\n createA11yPlugin({ strings: tinymceStrings, display: \"footer\", config: a11yRuntimeConfig }),\n);\ntinymce.PluginManager.add(SUP_SUB_PLUGIN_NAME, createSupSubPlugin());\n\n// Toggles between TinyMCE's WYSIWYG view and a syntax-highlighted CodeMirror source view, reusing\n// the shared renderer's implementation (live preview + pantoken lint/autocomplete) instead of a\n// second, drifted reimplementation.\ntinymce.PluginManager.add(\n SOURCE_TOGGLE_PLUGIN_NAME,\n createSourceTogglePlugin({\n strings: tinymceStrings,\n height: EDITOR_HEIGHT_PX,\n display: \"footer\",\n extensions: [\n pantokenHtmlLinter({ model: [...listComponents(), ...listUtilities()] as any, strings: tinymceStrings }),\n pantokenHtmlCompletion({ model: [...listComponents(), ...listUtilities()] as any }),\n ],\n onChange: () => {\n syncThemeColorFromEditor();\n if (syncIconAssetsFromEditor()) void refreshAll();\n debouncedUpdatePreview();\n },\n onToggle: () => void refreshAll(),\n }),\n);\n// Fullscreen, find-and-replace, and visual blocks ship as toolbar-only controls upstream — these\n// footer-only wrappers surface all three from the statusbar instead, alongside word count and the\n// a11y checker.\ntinymce.PluginManager.add(FULLSCREEN_FOOTER_PLUGIN_NAME, createFullscreenFooterPlugin());\ntinymce.PluginManager.add(SEARCHREPLACE_FOOTER_PLUGIN_NAME, createSearchReplaceFooterPlugin());\ntinymce.PluginManager.add(VISUALBLOCKS_FOOTER_PLUGIN_NAME, createVisualBlocksFooterPlugin());\ntinymce.PluginManager.add(\n SAVE_PLUGIN_NAME,\n createSavePlugin<CanvasThemePreset>({\n strings: tinymceStrings,\n capture: captureCanvasThemePreset,\n restore: restoreCanvasThemePreset,\n reset: resetCanvasThemePreset,\n isValid: isCanvasThemePreset,\n }),\n);\n\nconst providerSelect = document.querySelector<HTMLSelectElement>(\"#cdn-provider\")!;\nconst localProviderOption = document.createElement(\"option\");\nlocalProviderOption.value = LOCAL_PROVIDER_ID;\nlocalProviderOption.textContent = activeStrings.localProviderLabel;\nproviderSelect.append(localProviderOption);\nfor (const [id, provider] of Object.entries(CDN_PROVIDERS)) {\n const option = document.createElement(\"option\");\n option.value = id;\n option.textContent = provider.label;\n providerSelect.append(option);\n}\nproviderSelect.value = import.meta.env.DEV ? LOCAL_PROVIDER_ID : DEFAULT_CDN_PROVIDER_ID;\nif (isLocalPreview) {\n providerSelect.value = LOCAL_PROVIDER_ID;\n}\nif (\n preferences.cdnProvider &&\n [...providerSelect.options].some((option) => option.value === preferences.cdnProvider)\n) {\n providerSelect.value = preferences.cdnProvider;\n}\n\nconst themeButtons = document.querySelectorAll<HTMLButtonElement>(\".theme-picker [data-theme]\");\nconst colorButtons = document.querySelectorAll<HTMLButtonElement>(\n \".theme-picker__color-item[data-color]\",\n);\nconst customColorRow = document.querySelector<HTMLElement>(\"#custom-color-row\")!;\nconst customColorPicker = document.querySelector<HTMLInputElement>(\"#custom-color-picker\")!;\nconst customColorHex = document.querySelector<HTMLInputElement>(\"#custom-color-hex\")!;\nconst customColorSwatch = document.querySelector<HTMLElement>(\n '.theme-picker__color-item [data-swatch=\"custom\"]',\n)!;\nconst previewWidthButtons = document.querySelectorAll<HTMLButtonElement>(\n \".preview-width-picker [data-preview-width]\",\n);\nconst previewWidthValue = document.querySelector<HTMLElement>(\"#preview-width-value\")!;\nconst includeDarkModeRow = document.getElementById(\"include-dark-mode-row\")!;\nconst includeDarkModeCheckbox = document.querySelector<HTMLInputElement>(\"#include-dark-mode\")!;\nconst previewSchemeToggle = document.querySelector<HTMLButtonElement>(\"#preview-scheme-toggle\")!;\nconst previewFrame = document.querySelector<HTMLIFrameElement>(\"#preview\")!;\nconst previewPane = document.querySelector<HTMLElement>(\".preview-pane\")!;\nconst downloadCss = document.querySelector<HTMLAnchorElement>(\"#download-theme-css\")!;\nconst downloadJs = document.querySelector<HTMLAnchorElement>(\"#download-theme-js\")!;\nconst downloadPackageButton = document.querySelector<HTMLButtonElement>(\"#download-package\")!;\nconst downloadHtmlButton = document.querySelector<HTMLButtonElement>(\"#download-html\")!;\nconst copyButton = document.querySelector<HTMLButtonElement>(\"#copy-html\")!;\n\nlet activeEditor: Editor | undefined;\nlet cssObjectUrl: string | undefined;\nlet jsObjectUrl: string | undefined;\n\n// Only the tray (below) and the preview it drives read these — the chrome has its own,\n// docs-driven theme/color tracked separately by `applyChromeTheme`/`applyChromeColor` above.\nlet selectedTheme: ThemeVariant = \"rebrand\";\nlet selectedColor: PantokenColorNamespace = \"navy\";\nlet selectedCustomColor = DEFAULT_CUSTOM_COLOR;\nsetupStandaloneAppShell();\n\ninterface CanvasThemePreset {\n readonly version: 1;\n readonly theme: ThemeVariant;\n readonly color: PantokenColorNamespace;\n readonly customColor?: string;\n readonly mode: ThemeMode;\n readonly cdnProvider: string;\n readonly customCss: string;\n readonly customJs: string;\n readonly editorHtml: string;\n}\n\nfunction selectThemeColor(color: PantokenColorNamespace): void {\n selectedColor = color;\n const colorButton = [...colorButtons].find((button) => button.dataset.color === color);\n if (colorButton) selectButton(colorButtons, colorButton);\n customColorRow.hidden = color !== CUSTOM_COLOR_KEY;\n}\n\n/** Stores a validated custom hex and reflects it in the tray. */\nfunction setCustomColor(hex: string): void {\n selectedCustomColor = parseHexColor(hex);\n customColorPicker.value = selectedCustomColor;\n const typed = customColorHex.value;\n if (!isHexColor(typed) || parseHexColor(typed) !== selectedCustomColor) {\n customColorHex.value = selectedCustomColor;\n }\n customColorHex.classList.remove(\"-invalid\");\n customColorHex.removeAttribute(\"aria-invalid\");\n syncCustomSwatch(customColorSwatch, selectedCustomColor);\n}\n\n/** The `custom` scale's rule, only while it's the selected color. */\nfunction selectedCustomColorCss(): string {\n return selectedColor === CUSTOM_COLOR_KEY\n ? customColorCss(selectedCustomColor, { selector: \"\" })\n : \"\";\n}\n\nconst debouncedCustomColorRefresh = debounce(() => void refreshAll(), 150);\n\nfunction onCustomColorInput(value: string): void {\n if (!isHexColor(value)) {\n customColorHex.classList.add(\"-invalid\");\n customColorHex.setAttribute(\"aria-invalid\", \"true\");\n return;\n }\n setCustomColor(value);\n if (selectedColor === CUSTOM_COLOR_KEY) debouncedCustomColorRefresh();\n}\n\ncustomColorPicker.addEventListener(\"input\", () => onCustomColorInput(customColorPicker.value));\ncustomColorHex.addEventListener(\"input\", () => onCustomColorInput(customColorHex.value));\nsetCustomColor(DEFAULT_CUSTOM_COLOR);\n\nfunction parseEditorHtml(html: string): HTMLTemplateElement {\n const template = document.createElement(\"template\");\n template.innerHTML = html;\n return template;\n}\n\nfunction findColorWrapper(content: DocumentFragment): HTMLElement | undefined {\n const wrapper = content.firstElementChild as HTMLElement | null;\n if (!wrapper?.hasAttribute(\"data-pantoken-color\")) return undefined;\n const hasContentOutsideWrapper = [...content.childNodes].some(\n (node) => node !== wrapper && (node.nodeType !== Node.TEXT_NODE || node.textContent?.trim()),\n );\n return hasContentOutsideWrapper ? undefined : wrapper;\n}\n\nfunction normalizeEditorHtml(html: string, fallbackColor: PantokenColorNamespace): string {\n const template = parseEditorHtml(html);\n let wrapper = findColorWrapper(template.content);\n if (!wrapper) {\n wrapper = document.createElement(\"div\");\n wrapper.dataset.pantokenColor = fallbackColor;\n wrapper.append(...template.content.childNodes);\n template.content.append(wrapper);\n } else if (!isThemeColor(wrapper.dataset.pantokenColor)) {\n wrapper.dataset.pantokenColor = fallbackColor;\n }\n return template.innerHTML;\n}\n\nfunction editorHtmlColor(html: string): PantokenColorNamespace | undefined {\n const wrapper = findColorWrapper(parseEditorHtml(html).content);\n const color = wrapper?.dataset.pantokenColor;\n return isThemeColor(color) ? color : undefined;\n}\n\nfunction setEditorHtmlColor(html: string, color: PantokenColorNamespace): string {\n const template = parseEditorHtml(normalizeEditorHtml(html, color));\n findColorWrapper(template.content)!.dataset.pantokenColor = color;\n return template.innerHTML;\n}\n\nfunction syncThemeColorFromEditor(): void {\n const color = editorHtmlColor(getEditorHtml());\n if (color) selectThemeColor(color);\n}\n\nfunction applyThemeColor(color: PantokenColorNamespace, refresh = true): void {\n selectThemeColor(color);\n if (activeEditor) {\n const sourceToggle = activeEditor.plugins[SOURCE_TOGGLE_PLUGIN_NAME] as\n | SourceTogglePluginApi\n | undefined;\n const nextHtml = setEditorHtmlColor(getEditorHtml(), color);\n if (sourceToggle?.isSourceMode()) {\n sourceToggle.replaceAll(nextHtml);\n } else {\n activeEditor.undoManager.transact(() => activeEditor!.setContent(nextHtml));\n }\n }\n if (refresh) void refreshAll();\n}\n\n/** Reads the author's current HTML from whichever view (WYSIWYG or raw source) is active. */\nfunction getEditorHtml(): string {\n const sourceToggle = activeEditor?.plugins[SOURCE_TOGGLE_PLUGIN_NAME] as\n | SourceTogglePluginApi\n | undefined;\n if (sourceToggle?.isSourceMode()) return sourceToggle.getContent();\n return activeEditor?.getContent() ?? \"\";\n}\n\nfunction getNormalizedEditorHtml(): string {\n return normalizeEditorHtml(getEditorHtml(), selectedColor);\n}\n\nfunction assetKey(asset: CdnFile): string {\n return `${asset.package}:${asset.path}`;\n}\n\nasync function inlineAssetCss(assets: readonly CdnFile[]): Promise<string[]> {\n await Promise.all(\n assets.map(async (asset) => {\n const key = assetKey(asset);\n if (inlineAssetContents.has(key)) return;\n const response = await fetch(buildSelectedAssetUrl(asset));\n if (!response.ok) {\n throw new Error(`Unable to inline ${asset.package}/${asset.path}: ${response.status}`);\n }\n inlineAssetContents.set(key, await response.text());\n }),\n );\n return assets.map((asset) => inlineAssetContents.get(assetKey(asset))!);\n}\n\nfunction syncIconAssetsFromEditor(): boolean {\n const content = parseEditorHtml(getEditorHtml()).content;\n const iconAssetKeys = new Set(availableIcons.map((icon) => assetKey(getIconCdnFile(icon))));\n const logoAssetKeys = new Set(logos.map((logo) => assetKey(getLogoCdnFile(logo))));\n const nonSyncedAssets = currentAssets.filter(\n (asset) => !iconAssetKeys.has(assetKey(asset)) && !logoAssetKeys.has(assetKey(asset)),\n );\n const usedIconAssets = getUsedIconCdnFiles(content, availableIcons, currentAssets);\n const usedLogoAssets = getUsedLogoCdnFiles(content, logos);\n const nextAssets = [...nonSyncedAssets, ...usedIconAssets, ...usedLogoAssets];\n const changed = currentAssets.map(assetKey).join(\"\\n\") !== nextAssets.map(assetKey).join(\"\\n\");\n if (changed) currentAssets.splice(0, currentAssets.length, ...nextAssets);\n return changed;\n}\n\nfunction captureCanvasThemePreset(): CanvasThemePreset {\n return {\n version: 1,\n theme: selectedTheme,\n color: selectedColor,\n customColor: selectedCustomColor,\n mode: includeDarkModeCheckbox.checked ? \"adaptive\" : \"light\",\n cdnProvider: providerSelect.value,\n customCss: cssEditorView.state.doc.toString(),\n customJs: jsEditorView.state.doc.toString(),\n editorHtml: getNormalizedEditorHtml(),\n };\n}\n\nfunction isThemeVariant(value: unknown): value is ThemeVariant {\n return value === \"rebrand\" || value === \"canvas\" || value === \"canvasHighContrast\";\n}\n\nfunction isThemeMode(value: unknown): value is ThemeMode {\n return value === \"light\" || value === \"adaptive\";\n}\n\nfunction isCdnProvider(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n (Object.hasOwn(CDN_PROVIDERS, value) || value === LOCAL_PROVIDER_ID)\n );\n}\n\nfunction isCanvasThemePreset(value: unknown): value is CanvasThemePreset {\n if (typeof value !== \"object\" || value === null) return false;\n const preset = value as Partial<CanvasThemePreset>;\n return (\n preset.version === 1 &&\n isThemeVariant(preset.theme) &&\n isThemeColor(preset.color) &&\n (preset.customColor === undefined || isHexColor(preset.customColor)) &&\n isThemeMode(preset.mode) &&\n isCdnProvider(preset.cdnProvider) &&\n typeof preset.customCss === \"string\" &&\n typeof preset.customJs === \"string\" &&\n typeof preset.editorHtml === \"string\"\n );\n}\n\nfunction replaceEditorDocument(view: EditorView, content: string): void {\n view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: content } });\n}\n\nfunction resetCanvasThemePreset(): void {\n selectedTheme = \"rebrand\";\n const themeButton = [...themeButtons].find((button) => button.dataset.theme === selectedTheme);\n if (themeButton) selectToggleButton(themeButtons, themeButton);\n includeDarkModeCheckbox.checked = false;\n syncDarkModeAvailability();\n providerSelect.value = isLocalPreview ? LOCAL_PROVIDER_ID : DEFAULT_CDN_PROVIDER_ID;\n selectThemeColor(\"navy\");\n setCustomColor(DEFAULT_CUSTOM_COLOR);\n replaceEditorDocument(cssEditorView, \"\");\n replaceEditorDocument(jsEditorView, \"\");\n\n if (activeEditor) {\n const nextHtml = normalizeEditorHtml(\"\", \"navy\");\n activeEditor.resetContent(nextHtml);\n const sourceToggle = activeEditor.plugins[SOURCE_TOGGLE_PLUGIN_NAME] as\n | SourceTogglePluginApi\n | undefined;\n if (sourceToggle?.isSourceMode()) sourceToggle.replaceAll(nextHtml);\n retargetContentStylesheets(activeEditor, buildSelectedAssetUrl);\n }\n\n syncThemeColorFromEditor();\n applyEditorTheme(activeEditor);\n void refreshAll();\n}\n\nfunction restoreCanvasThemePreset(preset: CanvasThemePreset): void {\n if (!activeEditor || !isCanvasThemePreset(preset)) throw new TypeError(\"invalid-preset\");\n\n selectedTheme = preset.theme;\n const themeButton = [...themeButtons].find((button) => button.dataset.theme === preset.theme);\n if (themeButton) selectToggleButton(themeButtons, themeButton);\n includeDarkModeCheckbox.checked = preset.mode === \"adaptive\";\n syncDarkModeAvailability();\n providerSelect.value = preset.cdnProvider;\n selectThemeColor(preset.color);\n setCustomColor(preset.customColor ?? DEFAULT_CUSTOM_COLOR);\n replaceEditorDocument(cssEditorView, preset.customCss);\n replaceEditorDocument(jsEditorView, preset.customJs);\n\n const editorHtml = normalizeEditorHtml(preset.editorHtml, preset.color);\n activeEditor.resetContent(editorHtml);\n const sourceToggle = activeEditor.plugins[SOURCE_TOGGLE_PLUGIN_NAME] as\n | SourceTogglePluginApi\n | undefined;\n if (sourceToggle?.isSourceMode()) sourceToggle.replaceAll(editorHtml);\n // Setting `providerSelect.value` fires no change event, so re-point already-loaded sheets here.\n retargetContentStylesheets(activeEditor, buildSelectedAssetUrl);\n syncThemeColorFromEditor();\n\n applyEditorTheme(activeEditor);\n void refreshAll();\n}\n\nfunction currentSelection(): { provider: string; theme: ThemeVariant; mode: ThemeMode } {\n return {\n provider: providerSelect.value,\n theme: selectedTheme,\n mode: includeDarkModeCheckbox.checked ? \"adaptive\" : \"light\",\n };\n}\n\n/** `css`/`js` are theme.css/theme.js's actual downloadable content and the live preview's styling\n * alike — both follow the visitor's/browser's own dark-mode preference, same as a real Canvas\n * page would. The preview's manual light/dark toggle overrides that via `PREVIEW_SCHEME_FORCE_CSS`\n * (see `updatePreview`), not by swapping this CSS. */\nasync function buildCurrentTheme(): Promise<{ css: string; js: string }> {\n const selection = currentSelection();\n const customCss = selectedCustomColorCss();\n if (selection.provider !== LOCAL_PROVIDER_ID) {\n const theme = buildTheme({\n ...selection,\n css: [...defaultThemeCssAssets(selection.theme, selection.mode), ...currentAssets],\n });\n return { ...theme, css: [theme.css, customCss].filter(Boolean).join(\"\\n\") };\n }\n\n const tokensCss =\n selection.theme === \"canvas\"\n ? canvasTokensCss\n : selection.theme === \"canvasHighContrast\"\n ? canvasHighContrastTokensCss\n : selection.mode === \"adaptive\"\n ? adaptiveTokensCss\n : rebrandLightTokensCss;\n const dynamicCss = await inlineAssetCss(currentAssets);\n return {\n css: [tokensCss, LOCAL_COMPONENT_CSS, ...dynamicCss, customCss].filter(Boolean).join(\"\\n\"),\n js: localInteractionsJs,\n };\n}\n\n/** Marks the clicked button as selected within its `role=\"group\"` (theme or color pickers). */\nfunction selectButton(buttons: NodeListOf<HTMLButtonElement>, target: HTMLButtonElement): void {\n for (const button of buttons) {\n const selected = button === target;\n button.classList.toggle(\"-selected\", selected);\n button.setAttribute(\"aria-checked\", String(selected));\n }\n}\n\n/** Marks the clicked instui-button `-toggle` as pressed within its `role=\"group\"` (preview width). */\nfunction selectToggleButton(buttons: NodeListOf<HTMLButtonElement>, target: HTMLButtonElement): void {\n for (const button of buttons) button.setAttribute(\"aria-pressed\", String(button === target));\n}\n\n/** Only \"rebrand\" ships a dark scheme — canvas/canvasHighContrast are single-scheme themes. */\nfunction syncDarkModeAvailability(): void {\n const supportsDarkMode = selectedTheme === \"rebrand\";\n includeDarkModeRow.hidden = !supportsDarkMode;\n includeDarkModeCheckbox.disabled = !supportsDarkMode;\n if (!supportsDarkMode) includeDarkModeCheckbox.checked = false;\n syncPreviewSchemeToggleAvailability();\n}\n\n/** The preview's own light/dark switch only makes sense once \"include dark mode\" is on. */\nfunction syncPreviewSchemeToggleAvailability(): void {\n previewSchemeToggle.disabled = !includeDarkModeCheckbox.checked;\n if (previewSchemeToggle.disabled) {\n previewDarkOverride = false;\n previewSchemeToggle.setAttribute(\"aria-pressed\", \"false\");\n previewSchemeToggle.classList.replace(\"-icon-sun\", \"-icon-moon\");\n }\n}\n\nthemeButtons.forEach((button) => {\n button.addEventListener(\"click\", () => {\n selectedTheme = button.dataset.theme as ThemeVariant;\n selectToggleButton(themeButtons, button);\n syncDarkModeAvailability();\n applyEditorTheme(activeEditor);\n void refreshAll();\n });\n});\n\ncolorButtons.forEach((button) => {\n button.addEventListener(\"click\", () => {\n const color = button.dataset.color;\n if (isThemeColor(color)) applyThemeColor(color);\n });\n});\n\n// Canvas's own responsive breakpoints for course content, reused as-is from pantoken's tokens —\n// \"large\" is unconstrained (the current default), matching the desktop RCE width.\ntype PreviewWidthPreset = \"large\" | \"medium\" | \"small\";\n\nconst PREVIEW_WIDTHS: Record<Exclude<PreviewWidthPreset, \"large\">, string> = {\n medium: \"var(--instui-breakpoints-md)\",\n small: \"var(--instui-breakpoints-xs)\",\n};\n\nfunction isPreviewWidthPreset(value: unknown): value is PreviewWidthPreset {\n return value === \"large\" || value === \"medium\" || value === \"small\";\n}\n\nfunction isCustomPreviewWidth(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value > 0;\n}\n\nfunction parseCustomPreviewWidth(value: string): number | undefined {\n if (!/^[1-9]\\d*$/u.test(value)) return undefined;\n const width = Number(value);\n return isCustomPreviewWidth(width) ? width : undefined;\n}\n\nlet selectedPreviewWidth: PreviewWidthPreset | number =\n isPreviewWidthPreset(preferences.previewWidth) || isCustomPreviewWidth(preferences.previewWidth)\n ? preferences.previewWidth\n : \"large\";\n\nfunction clearPreviewWidthButtons(): void {\n for (const button of previewWidthButtons) button.setAttribute(\"aria-pressed\", \"false\");\n}\n\nfunction updatePreviewWidthValue(force = false): void {\n if (!force && document.activeElement === previewWidthValue) return;\n const width =\n typeof selectedPreviewWidth === \"number\"\n ? selectedPreviewWidth\n : Math.round(previewFrame.getBoundingClientRect().width);\n if (width <= 0) return;\n const value = String(width);\n previewWidthValue.textContent = value;\n previewWidthValue.setAttribute(\"value\", value);\n}\n\nconst previewWidthObserver = new ResizeObserver(() => updatePreviewWidthValue());\npreviewWidthObserver.observe(previewFrame);\n\n/**\n * In row layout, the *pane's* width is constrained so the editor pane's flex:1 can claim\n * whatever space a fixed-width (medium/small) preview gives up. In fullscreen the pane is\n * forced to fill the viewport (app.css's `!important` overlay), so there's no sibling to\n * reclaim space from — the constraint has to move to the iframe itself instead, centered\n * via app.css's `margin-inline: auto`.\n */\nfunction applyPreviewWidth(): void {\n const fullscreen = previewPane.classList.contains(\"-fullscreen\");\n previewPane.style.removeProperty(\"flex\");\n previewPane.style.removeProperty(\"width\");\n previewPane.style.removeProperty(\"min-width\");\n previewFrame.style.removeProperty(\"max-width\");\n if (selectedPreviewWidth === \"large\") {\n // In row layout, \"large\" only got a 50/50 flex share of `.content`'s width — on a narrow\n // window that's smaller than \"medium\"'s own fixed `--instui-breakpoints-md`, so the\n // \"desktop\" preview could render narrower than the \"tablet\" one. A `--instui-breakpoints-lg`\n // floor guarantees desktop is always at least as wide as the next size down.\n if (!fullscreen && document.querySelector(\".content\")?.getAttribute(\"data-layout\") === \"row\") {\n previewPane.style.minWidth = \"var(--instui-breakpoints-lg)\";\n }\n updatePreviewWidthValue();\n return;\n }\n const width =\n typeof selectedPreviewWidth === \"number\"\n ? `${selectedPreviewWidth}px`\n : PREVIEW_WIDTHS[selectedPreviewWidth];\n if (fullscreen) {\n previewFrame.style.maxWidth = width;\n } else {\n previewPane.style.flex = \"0 0 auto\";\n previewPane.style.width = width;\n }\n updatePreviewWidthValue();\n}\n\npreviewWidthButtons.forEach((button) => {\n button.addEventListener(\"click\", () => {\n selectToggleButton(previewWidthButtons, button);\n selectedPreviewWidth = button.dataset.previewWidth as PreviewWidthPreset;\n applyPreviewWidth();\n persistPreferences();\n });\n});\npreviewWidthValue.addEventListener(\"change\", (event) => {\n const width = parseCustomPreviewWidth(\n (event as CustomEvent<{ value: string }>).detail.value,\n );\n if (width === undefined) {\n updatePreviewWidthValue(true);\n return;\n }\n selectedPreviewWidth = width;\n clearPreviewWidthButtons();\n applyPreviewWidth();\n persistPreferences();\n});\nif (typeof selectedPreviewWidth === \"number\") {\n clearPreviewWidthButtons();\n applyPreviewWidth();\n} else if (selectedPreviewWidth !== \"large\") {\n const savedWidthButton = [...previewWidthButtons].find(\n (button) => button.dataset.previewWidth === selectedPreviewWidth,\n );\n if (savedWidthButton) {\n selectToggleButton(previewWidthButtons, savedWidthButton);\n applyPreviewWidth();\n }\n} else {\n applyPreviewWidth();\n}\n\nlet previewDarkOverride = false;\nsyncDarkModeAvailability();\n\n/** Makes the preview's own light/dark display follow an app-wide appearance change (its \"include\n * dark mode\" export checkbox stays untouched); the user can still flip it back independently\n * afterward via `previewSchemeToggle`. No-op while the current theme has no dark preview to show. */\nfunction syncPreviewSchemeToAppearance(mode: \"light\" | \"dark\"): void {\n if (!includeDarkModeCheckbox.checked) return;\n previewDarkOverride = mode === \"dark\";\n previewSchemeToggle.setAttribute(\"aria-pressed\", String(previewDarkOverride));\n previewSchemeToggle.classList.toggle(\"-icon-moon\", !previewDarkOverride);\n previewSchemeToggle.classList.toggle(\"-icon-sun\", previewDarkOverride);\n}\n\npreviewSchemeToggle.addEventListener(\"click\", () => {\n previewDarkOverride = !previewDarkOverride;\n previewSchemeToggle.setAttribute(\"aria-pressed\", String(previewDarkOverride));\n previewSchemeToggle.classList.toggle(\"-icon-moon\", !previewDarkOverride);\n previewSchemeToggle.classList.toggle(\"-icon-sun\", previewDarkOverride);\n void refreshAll();\n});\n\nconst previewFullscreenToggle = document.querySelector<HTMLButtonElement>(\n \"#preview-fullscreen-toggle\",\n)!;\nconst previewPopupToggle = document.querySelector<HTMLButtonElement>(\"#preview-popup-toggle\")!;\nconst previewFullscreenLabel = document.querySelector<HTMLElement>(\"#preview-fullscreen-label\")!;\nconst previewFullscreenTooltip = document.querySelector<HTMLElement>(\n \"#preview-fullscreen-toggle-tip\",\n)!;\nconst previewPopupReturnLabel = document.querySelector<HTMLElement>(\n \"#preview-popup-return-label\",\n)!;\nconst previewPopupTitle = document.querySelector<HTMLElement>(\"#preview-popup-title\")!;\nconst previewPopupBlockedMessage = document.querySelector<HTMLElement>(\n \"#preview-popup-blocked-message\",\n)!;\nconst previewAnchor = document.createComment(\"preview-pane-anchor\");\npreviewPane.before(previewAnchor);\nlet previewWasFullscreen = false;\nlet restoringPreview = false;\n\nfunction setPreviewFullscreen(fullscreen: boolean): void {\n previewFullscreenToggle.setAttribute(\"aria-pressed\", String(fullscreen));\n previewFullscreenToggle.classList.toggle(\"-icon-maximize\", !fullscreen);\n previewFullscreenToggle.classList.toggle(\"-icon-minimize\", fullscreen);\n previewPane.classList.toggle(\"-fullscreen\", fullscreen);\n applyPreviewWidth();\n resizePreviewFrame();\n}\n\nfunction setPreviewPopupLabels(detached: boolean): void {\n previewFullscreenLabel.hidden = detached;\n previewPopupReturnLabel.hidden = !detached;\n const label = (detached ? previewPopupReturnLabel : previewFullscreenLabel).textContent?.trim() ?? \"\";\n previewFullscreenToggle.setAttribute(\n \"aria-label\",\n label,\n );\n previewFullscreenTooltip.textContent = label;\n}\n\nfunction restorePreviewFromPopup(closePopup = true): void {\n if (restoringPreview || previewPane.ownerDocument === document) return;\n restoringPreview = true;\n const popup = previewPopup;\n if (previewPopupCloseTimer !== undefined) window.clearInterval(previewPopupCloseTimer);\n previewPopupCloseTimer = undefined;\n previewPopup = null;\n previewPopupStylePairs = [];\n document.adoptNode(previewPane);\n previewAnchor.after(previewPane);\n setPreviewPopupLabels(false);\n setPreviewFullscreen(previewWasFullscreen);\n if (closePopup && popup && !popup.closed) popup.close();\n restoringPreview = false;\n previewPopupToggle.focus();\n layoutDirectionToggle.disabled = false;\n}\n\nfunction openPreviewPopup(): void {\n if (previewPopup && !previewPopup.closed) {\n previewPopup.focus();\n return;\n }\n\n const width = Math.max(320, Math.min(1200, window.screen.availWidth - 80));\n const height = Math.max(320, Math.min(900, window.screen.availHeight - 80));\n const left = Math.max(\n 0,\n (window.screen.availLeft ?? 0) + (window.screen.availWidth - width) / 2,\n );\n const top = Math.max(\n 0,\n (window.screen.availTop ?? 0) + (window.screen.availHeight - height) / 2,\n );\n const popup = window.open(\n \"\",\n \"pantoken-canvas-preview\",\n `popup=yes,width=${width},height=${height},left=${Math.round(left)},top=${Math.round(top)}`,\n );\n if (!popup) {\n window.alert(previewPopupBlockedMessage.textContent?.trim() ?? \"Preview popup blocked.\");\n return;\n }\n\n previewPopup = popup;\n previewWasFullscreen = previewPane.classList.contains(\"-fullscreen\");\n const popupDocument = popup.document;\n popupDocument.head.replaceChildren();\n popupDocument.body.replaceChildren();\n popupDocument.title = previewPopupTitle.textContent?.trim() ?? \"Preview\";\n popupDocument.body.className = \"preview-popup\";\n previewPopupStylePairs = [];\n for (const source of document.head.querySelectorAll<HTMLLinkElement | HTMLStyleElement>(\n 'link[rel=\"stylesheet\"], style',\n )) {\n const clone = source.cloneNode(true) as HTMLLinkElement | HTMLStyleElement;\n if (source instanceof HTMLLinkElement && clone instanceof HTMLLinkElement) {\n clone.href = source.href;\n }\n popupDocument.head.append(clone);\n if (source instanceof HTMLStyleElement && clone instanceof HTMLStyleElement) {\n previewPopupStylePairs.push({ source, clone });\n }\n }\n syncPreviewPopupChrome();\n popupDocument.body.append(previewPane);\n setPreviewPopupLabels(true);\n setPreviewFullscreen(true);\n layoutDirectionToggle.disabled = true;\n popup.addEventListener(\"pagehide\", () => restorePreviewFromPopup(false), { once: true });\n previewPopupCloseTimer = window.setInterval(() => {\n if (previewPopup?.closed) restorePreviewFromPopup(false);\n }, 500);\n popup.focus();\n}\n\npreviewPopupToggle.addEventListener(\"click\", openPreviewPopup);\npreviewFullscreenToggle.addEventListener(\"click\", () => {\n if (previewPane.ownerDocument !== document) {\n restorePreviewFromPopup();\n return;\n }\n const fullscreen = previewFullscreenToggle.getAttribute(\"aria-pressed\") !== \"true\";\n setPreviewFullscreen(fullscreen);\n persistPreferences();\n});\nif (preferences.previewFullscreen === true) {\n setPreviewFullscreen(true);\n}\n\nwindow.addEventListener(\"beforeunload\", () => {\n if (previewPopupCloseTimer !== undefined) window.clearInterval(previewPopupCloseTimer);\n previewPopup?.close();\n});\n\nconst layoutDirectionToggle = document.querySelector<HTMLButtonElement>(\n \"#layout-direction-toggle\",\n)!;\nconst contentEl = document.querySelector<HTMLElement>(\".panes\")!;\n/** Applies (and reflects in the toggle button) row vs. column pane arrangement. */\nfunction applyLayoutDirection(row: boolean): void {\n layoutDirectionToggle.setAttribute(\"aria-pressed\", String(row));\n layoutDirectionToggle.classList.toggle(\"-icon-rows-2\", row);\n layoutDirectionToggle.classList.toggle(\"-icon-columns-2\", !row);\n contentEl.style.flexDirection = row ? \"row\" : \"column\";\n contentEl.dataset.layout = row ? \"row\" : \"column\";\n applyPreviewWidth();\n}\nlayoutDirectionToggle.addEventListener(\"click\", () => {\n applyLayoutDirection(layoutDirectionToggle.getAttribute(\"aria-pressed\") !== \"true\");\n persistPreferences();\n});\n// Column (stacked) is the default first-visit layout — matches the toggle's default markup\n// (aria-pressed=\"false\", the columns-2 icon) so there's no dead first click reconciling a\n// mismatched initial state.\napplyLayoutDirection(preferences.layout === \"row\");\n\n/** Saves this app's current layout/preview/CDN provider settings for the next visit. */\nfunction persistPreferences(): void {\n const mergedTinymceConfig = {\n ...(preferences.tinymceConfig ?? {}),\n a11y: {\n ...((preferences.tinymceConfig as Record<string, unknown> | undefined)?.a11y as Record<\n string,\n unknown\n > | null),\n highlightIssues: true,\n contrastThreshold: \"4.5:1\",\n enabledRules: {},\n },\n };\n\n savePreferences({\n ...preferences,\n layout: contentEl.dataset.layout === \"row\" ? \"row\" : \"column\",\n previewWidth: selectedPreviewWidth,\n previewFullscreen: previewPane.classList.contains(\"-fullscreen\"),\n cdnProvider: providerSelect.value,\n tinymceConfig: mergedTinymceConfig,\n });\n}\n\n\nincludeDarkModeCheckbox.addEventListener(\"change\", () => {\n syncPreviewSchemeToggleAvailability();\n void refreshAll();\n});\n\n/** Debounce helper — the preview pane only needs to refresh a beat after typing settles. */\nfunction debounce<Args extends unknown[]>(fn: (...args: Args) => void, ms: number) {\n let handle: ReturnType<typeof setTimeout> | undefined;\n return (...args: Args) => {\n if (handle) clearTimeout(handle);\n handle = setTimeout(() => fn(...args), ms);\n };\n}\n\n/**\n * Renders the editor's current HTML with the CSS/JS tab's *current editable text* embedded\n * directly (not linked from the CDN) — so hand-edits in those tabs show up in the preview too.\n * The body content is wrapped to match Canvas's own content-area background and max width.\n * The editable outer `data-pantoken-color` wrapper, plus the inlined `CUSTOM_THEME_COLORS_CSS`,\n * remaps brand colors instantly — a no-op for the default \"navy\" scheme. `#content`'s height is a min,\n * not a fixed viewport height, so the iframe (resized to match in `resizePreviewFrame`) grows to\n * fit instead of scrolling internally.\n */\nfunction updatePreview(theme: { css: string; js: string }): void {\n if (!activeEditor) return;\n // Canvas's own theme already frames the RCE content area — the picker's border would double up.\n previewFrame.style.borderColor =\n selectedTheme === \"canvas\" || selectedTheme === \"canvasHighContrast\" ? \"transparent\" : \"\";\n const themeCss = [theme.css, PREVIEW_SCHEME_FORCE_CSS, cssEditorView.state.doc.toString()]\n .filter(Boolean)\n .join(\"\\n\");\n const themeJs = [theme.js, jsEditorView.state.doc.toString()]\n .filter(Boolean)\n .join(\"\\n\");\n // Elevation is a rebrand-only affordance — Canvas's own themes don't use drop-shadow surfaces.\n const contentClass =\n selectedTheme === \"rebrand\"\n ? \"instui-view -background-primary --elevation-resting\"\n : \"instui-view -background-primary\";\n // The preview is a srcdoc document, so it's a hard scope boundary: it declares its own theme,\n // scheme, and color outright rather than inheriting anything from the editor chrome around it.\n // That's what lets the preview sit in light Canvas while the chrome sits in dark rebrand.\n const previewScheme =\n selectedTheme === \"rebrand\" && includeDarkModeCheckbox.checked && previewDarkOverride\n ? \"dark\"\n : \"light\";\n previewFrame.srcdoc = `<!doctype html><html data-pantoken-boundary data-pantoken-instance=\"${EDITOR_INSTANCE}-preview\" data-pantoken-theme=\"${selectedTheme}\" data-pantoken-scheme=\"${previewScheme}\" data-pantoken-color=\"${selectedColor}\" style=\"color-scheme:${previewScheme}\"><head><style>${themeCss}\n${CUSTOM_THEME_COLORS_CSS}</style><style>#wrapper{padding:32px;}#content{padding:36px 48px 48px;min-height:20rem;margin:0 auto;border-radius:12px;}@media not all and (min-width: 768px) {\n #wrapper{padding:24px;}#content{padding-left:12px;padding-right:12px;min-height:16rem;border-radius:8px;}</style></head><body>\n <div id=\"wrapper\" class=\"instui-view\"><div id=\"content\" class=\"${contentClass}\" style=\"max-width: ${CANVAS_CONTENT_MAX_WIDTH};\">\n ${getNormalizedEditorHtml()}\n </div></div>\n <script>${themeJs}<\/script>\n </body></html>`;\n}\nconst debouncedUpdatePreview = debounce(() => void refreshAll(), 300);\n\n// Keep the same-origin preview frame at its content height; the docs embedding page separately\n// receives its own postMessage height updates from `canvas-rce-iframe-height.js`.\nlet previewResizeObserver: ResizeObserver | undefined;\nlet previewMutationObserver: MutationObserver | undefined;\nconst PREVIEW_BORDER_PX = 2;\nfunction resizePreviewFrame(): void {\n // Fullscreen pins the pane to the viewport, so the frame flexes to fill it (app.css) rather than\n // growing past it — a content-height frame would push the overlay into a scrollbar.\n if (previewPane.classList.contains(\"-fullscreen\")) {\n previewFrame.style.removeProperty(\"height\");\n return;\n }\n const root = previewFrame.contentDocument?.documentElement;\n const body = previewFrame.contentDocument?.body;\n if (!root || !body) return;\n const style = getComputedStyle(body);\n const margins = Number.parseFloat(style.marginTop) + Number.parseFloat(style.marginBottom);\n const height = Math.ceil(Math.max(root.getBoundingClientRect().height, body.offsetHeight + margins));\n previewFrame.style.height = `${height + PREVIEW_BORDER_PX}px`;\n}\n\nfunction handlePreviewLinkClick(event: MouseEvent): void {\n if (event.defaultPrevented) return;\n const anchor = (event.target as Element | null)?.closest(\"a[href]\");\n const href = anchor?.getAttribute(\"href\")?.trim();\n if (!href?.startsWith(\"#\")) return;\n\n event.preventDefault();\n let fragment: string;\n try {\n fragment = decodeURIComponent(href.slice(1));\n } catch {\n return;\n }\n if (!fragment) return;\n\n const previewDocument = event.currentTarget as Document;\n const target =\n previewDocument.getElementById(fragment) ?? previewDocument.getElementsByName(fragment)[0];\n target?.scrollIntoView();\n}\n\npreviewFrame.addEventListener(\"load\", () => {\n previewResizeObserver?.disconnect();\n previewMutationObserver?.disconnect();\n resizePreviewFrame();\n previewFrame.contentDocument?.addEventListener(\"click\", handlePreviewLinkClick);\n const root = previewFrame.contentDocument?.documentElement;\n if (!root) return;\n previewResizeObserver = new ResizeObserver(resizePreviewFrame);\n previewResizeObserver.observe(root);\n previewMutationObserver = new MutationObserver(resizePreviewFrame);\n previewMutationObserver.observe(root, { childList: true, subtree: true, attributes: true });\n});\n\nfunction buildDownloadFiles(theme: { css: string; js: string }): {\n css: string;\n js: string;\n} {\n const { css: presetCss, js: presetJs } = theme;\n return {\n css: [presetCss, cssEditorView.state.doc.toString()].filter(Boolean).join(\"\\n\"),\n js: [presetJs, jsEditorView.state.doc.toString()].filter(Boolean).join(\"\\n\"),\n };\n}\n\n/** Regenerates the downloadable theme.css/theme.js blobs, appending the author's custom CSS/JS\n * tab content onto the generated preset for the chosen provider/theme/mode. */\nfunction updateDownloads(theme: { css: string; js: string }): void {\n const files = buildDownloadFiles(theme);\n if (cssObjectUrl) URL.revokeObjectURL(cssObjectUrl);\n if (jsObjectUrl) URL.revokeObjectURL(jsObjectUrl);\n cssObjectUrl = URL.createObjectURL(new Blob([files.css], { type: \"text/css\" }));\n jsObjectUrl = URL.createObjectURL(new Blob([files.js], { type: \"text/javascript\" }));\n downloadCss.href = cssObjectUrl;\n downloadJs.href = jsObjectUrl;\n}\n\nfunction downloadBlob(blob: Blob, filename: string): void {\n const objectUrl = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = objectUrl;\n anchor.download = filename;\n document.body.append(anchor);\n anchor.click();\n anchor.remove();\n setTimeout(() => URL.revokeObjectURL(objectUrl), 0);\n}\n\n/** The currently open/saved preset's name, if any — downloads use it so the file the author is\n * actually working on isn't always exported as a generic \"canvas-theme\"/\"untitled\". */\nfunction activePresetName(): string | undefined {\n const savePlugin = activeEditor?.plugins[SAVE_PLUGIN_NAME] as\n | SavePluginApi<CanvasThemePreset>\n | undefined;\n const activeId = savePlugin?.activePresetId;\n if (!activeId) return undefined;\n return savePlugin.list().find((preset) => preset.id === activeId)?.name;\n}\n\nasync function refreshAll(): Promise<void> {\n const generation = ++refreshGeneration;\n try {\n const theme = await buildCurrentTheme();\n if (generation !== refreshGeneration) return;\n updatePreview(theme);\n updateDownloads(theme);\n } catch (error) {\n console.error(\"Unable to build the selected theme\", error);\n }\n}\n\n// CSS/JS editors start blank — anything typed here is appended to the generated preset (in both\n// the preview and the downloaded files) rather than replacing it.\nconst cssEditorView = createEditor(\n document.querySelector<HTMLElement>(\"#css-editor\")!,\n \"css\",\n \"\",\n () => debouncedUpdatePreview(),\n);\nconst jsEditorView = createEditor(\n document.querySelector<HTMLElement>(\"#js-editor\")!,\n \"javascript\",\n \"\",\n () => debouncedUpdatePreview(),\n);\n\nproviderSelect.addEventListener(\"change\", () => {\n if (activeEditor) retargetContentStylesheets(activeEditor, buildSelectedAssetUrl);\n void refreshAll();\n persistPreferences();\n});\n\ndownloadHtmlButton.addEventListener(\"click\", () => {\n downloadBlob(\n new Blob([getNormalizedEditorHtml()], { type: \"text/html;charset=utf-8\" }),\n `${slugifyExportName(activePresetName() ?? \"index\")}.html`,\n );\n});\n\ndownloadPackageButton.addEventListener(\"click\", () => {\n downloadPackageButton.disabled = true;\n void buildCurrentTheme()\n .then((theme) => {\n const files = buildDownloadFiles(theme);\n const archive = zipSync({\n \"index.html\": strToU8(getNormalizedEditorHtml()),\n \"theme.css\": strToU8(files.css),\n \"theme.js\": strToU8(files.js),\n });\n downloadBlob(\n new Blob([archive], { type: \"application/zip\" }),\n `${slugifyExportName(activePresetName() ?? \"canvas-theme\")}.zip`,\n );\n })\n .catch((error) => {\n console.error(\"Unable to build the theme package\", error);\n })\n .finally(() => {\n downloadPackageButton.disabled = false;\n });\n});\n\ncopyButton.addEventListener(\"click\", () => {\n void navigator.clipboard.writeText(getNormalizedEditorHtml());\n});\n\nregisterPantokenIconPack(tinymce.IconManager);\n\nwindow.addEventListener(\"pagehide\", () => {\n if (!activeEditor) return;\n try {\n sessionStorage.setItem(SESSION_DRAFT_KEY, JSON.stringify(captureCanvasThemePreset()));\n } catch {\n // Disabled storage cannot preserve this session's unsaved changes.\n }\n});\n\nvoid registerPantokenPlugin.then(async () => {\n const languagePack = tinymceLanguages[activeLocale];\n let language = \"en\";\n if (languagePack) {\n try {\n await languagePack[1]();\n language = languagePack[0];\n const messages = tinymce.i18n.getData()[language];\n if (messages) {\n tinymce.addI18n(\n language,\n Object.fromEntries(\n Object.entries(messages).map(([source, translation]) => [source, translation || source]),\n ),\n );\n }\n } catch (error) {\n console.warn(\"Unable to load the TinyMCE language pack; using English\", error);\n }\n }\n return tinymce\n .init({\n selector: \"#editor\",\n language,\n language_load: false,\n plugins:\n \"pantoken pantoken_content_classes placehold pantoken_a11y pantoken_save pantoken_sup_sub pantoken_source_toggle pantoken_fullscreen_footer pantoken_searchreplace_footer pantoken_visualblocks_footer image link lists table media autosave fullscreen quickbars searchreplace wordcount visualblocks\",\n toolbar: `${SAVE_TOOLBAR_NAME} undo redo | pantoken | fontsize blocks | bold italic underline forecolor backcolor ${SUP_SUB_TOOLBAR_NAME} | link image placehold | align | bullist numlist | removeformat table media`,\n menubar: false,\n theme: \"silver\",\n icons: PANTOKEN_ICON_PACK_NAME,\n branding: false,\n // Self-hosted TinyMCE 6+ requires a license_key; \"gpl\" opts into the GPL license terms.\n license_key: \"gpl\",\n browser_spellcheck: true,\n convert_urls: false,\n toolbar_mode: \"floating\",\n height: EDITOR_HEIGHT_PX,\n skin: false,\n content_css: false,\n // Not part of the footer's fixed control set (a11y, word count, html editor, fullscreen,\n // find & replace) — the breadcrumb is dropped rather than added as a sixth item.\n elementpath: false,\n block_formats: \"Paragraph=p;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6\",\n // Hides the image dialog's Upload tab so only a remote http/https URL can be inserted — no\n // local file picker, no base64 data-URI embedding.\n image_uploadtab: false,\n image_advtab: true,\n // TinyMCE's autosave plugin persists drafts to localStorage by default.\n autosave_ask_before_unload: true,\n autosave_interval: \"30s\",\n autosave_retention: \"30m\",\n autosave_restore_when_empty: false,\n // Mirrors the fixed toolbar's own formatting groups so the contextual popup never offers a\n // control the fixed toolbar lacks.\n quickbars_selection_toolbar: `bold italic underline forecolor backcolor ${SUP_SUB_TOOLBAR_NAME} | link | align | removeformat`,\n quickbars_insert_toolbar: \"quickimage quicktable media placehold\",\n quickbars_image_toolbar: \"alignleft aligncenter alignright | image\",\n setup(editor: Editor): void {\n editor.on(\"input change Undo Redo SetContent\", () => {\n syncThemeColorFromEditor();\n if (syncIconAssetsFromEditor()) void refreshAll();\n debouncedUpdatePreview();\n });\n },\n })\n .then((editors: Editor[]) => {\n activeEditor = editors[0];\n try {\n const saved = sessionStorage.getItem(SESSION_DRAFT_KEY);\n if (saved) {\n sessionStorage.removeItem(SESSION_DRAFT_KEY);\n const draft: unknown = JSON.parse(saved);\n if (isCanvasThemePreset(draft)) restoreCanvasThemePreset(draft);\n }\n } catch {\n // Disabled or corrupt storage leaves the editor's initial content unchanged.\n }\n syncThemeColorFromEditor();\n syncIconAssetsFromEditor();\n document.documentElement.dataset.pantokenScheme = includeDarkModeCheckbox.checked\n ? \"dark\"\n : \"light\";\n applyEditorTheme(activeEditor);\n void refreshAll();\n });\n });\n",
34
- "src/preferences.ts": "/** Persists this app's own editor/preview UI settings across reloads — never the authored content. */\nconst STORAGE_KEY = \"pantoken-canvas-theme-editor-preferences\";\n\n/** Shape of the persisted UI preferences blob. */\nexport interface StoredPreferences {\n layout: \"row\" | \"column\";\n previewWidth: \"large\" | \"medium\" | \"small\" | number;\n previewFullscreen: boolean;\n cdnProvider: string;\n tinymceConfig?: Record<string, unknown>;\n}\n\n/** Reads stored preferences, tolerating missing/corrupt/blocked storage. */\nexport function loadPreferences(): Partial<StoredPreferences> {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return {};\n const parsed: unknown = JSON.parse(raw);\n return typeof parsed === \"object\" && parsed !== null\n ? (parsed as Partial<StoredPreferences>)\n : {};\n } catch {\n return {};\n }\n}\n\n/** Persists preferences, silently no-op-ing if storage is unavailable. */\nexport function savePreferences(preferences: Partial<StoredPreferences>): void {\n try {\n const current = loadPreferences();\n const nextTinymceConfig = {\n ...(typeof current.tinymceConfig === \"object\" && current.tinymceConfig !== null\n ? current.tinymceConfig\n : {}),\n ...(typeof preferences.tinymceConfig === \"object\" && preferences.tinymceConfig !== null\n ? preferences.tinymceConfig\n : {}),\n };\n const nextPreferences = {\n ...current,\n ...preferences,\n tinymceConfig: nextTinymceConfig,\n };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(nextPreferences));\n } catch {\n // Private mode / storage disabled — preferences just won't persist across reloads.\n }\n}\n",
35
+ "src/main.ts": "// @ts-nocheck\n/**\n * Authors starter page templates against pantoken's classes: TinyMCE for editing (pinned/\n * configured to match instructure/canvas-lms's own RCE — see README), a custom \"Insert template\"\n * plugin for the bundled starters, and a live styled preview pane fed by the chosen CDN\n * provider/theme/mode. The page shell itself is built with pantoken (wrapper layout, tray, modal,\n * tabs) so this authoring tool dogfoods the same library it's previewing.\n */\nimport \"@pantoken/components/components.css\";\nimport \"@pantoken/components/utilities.css\";\nimport \"@pantoken/components/base.css\";\nimport \"@pantoken/components/icons/copy.css\";\nimport \"@pantoken/components/icons/app-window-mac.css\";\nimport \"@pantoken/components/icons/x.css\";\nimport \"@pantoken/components/icons/check.css\";\nimport \"@pantoken/components/icons/download.css\";\nimport \"@pantoken/components/icons/file-archive.css\";\nimport \"@pantoken/components/icons/sliders-horizontal.css\"; // app.html's -icon-sliders-horizontal button modifier\nimport \"@pantoken/components/icons/circle-question-mark.css\"; // app.html's -icon-circle-question-mark button modifier\nimport \"@pantoken/components/icons/rows-2.css\"; // app.html's layout-direction toggle, row state\nimport \"@pantoken/components/icons/columns-2.css\"; // app.html's layout-direction toggle, column state\nimport \"@pantoken/components/icons/monitor.css\"; // app.html's preview-width-picker, large\nimport \"@pantoken/components/icons/tablet.css\"; // app.html's preview-width-picker, medium\nimport \"@pantoken/components/icons/smartphone.css\"; // app.html's preview-width-picker, small\nimport \"@pantoken/components/icons/app-window.css\"; // app.html's preview popup button\nimport \"@pantoken/components/icons/maximize.css\"; // app.html's preview-fullscreen-toggle, off state\nimport \"@pantoken/components/icons/minimize.css\"; // app.html's preview-fullscreen-toggle, on state\nimport \"@pantoken/components/icons/moon.css\"; // app.html's preview-scheme-toggle, light state\nimport \"@pantoken/components/icons/sun.css\"; // app.html's preview-scheme-toggle, dark state\nimport \"@pantoken/components/icons/rotate-ccw.css\";\nimport adaptiveTokensCss from \"@pantoken/css/style.lean.css?inline\";\nimport rebrandLightTokensCss from \"@pantoken/css/style.rebrand.light.lean.css?inline\";\nimport canvasTokensCss from \"@pantoken/css/style.canvas.lean.css?inline\";\nimport canvasHighContrastTokensCss from \"@pantoken/css/style.canvas-high-contrast.lean.css?inline\";\nimport baseCss from \"@pantoken/components/base.css?inline\";\nimport componentIconsCss from \"@pantoken/components/component-icons.css?inline\";\nimport componentsCss from \"@pantoken/components/components.css?inline\";\nimport utilitiesCss from \"@pantoken/components/utilities.css?inline\";\nimport fontsCss from \"@pantoken/components/fonts.css?inline\";\nimport logoPainterCss from \"@pantoken/plugin-custom-components/logo.css?inline\";\nimport customComponentsCss from \"@pantoken/plugin-custom-components/custom-components.css?inline\";\nconst fontAssetUrls = import.meta.glob<string>(\n \"/node_modules/@pantoken/components/assets/fonts/**/*.woff2\",\n { eager: true, query: \"?url\", import: \"default\" },\n);\nconst localFontsCss = fontsCss.replace(/\\.\\.\\/assets\\/fonts\\/([^\"\\s)]+\\.woff2)/gu, (_, path: string) => {\n const url = fontAssetUrls[`/node_modules/@pantoken/components/assets/fonts/${path}`];\n if (!url) throw new Error(`Missing local font asset: ${path}`);\n return url;\n});\nimport localInteractionsJs from \"@pantoken/interactions/interactions.iife.js?raw\";\nimport componentCapabilities from \"@pantoken/interactions/component-capabilities.json\";\nimport { componentNeedsInteractions } from \"./component-availability.ts\";\nimport { InlineDocument } from \"./inline-document.ts\";\nimport { trackPreviewChanges } from \"./preview-state.ts\";\n// A resolved asset URL for a real <script> tag — a dynamic import() of a pure side-effect module\n// from a \"sideEffects\": false package can get tree-shaken out of a production bundle.\nimport interactionsIifeUrl from \"@pantoken/interactions/interactions.iife.js?url\";\n\nimport \"@pantoken/plugin-custom-components/custom-components.css\";\nimport \"@pantoken/plugin-layouts/layouts.css\";\nimport \"./app.css\";\nimport appHtml from \"./app.html?raw\";\nimport { STRINGS } from \"./strings.ts\";\nimport { LOCALE_STRINGS } from \"./locale-strings.ts\";\nimport { LOCALE_DIRS } from \"./locale-dirs.ts\";\nimport { TINYMCE_LOCALE_STRINGS } from \"./tinymce-locale-strings.ts\";\nimport { selectEditorLocale } from \"./locale.ts\";\nimport tinymce from \"tinymce\";\nimport \"tinymce/models/dom/model\";\nimport \"tinymce/themes/silver/theme\";\nimport \"tinymce/icons/default\";\nimport \"tinymce/plugins/image\";\nimport \"tinymce/plugins/link\";\nimport \"tinymce/plugins/lists\";\nimport \"tinymce/plugins/autosave\";\nimport \"tinymce/plugins/fullscreen\";\nimport \"tinymce/plugins/quickbars\";\nimport \"tinymce/plugins/searchreplace\";\nimport \"tinymce/plugins/wordcount\";\nimport \"tinymce/plugins/table\";\nimport \"tinymce/plugins/media\";\nimport \"tinymce/plugins/visualblocks\";\nimport nextGenSkinCss from \"@pantoken/tinymce/skins/next-gen/skin.css?inline\";\nimport nextGenContentCss from \"@pantoken/tinymce/skins/next-gen/content.css?inline\";\nimport canvasSkinCss from \"@pantoken/tinymce/skins/canvas/skin.css?inline\";\nimport canvasContentCss from \"@pantoken/tinymce/skins/canvas/content.css?inline\";\nimport canvasHighContrastSkinCss from \"@pantoken/tinymce/skins/canvas-high-contrast/skin.css?inline\";\nimport canvasHighContrastContentCss from \"@pantoken/tinymce/skins/canvas-high-contrast/content.css?inline\";\nimport {\n buildTheme,\n CDN_PROVIDERS,\n DEFAULT_CDN_PROVIDER_ID,\n defaultThemeCssAssets,\n type ThemeMode,\n type ThemeVariant,\n} from \"@pantoken/canvas-theme-editor\";\nimport { Check, ChevronDown, createElement, Languages, MoonStar, Palette, SunMedium } from \"lucide\";\n// Inlined (not CDN-fetched) so the live preview's color swap never depends on a network round trip.\nimport {\n COLOR_KEYS,\n CUSTOM_COLOR_KEY,\n customColorCss,\n customThemeColorsCss,\n isHexColor,\n parseHexColor,\n type PantokenColorNamespace,\n} from \"@pantoken/plugin-custom-theme-colors\";\nimport type { Editor } from \"tinymce\";\nimport { basicSetup, EditorView } from \"codemirror\";\nimport { css } from \"@codemirror/lang-css\";\nimport { html } from \"@codemirror/lang-html\";\nimport { javascript } from \"@codemirror/lang-javascript\";\nimport { strToU8, zipSync } from \"fflate\";\nimport { buildFileUrl, type CdnFile } from \"@pantoken/cdn\";\nimport {\n CONTENT_CLASSES_PLUGIN_NAME,\n createContentClassesPlugin,\n createFullscreenFooterPlugin,\n createPantokenPlugin,\n createSearchReplaceFooterPlugin,\n createSupSubPlugin,\n createVisualBlocksFooterPlugin,\n FULLSCREEN_FOOTER_PLUGIN_NAME,\n getIconCdnFile,\n getUsedIconCdnFiles,\n getLogoCdnFile,\n getUsedLogoCdnFiles,\n injectContentStylesheet,\n listComponents,\n listUtilities,\n loadAllIcons,\n logos,\n PANTOKEN_ICON,\n PANTOKEN_ICON_PACK_NAME,\n products,\n registerPantokenIconPack,\n retargetContentStylesheets,\n pantokenHtmlLinter,\n pantokenHtmlCompletion,\n SEARCHREPLACE_FOOTER_PLUGIN_NAME,\n SUP_SUB_PLUGIN_NAME,\n SUP_SUB_TOOLBAR_NAME,\n VISUALBLOCKS_FOOTER_PLUGIN_NAME,\n type TaggedIcon,\n} from \"@pantoken/tinymce\";\nimport {\n createSourceTogglePlugin,\n SOURCE_TOGGLE_PLUGIN_NAME,\n type SourceTogglePluginApi,\n} from \"@pantoken/tinymce-codemirror\";\nimport {\n buildPlaceholdImage,\n createPlaceholdPlugin,\n PLACEHOLD_PLUGIN_NAME,\n} from \"@pantoken/tinymce-placehold\";\nimport {\n A11Y_PLUGIN_NAME,\n createA11yPlugin,\n type A11yCheckConfig,\n type A11yColorScheme,\n} from \"@pantoken/tinymce-a11y\";\nimport {\n createSavePlugin,\n SAVE_PLUGIN_NAME,\n SAVE_TOOLBAR_NAME,\n slugifyExportName,\n type SavePluginApi,\n} from \"@pantoken/tinymce-save\";\nimport { loadPreferences, savePreferences } from \"./preferences.ts\";\n\n// Shared with the toolbar's source-view editor so both stay the same size.\nconst EDITOR_HEIGHT_PX = 400;\n// This app's pantoken instance, and the one it accepts theme messages from. Two pantoken instances\n// can share a page (this editor embedded in the docs site being the case that forced the issue), so\n// both sides tag their messages and ignore anything addressed elsewhere.\nconst EDITOR_INSTANCE = \"canvas-theme-editor\";\nconst HOST_INSTANCE = \"docs\";\n// Canvas's content area caps out at this width — the preview mirrors that constraint.\nconst CANVAS_CONTENT_MAX_WIDTH = \"59.25rem\";\n// All 13 `[data-pantoken-color=\"…\"]` color-remap rules, computed once — editable Canvas content,\n// the shell, and the preview can each own an independent color scope. `resetSelector`\n// pins the theme tray's own subtree (buttons, swatches) and the standalone shell's menus (its\n// color swatches) back to true colors, immune to whatever color the chrome currently has active —\n// the shell's brand mark stays outside it so it follows the chrome color. See\n// plugins/pantoken/custom-theme-colors.\nconst CUSTOM_THEME_COLORS_CSS = customThemeColorsCss(undefined, {\n selector: \"\",\n resetSelector: \"#theme-tray, #canvas-rce-shell .canvas-rce-shell__actions\",\n});\n// The scaffold's own chrome (toolbar, buttons outside the tray) mirrors the embedding docs page's\n// active theme and color — entirely independent of the preview and the tray, which drive their own\n// theme/color separately below. The color remaps follow this theme block in the cascade so a parent\n// color change overrides the theme's root token declarations.\nconst chromeThemeStyle = document.createElement(\"style\");\ndocument.head.append(chromeThemeStyle);\nconst customThemeColorsStyle = document.createElement(\"style\");\ncustomThemeColorsStyle.textContent = CUSTOM_THEME_COLORS_CSS;\ndocument.head.append(customThemeColorsStyle);\n// The chrome's own `custom` scale, independent of the tray's; empty unless the chrome is on custom.\nconst chromeCustomColorStyle = document.createElement(\"style\");\ndocument.head.append(chromeCustomColorStyle);\n// Seeded with navy100 so switching to Custom starts from the default brand color.\nconst DEFAULT_CUSTOM_COLOR = \"#4c79aa\";\nlet chromeCustomColor = DEFAULT_CUSTOM_COLOR;\nlet syncShellCustomColor: (() => void) | undefined;\n\n/** Fill the Custom swatch's center with a picked hex; the untouched default leaves it empty. */\nfunction syncCustomSwatch(swatch: HTMLElement, hex: string): void {\n if (hex === DEFAULT_CUSTOM_COLOR) swatch.style.removeProperty(\"--custom-swatch-fill\");\n else swatch.style.setProperty(\"--custom-swatch-fill\", hex);\n}\nconst preferences = loadPreferences();\nlet previewPopup: Window | null = null;\nlet previewPopupCloseTimer: number | undefined;\nlet previewPopupStylePairs: Array<{\n source: HTMLStyleElement;\n clone: HTMLStyleElement;\n}> = [];\nconst LOCAL_PROVIDER_ID = \"none\";\nconst INLINE_PROVIDER_ID = \"inline\";\nconst inlineDocument = new InlineDocument();\nlet inlineRendered = false;\nlet applyingInline = false;\nlet lastInlineHtml = \"\";\nlet lastInlineCss = \"\";\n// `import.meta.env.DEV` is baked in at build time, so it's `false` for any `vite build` output —\n// including docs' Canvas RCE preview, which is always built for production yet only ever served on\n// localhost. Fall back to a hostname check so a local, non-CDN preview is detected either way.\nconst isLocalPreview =\n import.meta.env.DEV || [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(window.location.hostname);\nconst LOCAL_COMPONENT_CSS = [\n baseCss,\n componentIconsCss,\n componentsCss,\n customComponentsCss,\n utilitiesCss,\n logoPainterCss,\n CUSTOM_THEME_COLORS_CSS,\n localFontsCss,\n].join(\"\\n\");\n// pantoken's token sheets express dark mode as `light-dark()`, which lightningcss (this bundle's\n// minifier) downlevels to two OS-preference-gated control variables — fine for theme.css (a real\n// Canvas page can't force a scheme anyway), but it means `color-scheme`/`data-pantoken-scheme`\n// alone can't force the *preview's* scheme against the visitor's own OS setting. This block\n// re-derives those two control variables from `data-pantoken-scheme` so the preview's light/dark\n// toggle actually overrides it. `--lightningcss-light`/`-dark` are lightningcss's fixed,\n// undocumented-but-stable names for this downlevel — see the vendored `--lightningcss-*` custom\n// properties in @pantoken/css's built output.\nconst PREVIEW_SCHEME_FORCE_CSS = `\n[data-pantoken-scheme=\"light\"] { --lightningcss-light: initial; --lightningcss-dark: ; }\n[data-pantoken-scheme=\"dark\"] { --lightningcss-light: ; --lightningcss-dark: initial; }\n`;\n\n/** Minimal `{{key}}` substitution — every key must exist in `strings`, values are inserted raw. */\nfunction render(template: string, strings: Record<string, string>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key: string) => strings[key] ?? match);\n}\n\nfunction syncPreviewPopupChrome(): void {\n if (!previewPopup || previewPopup.closed) return;\n const popupDocument = previewPopup.document;\n for (const { source, clone } of previewPopupStylePairs) clone.textContent = source.textContent;\n for (const attribute of [\n \"lang\",\n \"dir\",\n \"data-pantoken-instance\",\n \"data-pantoken-theme\",\n \"data-pantoken-scheme\",\n \"data-pantoken-color\",\n ]) {\n const value = document.documentElement.getAttribute(attribute);\n if (value === null) popupDocument.documentElement.removeAttribute(attribute);\n else popupDocument.documentElement.setAttribute(attribute, value);\n }\n popupDocument.documentElement.style.colorScheme = document.documentElement.style.colorScheme;\n}\n\nfunction createShellIcon(icon: Parameters<typeof createElement>[0]): SVGSVGElement {\n const svg = createElement(icon, { width: 16, height: 16, \"stroke-width\": 2 });\n svg.classList.add(\"canvas-rce-shell__icon\");\n return svg;\n}\n\nfunction syncBrowserMetadata(): void {\n const themeColorMeta =\n document.querySelector<HTMLMetaElement>('meta[name=\"theme-color\"]') ??\n document.createElement(\"meta\");\n themeColorMeta.name = \"theme-color\";\n const backgroundColor = getComputedStyle(document.documentElement).backgroundColor;\n if (backgroundColor) themeColorMeta.content = backgroundColor;\n if (!themeColorMeta.parentElement) document.head.append(themeColorMeta);\n\n const favicon = document.querySelector<HTMLLinkElement>(\n 'link[rel=\"icon\"][data-pantoken-themed-icon]',\n );\n if (!favicon) return;\n const accentColor = getComputedStyle(document.documentElement)\n .getPropertyValue(\"--instui-primitive-color-navy-navy100\")\n .trim();\n if (!accentColor) return;\n const mark = PANTOKEN_ICON.replace(\n \"<svg \",\n '<svg x=\"32\" y=\"32\" width=\"64\" height=\"64\" ',\n ).replaceAll(/fill=\"[^\"]+\"/gu, 'fill=\"#fff\"');\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 128 128\"><rect width=\"128\" height=\"128\" rx=\"24\" fill=\"${accentColor}\"/>${mark}</svg>`;\n favicon.href = `data:image/svg+xml,${encodeURIComponent(svg)}`;\n}\n\nfunction setupStandaloneAppShell(): void {\n if (window.self !== window.top || document.getElementById(\"canvas-rce-shell\")) return;\n\n document.body.classList.add(\"canvas-rce-shell-enabled\");\n document.title =\n document.querySelector<HTMLMetaElement>('meta[name=\"application-name\"]')?.content ||\n \"Canvas Theme Editor\";\n\n const shell = document.createElement(\"header\");\n shell.id = \"canvas-rce-shell\";\n shell.className = \"canvas-rce-shell\";\n\n const brand = document.createElement(\"div\");\n brand.className = \"canvas-rce-shell__brand\";\n\n const brandMark = document.createElement(\"a\");\n brandMark.className = \"instui-button -color-primary -shape-square canvas-rce-shell__brand-mark\";\n brandMark.href = \"https://pantoken.app/\";\n brandMark.target = \"_blank\";\n brandMark.rel = \"noopener noreferrer\";\n brandMark.setAttribute(\"aria-label\", \"Pantoken (opens pantoken.app in a new tab)\");\n brandMark.innerHTML = PANTOKEN_ICON;\n\n const brandText = document.createElement(\"div\");\n brandText.className = \"canvas-rce-shell__brand-text instui-hidden-max-sm\";\n const eyebrow = document.createElement(\"span\");\n eyebrow.className = \"canvas-rce-shell__eyebrow\";\n eyebrow.textContent = \"Pantoken\";\n const title = document.createElement(\"strong\");\n title.textContent = \"Canvas Theme Editor\";\n brandText.append(eyebrow, title);\n brand.append(brandMark, brandText);\n\n const actions = document.createElement(\"div\");\n actions.className = \"canvas-rce-shell__actions\";\n\n const localeMenu = document.createElement(\"details\");\n localeMenu.className = \"canvas-rce-shell__menu\";\n const localeSummary = document.createElement(\"summary\");\n localeSummary.className = \"canvas-rce-shell__summary instui-button -color-tertiary\";\n localeSummary.append(createShellIcon(Languages));\n const localeLabel = document.createElement(\"span\");\n localeLabel.className = \"canvas-rce-shell__label instui-hidden-max-md\";\n const localeLocale = (\n document.documentElement.lang || navigator.languages?.[0] || navigator.language || \"en-US\"\n ).trim();\n let localeText = \"English\";\n try {\n // Names itself, in its own script (matching the picker's own option labels below).\n localeText = new Intl.DisplayNames([localeLocale], { type: \"language\" }).of(localeLocale) ?? localeText;\n } catch {\n localeText = localeLocale.split(\"-\")[0].toUpperCase();\n }\n localeLabel.textContent = localeText;\n localeSummary.setAttribute(\"aria-label\", localeText);\n localeSummary.append(localeLabel, createShellIcon(ChevronDown));\n\n const localePanel = document.createElement(\"div\");\n localePanel.className = \"canvas-rce-shell__panel\";\n const localePanelScroll = document.createElement(\"div\");\n localePanelScroll.className = \"canvas-rce-shell__panel-scroll\";\n const availableLocales = [\"en\", ...Object.keys(LOCALE_STRINGS).sort()];\n const localeDisplayNames = new Intl.DisplayNames(availableLocales, { type: \"language\" });\n for (const locale of availableLocales) {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.className = \"canvas-rce-shell__option\";\n option.dataset.locale = locale;\n const optionLabel = document.createElement(\"span\");\n // Each locale names itself, in its own script — matching the summary's own display name.\n optionLabel.textContent =\n new Intl.DisplayNames([locale], { type: \"language\" }).of(locale) ??\n localeDisplayNames.of(locale) ??\n locale;\n const optionMark = document.createElement(\"span\");\n optionMark.className = \"canvas-rce-shell__mark\";\n optionMark.append(createShellIcon(Check));\n option.append(optionLabel, optionMark);\n if (document.documentElement.lang === locale || (!document.documentElement.lang && locale === \"en\")) {\n option.classList.add(\"is-selected\");\n }\n option.addEventListener(\"click\", () => {\n if (locale === document.documentElement.lang) {\n localeMenu.removeAttribute(\"open\");\n return;\n }\n try {\n localStorage.setItem(LOCALE_STORAGE_KEY, locale);\n } catch {\n // Private mode / storage disabled — the reload below still applies it for this load.\n }\n // The app's own strings are only ever resolved once, at the initial `render()` call — a\n // reload re-runs that with the newly persisted locale instead of trying to re-render (and\n // re-initialize TinyMCE, the popup, etc.) in place.\n window.location.reload();\n });\n localePanelScroll.append(option);\n }\n localePanel.append(localePanelScroll);\n localeMenu.append(localeSummary, localePanel);\n\n const themeMenu = document.createElement(\"details\");\n themeMenu.className = \"canvas-rce-shell__menu\";\n const themeSummary = document.createElement(\"summary\");\n themeSummary.className = \"canvas-rce-shell__summary instui-button -color-tertiary\";\n themeSummary.append(createShellIcon(Palette));\n const themeLabel = document.createElement(\"span\");\n themeLabel.className = \"canvas-rce-shell__label instui-hidden-max-md\";\n themeLabel.textContent = activeStrings.themeLabel;\n themeSummary.setAttribute(\"aria-label\", activeStrings.themeLabel);\n themeSummary.append(themeLabel, createShellIcon(ChevronDown));\n\n const themePanel = document.createElement(\"div\");\n themePanel.className = \"canvas-rce-shell__panel\";\n const themePanelScroll = document.createElement(\"div\");\n themePanelScroll.className = \"canvas-rce-shell__panel-scroll\";\n\n const appearanceGroup = document.createElement(\"div\");\n appearanceGroup.className = \"canvas-rce-shell__group\";\n const appearanceTitle = document.createElement(\"span\");\n appearanceTitle.className = \"canvas-rce-shell__group-title\";\n appearanceTitle.textContent = activeStrings.appearanceLabel;\n appearanceGroup.append(appearanceTitle);\n // Shared by the click handler below and the initial application at the end of this function.\n const applyAppearance = (appearance: \"light\" | \"dark\"): void => {\n document.body.dataset.appearanceMode = appearance;\n document.documentElement.style.colorScheme = appearance;\n document.documentElement.dataset.pantokenScheme = appearance;\n if (typeof applyChromeTheme === \"function\") {\n applyChromeTheme(selectedTheme ?? \"rebrand\", appearance);\n }\n for (const candidate of themePanel.querySelectorAll<HTMLButtonElement>(\"[data-appearance]\")) {\n candidate.classList.toggle(\"is-selected\", candidate.dataset.appearance === appearance);\n }\n };\n for (const [appearance, label, icon] of [\n [\"light\", activeStrings.appearanceLightLabel, SunMedium],\n [\"dark\", activeStrings.appearanceDarkLabel, MoonStar],\n ] as const) {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.className = \"canvas-rce-shell__option\";\n option.dataset.appearance = appearance;\n const text = document.createElement(\"span\");\n text.textContent = label;\n const mark = document.createElement(\"span\");\n mark.className = \"canvas-rce-shell__mark\";\n mark.append(createShellIcon(icon));\n option.append(text, mark);\n if (appearance === \"light\") option.classList.add(\"is-selected\");\n option.addEventListener(\"click\", () => {\n applyAppearance(appearance);\n applyEditorTheme(activeEditor);\n themeMenu.removeAttribute(\"open\");\n });\n appearanceGroup.append(option);\n }\n\n const colorGroup = document.createElement(\"div\");\n colorGroup.className = \"canvas-rce-shell__group\";\n const colorTitle = document.createElement(\"span\");\n colorTitle.className = \"canvas-rce-shell__group-title\";\n colorTitle.textContent = activeStrings.colorLabel;\n colorGroup.append(colorTitle);\n for (const color of [...COLOR_KEYS, CUSTOM_COLOR_KEY]) {\n const option = document.createElement(\"button\");\n option.type = \"button\";\n option.className = \"canvas-rce-shell__option\";\n option.dataset.color = color;\n const swatch = document.createElement(\"span\");\n swatch.className = \"theme-picker__swatch\";\n swatch.dataset.swatch = color;\n const text = document.createElement(\"span\");\n const colorKey = `color${color.charAt(0).toUpperCase()}${color.slice(1)}Label`;\n text.textContent = activeStrings[colorKey] ?? color.charAt(0).toUpperCase() + color.slice(1);\n const mark = document.createElement(\"span\");\n mark.className = \"canvas-rce-shell__mark\";\n mark.append(createShellIcon(Check));\n option.append(swatch, text, mark);\n // \"navy\" is the app's actual default (see `selectedColor`/`applyChromeColor(\"navy\")` below) —\n // without this the picker showed no color as selected until the user picked one explicitly.\n if (color === \"navy\") option.classList.add(\"is-selected\");\n option.addEventListener(\"click\", () => {\n applyChromeColor(color);\n // Custom stays open so the hex field below is reachable.\n if (color !== CUSTOM_COLOR_KEY) themeMenu.removeAttribute(\"open\");\n });\n colorGroup.append(option);\n }\n\n const customRow = document.createElement(\"div\");\n customRow.className = \"theme-picker__custom canvas-rce-shell__custom\";\n customRow.hidden = true;\n const customLabel = document.createElement(\"label\");\n customLabel.htmlFor = \"canvas-rce-shell-custom-hex\";\n customLabel.textContent = activeStrings.customColorInputLabel;\n const customInputs = document.createElement(\"div\");\n customInputs.className = \"theme-picker__custom-inputs\";\n const customPicker = document.createElement(\"input\");\n customPicker.type = \"color\";\n customPicker.setAttribute(\"aria-label\", activeStrings.customColorInputLabel);\n const customHex = document.createElement(\"input\");\n customHex.type = \"text\";\n customHex.id = \"canvas-rce-shell-custom-hex\";\n customHex.className = \"instui-text-input -size-sm\";\n customHex.maxLength = 7;\n customHex.spellcheck = false;\n customHex.autocomplete = \"off\";\n customInputs.append(customPicker, customHex);\n customRow.append(customLabel, customInputs);\n colorGroup.append(customRow);\n\n const onShellCustomInput = (value: string): void => {\n const valid = isHexColor(value);\n customHex.classList.toggle(\"-invalid\", !valid);\n customHex.toggleAttribute(\"aria-invalid\", !valid);\n if (valid) applyChromeColor(CUSTOM_COLOR_KEY, value);\n };\n customPicker.addEventListener(\"input\", () => onShellCustomInput(customPicker.value));\n customHex.addEventListener(\"input\", () => onShellCustomInput(customHex.value));\n\n syncShellCustomColor = () => {\n const color = document.documentElement.dataset.pantokenColor;\n for (const candidate of themePanel.querySelectorAll<HTMLButtonElement>(\"[data-color]\")) {\n candidate.classList.toggle(\"is-selected\", candidate.dataset.color === color);\n }\n customRow.hidden = color !== CUSTOM_COLOR_KEY;\n customPicker.value = chromeCustomColor;\n if (!isHexColor(customHex.value) || parseHexColor(customHex.value) !== chromeCustomColor) {\n customHex.value = chromeCustomColor;\n }\n syncCustomSwatch(colorGroup.querySelector('[data-swatch=\"custom\"]')!, chromeCustomColor);\n };\n syncShellCustomColor();\n\n themePanelScroll.append(appearanceGroup, colorGroup);\n themePanel.append(themePanelScroll);\n themeMenu.append(themeSummary, themePanel);\n actions.append(localeMenu, themeMenu);\n shell.append(brand, actions);\n document.body.prepend(shell);\n\n // Native <details> doesn't close on its own for either of these — without this a click\n // elsewhere on the page, or Escape, leaves the panel open.\n const shellMenus = [localeMenu, themeMenu];\n document.addEventListener(\"click\", (event) => {\n for (const menu of shellMenus) {\n if (menu.open && !menu.contains(event.target as Node)) menu.removeAttribute(\"open\");\n }\n });\n document.addEventListener(\"keydown\", (event) => {\n if (event.key !== \"Escape\") return;\n for (const menu of shellMenus) {\n if (!menu.open) continue;\n menu.removeAttribute(\"open\");\n menu.querySelector<HTMLElement>(\"summary\")?.focus();\n }\n });\n\n applyAppearance(\"light\");\n}\n\n/** Persists the shell's own locale choice — never the authored content's own `lang`/`dir`. */\nconst LOCALE_STORAGE_KEY = \"pantoken-canvas-theme-editor-locale\";\nconst SESSION_DRAFT_KEY = \"pantoken-canvas-theme-editor-session-draft\";\n\n/** Reads the docs locale when embedded, otherwise the standalone shell's saved choice. */\nfunction loadLocale(): string {\n const embedded = window.self !== window.top;\n const queryLocale = embedded ? new URLSearchParams(window.location.search).get(\"locale\") : null;\n let storedLocale: string | null = null;\n try {\n if (!embedded) storedLocale = localStorage.getItem(LOCALE_STORAGE_KEY);\n } catch {\n // Storage can be disabled; the scaffold's initial HTML locale is still available.\n }\n return selectEditorLocale(\n embedded,\n queryLocale,\n storedLocale,\n document.documentElement.lang,\n LOCALE_DIRS,\n );\n}\n\nconst activeLocale = loadLocale();\nconst tinymceStrings = TINYMCE_LOCALE_STRINGS[activeLocale] ?? {};\nconst tinymceLanguages: Record<string, [string, () => Promise<unknown>]> = {\n ar: [\"ar\", () => import(\"tinymce-i18n/langs8/ar.js\")],\n hy: [\"hy\", () => import(\"tinymce-i18n/langs8/hy.js\")],\n ca: [\"ca\", () => import(\"tinymce-i18n/langs8/ca.js\")],\n da: [\"da\", () => import(\"tinymce-i18n/langs8/da.js\")],\n nl: [\"nl\", () => import(\"tinymce-i18n/langs8/nl.js\")],\n fi: [\"fi\", () => import(\"tinymce-i18n/langs8/fi.js\")],\n fr: [\"fr-FR\", () => import(\"tinymce-i18n/langs8/fr-FR.js\")],\n \"fr-CA\": [\"fr-FR\", () => import(\"tinymce-i18n/langs8/fr-FR.js\")],\n de: [\"de\", () => import(\"tinymce-i18n/langs8/de.js\")],\n el: [\"el\", () => import(\"tinymce-i18n/langs8/el.js\")],\n he: [\"he-IL\", () => import(\"tinymce-i18n/langs8/he-IL.js\")],\n hu: [\"hu-HU\", () => import(\"tinymce-i18n/langs8/hu-HU.js\")],\n is: [\"is-IS\", () => import(\"tinymce-i18n/langs8/is-IS.js\")],\n id: [\"id\", () => import(\"tinymce-i18n/langs8/id.js\")],\n it: [\"it\", () => import(\"tinymce-i18n/langs8/it.js\")],\n ja: [\"ja\", () => import(\"tinymce-i18n/langs8/ja.js\")],\n ko: [\"ko-KR\", () => import(\"tinymce-i18n/langs8/ko-KR.js\")],\n nb: [\"nb-NO\", () => import(\"tinymce-i18n/langs8/nb-NO.js\")],\n fa: [\"fa\", () => import(\"tinymce-i18n/langs8/fa.js\")],\n pl: [\"pl\", () => import(\"tinymce-i18n/langs8/pl.js\")],\n pt: [\"pt-PT\", () => import(\"tinymce-i18n/langs8/pt-PT.js\")],\n \"pt-BR\": [\"pt-BR\", () => import(\"tinymce-i18n/langs8/pt-BR.js\")],\n ru: [\"ru\", () => import(\"tinymce-i18n/langs8/ru.js\")],\n \"zh-Hans\": [\"zh-CN\", () => import(\"tinymce-i18n/langs8/zh-CN.js\")],\n sl: [\"sl-SI\", () => import(\"tinymce-i18n/langs8/sl-SI.js\")],\n es: [\"es\", () => import(\"tinymce-i18n/langs8/es.js\")],\n sv: [\"sv-SE\", () => import(\"tinymce-i18n/langs8/sv-SE.js\")],\n th: [\"th-TH\", () => import(\"tinymce-i18n/langs8/th-TH.js\")],\n \"zh-Hant\": [\"zh-TW\", () => import(\"tinymce-i18n/langs8/zh-TW.js\")],\n tr: [\"tr\", () => import(\"tinymce-i18n/langs8/tr.js\")],\n uk: [\"uk\", () => import(\"tinymce-i18n/langs8/uk.js\")],\n vi: [\"vi\", () => import(\"tinymce-i18n/langs8/vi.js\")],\n cy: [\"cy\", () => import(\"tinymce-i18n/langs8/cy.js\")],\n};\n// A missing key/locale in `LOCALE_STRINGS` falls back to English — see generate.ts's own comment.\nconst activeStrings: Record<string, string> = { ...STRINGS, ...LOCALE_STRINGS[activeLocale] };\ndocument.documentElement.lang = activeLocale;\ndocument.documentElement.dir = LOCALE_DIRS[activeLocale] ?? \"ltr\";\n\ndocument.querySelector<HTMLDivElement>(\"#app\")!.innerHTML = render(appHtml, activeStrings);\nconst interactionsScript = document.createElement(\"script\");\ninteractionsScript.src = interactionsIifeUrl;\ndocument.head.append(interactionsScript);\n\n// Shared CSS assets array — tracks stylesheets for dynamic injection and generated theme CSS.\nconst currentAssets: CdnFile[] = [];\nconst onMissingAsset = () => void refreshAll();\nlet availableIcons: TaggedIcon[] = [];\nconst inlineAssetContents = new Map<string, string>();\nlet refreshGeneration = 0;\n// Covers `plugin-logos`, the core component icons (both real dependencies for any scaffolded\n// project), and the icon packages `build-canvas-rce.ts` vendors into `node_modules` purely so this\n// docs-hosted preview's \"None (inline)\" provider doesn't have to hit a CDN for any glyph.\nconst localAssetUrls = import.meta.glob<string>(\n [\n \"/node_modules/@pantoken/components/dist/icons/*.css\",\n \"/node_modules/@pantoken/plugin-{logos,simple-icons,lucide-lab,custom-icons,custom-components}/dist/**/*.css\",\n ],\n { eager: true, import: \"default\", query: \"?url\" },\n);\n\nfunction buildSelectedAssetUrl(file: CdnFile): string {\n if (![LOCAL_PROVIDER_ID, INLINE_PROVIDER_ID].includes(providerSelect.value)) {\n return buildFileUrl(file, providerSelect.value);\n }\n const localUrl = localAssetUrls[`/node_modules/${file.package}/${file.path}`];\n return localUrl ?? buildFileUrl(file);\n}\n\nconst editorThemeCss: Record<\n ThemeVariant,\n { skin: string; content: string }\n> = {\n rebrand: { skin: nextGenSkinCss, content: nextGenContentCss },\n canvas: { skin: canvasSkinCss, content: canvasContentCss },\n canvasHighContrast: {\n skin: canvasHighContrastSkinCss,\n content: canvasHighContrastContentCss,\n },\n};\n\nconst editorSkinStyle = document.createElement(\"style\");\ndocument.head.append(editorSkinStyle);\nlet editorContentStyle: HTMLStyleElement | undefined;\n\nfunction isThemeColor(color: unknown): color is PantokenColorNamespace {\n return color === CUSTOM_COLOR_KEY || isShippedColor(color);\n}\n\n/** The docs host only ever offers the 13 shipped scales, so the chrome never takes `custom`. */\nfunction isShippedColor(color: unknown): color is (typeof COLOR_KEYS)[number] {\n return typeof color === \"string\" && (COLOR_KEYS as readonly string[]).includes(color);\n}\n\n/** Applies the selected static skin to TinyMCE's chrome and iframe document. */\nfunction applyEditorTheme(editor: Editor | undefined): void {\n const css = editorThemeCss[selectedTheme];\n editorSkinStyle.textContent = css.skin;\n\n if (!editor) return;\n const editorDocument = editor.getDoc();\n if (!editorContentStyle || editorContentStyle.ownerDocument !== editorDocument) {\n editorContentStyle?.remove();\n editorContentStyle = editorDocument.createElement(\"style\");\n editorDocument.head.append(editorContentStyle);\n }\n const tokensCss = selectedTheme === \"canvas\" ? canvasTokensCss\n : selectedTheme === \"canvasHighContrast\" ? canvasHighContrastTokensCss\n : adaptiveTokensCss;\n editorContentStyle.textContent = [tokensCss, LOCAL_COMPONENT_CSS, css.content, PREVIEW_SCHEME_FORCE_CSS,\n 'body.mce-content-body > [data-pantoken-color] { background-color: var(--instui-color-background-container) !important; }',\n ':has(> [data-pantoken-inline-generated=\"::before\"])::before, :has(> [data-pantoken-inline-generated=\"::after\"])::after { content: none !important; }',\n ].join(\"\\n\");\n // The content CSS's dark rules key off this attribute on the iframe's own root, which doesn't\n // inherit it from the host document.\n const scheme = document.documentElement.dataset.pantokenScheme === \"dark\" ? \"dark\" : \"light\";\n editorDocument.documentElement.dataset.pantokenScheme = scheme;\n editorDocument.documentElement.style.colorScheme = scheme;\n}\n\n/** Temporarily overrides the editing iframe's scheme so the a11y checker can test contrast under\n * both light and dark; the next `applyEditorTheme` call restores the chrome-mirrored value. */\nfunction forceEditorColorScheme(scheme: A11yColorScheme): void {\n if (!activeEditor) return;\n activeEditor.getDoc().documentElement.dataset.pantokenScheme = scheme;\n activeEditor.getDoc().documentElement.style.colorScheme = scheme;\n}\n\nfunction getEditorColorScheme(): A11yColorScheme {\n return activeEditor?.getDoc().documentElement.dataset.pantokenScheme === \"dark\"\n ? \"dark\"\n : \"light\";\n}\n\n/** Only \"rebrand\" ships a dark scheme (`syncDarkModeAvailability` hides/disables the checkbox for\n * the others), so the a11y checker only ever tests both schemes for it. */\nconst a11yRuntimeConfig: A11yCheckConfig = {\n setColorScheme: forceEditorColorScheme,\n getColorScheme: getEditorColorScheme,\n get colorSchemes(): readonly A11yColorScheme[] {\n return selectedTheme === \"rebrand\" && includeDarkModeCheckbox.checked\n ? [\"light\", \"dark\"]\n : [\"light\"];\n },\n};\n\n/** Re-themes the chrome's token variant + light/dark scheme — the tray and shell are regular app\n * chrome and inherit this too; only the preview `srcdoc` has its own independent theme/scheme. */\nfunction applyChromeTheme(theme: ThemeVariant, mode: \"light\" | \"dark\"): void {\n const tokensCss =\n theme === \"canvas\"\n ? canvasTokensCss\n : theme === \"canvasHighContrast\"\n ? canvasHighContrastTokensCss\n : adaptiveTokensCss;\n // Without `PREVIEW_SCHEME_FORCE_CSS`, the chrome's own buttons/text stay pinned to the OS\n // `prefers-color-scheme` (see that constant's comment) even though `colorScheme` below is set\n // explicitly — only the native-CSS background rules that key off `color-scheme` directly would\n // follow the toggle, leaving everything else stuck on the OS default.\n chromeThemeStyle.textContent = [tokensCss, PREVIEW_SCHEME_FORCE_CSS].join(\"\\n\");\n // Pins `light-dark()` resolution to the docs page's explicit mode instead of the OS preference —\n // single-scheme themes (canvas/canvasHighContrast) only ever render light.\n const scheme = theme === \"rebrand\" ? mode : \"light\";\n document.documentElement.dataset.pantokenTheme = theme;\n document.documentElement.dataset.pantokenScheme = scheme;\n document.documentElement.style.colorScheme = scheme;\n syncBrowserMetadata();\n syncPreviewPopupChrome();\n}\n\n/** Re-colors the chrome only — the tray's `#theme-tray` reset scope keeps it (and the preview,\n * which reads `selectedColor` directly) immune to this. */\nfunction applyChromeColor(color: PantokenColorNamespace, customHex?: string): void {\n if (customHex !== undefined) chromeCustomColor = parseHexColor(customHex);\n chromeCustomColorStyle.textContent =\n color === CUSTOM_COLOR_KEY ? customColorCss(chromeCustomColor) : \"\";\n document.documentElement.dataset.pantokenColor = color;\n syncShellCustomColor?.();\n syncBrowserMetadata();\n syncPreviewPopupChrome();\n}\n\n/** A host color message: a shipped scale, or `custom` with a valid hex. */\nfunction applyHostColor(color: unknown, customHex: unknown): void {\n if (isShippedColor(color)) applyChromeColor(color);\n else if (color === CUSTOM_COLOR_KEY && isHexColor(customHex)) applyChromeColor(color, customHex);\n}\n\nfunction applyParentTheme(theme: ThemeVariant, mode: \"light\" | \"dark\"): void {\n selectedTheme = theme;\n // The docs page's own light/dark mode re-themes the chrome only — \"include dark mode\" is an\n // independent authoring choice about what ships with the exported theme, not a mirror of it.\n document.documentElement.dataset.pantokenScheme = mode;\n const themeButton = [...themeButtons].find((button) => button.dataset.theme === theme);\n if (themeButton) selectToggleButton(themeButtons, themeButton);\n syncDarkModeAvailability();\n applyEditorTheme(activeEditor);\n void refreshAll();\n syncPreviewPopupChrome();\n}\n\n// This app is its own pantoken instance. Claiming the root stops an embedding page's scope from\n// being mistaken for ours, and stops our own preview/tray scopes from being re-themed by it.\ndocument.documentElement.dataset.pantokenInstance = EDITOR_INSTANCE;\napplyChromeTheme(\"rebrand\", \"light\");\napplyChromeColor(\"navy\");\n\nwindow.addEventListener(\"message\", (event) => {\n if (event.source !== window.parent || event.origin !== window.location.origin) return;\n const data = event.data as {\n type?: unknown;\n theme?: unknown;\n mode?: unknown;\n color?: unknown;\n customColor?: unknown;\n instanceId?: unknown;\n };\n // A message tagged for a different instance belongs to another pantoken on the host page.\n if (typeof data?.instanceId === \"string\" && data.instanceId !== HOST_INSTANCE) return;\n if (data?.type === \"pantoken-demo-color\") {\n applyHostColor(data.color, data.customColor);\n return;\n }\n if (data?.type !== \"pantoken-demo-theme\") return;\n if (\n (data.theme !== \"rebrand\" &&\n data.theme !== \"canvas\" &&\n data.theme !== \"canvasHighContrast\") ||\n (data.mode !== \"light\" && data.mode !== \"dark\")\n ) {\n return;\n }\n applyChromeTheme(data.theme, data.mode);\n applyParentTheme(data.theme, data.mode);\n applyHostColor(data.color, data.customColor);\n});\n\nwindow.parent.postMessage({ type: \"pantoken-demo-request-theme\" }, window.location.origin);\n\n/** Creates a CodeMirror editor for the given language, wired to call `onChange` on user edits. */\nfunction createEditor(\n container: HTMLElement,\n lang: \"html\" | \"css\" | \"javascript\",\n value: string,\n onChange: () => void,\n): EditorView {\n const langExtension = lang === \"css\" ? css() : lang === \"javascript\" ? javascript() : html();\n const extensions: any[] = [\n basicSetup,\n langExtension,\n EditorView.lineWrapping,\n EditorView.updateListener.of((update: any): void => {\n if (update.docChanged) onChange();\n }),\n ];\n \n // Add pantoken linter + autocomplete for HTML editor only.\n if (lang === \"html\") {\n extensions.push(\n pantokenHtmlLinter({ model: [...listComponents(), ...listUtilities()] as any }),\n pantokenHtmlCompletion({ model: [...listComponents(), ...listUtilities()] as any })\n );\n }\n \n return new EditorView({\n doc: value,\n extensions,\n parent: container,\n });\n}\n\n// Register one pantoken plugin that composes components, icons, logos, layouts, and templates\n// behind a single toolbar menu. tinymce.init() waits until the icon catalog is available.\nconst registerPantokenPlugin = (async () => {\n const componentModel = [...listComponents(), ...listUtilities()];\n const allIcons = await loadAllIcons();\n availableIcons = allIcons;\n\n tinymce.PluginManager.add(\n \"pantoken\",\n createPantokenPlugin({\n strings: tinymceStrings,\n components: {\n model: componentModel as any,\n currentAssets,\n onMissingAsset,\n buildAssetUrl: buildSelectedAssetUrl,\n includeInteractions: () => includeInteractionsCheckbox.checked,\n isAvailable: (entry) => includeInteractionsCheckbox.checked || !componentNeedsInteractions(entry, componentCapabilities.components),\n },\n icons: {\n icons: allIcons,\n currentAssets,\n onMissingAsset,\n buildAssetUrl: buildSelectedAssetUrl,\n },\n logos: {\n // pantoken's own marks aren't Canvas content; pasted ones still render via glyph sync.\n logos: logos.filter((logo) => logo.product !== \"pantoken\"),\n products: products.filter((product) => product !== \"pantoken\"),\n currentAssets,\n onMissingAsset,\n buildAssetUrl: buildSelectedAssetUrl,\n },\n layouts: {\n locale: activeLocale,\n resolveImage: (placeholder) => {\n const image = buildPlaceholdImage({\n width: placeholder.width,\n height: placeholder.height,\n backgroundColor: \"#eeeeee\",\n textColor: \"#31343c\",\n text: placeholder.text,\n });\n return {\n src: image.url,\n alt: placeholder.altText ?? \"\",\n width: image.width,\n height: image.height,\n };\n },\n onInsert: () => {\n applyThemeColor(selectedColor, false);\n void refreshAll();\n },\n },\n }),\n );\n})();\n\ntinymce.PluginManager.add(\n PLACEHOLD_PLUGIN_NAME,\n createPlaceholdPlugin({ strings: tinymceStrings, onInsert: () => void refreshAll() }),\n);\ntinymce.PluginManager.add(CONTENT_CLASSES_PLUGIN_NAME, createContentClassesPlugin());\ntinymce.PluginManager.add(\n A11Y_PLUGIN_NAME,\n createA11yPlugin({ strings: tinymceStrings, display: \"footer\", config: a11yRuntimeConfig }),\n);\ntinymce.PluginManager.add(SUP_SUB_PLUGIN_NAME, createSupSubPlugin());\n\n// Toggles between TinyMCE's WYSIWYG view and a syntax-highlighted CodeMirror source view, reusing\n// the shared renderer's implementation (live preview + pantoken lint/autocomplete) instead of a\n// second, drifted reimplementation.\ntinymce.PluginManager.add(\n SOURCE_TOGGLE_PLUGIN_NAME,\n createSourceTogglePlugin({\n strings: tinymceStrings,\n height: EDITOR_HEIGHT_PX,\n display: \"footer\",\n extensions: [\n pantokenHtmlLinter({ model: [...listComponents(), ...listUtilities()] as any, strings: tinymceStrings }),\n pantokenHtmlCompletion({ model: [...listComponents(), ...listUtilities()] as any }),\n ],\n onChange: () => {\n if (applyingInline) return;\n syncThemeColorFromEditor();\n if (syncIconAssetsFromEditor()) void refreshAll();\n debouncedUpdatePreview();\n },\n onToggle: () => void refreshAll(),\n }),\n);\n// Fullscreen, find-and-replace, and visual blocks ship as toolbar-only controls upstream — these\n// footer-only wrappers surface all three from the statusbar instead, alongside word count and the\n// a11y checker.\ntinymce.PluginManager.add(FULLSCREEN_FOOTER_PLUGIN_NAME, createFullscreenFooterPlugin());\ntinymce.PluginManager.add(SEARCHREPLACE_FOOTER_PLUGIN_NAME, createSearchReplaceFooterPlugin());\ntinymce.PluginManager.add(VISUALBLOCKS_FOOTER_PLUGIN_NAME, createVisualBlocksFooterPlugin());\ntinymce.PluginManager.add(\n SAVE_PLUGIN_NAME,\n createSavePlugin<CanvasThemePreset>({\n strings: tinymceStrings,\n capture: captureCanvasThemePreset,\n restore: restoreCanvasThemePreset,\n reset: resetCanvasThemePreset,\n isValid: isCanvasThemePreset,\n }),\n);\n\nconst providerSelect = document.querySelector<HTMLSelectElement>(\"#cdn-provider\")!;\nconst localProviderOption = document.createElement(\"option\");\nlocalProviderOption.value = LOCAL_PROVIDER_ID;\nlocalProviderOption.textContent = activeStrings.localProviderLabel;\nproviderSelect.append(localProviderOption);\nconst inlineProviderOption = document.createElement(\"option\");\ninlineProviderOption.value = INLINE_PROVIDER_ID;\ninlineProviderOption.textContent = activeStrings.inlineProviderLabel;\nproviderSelect.append(inlineProviderOption);\nfor (const [id, provider] of Object.entries(CDN_PROVIDERS)) {\n const option = document.createElement(\"option\");\n option.value = id;\n option.textContent = provider.label;\n providerSelect.append(option);\n}\nproviderSelect.value = import.meta.env.DEV ? LOCAL_PROVIDER_ID : DEFAULT_CDN_PROVIDER_ID;\nif (isLocalPreview) {\n providerSelect.value = LOCAL_PROVIDER_ID;\n}\nif (\n preferences.cdnProvider &&\n [...providerSelect.options].some((option) => option.value === preferences.cdnProvider)\n) {\n providerSelect.value = preferences.cdnProvider;\n}\n\nconst themeButtons = document.querySelectorAll<HTMLButtonElement>(\".theme-picker [data-theme]\");\nconst colorButtons = document.querySelectorAll<HTMLButtonElement>(\n \".theme-picker__color-item[data-color]\",\n);\nconst customColorRow = document.querySelector<HTMLElement>(\"#custom-color-row\")!;\nconst customColorPicker = document.querySelector<HTMLInputElement>(\"#custom-color-picker\")!;\nconst customColorHex = document.querySelector<HTMLInputElement>(\"#custom-color-hex\")!;\nconst customColorSwatch = document.querySelector<HTMLElement>(\n '.theme-picker__color-item [data-swatch=\"custom\"]',\n)!;\nconst previewWidthButtons = document.querySelectorAll<HTMLButtonElement>(\n \".preview-width-picker [data-preview-width]\",\n);\nconst previewWidthValue = document.querySelector<HTMLElement>(\"#preview-width-value\")!;\nconst includeDarkModeRow = document.getElementById(\"include-dark-mode-row\")!;\nconst includeDarkModeCheckbox = document.querySelector<HTMLInputElement>(\"#include-dark-mode\")!;\nconst includeInteractionsCheckbox = document.querySelector<HTMLInputElement>(\"#include-interactions\")!;\nincludeInteractionsCheckbox.checked = preferences.includeInteractions !== false;\nlet rememberedInteractions = includeInteractionsCheckbox.checked;\nlet rememberedDarkMode = false;\nlet previousProvider = providerSelect.value;\nconst previewSchemeToggle = document.querySelector<HTMLButtonElement>(\"#preview-scheme-toggle\")!;\nconst previewFrame = document.querySelector<HTMLIFrameElement>(\"#preview\")!;\nconst previewResetButton = document.querySelector<HTMLButtonElement>(\"#preview-reset\")!;\nlet latestPreviewSrcdoc = \"\";\nlet previewDirty = false;\nlet previewLoading = true;\nlet stopPreviewTracking: (() => void) | undefined;\n\nfunction syncPreviewResetAvailability(): void {\n previewResetButton.disabled = !includeInteractionsCheckbox.checked || previewLoading || !previewDirty;\n}\n\nfunction loadPreviewDocument(source: string): void {\n stopPreviewTracking?.();\n previewLoading = true;\n previewDirty = false;\n syncPreviewResetAvailability();\n latestPreviewSrcdoc = source;\n previewFrame.srcdoc = source;\n}\n\npreviewResetButton.addEventListener(\"click\", () => {\n if (!previewResetButton.disabled && latestPreviewSrcdoc) loadPreviewDocument(latestPreviewSrcdoc);\n});\nconst previewPane = document.querySelector<HTMLElement>(\".preview-pane\")!;\nconst downloadCss = document.querySelector<HTMLAnchorElement>(\"#download-theme-css\")!;\nconst downloadJs = document.querySelector<HTMLAnchorElement>(\"#download-theme-js\")!;\nconst downloadPackageButton = document.querySelector<HTMLButtonElement>(\"#download-package\")!;\nconst downloadHtmlButton = document.querySelector<HTMLButtonElement>(\"#download-html\")!;\nconst copyButton = document.querySelector<HTMLButtonElement>(\"#copy-html\")!;\n\nlet activeEditor: Editor | undefined;\nlet cssObjectUrl: string | undefined;\nlet jsObjectUrl: string | undefined;\n\n// Only the tray (below) and the preview it drives read these — the chrome has its own,\n// docs-driven theme/color tracked separately by `applyChromeTheme`/`applyChromeColor` above.\nlet selectedTheme: ThemeVariant = \"rebrand\";\nlet selectedColor: PantokenColorNamespace = \"navy\";\nlet selectedCustomColor = DEFAULT_CUSTOM_COLOR;\nsetupStandaloneAppShell();\n\ninterface CanvasThemePreset {\n readonly version: 1;\n readonly theme: ThemeVariant;\n readonly color: PantokenColorNamespace;\n readonly customColor?: string;\n readonly mode: ThemeMode;\n readonly cdnProvider: string;\n readonly includeInteractions?: boolean;\n readonly preferredInteractions?: boolean;\n readonly preferredMode?: ThemeMode;\n readonly customCss: string;\n readonly customJs: string;\n readonly editorHtml: string;\n}\n\nfunction selectThemeColor(color: PantokenColorNamespace): void {\n selectedColor = color;\n const colorButton = [...colorButtons].find((button) => button.dataset.color === color);\n if (colorButton) selectButton(colorButtons, colorButton);\n customColorRow.hidden = color !== CUSTOM_COLOR_KEY;\n}\n\n/** Stores a validated custom hex and reflects it in the tray. */\nfunction setCustomColor(hex: string): void {\n selectedCustomColor = parseHexColor(hex);\n customColorPicker.value = selectedCustomColor;\n const typed = customColorHex.value;\n if (!isHexColor(typed) || parseHexColor(typed) !== selectedCustomColor) {\n customColorHex.value = selectedCustomColor;\n }\n customColorHex.classList.remove(\"-invalid\");\n customColorHex.removeAttribute(\"aria-invalid\");\n syncCustomSwatch(customColorSwatch, selectedCustomColor);\n}\n\n/** The `custom` scale's rule, only while it's the selected color. */\nfunction selectedCustomColorCss(): string {\n return selectedColor === CUSTOM_COLOR_KEY\n ? customColorCss(selectedCustomColor, { selector: \"\" })\n : \"\";\n}\n\nconst debouncedCustomColorRefresh = debounce(() => void refreshAll(), 150);\n\nfunction onCustomColorInput(value: string): void {\n if (!isHexColor(value)) {\n customColorHex.classList.add(\"-invalid\");\n customColorHex.setAttribute(\"aria-invalid\", \"true\");\n return;\n }\n setCustomColor(value);\n if (selectedColor === CUSTOM_COLOR_KEY) debouncedCustomColorRefresh();\n}\n\ncustomColorPicker.addEventListener(\"input\", () => onCustomColorInput(customColorPicker.value));\ncustomColorHex.addEventListener(\"input\", () => onCustomColorInput(customColorHex.value));\nsetCustomColor(DEFAULT_CUSTOM_COLOR);\n\nfunction parseEditorHtml(html: string): HTMLTemplateElement {\n const template = document.createElement(\"template\");\n template.innerHTML = html;\n return template;\n}\n\nfunction findColorWrapper(content: DocumentFragment): HTMLElement | undefined {\n const wrapper = content.firstElementChild as HTMLElement | null;\n if (!wrapper?.hasAttribute(\"data-pantoken-color\")) return undefined;\n const hasContentOutsideWrapper = [...content.childNodes].some(\n (node) => node !== wrapper && (node.nodeType !== Node.TEXT_NODE || node.textContent?.trim()),\n );\n return hasContentOutsideWrapper ? undefined : wrapper;\n}\n\nfunction normalizeEditorHtml(html: string, fallbackColor: PantokenColorNamespace): string {\n const template = parseEditorHtml(html);\n let wrapper = findColorWrapper(template.content);\n if (!wrapper) {\n wrapper = document.createElement(\"div\");\n wrapper.dataset.pantokenColor = fallbackColor;\n wrapper.append(...template.content.childNodes);\n template.content.append(wrapper);\n } else if (!isThemeColor(wrapper.dataset.pantokenColor)) {\n wrapper.dataset.pantokenColor = fallbackColor;\n }\n return template.innerHTML;\n}\n\nfunction editorHtmlColor(html: string): PantokenColorNamespace | undefined {\n const wrapper = findColorWrapper(parseEditorHtml(html).content);\n const color = wrapper?.dataset.pantokenColor;\n return isThemeColor(color) ? color : undefined;\n}\n\nfunction setEditorHtmlColor(html: string, color: PantokenColorNamespace): string {\n const template = parseEditorHtml(normalizeEditorHtml(html, color));\n findColorWrapper(template.content)!.dataset.pantokenColor = color;\n return template.innerHTML;\n}\n\nfunction syncThemeColorFromEditor(): void {\n const color = editorHtmlColor(getEditorHtml());\n if (color) selectThemeColor(color);\n}\n\nfunction applyThemeColor(color: PantokenColorNamespace, refresh = true): void {\n selectThemeColor(color);\n if (activeEditor) {\n const sourceToggle = activeEditor.plugins[SOURCE_TOGGLE_PLUGIN_NAME] as\n | SourceTogglePluginApi\n | undefined;\n const nextHtml = setEditorHtmlColor(getEditorHtml(), color);\n if (sourceToggle?.isSourceMode()) {\n sourceToggle.replaceAll(nextHtml);\n } else {\n activeEditor.undoManager.transact(() => activeEditor!.setContent(nextHtml));\n }\n }\n if (refresh) void refreshAll();\n}\n\n/** Reads the author's current HTML from whichever view (WYSIWYG or raw source) is active. */\nfunction getEditorHtml(): string {\n const sourceToggle = activeEditor?.plugins[SOURCE_TOGGLE_PLUGIN_NAME] as\n | SourceTogglePluginApi\n | undefined;\n if (sourceToggle?.isSourceMode()) return sourceToggle.getContent();\n return activeEditor?.getContent() ?? \"\";\n}\n\nfunction getNormalizedEditorHtml(): string {\n return inlineDocument.export(normalizeEditorHtml(getEditorHtml(), selectedColor));\n}\n\nfunction replaceProviderHtml(content: string): void {\n if (!activeEditor) return;\n const sourceToggle = activeEditor.plugins[SOURCE_TOGGLE_PLUGIN_NAME] as SourceTogglePluginApi | undefined;\n applyingInline = true;\n try {\n const bookmark = activeEditor.selection.getBookmark();\n activeEditor.undoManager.ignore(() => activeEditor!.setContent(content));\n if (sourceToggle?.isSourceMode()) sourceToggle.replaceAll(content);\n else activeEditor.selection.moveToBookmark(bookmark);\n } finally {\n applyingInline = false;\n }\n}\n\nasync function syncInlineProvider(theme: { css: string }): Promise<void> {\n const current = getEditorHtml();\n if (providerSelect.value !== INLINE_PROVIDER_ID) {\n if (inlineRendered) replaceProviderHtml(inlineDocument.canonical(current));\n inlineRendered = false;\n lastInlineHtml = \"\";\n return;\n }\n const canonical = inlineDocument.canonical(current);\n const css = [theme.css, cssEditorView.state.doc.toString(), ':root { color-scheme: light; } :where(body > [data-pantoken-color]) { background-color: var(--instui-color-background-container, #fff); }'].join(\"\\n\");\n if (inlineRendered && canonical === lastInlineHtml && css === lastInlineCss) return;\n const { inlineHtmlInBrowser } = await import(\"@pantoken/inline-styles/browser\");\n if (providerSelect.value !== INLINE_PROVIDER_ID || getEditorHtml() !== current) return;\n const rendered = await inlineDocument.renderAsync(normalizeEditorHtml(current, selectedColor), css, (html, stylesheet) => inlineHtmlInBrowser(html, stylesheet, {\n rootAttributes: { \"data-pantoken-theme\": selectedTheme, \"data-pantoken-color\": selectedColor, \"data-pantoken-scheme\": \"light\" },\n }));\n if (providerSelect.value !== INLINE_PROVIDER_ID || getEditorHtml() !== current) return;\n inlineRendered = true;\n replaceProviderHtml(rendered);\n lastInlineHtml = inlineDocument.canonical(getEditorHtml());\n lastInlineCss = css;\n}\n\nfunction assetKey(asset: CdnFile): string {\n return `${asset.package}:${asset.path}`;\n}\n\nasync function inlineAssetCss(assets: readonly CdnFile[]): Promise<string[]> {\n const urls = assets.map(buildSelectedAssetUrl);\n await Promise.all(\n assets.map(async (asset, index) => {\n const key = urls[index];\n if (inlineAssetContents.has(key)) return;\n const response = await fetch(key);\n if (!response.ok) {\n throw new Error(`Unable to inline ${asset.package}/${asset.path}: ${response.status}`);\n }\n inlineAssetContents.set(key, await response.text());\n }),\n );\n return urls.map((url) => inlineAssetContents.get(url)!);\n}\n\nfunction syncIconAssetsFromEditor(): boolean {\n const content = parseEditorHtml(getEditorHtml()).content;\n const iconAssetKeys = new Set(availableIcons.map((icon) => assetKey(getIconCdnFile(icon))));\n const logoAssetKeys = new Set(logos.map((logo) => assetKey(getLogoCdnFile(logo))));\n const nonSyncedAssets = currentAssets.filter(\n (asset) => !iconAssetKeys.has(assetKey(asset)) && !logoAssetKeys.has(assetKey(asset)),\n );\n const usedIconAssets = getUsedIconCdnFiles(content, availableIcons, currentAssets);\n const usedLogoAssets = getUsedLogoCdnFiles(content, logos);\n if (activeEditor) {\n for (const asset of [...usedIconAssets, ...usedLogoAssets]) {\n injectContentStylesheet(activeEditor, buildSelectedAssetUrl(asset), asset);\n }\n }\n const nextAssets = [...nonSyncedAssets, ...usedIconAssets, ...usedLogoAssets];\n const changed = currentAssets.map(assetKey).join(\"\\n\") !== nextAssets.map(assetKey).join(\"\\n\");\n if (changed) currentAssets.splice(0, currentAssets.length, ...nextAssets);\n return changed;\n}\n\nfunction captureCanvasThemePreset(): CanvasThemePreset {\n return {\n version: 1,\n theme: selectedTheme,\n color: selectedColor,\n customColor: selectedCustomColor,\n mode: includeDarkModeCheckbox.checked ? \"adaptive\" : \"light\",\n cdnProvider: providerSelect.value,\n includeInteractions: includeInteractionsCheckbox.checked,\n preferredInteractions: providerSelect.value === INLINE_PROVIDER_ID ? rememberedInteractions : includeInteractionsCheckbox.checked,\n preferredMode: (providerSelect.value === INLINE_PROVIDER_ID ? rememberedDarkMode : includeDarkModeCheckbox.checked) ? \"adaptive\" : \"light\",\n customCss: cssEditorView.state.doc.toString(),\n customJs: jsEditorView.state.doc.toString(),\n editorHtml: normalizeEditorHtml(inlineDocument.canonical(getEditorHtml()), selectedColor),\n };\n}\n\nfunction isThemeVariant(value: unknown): value is ThemeVariant {\n return value === \"rebrand\" || value === \"canvas\" || value === \"canvasHighContrast\";\n}\n\nfunction isThemeMode(value: unknown): value is ThemeMode {\n return value === \"light\" || value === \"adaptive\";\n}\n\nfunction isCdnProvider(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n (Object.hasOwn(CDN_PROVIDERS, value) || value === LOCAL_PROVIDER_ID || value === INLINE_PROVIDER_ID)\n );\n}\n\nfunction isCanvasThemePreset(value: unknown): value is CanvasThemePreset {\n if (typeof value !== \"object\" || value === null) return false;\n const preset = value as Partial<CanvasThemePreset>;\n return (\n preset.version === 1 &&\n isThemeVariant(preset.theme) &&\n isThemeColor(preset.color) &&\n (preset.customColor === undefined || isHexColor(preset.customColor)) &&\n isThemeMode(preset.mode) &&\n isCdnProvider(preset.cdnProvider) &&\n (preset.includeInteractions === undefined || typeof preset.includeInteractions === \"boolean\") &&\n (preset.preferredInteractions === undefined || typeof preset.preferredInteractions === \"boolean\") &&\n (preset.preferredMode === undefined || isThemeMode(preset.preferredMode)) &&\n typeof preset.customCss === \"string\" &&\n typeof preset.customJs === \"string\" &&\n typeof preset.editorHtml === \"string\"\n );\n}\n\nfunction replaceEditorDocument(view: EditorView, content: string): void {\n view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: content } });\n}\n\nfunction resetCanvasThemePreset(): void {\n inlineRendered = false;\n lastInlineHtml = \"\";\n selectedTheme = \"rebrand\";\n const themeButton = [...themeButtons].find((button) => button.dataset.theme === selectedTheme);\n if (themeButton) selectToggleButton(themeButtons, themeButton);\n includeDarkModeCheckbox.checked = false;\n includeInteractionsCheckbox.checked = true;\n rememberedInteractions = true;\n rememberedDarkMode = false;\n syncDarkModeAvailability();\n providerSelect.value = isLocalPreview ? LOCAL_PROVIDER_ID : DEFAULT_CDN_PROVIDER_ID;\n previousProvider = providerSelect.value;\n syncProviderPolicy();\n selectThemeColor(\"navy\");\n setCustomColor(DEFAULT_CUSTOM_COLOR);\n replaceEditorDocument(cssEditorView, \"\");\n replaceEditorDocument(jsEditorView, \"\");\n\n if (activeEditor) {\n const nextHtml = normalizeEditorHtml(\"\", \"navy\");\n activeEditor.resetContent(nextHtml);\n const sourceToggle = activeEditor.plugins[SOURCE_TOGGLE_PLUGIN_NAME] as\n | SourceTogglePluginApi\n | undefined;\n if (sourceToggle?.isSourceMode()) sourceToggle.replaceAll(nextHtml);\n retargetContentStylesheets(activeEditor, buildSelectedAssetUrl);\n }\n\n syncThemeColorFromEditor();\n applyEditorTheme(activeEditor);\n void refreshAll();\n}\n\nfunction restoreCanvasThemePreset(preset: CanvasThemePreset): void {\n if (!activeEditor || !isCanvasThemePreset(preset)) throw new TypeError(\"invalid-preset\");\n inlineRendered = false;\n lastInlineHtml = \"\";\n\n selectedTheme = preset.theme;\n const themeButton = [...themeButtons].find((button) => button.dataset.theme === preset.theme);\n if (themeButton) selectToggleButton(themeButtons, themeButton);\n includeDarkModeCheckbox.checked = preset.mode === \"adaptive\";\n includeInteractionsCheckbox.checked = preset.includeInteractions !== false;\n rememberedInteractions = preset.preferredInteractions ?? preset.includeInteractions !== false;\n rememberedDarkMode = (preset.preferredMode ?? preset.mode) === \"adaptive\";\n providerSelect.value = preset.cdnProvider;\n previousProvider = preset.cdnProvider;\n syncProviderPolicy();\n selectThemeColor(preset.color);\n setCustomColor(preset.customColor ?? DEFAULT_CUSTOM_COLOR);\n replaceEditorDocument(cssEditorView, preset.customCss);\n replaceEditorDocument(jsEditorView, preset.customJs);\n\n const editorHtml = normalizeEditorHtml(preset.editorHtml, preset.color);\n activeEditor.resetContent(editorHtml);\n const sourceToggle = activeEditor.plugins[SOURCE_TOGGLE_PLUGIN_NAME] as\n | SourceTogglePluginApi\n | undefined;\n if (sourceToggle?.isSourceMode()) sourceToggle.replaceAll(editorHtml);\n // Setting `providerSelect.value` fires no change event, so re-point already-loaded sheets here.\n retargetContentStylesheets(activeEditor, buildSelectedAssetUrl);\n syncThemeColorFromEditor();\n\n applyEditorTheme(activeEditor);\n void refreshAll();\n}\n\nfunction currentSelection(): { provider: string; theme: ThemeVariant; mode: ThemeMode } {\n return {\n provider: providerSelect.value,\n theme: selectedTheme,\n mode: includeDarkModeCheckbox.checked ? \"adaptive\" : \"light\",\n };\n}\n\n/** `css`/`js` are theme.css/theme.js's actual downloadable content and the live preview's styling\n * alike — both follow the visitor's/browser's own dark-mode preference, same as a real Canvas\n * page would. The preview's manual light/dark toggle overrides that via `PREVIEW_SCHEME_FORCE_CSS`\n * (see `updatePreview`), not by swapping this CSS. */\nasync function buildCurrentTheme(): Promise<{ css: string; js: string }> {\n const selection = currentSelection();\n const customCss = selectedCustomColorCss();\n if (![LOCAL_PROVIDER_ID, INLINE_PROVIDER_ID].includes(selection.provider)) {\n const theme = buildTheme({\n ...selection,\n js: includeInteractionsCheckbox.checked ? undefined : [],\n css: [...defaultThemeCssAssets(selection.theme, selection.mode), ...currentAssets],\n });\n return { ...theme, css: [theme.css, customCss].filter(Boolean).join(\"\\n\") };\n }\n\n const tokensCss =\n selection.theme === \"canvas\"\n ? canvasTokensCss\n : selection.theme === \"canvasHighContrast\"\n ? canvasHighContrastTokensCss\n : selection.mode === \"adaptive\"\n ? adaptiveTokensCss\n : rebrandLightTokensCss;\n const dynamicCss = await inlineAssetCss(currentAssets);\n return {\n css: [tokensCss, LOCAL_COMPONENT_CSS, ...dynamicCss, customCss].filter(Boolean).join(\"\\n\"),\n js: includeInteractionsCheckbox.checked ? localInteractionsJs : \"\",\n };\n}\n\n/** Marks the clicked button as selected within its `role=\"group\"` (theme or color pickers). */\nfunction selectButton(buttons: NodeListOf<HTMLButtonElement>, target: HTMLButtonElement): void {\n for (const button of buttons) {\n const selected = button === target;\n button.classList.toggle(\"-selected\", selected);\n button.setAttribute(\"aria-checked\", String(selected));\n }\n}\n\n/** Marks the clicked instui-button `-toggle` as pressed within its `role=\"group\"` (preview width). */\nfunction selectToggleButton(buttons: NodeListOf<HTMLButtonElement>, target: HTMLButtonElement): void {\n for (const button of buttons) button.setAttribute(\"aria-pressed\", String(button === target));\n}\n\n/** Only \"rebrand\" ships a dark scheme — canvas/canvasHighContrast are single-scheme themes. */\nfunction syncDarkModeAvailability(): void {\n const supportsDarkMode = selectedTheme === \"rebrand\";\n includeDarkModeRow.hidden = !supportsDarkMode;\n includeDarkModeCheckbox.disabled = !supportsDarkMode || providerSelect.value === INLINE_PROVIDER_ID;\n if (includeDarkModeCheckbox.disabled) includeDarkModeCheckbox.checked = false;\n syncPreviewSchemeToggleAvailability();\n}\n\nfunction syncProviderPolicy(): void {\n const inline = providerSelect.value === INLINE_PROVIDER_ID;\n if (inline) {\n if (previousProvider !== INLINE_PROVIDER_ID) {\n rememberedInteractions = includeInteractionsCheckbox.checked;\n rememberedDarkMode = includeDarkModeCheckbox.checked;\n }\n includeInteractionsCheckbox.checked = false;\n includeDarkModeCheckbox.checked = false;\n } else if (previousProvider === INLINE_PROVIDER_ID) {\n includeInteractionsCheckbox.checked = rememberedInteractions;\n includeDarkModeCheckbox.checked = rememberedDarkMode;\n }\n includeInteractionsCheckbox.disabled = inline;\n previousProvider = providerSelect.value;\n syncDarkModeAvailability();\n syncPreviewResetAvailability();\n}\n\n/** The preview's own light/dark switch only makes sense once \"include dark mode\" is on. */\nfunction syncPreviewSchemeToggleAvailability(): void {\n previewSchemeToggle.disabled = !includeDarkModeCheckbox.checked;\n if (previewSchemeToggle.disabled) {\n previewDarkOverride = false;\n previewSchemeToggle.setAttribute(\"aria-pressed\", \"false\");\n previewSchemeToggle.classList.replace(\"-icon-sun\", \"-icon-moon\");\n }\n}\n\nthemeButtons.forEach((button) => {\n button.addEventListener(\"click\", () => {\n selectedTheme = button.dataset.theme as ThemeVariant;\n selectToggleButton(themeButtons, button);\n syncDarkModeAvailability();\n applyEditorTheme(activeEditor);\n void refreshAll();\n });\n});\n\ncolorButtons.forEach((button) => {\n button.addEventListener(\"click\", () => {\n const color = button.dataset.color;\n if (isThemeColor(color)) applyThemeColor(color);\n });\n});\n\n// Canvas's own responsive breakpoints for course content, reused as-is from pantoken's tokens —\n// \"large\" is unconstrained (the current default), matching the desktop RCE width.\ntype PreviewWidthPreset = \"large\" | \"medium\" | \"small\";\n\nconst PREVIEW_WIDTHS: Record<Exclude<PreviewWidthPreset, \"large\">, string> = {\n medium: \"var(--instui-breakpoints-md)\",\n small: \"var(--instui-breakpoints-xs)\",\n};\n\nfunction isPreviewWidthPreset(value: unknown): value is PreviewWidthPreset {\n return value === \"large\" || value === \"medium\" || value === \"small\";\n}\n\nfunction isCustomPreviewWidth(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value > 0;\n}\n\nfunction parseCustomPreviewWidth(value: string): number | undefined {\n if (!/^[1-9]\\d*$/u.test(value)) return undefined;\n const width = Number(value);\n return isCustomPreviewWidth(width) ? width : undefined;\n}\n\nlet selectedPreviewWidth: PreviewWidthPreset | number =\n isPreviewWidthPreset(preferences.previewWidth) || isCustomPreviewWidth(preferences.previewWidth)\n ? preferences.previewWidth\n : \"large\";\n\nfunction clearPreviewWidthButtons(): void {\n for (const button of previewWidthButtons) button.setAttribute(\"aria-pressed\", \"false\");\n}\n\nfunction updatePreviewWidthValue(force = false): void {\n if (!force && document.activeElement === previewWidthValue) return;\n const width =\n typeof selectedPreviewWidth === \"number\"\n ? selectedPreviewWidth\n : Math.round(previewFrame.getBoundingClientRect().width);\n if (width <= 0) return;\n const value = String(width);\n previewWidthValue.textContent = value;\n previewWidthValue.setAttribute(\"value\", value);\n}\n\nconst previewWidthObserver = new ResizeObserver(() => updatePreviewWidthValue());\npreviewWidthObserver.observe(previewFrame);\n\n/**\n * In row layout, the *pane's* width is constrained so the editor pane's flex:1 can claim\n * whatever space a fixed-width (medium/small) preview gives up. In fullscreen the pane is\n * forced to fill the viewport (app.css's `!important` overlay), so there's no sibling to\n * reclaim space from — the constraint has to move to the iframe itself instead, centered\n * via app.css's `margin-inline: auto`.\n */\nfunction applyPreviewWidth(): void {\n const fullscreen = previewPane.classList.contains(\"-fullscreen\");\n previewPane.style.removeProperty(\"flex\");\n previewPane.style.removeProperty(\"width\");\n previewPane.style.removeProperty(\"min-width\");\n previewFrame.style.removeProperty(\"max-width\");\n if (selectedPreviewWidth === \"large\") {\n // In row layout, \"large\" only got a 50/50 flex share of `.content`'s width — on a narrow\n // window that's smaller than \"medium\"'s own fixed `--instui-breakpoints-md`, so the\n // \"desktop\" preview could render narrower than the \"tablet\" one. A `--instui-breakpoints-lg`\n // floor guarantees desktop is always at least as wide as the next size down.\n if (!fullscreen && document.querySelector(\".content\")?.getAttribute(\"data-layout\") === \"row\") {\n previewPane.style.minWidth = \"var(--instui-breakpoints-lg)\";\n }\n updatePreviewWidthValue();\n return;\n }\n const width =\n typeof selectedPreviewWidth === \"number\"\n ? `${selectedPreviewWidth}px`\n : PREVIEW_WIDTHS[selectedPreviewWidth];\n if (fullscreen) {\n previewFrame.style.maxWidth = width;\n } else {\n previewPane.style.flex = \"0 0 auto\";\n previewPane.style.width = width;\n }\n updatePreviewWidthValue();\n}\n\npreviewWidthButtons.forEach((button) => {\n button.addEventListener(\"click\", () => {\n selectToggleButton(previewWidthButtons, button);\n selectedPreviewWidth = button.dataset.previewWidth as PreviewWidthPreset;\n applyPreviewWidth();\n persistPreferences();\n });\n});\npreviewWidthValue.addEventListener(\"change\", (event) => {\n const width = parseCustomPreviewWidth(\n (event as CustomEvent<{ value: string }>).detail.value,\n );\n if (width === undefined) {\n updatePreviewWidthValue(true);\n return;\n }\n selectedPreviewWidth = width;\n clearPreviewWidthButtons();\n applyPreviewWidth();\n persistPreferences();\n});\nif (typeof selectedPreviewWidth === \"number\") {\n clearPreviewWidthButtons();\n applyPreviewWidth();\n} else if (selectedPreviewWidth !== \"large\") {\n const savedWidthButton = [...previewWidthButtons].find(\n (button) => button.dataset.previewWidth === selectedPreviewWidth,\n );\n if (savedWidthButton) {\n selectToggleButton(previewWidthButtons, savedWidthButton);\n applyPreviewWidth();\n }\n} else {\n applyPreviewWidth();\n}\n\nlet previewDarkOverride = false;\nsyncDarkModeAvailability();\n\npreviewSchemeToggle.addEventListener(\"click\", () => {\n previewDarkOverride = !previewDarkOverride;\n previewSchemeToggle.setAttribute(\"aria-pressed\", String(previewDarkOverride));\n previewSchemeToggle.classList.toggle(\"-icon-moon\", !previewDarkOverride);\n previewSchemeToggle.classList.toggle(\"-icon-sun\", previewDarkOverride);\n void refreshAll();\n});\n\nconst previewFullscreenToggle = document.querySelector<HTMLButtonElement>(\n \"#preview-fullscreen-toggle\",\n)!;\nconst previewPopupToggle = document.querySelector<HTMLButtonElement>(\"#preview-popup-toggle\")!;\nconst previewFullscreenLabel = document.querySelector<HTMLElement>(\"#preview-fullscreen-label\")!;\nconst previewFullscreenTooltip = document.querySelector<HTMLElement>(\n \"#preview-fullscreen-toggle-tip\",\n)!;\nconst previewPopupReturnLabel = document.querySelector<HTMLElement>(\n \"#preview-popup-return-label\",\n)!;\nconst previewPopupTitle = document.querySelector<HTMLElement>(\"#preview-popup-title\")!;\nconst previewPopupBlockedMessage = document.querySelector<HTMLElement>(\n \"#preview-popup-blocked-message\",\n)!;\nconst previewAnchor = document.createComment(\"preview-pane-anchor\");\npreviewPane.before(previewAnchor);\nlet previewWasFullscreen = false;\nlet restoringPreview = false;\n\nfunction setPreviewFullscreen(fullscreen: boolean): void {\n previewFullscreenToggle.setAttribute(\"aria-pressed\", String(fullscreen));\n previewFullscreenToggle.classList.toggle(\"-icon-maximize\", !fullscreen);\n previewFullscreenToggle.classList.toggle(\"-icon-minimize\", fullscreen);\n previewPane.classList.toggle(\"-fullscreen\", fullscreen);\n applyPreviewWidth();\n resizePreviewFrame();\n}\n\nfunction setPreviewPopupLabels(detached: boolean): void {\n previewFullscreenLabel.hidden = detached;\n previewPopupReturnLabel.hidden = !detached;\n const label = (detached ? previewPopupReturnLabel : previewFullscreenLabel).textContent?.trim() ?? \"\";\n previewFullscreenToggle.setAttribute(\n \"aria-label\",\n label,\n );\n previewFullscreenTooltip.textContent = label;\n}\n\nfunction restorePreviewFromPopup(closePopup = true): void {\n if (restoringPreview || previewPane.ownerDocument === document) return;\n restoringPreview = true;\n const popup = previewPopup;\n if (previewPopupCloseTimer !== undefined) window.clearInterval(previewPopupCloseTimer);\n previewPopupCloseTimer = undefined;\n previewPopup = null;\n previewPopupStylePairs = [];\n document.adoptNode(previewPane);\n previewAnchor.after(previewPane);\n setPreviewPopupLabels(false);\n setPreviewFullscreen(previewWasFullscreen);\n if (closePopup && popup && !popup.closed) popup.close();\n restoringPreview = false;\n previewPopupToggle.focus();\n layoutDirectionToggle.disabled = false;\n}\n\nfunction openPreviewPopup(): void {\n if (previewPopup && !previewPopup.closed) {\n previewPopup.focus();\n return;\n }\n\n const width = Math.max(320, Math.min(1200, window.screen.availWidth - 80));\n const height = Math.max(320, Math.min(900, window.screen.availHeight - 80));\n const left = Math.max(\n 0,\n (window.screen.availLeft ?? 0) + (window.screen.availWidth - width) / 2,\n );\n const top = Math.max(\n 0,\n (window.screen.availTop ?? 0) + (window.screen.availHeight - height) / 2,\n );\n const popup = window.open(\n \"\",\n \"pantoken-canvas-preview\",\n `popup=yes,width=${width},height=${height},left=${Math.round(left)},top=${Math.round(top)}`,\n );\n if (!popup) {\n window.alert(previewPopupBlockedMessage.textContent?.trim() ?? \"Preview popup blocked.\");\n return;\n }\n\n previewPopup = popup;\n previewWasFullscreen = previewPane.classList.contains(\"-fullscreen\");\n const popupDocument = popup.document;\n popupDocument.head.replaceChildren();\n popupDocument.body.replaceChildren();\n popupDocument.title = previewPopupTitle.textContent?.trim() ?? \"Preview\";\n popupDocument.body.className = \"preview-popup\";\n previewPopupStylePairs = [];\n for (const source of document.head.querySelectorAll<HTMLLinkElement | HTMLStyleElement>(\n 'link[rel=\"stylesheet\"], style',\n )) {\n const clone = source.cloneNode(true) as HTMLLinkElement | HTMLStyleElement;\n if (source instanceof HTMLLinkElement && clone instanceof HTMLLinkElement) {\n clone.href = source.href;\n }\n popupDocument.head.append(clone);\n if (source instanceof HTMLStyleElement && clone instanceof HTMLStyleElement) {\n previewPopupStylePairs.push({ source, clone });\n }\n }\n syncPreviewPopupChrome();\n popupDocument.body.append(previewPane);\n setPreviewPopupLabels(true);\n setPreviewFullscreen(true);\n layoutDirectionToggle.disabled = true;\n popup.addEventListener(\"pagehide\", () => restorePreviewFromPopup(false), { once: true });\n previewPopupCloseTimer = window.setInterval(() => {\n if (previewPopup?.closed) restorePreviewFromPopup(false);\n }, 500);\n popup.focus();\n}\n\npreviewPopupToggle.addEventListener(\"click\", openPreviewPopup);\npreviewFullscreenToggle.addEventListener(\"click\", () => {\n if (previewPane.ownerDocument !== document) {\n restorePreviewFromPopup();\n return;\n }\n const fullscreen = previewFullscreenToggle.getAttribute(\"aria-pressed\") !== \"true\";\n setPreviewFullscreen(fullscreen);\n persistPreferences();\n});\nif (preferences.previewFullscreen === true) {\n setPreviewFullscreen(true);\n}\n\nwindow.addEventListener(\"beforeunload\", () => {\n if (previewPopupCloseTimer !== undefined) window.clearInterval(previewPopupCloseTimer);\n previewPopup?.close();\n});\n\nconst layoutDirectionToggle = document.querySelector<HTMLButtonElement>(\n \"#layout-direction-toggle\",\n)!;\nconst contentEl = document.querySelector<HTMLElement>(\".panes\")!;\n/** Applies (and reflects in the toggle button) row vs. column pane arrangement. */\nfunction applyLayoutDirection(row: boolean): void {\n layoutDirectionToggle.setAttribute(\"aria-pressed\", String(row));\n layoutDirectionToggle.classList.toggle(\"-icon-rows-2\", row);\n layoutDirectionToggle.classList.toggle(\"-icon-columns-2\", !row);\n contentEl.style.flexDirection = row ? \"row\" : \"column\";\n contentEl.dataset.layout = row ? \"row\" : \"column\";\n applyPreviewWidth();\n}\nlayoutDirectionToggle.addEventListener(\"click\", () => {\n applyLayoutDirection(layoutDirectionToggle.getAttribute(\"aria-pressed\") !== \"true\");\n persistPreferences();\n});\n// Column (stacked) is the default first-visit layout — matches the toggle's default markup\n// (aria-pressed=\"false\", the columns-2 icon) so there's no dead first click reconciling a\n// mismatched initial state.\napplyLayoutDirection(preferences.layout === \"row\");\n\n/** Saves this app's current layout/preview/CDN provider settings for the next visit. */\nfunction persistPreferences(): void {\n const mergedTinymceConfig = {\n ...(preferences.tinymceConfig ?? {}),\n a11y: {\n ...((preferences.tinymceConfig as Record<string, unknown> | undefined)?.a11y as Record<\n string,\n unknown\n > | null),\n highlightIssues: true,\n contrastThreshold: \"4.5:1\",\n enabledRules: {},\n },\n };\n\n savePreferences({\n ...preferences,\n layout: contentEl.dataset.layout === \"row\" ? \"row\" : \"column\",\n previewWidth: selectedPreviewWidth,\n previewFullscreen: previewPane.classList.contains(\"-fullscreen\"),\n cdnProvider: providerSelect.value,\n includeInteractions: includeInteractionsCheckbox.checked,\n ...(providerSelect.value === INLINE_PROVIDER_ID ? { includeInteractions: rememberedInteractions } : {}),\n tinymceConfig: mergedTinymceConfig,\n });\n}\n\n\nincludeDarkModeCheckbox.addEventListener(\"change\", () => {\n syncPreviewSchemeToggleAvailability();\n applyEditorTheme(activeEditor);\n void refreshAll();\n});\n\nincludeInteractionsCheckbox.addEventListener(\"change\", () => {\n syncPreviewResetAvailability();\n void refreshAll();\n persistPreferences();\n});\n\n/** Debounce helper — the preview pane only needs to refresh a beat after typing settles. */\nfunction debounce<Args extends unknown[]>(fn: (...args: Args) => void, ms: number) {\n let handle: ReturnType<typeof setTimeout> | undefined;\n return (...args: Args) => {\n if (handle) clearTimeout(handle);\n handle = setTimeout(() => fn(...args), ms);\n };\n}\n\n/**\n * Renders the editor's current HTML with the CSS/JS tab's *current editable text* embedded\n * directly (not linked from the CDN) — so hand-edits in those tabs show up in the preview too.\n * The body content is wrapped to match Canvas's own content-area background and max width.\n * The editable outer `data-pantoken-color` wrapper, plus the inlined `CUSTOM_THEME_COLORS_CSS`,\n * remaps brand colors instantly — a no-op for the default \"navy\" scheme. `#content`'s height is a min,\n * not a fixed viewport height, so the iframe (resized to match in `resizePreviewFrame`) grows to\n * fit instead of scrolling internally.\n */\nfunction updatePreview(theme: { css: string; js: string }): void {\n if (!activeEditor) return;\n // Canvas's own theme already frames the RCE content area — the picker's border would double up.\n previewFrame.style.borderColor =\n selectedTheme === \"canvas\" || selectedTheme === \"canvasHighContrast\" ? \"transparent\" : \"\";\n const portable = providerSelect.value === INLINE_PROVIDER_ID;\n if (portable) previewFrame.setAttribute(\"sandbox\", \"allow-same-origin\");\n else previewFrame.removeAttribute(\"sandbox\");\n const previewTokensCss = selectedTheme === \"canvas\" ? canvasTokensCss\n : selectedTheme === \"canvasHighContrast\" ? canvasHighContrastTokensCss\n : adaptiveTokensCss;\n const previewFrameCss = `@scope (:root) to (#content > *) {\n${baseCss}\n${componentsCss}\n${utilitiesCss}\n}`;\n const themeCss = (portable ? [previewTokensCss, PREVIEW_SCHEME_FORCE_CSS] : [theme.css, PREVIEW_SCHEME_FORCE_CSS, cssEditorView.state.doc.toString()])\n .filter(Boolean)\n .join(\"\\n\");\n const themeJs = (portable ? [] : [includeInteractionsCheckbox.checked ? localInteractionsJs : \"\", jsEditorView.state.doc.toString()])\n .filter(Boolean)\n .join(\"\\n\");\n // Elevation is a rebrand-only affordance — Canvas's own themes don't use drop-shadow surfaces.\n const contentClass =\n selectedTheme === \"rebrand\"\n ? \"instui-view -background-primary --elevation-resting\"\n : \"instui-view -background-primary\";\n // The preview is a srcdoc document, so it's a hard scope boundary: it declares its own theme,\n // scheme, and color outright rather than inheriting anything from the editor chrome around it.\n // That's what lets the preview sit in light Canvas while the chrome sits in dark rebrand.\n const previewScheme =\n selectedTheme === \"rebrand\" && includeDarkModeCheckbox.checked && previewDarkOverride\n ? \"dark\"\n : \"light\";\n loadPreviewDocument(`<!doctype html><html data-pantoken-boundary data-pantoken-instance=\"${EDITOR_INSTANCE}-preview\" data-pantoken-theme=\"${selectedTheme}\" data-pantoken-scheme=\"${previewScheme}\" data-pantoken-color=\"${selectedColor}\" style=\"color-scheme:${previewScheme}\"><head><style>${previewFrameCss}\n${themeCss}\n${portable ? \"\" : CUSTOM_THEME_COLORS_CSS}</style><style>html{background:var(--instui-color-background-page)}#wrapper{padding:32px;}#content{padding:36px 48px 48px;min-height:20rem;margin:0 auto;border-radius:12px;}@media not all and (min-width: 768px) {\n #wrapper{padding:24px;}#content{padding-left:12px;padding-right:12px;min-height:16rem;border-radius:8px;}</style></head><body>\n <div id=\"wrapper\" class=\"instui-view\"><div id=\"content\" class=\"${contentClass}\" style=\"max-width: ${CANVAS_CONTENT_MAX_WIDTH};\">\n ${getNormalizedEditorHtml()}\n </div></div>\n ${portable ? \"\" : \"<script>\" + themeJs + \"<\/script>\"}\n </body></html>`);\n}\nconst debouncedUpdatePreview = debounce(() => void refreshAll(), 300);\n\n// Keep the same-origin preview frame at its content height; the docs embedding page separately\n// receives its own postMessage height updates from `canvas-rce-iframe-height.js`.\nlet previewResizeObserver: ResizeObserver | undefined;\nlet previewMutationObserver: MutationObserver | undefined;\nconst PREVIEW_BORDER_PX = 2;\nfunction resizePreviewFrame(): void {\n // Fullscreen pins the pane to the viewport, so the frame flexes to fill it (app.css) rather than\n // growing past it — a content-height frame would push the overlay into a scrollbar.\n if (previewPane.classList.contains(\"-fullscreen\")) {\n previewFrame.style.removeProperty(\"height\");\n return;\n }\n const root = previewFrame.contentDocument?.documentElement;\n const body = previewFrame.contentDocument?.body;\n if (!root || !body) return;\n const style = getComputedStyle(body);\n const margins = Number.parseFloat(style.marginTop) + Number.parseFloat(style.marginBottom);\n const height = Math.ceil(Math.max(root.getBoundingClientRect().height, body.offsetHeight + margins));\n previewFrame.style.height = `${height + PREVIEW_BORDER_PX}px`;\n}\n\nfunction handlePreviewLinkClick(event: MouseEvent): void {\n if (event.defaultPrevented) return;\n const anchor = (event.target as Element | null)?.closest(\"a[href]\");\n const href = anchor?.getAttribute(\"href\")?.trim();\n if (!href?.startsWith(\"#\")) return;\n\n event.preventDefault();\n let fragment: string;\n try {\n fragment = decodeURIComponent(href.slice(1));\n } catch {\n return;\n }\n if (!fragment) return;\n\n const previewDocument = event.currentTarget as Document;\n const target =\n previewDocument.getElementById(fragment) ?? previewDocument.getElementsByName(fragment)[0];\n target?.scrollIntoView();\n}\n\npreviewFrame.addEventListener(\"load\", () => {\n stopPreviewTracking?.();\n previewResizeObserver?.disconnect();\n previewMutationObserver?.disconnect();\n resizePreviewFrame();\n previewFrame.contentDocument?.addEventListener(\"click\", handlePreviewLinkClick);\n const root = previewFrame.contentDocument?.documentElement;\n if (!root) return;\n previewResizeObserver = new ResizeObserver(resizePreviewFrame);\n previewResizeObserver.observe(root);\n previewMutationObserver = new MutationObserver(resizePreviewFrame);\n previewMutationObserver.observe(root, { childList: true, subtree: true, attributes: true });\n const loadedDocument = previewFrame.contentDocument;\n requestAnimationFrame(() => requestAnimationFrame(() => {\n if (previewFrame.contentDocument !== loadedDocument) return;\n const content = loadedDocument?.querySelector<HTMLElement>(\"#content\");\n previewLoading = false;\n if (content) stopPreviewTracking = trackPreviewChanges(content, (dirty) => {\n if (previewFrame.contentDocument !== loadedDocument) return;\n previewDirty = dirty;\n syncPreviewResetAvailability();\n });\n syncPreviewResetAvailability();\n }));\n});\n\nfunction buildDownloadFiles(theme: { css: string; js: string }): {\n css: string;\n js: string;\n} {\n const { css: presetCss, js: presetJs } = providerSelect.value === INLINE_PROVIDER_ID\n ? { css: \"\", js: \"\" }\n : theme;\n return {\n css: [presetCss, cssEditorView.state.doc.toString()].filter(Boolean).join(\"\\n\"),\n js: [presetJs, jsEditorView.state.doc.toString()].filter(Boolean).join(\"\\n\"),\n };\n}\n\n/** Regenerates the downloadable theme.css/theme.js blobs, appending the author's custom CSS/JS\n * tab content onto the generated preset for the chosen provider/theme/mode. */\nfunction updateDownloads(theme: { css: string; js: string }): void {\n const files = buildDownloadFiles(theme);\n if (cssObjectUrl) URL.revokeObjectURL(cssObjectUrl);\n if (jsObjectUrl) URL.revokeObjectURL(jsObjectUrl);\n cssObjectUrl = files.css.trim() ? URL.createObjectURL(new Blob([files.css], { type: \"text/css\" })) : \"\";\n jsObjectUrl = files.js.trim() ? URL.createObjectURL(new Blob([files.js], { type: \"text/javascript\" })) : \"\";\n for (const [link, objectUrl] of [[downloadCss, cssObjectUrl], [downloadJs, jsObjectUrl]] as const) {\n if (objectUrl) link.href = objectUrl;\n else link.removeAttribute(\"href\");\n link.setAttribute(\"aria-disabled\", String(!objectUrl));\n link.tabIndex = objectUrl ? 0 : -1;\n link.style.color = objectUrl ? \"\" : \"var(--instui-color-text-interactive-disabled-base)\";\n }\n}\n\nfunction downloadBlob(blob: Blob, filename: string): void {\n const objectUrl = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = objectUrl;\n anchor.download = filename;\n document.body.append(anchor);\n anchor.click();\n anchor.remove();\n setTimeout(() => URL.revokeObjectURL(objectUrl), 0);\n}\n\n/** The currently open/saved preset's name, if any — downloads use it so the file the author is\n * actually working on isn't always exported as a generic \"canvas-theme\"/\"untitled\". */\nfunction activePresetName(): string | undefined {\n const savePlugin = activeEditor?.plugins[SAVE_PLUGIN_NAME] as\n | SavePluginApi<CanvasThemePreset>\n | undefined;\n const activeId = savePlugin?.activePresetId;\n if (!activeId) return undefined;\n return savePlugin.list().find((preset) => preset.id === activeId)?.name;\n}\n\nasync function refreshAll(): Promise<void> {\n const generation = ++refreshGeneration;\n try {\n const theme = await buildCurrentTheme();\n if (generation !== refreshGeneration) return;\n await syncInlineProvider(theme);\n if (generation !== refreshGeneration) return;\n updatePreview(theme);\n updateDownloads(theme);\n } catch (error) {\n console.error(\"Unable to build the selected theme\", error);\n }\n}\n\n// CSS/JS editors start blank — anything typed here is appended to the generated preset (in both\n// the preview and the downloaded files) rather than replacing it.\nconst cssEditorView = createEditor(\n document.querySelector<HTMLElement>(\"#css-editor\")!,\n \"css\",\n \"\",\n () => debouncedUpdatePreview(),\n);\nconst jsEditorView = createEditor(\n document.querySelector<HTMLElement>(\"#js-editor\")!,\n \"javascript\",\n \"\",\n () => debouncedUpdatePreview(),\n);\n\nproviderSelect.addEventListener(\"change\", () => {\n syncProviderPolicy();\n applyEditorTheme(activeEditor);\n if (activeEditor) retargetContentStylesheets(activeEditor, buildSelectedAssetUrl);\n void refreshAll();\n persistPreferences();\n});\n\ndownloadHtmlButton.addEventListener(\"click\", () => {\n downloadBlob(\n new Blob([getNormalizedEditorHtml()], { type: \"text/html;charset=utf-8\" }),\n `${slugifyExportName(activePresetName() ?? \"index\")}.html`,\n );\n});\n\ndownloadPackageButton.addEventListener(\"click\", () => {\n downloadPackageButton.disabled = true;\n void buildCurrentTheme()\n .then((theme) => {\n const files = buildDownloadFiles(theme);\n const archive = zipSync({\n \"index.html\": strToU8(getNormalizedEditorHtml()),\n \"theme.css\": strToU8(files.css),\n \"theme.js\": strToU8(files.js),\n });\n downloadBlob(\n new Blob([archive], { type: \"application/zip\" }),\n `${slugifyExportName(activePresetName() ?? \"canvas-theme\")}.zip`,\n );\n })\n .catch((error) => {\n console.error(\"Unable to build the theme package\", error);\n })\n .finally(() => {\n downloadPackageButton.disabled = false;\n });\n});\n\ncopyButton.addEventListener(\"click\", () => {\n void navigator.clipboard.writeText(getNormalizedEditorHtml());\n});\n\nregisterPantokenIconPack(tinymce.IconManager);\n\nwindow.addEventListener(\"pagehide\", () => {\n if (!activeEditor) return;\n try {\n sessionStorage.setItem(SESSION_DRAFT_KEY, JSON.stringify(captureCanvasThemePreset()));\n } catch {\n // Disabled storage cannot preserve this session's unsaved changes.\n }\n});\n\nvoid registerPantokenPlugin.then(async () => {\n const languagePack = tinymceLanguages[activeLocale];\n let language = \"en\";\n if (languagePack) {\n try {\n await languagePack[1]();\n language = languagePack[0];\n const messages = tinymce.i18n.getData()[language];\n if (messages) {\n tinymce.addI18n(\n language,\n Object.fromEntries(\n Object.entries(messages).map(([source, translation]) => [source, translation || source]),\n ),\n );\n }\n } catch (error) {\n console.warn(\"Unable to load the TinyMCE language pack; using English\", error);\n }\n }\n return tinymce\n .init({\n selector: \"#editor\",\n language,\n language_load: false,\n plugins:\n \"pantoken pantoken_content_classes placehold pantoken_a11y pantoken_save pantoken_sup_sub pantoken_source_toggle pantoken_fullscreen_footer pantoken_searchreplace_footer pantoken_visualblocks_footer image link lists table media autosave fullscreen quickbars searchreplace wordcount visualblocks\",\n toolbar: `${SAVE_TOOLBAR_NAME} undo redo | pantoken | fontsize blocks | bold italic underline forecolor backcolor ${SUP_SUB_TOOLBAR_NAME} | link image placehold | align | bullist numlist | removeformat table media`,\n menubar: false,\n theme: \"silver\",\n icons: PANTOKEN_ICON_PACK_NAME,\n branding: false,\n // Self-hosted TinyMCE 6+ requires a license_key; \"gpl\" opts into the GPL license terms.\n license_key: \"gpl\",\n browser_spellcheck: true,\n convert_urls: false,\n toolbar_mode: \"floating\",\n height: EDITOR_HEIGHT_PX,\n skin: false,\n content_css: false,\n // Not part of the footer's fixed control set (a11y, word count, html editor, fullscreen,\n // find & replace) — the breadcrumb is dropped rather than added as a sixth item.\n elementpath: false,\n block_formats: \"Paragraph=p;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6\",\n // Hides the image dialog's Upload tab so only a remote http/https URL can be inserted — no\n // local file picker, no base64 data-URI embedding.\n image_uploadtab: false,\n image_advtab: true,\n // TinyMCE's autosave plugin persists drafts to localStorage by default.\n autosave_ask_before_unload: true,\n autosave_interval: \"30s\",\n autosave_retention: \"30m\",\n autosave_restore_when_empty: false,\n // Mirrors the fixed toolbar's own formatting groups so the contextual popup never offers a\n // control the fixed toolbar lacks.\n quickbars_selection_toolbar: `bold italic underline forecolor backcolor ${SUP_SUB_TOOLBAR_NAME} | link | align | removeformat`,\n quickbars_insert_toolbar: \"quickimage quicktable media placehold\",\n quickbars_image_toolbar: \"alignleft aligncenter alignright | image\",\n setup(editor: Editor): void {\n editor.on(\"input change Undo Redo SetContent\", () => {\n if (applyingInline) return;\n syncThemeColorFromEditor();\n if (syncIconAssetsFromEditor()) void refreshAll();\n debouncedUpdatePreview();\n });\n },\n })\n .then((editors: Editor[]) => {\n activeEditor = editors[0];\n syncProviderPolicy();\n try {\n const saved = sessionStorage.getItem(SESSION_DRAFT_KEY);\n if (saved) {\n sessionStorage.removeItem(SESSION_DRAFT_KEY);\n const draft: unknown = JSON.parse(saved);\n if (isCanvasThemePreset(draft)) restoreCanvasThemePreset(draft);\n }\n } catch {\n // Disabled or corrupt storage leaves the editor's initial content unchanged.\n }\n syncThemeColorFromEditor();\n syncIconAssetsFromEditor();\n document.documentElement.dataset.pantokenScheme = includeDarkModeCheckbox.checked\n ? \"dark\"\n : \"light\";\n applyEditorTheme(activeEditor);\n void refreshAll();\n });\n });\n",
36
+ "src/preferences.ts": "/** Persists this app's own editor/preview UI settings across reloads — never the authored content. */\nconst STORAGE_KEY = \"pantoken-canvas-theme-editor-preferences\";\n\n/** Shape of the persisted UI preferences blob. */\nexport interface StoredPreferences {\n layout: \"row\" | \"column\";\n previewWidth: \"large\" | \"medium\" | \"small\" | number;\n previewFullscreen: boolean;\n cdnProvider: string;\n includeInteractions?: boolean;\n tinymceConfig?: Record<string, unknown>;\n}\n\n/** Reads stored preferences, tolerating missing/corrupt/blocked storage. */\nexport function loadPreferences(): Partial<StoredPreferences> {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return {};\n const parsed: unknown = JSON.parse(raw);\n return typeof parsed === \"object\" && parsed !== null\n ? (parsed as Partial<StoredPreferences>)\n : {};\n } catch {\n return {};\n }\n}\n\n/** Persists preferences, silently no-op-ing if storage is unavailable. */\nexport function savePreferences(preferences: Partial<StoredPreferences>): void {\n try {\n const current = loadPreferences();\n const nextTinymceConfig = {\n ...(typeof current.tinymceConfig === \"object\" && current.tinymceConfig !== null\n ? current.tinymceConfig\n : {}),\n ...(typeof preferences.tinymceConfig === \"object\" && preferences.tinymceConfig !== null\n ? preferences.tinymceConfig\n : {}),\n };\n const nextPreferences = {\n ...current,\n ...preferences,\n tinymceConfig: nextTinymceConfig,\n };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(nextPreferences));\n } catch {\n // Private mode / storage disabled — preferences just won't persist across reloads.\n }\n}\n",
37
+ "src/preview-state.ts": "function fingerprint(root: HTMLElement): string {\n const states = [\n ...root.querySelectorAll<HTMLInputElement>(\"input,select,textarea,details,dialog,[popover]\"),\n ].map((element) => [\n element.value,\n element.checked,\n (element as unknown as HTMLDetailsElement).open,\n element.hasAttribute(\"popover\") && element.matches(\":popover-open\"),\n ]);\n return JSON.stringify([root.innerHTML, states]);\n}\n\n/** Observe meaningful preview changes against its loaded baseline; never modify authored HTML. */\nexport function trackPreviewChanges(\n root: HTMLElement,\n onChange: (dirty: boolean) => void,\n): () => void {\n const baseline = fingerprint(root);\n let dirty = false;\n const check = (): void => {\n const next = fingerprint(root) !== baseline;\n if (dirty === next) return;\n dirty = next;\n onChange(dirty);\n };\n const observer = new MutationObserver(check);\n observer.observe(root, { childList: true, subtree: true, attributes: true, characterData: true });\n for (const event of [\"input\", \"change\", \"toggle\"]) root.addEventListener(event, check, true);\n onChange(false);\n return () => {\n observer.disconnect();\n for (const event of [\"input\", \"change\", \"toggle\"]) root.removeEventListener(event, check, true);\n };\n}\n",
35
38
  "cssdoc.json": "{\n \"$schema\": \"https://cssdoc.dev/cssdoc.schema.json\",\n \"extends\": [\n \"./node_modules/@pantoken/pantoken/cssdoc-base.json\"\n ],\n \"modifierConvention\": \"rscss\",\n \"inlineComments\": \"ignore\",\n \"providers\": [\n {\n \"path\": \"./node_modules/@pantoken/pantoken/model.json\"\n }\n ]\n}",
36
- "src/strings.ts": "// GENERATED by scripts/generate.ts — do not edit by hand.\n/** English UI strings, resolved at runtime by the platform's `{{key}}` substitution. */\nexport const STRINGS: Record<string, string> = {\n \"pageTitle\": \"RCE template authoring\",\n \"pageDescription\": \"Author Canvas RCE page templates styled with pantoken, with a live preview.\",\n \"editThemeLabel\": \"Edit theme\",\n \"layoutDirectionLabel\": \"Switch layout orientation\",\n \"helpAriaLabel\": \"Help\",\n \"appModeLabel\": \"Open web app\",\n \"copyHtmlLabel\": \"Copy HTML\",\n \"downloadPackageLabel\": \"Download package\",\n \"previewFrameTitle\": \"Styled preview\",\n \"previewWidthGroupLabel\": \"Preview width\",\n \"previewWidthLargeLabel\": \"Large\",\n \"previewWidthMediumLabel\": \"Medium\",\n \"previewWidthSmallLabel\": \"Small\",\n \"previewWidthValueLabel\": \"Preview width in pixels\",\n \"previewSchemeToggleLabel\": \"Preview dark mode\",\n \"previewPopupLabel\": \"Open preview in a popup\",\n \"previewPopupTitle\": \"Canvas content preview\",\n \"previewPopupBlockedMessage\": \"The preview popup was blocked. Allow popups for this site and try again.\",\n \"previewFullscreenLabel\": \"Show preview fullscreen\",\n \"previewPopupReturnLabel\": \"Return preview to the editor\",\n \"downloadHtmlLabel\": \"Download HTML\",\n \"themeTrayAriaLabel\": \"Theme settings\",\n \"tabConfigLabel\": \"Config\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN provider\",\n \"localProviderLabel\": \"None (inline)\",\n \"cdnSectionLabel\": \"CDN\",\n \"themeLabel\": \"Theme\",\n \"appearanceLabel\": \"Appearance\",\n \"appearanceLightLabel\": \"Light\",\n \"appearanceDarkLabel\": \"Dark\",\n \"themeRebrandLabel\": \"Next gen\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas high contrast\",\n \"includeDarkModeLabel\": \"Include dark mode\",\n \"colorLabel\": \"Color scheme\",\n \"colorNavyLabel\": \"Navy\",\n \"colorBlueLabel\": \"Blue\",\n \"colorGreenLabel\": \"Green\",\n \"colorRedLabel\": \"Red\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Grey\",\n \"colorPlumLabel\": \"Plum\",\n \"colorVioletLabel\": \"Violet\",\n \"colorStoneLabel\": \"Stone\",\n \"colorSkyLabel\": \"Sky\",\n \"colorHoneyLabel\": \"Honey\",\n \"colorSeaLabel\": \"Sea\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Custom\",\n \"customColorInputLabel\": \"Brand color (hex)\",\n \"downloadCssLabel\": \"Download theme.css\",\n \"downloadJsLabel\": \"Download theme.js\",\n \"cssPanelHintLabel\": \"Add custom CSS here — it's appended to the generated theme.css, in the preview and the download.\",\n \"jsPanelHintLabel\": \"Add custom JS here — it's appended to the generated theme.js, in the preview and the download.\",\n \"helpModalTitle\": \"How to use this page\",\n \"helpModalBody1\": \"Pick a starter template, edit it like you would in the Canvas Rich Content Editor, then click <strong>Copy HTML</strong> and paste the result into a Canvas page (switch to the HTML editor view first). Canvas sanitizes pasted HTML server-side — this preview doesn't attempt to replicate that, so always verify the pasted result in Canvas.\",\n \"helpModalBody2\": \"Use <strong>Edit theme</strong> to change the CDN provider, theme, or mode, and to add custom CSS/JS that's appended to the generated <code>theme.css</code>/<code>theme.js</code> before downloading them.\",\n \"closeLabel\": \"Close\"\n};\n",
39
+ "src/strings.ts": "// GENERATED by scripts/generate.ts — do not edit by hand.\n/** English UI strings, resolved at runtime by the platform's `{{key}}` substitution. */\nexport const STRINGS: Record<string, string> = {\n \"pageTitle\": \"RCE template authoring\",\n \"pageDescription\": \"Author Canvas RCE page templates styled with pantoken, with a live preview.\",\n \"editThemeLabel\": \"Edit theme\",\n \"layoutDirectionLabel\": \"Switch layout orientation\",\n \"helpAriaLabel\": \"Help\",\n \"appModeLabel\": \"Open web app\",\n \"copyHtmlLabel\": \"Copy HTML\",\n \"downloadPackageLabel\": \"Download package\",\n \"previewFrameTitle\": \"Styled preview\",\n \"previewWidthGroupLabel\": \"Preview width\",\n \"previewWidthLargeLabel\": \"Large\",\n \"previewWidthMediumLabel\": \"Medium\",\n \"previewWidthSmallLabel\": \"Small\",\n \"previewWidthValueLabel\": \"Preview width in pixels\",\n \"previewSchemeToggleLabel\": \"Preview dark mode\",\n \"previewPopupLabel\": \"Open preview in a popup\",\n \"previewPopupTitle\": \"Canvas content preview\",\n \"previewPopupBlockedMessage\": \"The preview popup was blocked. Allow popups for this site and try again.\",\n \"previewFullscreenLabel\": \"Show preview fullscreen\",\n \"previewPopupReturnLabel\": \"Return preview to the editor\",\n \"downloadHtmlLabel\": \"Download HTML\",\n \"themeTrayAriaLabel\": \"Theme settings\",\n \"tabConfigLabel\": \"Config\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN provider\",\n \"localProviderLabel\": \"None\",\n \"inlineProviderLabel\": \"Inline\",\n \"cdnSectionLabel\": \"CDN\",\n \"themeLabel\": \"Theme\",\n \"appearanceLabel\": \"Appearance\",\n \"appearanceLightLabel\": \"Light\",\n \"appearanceDarkLabel\": \"Dark\",\n \"themeRebrandLabel\": \"Next gen\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas high contrast\",\n \"includeDarkModeLabel\": \"Include dark mode\",\n \"includeInteractionsLabel\": \"Include interactions\",\n \"previewResetLabel\": \"Reset preview\",\n \"colorLabel\": \"Color scheme\",\n \"colorNavyLabel\": \"Navy\",\n \"colorBlueLabel\": \"Blue\",\n \"colorGreenLabel\": \"Green\",\n \"colorRedLabel\": \"Red\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Grey\",\n \"colorPlumLabel\": \"Plum\",\n \"colorVioletLabel\": \"Violet\",\n \"colorStoneLabel\": \"Stone\",\n \"colorSkyLabel\": \"Sky\",\n \"colorHoneyLabel\": \"Honey\",\n \"colorSeaLabel\": \"Sea\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Custom\",\n \"customColorInputLabel\": \"Brand color (hex)\",\n \"downloadCssLabel\": \"Download theme.css\",\n \"downloadJsLabel\": \"Download theme.js\",\n \"cssPanelHintLabel\": \"Add custom CSS here — it's appended to the generated theme.css, in the preview and the download.\",\n \"jsPanelHintLabel\": \"Add custom JS here — it's appended to the generated theme.js, in the preview and the download.\",\n \"helpModalTitle\": \"How to use this page\",\n \"helpModalBody1\": \"Pick a starter template, edit it like you would in the Canvas Rich Content Editor, then click <strong>Copy HTML</strong> and paste the result into a Canvas page (switch to the HTML editor view first). Canvas sanitizes pasted HTML server-side — this preview doesn't attempt to replicate that, so always verify the pasted result in Canvas.\",\n \"helpModalBody2\": \"Use <strong>Edit theme</strong> to change the CDN provider, theme, or mode, and to add custom CSS/JS that's appended to the generated <code>theme.css</code>/<code>theme.js</code> before downloading them.\",\n \"closeLabel\": \"Close\"\n};\n",
37
40
  "src/locale-strings.ts": "// GENERATED by scripts/generate.ts — do not edit by hand.\n/** Locale → UI string overrides layered over `STRINGS`; a missing key/locale falls back to English. */\nexport const LOCALE_STRINGS: Record<string, Record<string, string>> = {\n \"ar\": {\n \"pageTitle\": \"إنشاء قوالب RCE\",\n \"pageDescription\": \"أنشئ قوالب صفحات Canvas RCE منمقة باستخدام pantoken، مع معاينة مباشرة.\",\n \"editThemeLabel\": \"تعديل السمة\",\n \"layoutDirectionLabel\": \"تبديل اتجاه التخطيط\",\n \"helpAriaLabel\": \"مساعدة\",\n \"appModeLabel\": \"فتح تطبيق الويب\",\n \"copyHtmlLabel\": \"نسخ HTML\",\n \"previewFrameTitle\": \"معاينة منمقة\",\n \"previewWidthLargeLabel\": \"كبير\",\n \"previewWidthMediumLabel\": \"متوسط\",\n \"previewWidthSmallLabel\": \"صغير\",\n \"previewSchemeToggleLabel\": \"معاينة الوضع الداكن\",\n \"previewPopupLabel\": \"فتح المعاينة في نافذة منبثقة\",\n \"previewPopupTitle\": \"معاينة محتوى اللوحة\",\n \"previewPopupBlockedMessage\": \"تم حظر النافذة المنبثقة للمعاينة. قم بالسماح بالنوافذ المنبثقة لهذا الموقع وحاول مرة أخرى.\",\n \"previewFullscreenLabel\": \"عرض المعاينة بملء الشاشة\",\n \"previewPopupReturnLabel\": \"إعادة المعاينة إلى المحرر\",\n \"downloadHtmlLabel\": \"تنزيل HTML\",\n \"themeTrayAriaLabel\": \"إعدادات السمة\",\n \"tabConfigLabel\": \"الإعداد\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"مزود CDN\",\n \"localProviderLabel\": \"لا شيء (ضمن السطر)\",\n \"themeLabel\": \"السمة\",\n \"appearanceLabel\": \"المظهر\",\n \"appearanceLightLabel\": \"فاتح\",\n \"appearanceDarkLabel\": \"داكن\",\n \"themeCanvasLabel\": \"اللوحة\",\n \"themeCanvasHighContrastLabel\": \"اللوحة بتباين مرتفع\",\n \"includeDarkModeLabel\": \"تضمين الوضع الداكن\",\n \"colorLabel\": \"مخطط الألوان\",\n \"colorNavyLabel\": \"كحلي\",\n \"colorBlueLabel\": \"أزرق\",\n \"colorGreenLabel\": \"أخضر\",\n \"colorRedLabel\": \"أحمر\",\n \"colorOrangeLabel\": \"برتقالي\",\n \"colorGreyLabel\": \"رمادي\",\n \"colorPlumLabel\": \"برقوقي\",\n \"colorVioletLabel\": \"بنفسجي\",\n \"colorStoneLabel\": \"حجري\",\n \"colorSkyLabel\": \"سماوي\",\n \"colorHoneyLabel\": \"عسلي\",\n \"colorSeaLabel\": \"بحري\",\n \"colorAuroraLabel\": \"أورورا\",\n \"colorCustomLabel\": \"مخصص\",\n \"customColorInputLabel\": \"لون العلامة التجارية (سداسي عشري)\",\n \"downloadCssLabel\": \"تحميل theme.css\",\n \"downloadJsLabel\": \"تحميل theme.js\",\n \"cssPanelHintLabel\": \"أضف CSS مخصصًا هنا — سيتم إلحاقه بملف theme.css الذي تم إنشاؤه، في المعاينة وعند التنزيل.\",\n \"jsPanelHintLabel\": \"أضف JS مخصصًا هنا — سيتم إلحاقه بملف theme.js الذي تم إنشاؤه، في المعاينة وعند التنزيل.\",\n \"helpModalTitle\": \"كيفية استخدام هذه الصفحة\",\n \"helpModalBody1\": \"اختر قالب بداية، عدّله كما تفعل في محرر المحتوى الغني Canvas، ثم انقر <strong>نسخ HTML</strong> والصق النتيجة في صفحة Canvas (انتقل أولًا إلى عرض محرر HTML). يقوم Canvas بتصفية HTML الملصوق على مستوى الخادم — هذه المعاينة لا تحاول محاكاة ذلك، لذا تحقق دائمًا من النتيجة الملصوقة داخل Canvas.\",\n \"helpModalBody2\": \"استخدم <strong>تعديل السمة</strong> لتغيير مزود CDN أو السمة أو الوضع، ولتحرير الملفات المولدة <code>theme.css</code>/<code>theme.js</code يدويًا قبل تحميلها.\",\n \"closeLabel\": \"إغلاق\"\n },\n \"hy\": {\n \"pageTitle\": \"RCE տեմպլեյթի հեղինակություն\",\n \"pageDescription\": \"Արտադրեք Canvas RCE էջի տեմպլեյթներ՝ pantoken-ով ոճավորված, կենդանի նախադիտումով.\",\n \"editThemeLabel\": \"Խմբագրել թեման\",\n \"layoutDirectionLabel\": \"Փոխել դասավորության ուղղությունը\",\n \"helpAriaLabel\": \"Օգնություն\",\n \"appModeLabel\": \"Բացել web հավելվածը\",\n \"copyHtmlLabel\": \"Պատճենել HTML\",\n \"previewFrameTitle\": \"Ոճավորված նախադիտում\",\n \"previewWidthLargeLabel\": \"Մեծ\",\n \"previewWidthMediumLabel\": \"Միջին\",\n \"previewWidthSmallLabel\": \"Փոքր\",\n \"previewSchemeToggleLabel\": \"Նախադիտել մութ ռեժիմը\",\n \"previewPopupLabel\": \"Բացել նախադիտումը բացվող պատուհանում\",\n \"previewPopupTitle\": \"Canvas բովանդակության նախադիտում\",\n \"previewPopupBlockedMessage\": \"Նախադիտման բացվող պատուհանը արգելափակվել է. Միացրեք այդ կայքի բացվող պատուհանները և փորձեք կրկին.\",\n \"previewFullscreenLabel\": \"Ցուցադրել նախադիտումը ամբողջ էկրանով\",\n \"previewPopupReturnLabel\": \"Վերադարձնել նախադիտումը խմբագրիչին\",\n \"downloadHtmlLabel\": \"Ներբեռնել HTML\",\n \"themeTrayAriaLabel\": \"Թեմայի կարգավորումներ\",\n \"tabConfigLabel\": \"Կոնֆիգ\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN մատակարար\",\n \"localProviderLabel\": \"Ոչ (inline)\",\n \"themeLabel\": \"Թեմա\",\n \"appearanceLabel\": \"Տեսք\",\n \"appearanceLightLabel\": \"Թեթև\",\n \"appearanceDarkLabel\": \"Մութ\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas՝ բարձր հակադրությամբ\",\n \"includeDarkModeLabel\": \"Ընդգրկել մութ ռեժիմը\",\n \"colorLabel\": \"Գույնի սխեմա\",\n \"colorNavyLabel\": \"Նավի (խոր կապույտ)\",\n \"colorBlueLabel\": \"Կապույտ\",\n \"colorGreenLabel\": \"Կանաչ\",\n \"colorRedLabel\": \"Կարմիր\",\n \"colorOrangeLabel\": \"Նարնջագույն\",\n \"colorGreyLabel\": \"Մոխրագույն\",\n \"colorPlumLabel\": \"Ծիրանագույն\",\n \"colorVioletLabel\": \"Մանուշակագույն\",\n \"colorStoneLabel\": \"Քարային\",\n \"colorSkyLabel\": \"Երկնագույն\",\n \"colorHoneyLabel\": \"Մեղրագույն\",\n \"colorSeaLabel\": \"Ծովային\",\n \"colorAuroraLabel\": \"Աուրորա\",\n \"colorCustomLabel\": \"Պատվերով\",\n \"customColorInputLabel\": \"Ապրանքանիշի գույն (hex)\",\n \"downloadCssLabel\": \"Ներբեռնել theme.css\",\n \"downloadJsLabel\": \"Ներբեռնել theme.js\",\n \"cssPanelHintLabel\": \"Ավելացրեք համապատասխան CSS այստեղ — այն հավելվում է 생성ված theme.css ֆայլին, թե՛ նախադիտման մեջ, թե՛ ներբեռնումում.\",\n \"jsPanelHintLabel\": \"Ավելացրեք համապատասխան JS այստեղ — այն հավելվում է 생성ված theme.js ֆայլին, թե՛ նախադիտման մեջ, թե՛ ներբեռնումում.\",\n \"helpModalTitle\": \"Ինչպես օգտագործել այս էջը\",\n \"helpModalBody1\": \"Ընտրեք ստարտեր տեմպլեյթ, խմբագրեք այն ինչպես Canvas Rich Content Editor-ում, այնուհետև սեղմեք <strong>Copy HTML</strong> և պատճենեք արդյունքը Canvas էջում (առաջին հերթին անցեք HTML խմբագրիչ ռեժիմին). Canvas-ը սերվեր կերպով սանիտիզացնում է պատճենված HTML-ը — այս նախադիտումը չի փորձարկում նույն սպեցիֆիկացումը, այնպես որ միշտ ստուգեք արդյունքը Canvas-ում:\",\n \"helpModalBody2\": \"Օգտագործեք <strong>Edit theme</strong>-ը՝ փոխելու CDN մատակարարին, թեմային կամ ռեժիմին, և ձեռքով խմբագրելու գեներացված <code>theme.css</code>/<code>theme.js</code>-ը մինչև դրանք ներբեռնելը.\",\n \"closeLabel\": \"Փակել\"\n },\n \"ca\": {\n \"pageTitle\": \"Creació de plantilles RCE\",\n \"pageDescription\": \"Crea plantilles de pàgina per al Rich Content Editor de Canvas estilades amb pantoken, amb previsualització en viu.\",\n \"editThemeLabel\": \"Edita el tema\",\n \"layoutDirectionLabel\": \"Canvia l'orientació del disseny\",\n \"helpAriaLabel\": \"Ajuda\",\n \"appModeLabel\": \"Obre l'aplicació web\",\n \"copyHtmlLabel\": \"Copia HTML\",\n \"previewFrameTitle\": \"Previsualització amb estil\",\n \"previewWidthLargeLabel\": \"Gran\",\n \"previewWidthMediumLabel\": \"Mitjà\",\n \"previewWidthSmallLabel\": \"Petit\",\n \"previewSchemeToggleLabel\": \"Previsualitza el mode fosc\",\n \"previewPopupLabel\": \"Obre la previsualització en una finestra emergent\",\n \"previewPopupTitle\": \"Previsualització del contingut del llenç\",\n \"previewPopupBlockedMessage\": \"La finestra emergent de previsualització ha estat bloquejada. Permet les finestres emergents per a aquest lloc i torna-ho a intentar.\",\n \"previewFullscreenLabel\": \"Mostra la previsualització a pantalla completa\",\n \"previewPopupReturnLabel\": \"Torna la previsualització a l'editor\",\n \"downloadHtmlLabel\": \"Descarrega HTML\",\n \"themeTrayAriaLabel\": \"Configuració del tema\",\n \"tabConfigLabel\": \"Configuració\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Proveïdor CDN\",\n \"localProviderLabel\": \"Cap (en línia)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Aparença\",\n \"appearanceLightLabel\": \"Clar\",\n \"appearanceDarkLabel\": \"Fosc\",\n \"themeCanvasLabel\": \"Llenç\",\n \"themeCanvasHighContrastLabel\": \"Llenç d'alt contrast\",\n \"includeDarkModeLabel\": \"Inclou el mode fosc\",\n \"colorLabel\": \"Esquema de colors\",\n \"colorNavyLabel\": \"Blau marí\",\n \"colorBlueLabel\": \"Blau\",\n \"colorGreenLabel\": \"Verd\",\n \"colorRedLabel\": \"Vermell\",\n \"colorOrangeLabel\": \"Taronja\",\n \"colorGreyLabel\": \"Gris\",\n \"colorPlumLabel\": \"Pruna\",\n \"colorVioletLabel\": \"Violeta\",\n \"colorStoneLabel\": \"Pedra\",\n \"colorSkyLabel\": \"Cel\",\n \"colorHoneyLabel\": \"Mel\",\n \"colorSeaLabel\": \"Mar\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Personalitzat\",\n \"customColorInputLabel\": \"Color de la marca (hex)\",\n \"downloadCssLabel\": \"Descarrega theme.css\",\n \"downloadJsLabel\": \"Descarrega theme.js\",\n \"cssPanelHintLabel\": \"Afegeix CSS personalitzat aquí — s'afegeix al theme.css generat, a la previsualització i a la descàrrega.\",\n \"jsPanelHintLabel\": \"Afegeix JS personalitzat aquí — s'afegeix al theme.js generat, a la previsualització i a la descàrrega.\",\n \"helpModalTitle\": \"Com utilitzar aquesta pàgina\",\n \"helpModalBody1\": \"Tria una plantilla inicial, edita-la com ho faries al Rich Content Editor de Canvas, després fes clic a <strong>Copia HTML</strong> i enganxa el resultat a una pàgina de Canvas (canvia primer a la vista d'editor HTML). Canvas neteja l'HTML enganxat al servidor — aquesta previsualització no intenta replicar-ho, així que comprova sempre el resultat enganxat a Canvas.\",\n \"helpModalBody2\": \"Utilitza <strong>Edita el tema</strong> per canviar el proveïdor CDN, el tema o el mode, i per editar manualment els fitxers generats <code>theme.css</code>/<code>theme.js</code> abans de descarregar-los.\",\n \"closeLabel\": \"Tanca\"\n },\n \"da\": {\n \"pageTitle\": \"RCE-skabelonforfatning\",\n \"pageDescription\": \"Forfat Canvas RCE-sideskabeloner stylet med pantoken, med live-preview.\",\n \"editThemeLabel\": \"Rediger tema\",\n \"layoutDirectionLabel\": \"Skift layoutretning\",\n \"helpAriaLabel\": \"Hjælp\",\n \"appModeLabel\": \"Åbn webapp\",\n \"copyHtmlLabel\": \"Kopier HTML\",\n \"previewFrameTitle\": \"Stylet preview\",\n \"previewWidthLargeLabel\": \"Stor\",\n \"previewWidthMediumLabel\": \"Mellem\",\n \"previewWidthSmallLabel\": \"Lille\",\n \"previewSchemeToggleLabel\": \"Forhåndsvis mørk tilstand\",\n \"previewPopupLabel\": \"Åbn forhåndsvisning i en popup\",\n \"previewPopupTitle\": \"Forhåndsvisning af canvas-indhold\",\n \"previewPopupBlockedMessage\": \"Forhåndsvisnings-popup'en blev blokeret. Tillad popups for dette websted og prøv igen.\",\n \"previewFullscreenLabel\": \"Vis forhåndsvisning i fuld skærm\",\n \"previewPopupReturnLabel\": \"Returner forhåndsvisningen til editoren\",\n \"downloadHtmlLabel\": \"Download HTML\",\n \"themeTrayAriaLabel\": \"Temainstillinger\",\n \"tabConfigLabel\": \"Konfig\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN-udbyder\",\n \"localProviderLabel\": \"Ingen (inline)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Udseende\",\n \"appearanceLightLabel\": \"Lys\",\n \"appearanceDarkLabel\": \"Mørk\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas høj kontrast\",\n \"includeDarkModeLabel\": \"Inkluder mørk tilstand\",\n \"colorLabel\": \"Farveskema\",\n \"colorNavyLabel\": \"Marineblå\",\n \"colorBlueLabel\": \"Blå\",\n \"colorGreenLabel\": \"Grøn\",\n \"colorRedLabel\": \"Rød\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Grå\",\n \"colorPlumLabel\": \"Blomme\",\n \"colorVioletLabel\": \"Fiolett\",\n \"colorStoneLabel\": \"Sten\",\n \"colorSkyLabel\": \"Himmel\",\n \"colorHoneyLabel\": \"Honning\",\n \"colorSeaLabel\": \"Hav\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Tilpasset\",\n \"customColorInputLabel\": \"Brandfarve (hex)\",\n \"downloadCssLabel\": \"Download theme.css\",\n \"downloadJsLabel\": \"Download theme.js\",\n \"cssPanelHintLabel\": \"Tilføj brugerdefineret CSS her — det føjes til den genererede theme.css, i forhåndsvisningen og ved download.\",\n \"jsPanelHintLabel\": \"Tilføj brugerdefineret JS her — det føjes til den genererede theme.js, i forhåndsvisningen og ved download.\",\n \"helpModalTitle\": \"Sådan bruges denne side\",\n \"helpModalBody1\": \"Vælg en startskabelon, rediger den som i Canvas Rich Content Editor, klik derefter på <strong>Kopier HTML</strong> og indsæt resultatet i en Canvas-side (skift først til HTML-editoren). Canvas rensker indsat HTML server-side — denne preview forsøger ikke at efterligne det, så verificer altid det indsatte resultat i Canvas.\",\n \"helpModalBody2\": \"Brug <strong>Rediger tema</strong> til at ændre CDN-udbyder, tema eller tilstand, og til at redigere det genererede <code>theme.css</code>/<code>theme.js</code> manuelt før download.\",\n \"closeLabel\": \"Luk\"\n },\n \"nl\": {\n \"pageTitle\": \"RCE-sjabloon maken\",\n \"pageDescription\": \"Maak Canvas RCE-pagina-sjablonen gestyled met pantoken, met een live preview.\",\n \"editThemeLabel\": \"Thema bewerken\",\n \"layoutDirectionLabel\": \"Schakel lay-outoriëntatie\",\n \"helpAriaLabel\": \"Help\",\n \"appModeLabel\": \"Open webapp\",\n \"copyHtmlLabel\": \"HTML kopiëren\",\n \"previewFrameTitle\": \"Gestileerde preview\",\n \"previewWidthLargeLabel\": \"Groot\",\n \"previewWidthMediumLabel\": \"Medium\",\n \"previewWidthSmallLabel\": \"Klein\",\n \"previewSchemeToggleLabel\": \"Voorbeeld donkere modus\",\n \"previewPopupLabel\": \"Open voorbeeld in een popup\",\n \"previewPopupTitle\": \"Canvasinhoudvoorbeeld\",\n \"previewPopupBlockedMessage\": \"De voorbeeld-popup is geblokkeerd. Sta pop-ups voor deze site toe en probeer het opnieuw.\",\n \"previewFullscreenLabel\": \"Toon voorbeeld volledig scherm\",\n \"previewPopupReturnLabel\": \"Zet voorbeeld terug naar de editor\",\n \"downloadHtmlLabel\": \"Download HTML\",\n \"themeTrayAriaLabel\": \"Thema-instellingen\",\n \"tabConfigLabel\": \"Configuratie\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN-provider\",\n \"localProviderLabel\": \"Geen (inline)\",\n \"themeLabel\": \"Thema\",\n \"appearanceLabel\": \"Uiterlijk\",\n \"appearanceLightLabel\": \"Licht\",\n \"appearanceDarkLabel\": \"Donker\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas hoge contrast\",\n \"includeDarkModeLabel\": \"Donkere modus opnemen\",\n \"colorLabel\": \"Kleurenschema\",\n \"colorNavyLabel\": \"Marine\",\n \"colorBlueLabel\": \"Blauw\",\n \"colorGreenLabel\": \"Groen\",\n \"colorRedLabel\": \"Rood\",\n \"colorOrangeLabel\": \"Oranje\",\n \"colorGreyLabel\": \"Grijs\",\n \"colorPlumLabel\": \"Pruim\",\n \"colorVioletLabel\": \"Violet\",\n \"colorStoneLabel\": \"Steen\",\n \"colorSkyLabel\": \"Lucht\",\n \"colorHoneyLabel\": \"Honing\",\n \"colorSeaLabel\": \"Zee\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Aangepast\",\n \"customColorInputLabel\": \"Merkkleur (hex)\",\n \"downloadCssLabel\": \"Download theme.css\",\n \"downloadJsLabel\": \"Download theme.js\",\n \"cssPanelHintLabel\": \"Voeg hier aangepaste CSS toe — het wordt toegevoegd aan de gegenereerde theme.css, in de voorbeeldweergave en de download.\",\n \"jsPanelHintLabel\": \"Voeg hier aangepaste JS toe — het wordt toegevoegd aan de gegenereerde theme.js, in de voorbeeldweergave en de download.\",\n \"helpModalTitle\": \"Hoe deze pagina te gebruiken\",\n \"helpModalBody1\": \"Kies een starttemplate, bewerk het zoals in de Canvas Rich Content Editor, klik vervolgens op <strong>HTML kopiëren</strong> en plak het resultaat in een Canvas-pagina (switch eerst naar de HTML-editor). Canvas sanitizeert geplakte HTML server-side — deze preview probeert dat niet te repliceren, dus controleer altijd het geplakte resultaat in Canvas.\",\n \"helpModalBody2\": \"Gebruik <strong>Thema bewerken</strong> om de CDN-provider, het thema of de modus te wijzigen en om de gegenereerde <code>theme.css</code>/<code>theme.js</code> handmatig aan te passen voordat je ze downloadt.\",\n \"closeLabel\": \"Sluiten\"\n },\n \"en-AU\": {\n \"pageTitle\": \"RCE template authoring\",\n \"pageDescription\": \"Author Canvas RCE page templates styled with pantoken, with a live preview.\",\n \"editThemeLabel\": \"Edit theme\",\n \"layoutDirectionLabel\": \"Switch layout orientation\",\n \"helpAriaLabel\": \"Help\",\n \"appModeLabel\": \"Open web app\",\n \"copyHtmlLabel\": \"Copy HTML\",\n \"previewFrameTitle\": \"Styled preview\",\n \"previewWidthLargeLabel\": \"Large\",\n \"previewWidthMediumLabel\": \"Medium\",\n \"previewWidthSmallLabel\": \"Small\",\n \"previewSchemeToggleLabel\": \"Preview dark mode\",\n \"previewPopupLabel\": \"Open preview in a pop-up\",\n \"previewPopupTitle\": \"Canvas content preview\",\n \"previewPopupBlockedMessage\": \"The preview pop-up was blocked. Allow pop-ups for this site and try again.\",\n \"previewFullscreenLabel\": \"Show preview fullscreen\",\n \"previewPopupReturnLabel\": \"Return preview to the editor\",\n \"downloadHtmlLabel\": \"Download HTML\",\n \"themeTrayAriaLabel\": \"Theme settings\",\n \"tabConfigLabel\": \"Config\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN provider\",\n \"localProviderLabel\": \"None (inline)\",\n \"themeLabel\": \"Theme\",\n \"appearanceLabel\": \"Appearance\",\n \"appearanceLightLabel\": \"Light\",\n \"appearanceDarkLabel\": \"Dark\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas high contrast\",\n \"includeDarkModeLabel\": \"Include dark mode\",\n \"colorLabel\": \"Colour scheme\",\n \"colorNavyLabel\": \"Navy\",\n \"colorBlueLabel\": \"Blue\",\n \"colorGreenLabel\": \"Green\",\n \"colorRedLabel\": \"Red\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Grey\",\n \"colorPlumLabel\": \"Plum\",\n \"colorVioletLabel\": \"Violet\",\n \"colorStoneLabel\": \"Stone\",\n \"colorSkyLabel\": \"Sky\",\n \"colorHoneyLabel\": \"Honey\",\n \"colorSeaLabel\": \"Sea\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Custom\",\n \"customColorInputLabel\": \"Brand colour (hex)\",\n \"downloadCssLabel\": \"Download theme.css\",\n \"downloadJsLabel\": \"Download theme.js\",\n \"cssPanelHintLabel\": \"Add custom CSS here — it's appended to the generated theme.css, in the preview and the download.\",\n \"jsPanelHintLabel\": \"Add custom JS here — it's appended to the generated theme.js, in the preview and the download.\",\n \"helpModalTitle\": \"How to use this page\",\n \"helpModalBody1\": \"Pick a starter template, edit it like you would in the Canvas Rich Content Editor, then click <strong>Copy HTML</strong> and paste the result into a Canvas page (switch to the HTML editor view first). Canvas sanitises pasted HTML server-side — this preview doesn't attempt to replicate that, so always verify the pasted result in Canvas.\",\n \"helpModalBody2\": \"Use <strong>Edit theme</strong> to change the CDN provider, theme, or mode, and to hand-edit the generated <code>theme.css</code>/<code>theme.js</code> before downloading them.\",\n \"closeLabel\": \"Close\"\n },\n \"en-CA\": {\n \"pageTitle\": \"RCE template authoring\",\n \"pageDescription\": \"Author Canvas RCE page templates styled with pantoken, with a live preview.\",\n \"editThemeLabel\": \"Edit theme\",\n \"layoutDirectionLabel\": \"Switch layout orientation\",\n \"helpAriaLabel\": \"Help\",\n \"appModeLabel\": \"Open web app\",\n \"copyHtmlLabel\": \"Copy HTML\",\n \"previewFrameTitle\": \"Styled preview\",\n \"previewWidthLargeLabel\": \"Large\",\n \"previewWidthMediumLabel\": \"Medium\",\n \"previewWidthSmallLabel\": \"Small\",\n \"previewSchemeToggleLabel\": \"Preview dark mode\",\n \"previewPopupLabel\": \"Open preview in a popup\",\n \"previewPopupTitle\": \"Canvas content preview\",\n \"previewPopupBlockedMessage\": \"The preview pop-up was blocked. Allow pop-ups for this site and try again.\",\n \"previewFullscreenLabel\": \"Show preview full-screen\",\n \"previewPopupReturnLabel\": \"Return preview to the editor\",\n \"downloadHtmlLabel\": \"Download HTML\",\n \"themeTrayAriaLabel\": \"Theme settings\",\n \"tabConfigLabel\": \"Config\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN provider\",\n \"localProviderLabel\": \"None (inline)\",\n \"themeLabel\": \"Theme\",\n \"appearanceLabel\": \"Appearance\",\n \"appearanceLightLabel\": \"Light\",\n \"appearanceDarkLabel\": \"Dark\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas high contrast\",\n \"includeDarkModeLabel\": \"Include dark mode\",\n \"colorLabel\": \"Color scheme\",\n \"colorNavyLabel\": \"Navy\",\n \"colorBlueLabel\": \"Blue\",\n \"colorGreenLabel\": \"Green\",\n \"colorRedLabel\": \"Red\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Grey\",\n \"colorPlumLabel\": \"Plum\",\n \"colorVioletLabel\": \"Violet\",\n \"colorStoneLabel\": \"Stone\",\n \"colorSkyLabel\": \"Sky\",\n \"colorHoneyLabel\": \"Honey\",\n \"colorSeaLabel\": \"Sea\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Custom\",\n \"customColorInputLabel\": \"Brand colour (hex)\",\n \"downloadCssLabel\": \"Download theme.css\",\n \"downloadJsLabel\": \"Download theme.js\",\n \"cssPanelHintLabel\": \"Add custom CSS here — it's appended to the generated theme.css, in the preview and the download.\",\n \"jsPanelHintLabel\": \"Add custom JS here — it's appended to the generated theme.js, in the preview and the download.\",\n \"helpModalTitle\": \"How to use this page\",\n \"helpModalBody1\": \"Pick a starter template, edit it like you would in the Canvas Rich Content Editor, then click <strong>Copy HTML</strong> and paste the result into a Canvas page (switch to the HTML editor view first). Canvas sanitizes pasted HTML server-side — this preview doesn't attempt to replicate that, so always verify the pasted result in Canvas.\",\n \"helpModalBody2\": \"Use <strong>Edit theme</strong> to change the CDN provider, theme, or mode, and to hand-edit the generated <code>theme.css</code>/<code>theme.js</code> before downloading them.\",\n \"closeLabel\": \"Close\"\n },\n \"en-GB\": {\n \"pageTitle\": \"RCE template authoring\",\n \"pageDescription\": \"Author Canvas RCE page templates styled with pantoken, with a live preview.\",\n \"editThemeLabel\": \"Edit theme\",\n \"layoutDirectionLabel\": \"Switch layout orientation\",\n \"helpAriaLabel\": \"Help\",\n \"appModeLabel\": \"Open web app\",\n \"copyHtmlLabel\": \"Copy HTML\",\n \"previewFrameTitle\": \"Styled preview\",\n \"previewWidthLargeLabel\": \"Large\",\n \"previewWidthMediumLabel\": \"Medium\",\n \"previewWidthSmallLabel\": \"Small\",\n \"previewSchemeToggleLabel\": \"Preview dark mode\",\n \"previewPopupLabel\": \"Open preview in a popup\",\n \"previewPopupTitle\": \"Canvas content preview\",\n \"previewPopupBlockedMessage\": \"The preview popup was blocked. Allow popups for this site and try again.\",\n \"previewFullscreenLabel\": \"Show preview fullscreen\",\n \"previewPopupReturnLabel\": \"Return preview to the editor\",\n \"downloadHtmlLabel\": \"Download HTML\",\n \"themeTrayAriaLabel\": \"Theme settings\",\n \"tabConfigLabel\": \"Config\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN provider\",\n \"localProviderLabel\": \"None (inline)\",\n \"themeLabel\": \"Theme\",\n \"appearanceLabel\": \"Appearance\",\n \"appearanceLightLabel\": \"Light\",\n \"appearanceDarkLabel\": \"Dark\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas high contrast\",\n \"includeDarkModeLabel\": \"Include dark mode\",\n \"colorLabel\": \"Colour scheme\",\n \"colorNavyLabel\": \"Navy\",\n \"colorBlueLabel\": \"Blue\",\n \"colorGreenLabel\": \"Green\",\n \"colorRedLabel\": \"Red\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Grey\",\n \"colorPlumLabel\": \"Plum\",\n \"colorVioletLabel\": \"Violet\",\n \"colorStoneLabel\": \"Stone\",\n \"colorSkyLabel\": \"Sky\",\n \"colorHoneyLabel\": \"Honey\",\n \"colorSeaLabel\": \"Sea\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Custom\",\n \"customColorInputLabel\": \"Brand colour (hex)\",\n \"downloadCssLabel\": \"Download theme.css\",\n \"downloadJsLabel\": \"Download theme.js\",\n \"cssPanelHintLabel\": \"Add custom CSS here — it's appended to the generated theme.css, in the preview and the download.\",\n \"jsPanelHintLabel\": \"Add custom JS here — it's appended to the generated theme.js, in the preview and the download.\",\n \"helpModalTitle\": \"How to use this page\",\n \"helpModalBody1\": \"Pick a starter template, edit it like you would in the Canvas Rich Content Editor, then click <strong>Copy HTML</strong> and paste the result into a Canvas page (switch to the HTML editor view first). Canvas sanitises pasted HTML server-side — this preview doesn’t attempt to replicate that, so always verify the pasted result in Canvas.\",\n \"helpModalBody2\": \"Use <strong>Edit theme</strong> to change the CDN provider, theme, or mode, and to hand-edit the generated <code>theme.css</code>/<code>theme.js</code> before downloading them.\",\n \"closeLabel\": \"Close\"\n },\n \"fi\": {\n \"pageTitle\": \"RCE-mallien luominen\",\n \"pageDescription\": \"Laadi Canvas RCE -sivupohjia, jotka on tyylitelty pantokenilla, ja esikatsele muutoksia reaaliajassa.\",\n \"editThemeLabel\": \"Muokkaa teemaa\",\n \"layoutDirectionLabel\": \"Vaihda asettelun suunta\",\n \"helpAriaLabel\": \"Ohje\",\n \"appModeLabel\": \"Avaa web-sovellus\",\n \"copyHtmlLabel\": \"Kopioi HTML\",\n \"previewFrameTitle\": \"Tyylitelty esikatselu\",\n \"previewWidthLargeLabel\": \"Suuri\",\n \"previewWidthMediumLabel\": \"Keskikokoinen\",\n \"previewWidthSmallLabel\": \"Pieni\",\n \"previewSchemeToggleLabel\": \"Esikatsele tummaa tilaa\",\n \"previewPopupLabel\": \"Avaa esikatselu ponnahdusikkunaan\",\n \"previewPopupTitle\": \"Canvas-sisällön esikatselu\",\n \"previewPopupBlockedMessage\": \"Esikatselun ponnahdusikkuna estettiin. Salli ponnahdusikkunat tälle sivustolle ja yritä uudelleen.\",\n \"previewFullscreenLabel\": \"Näytä esikatselu koko näytöllä\",\n \"previewPopupReturnLabel\": \"Palauta esikatselu editoriin\",\n \"downloadHtmlLabel\": \"Lataa HTML\",\n \"themeTrayAriaLabel\": \"Teeman asetukset\",\n \"tabConfigLabel\": \"Asetukset\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN-palvelu\",\n \"localProviderLabel\": \"Ei mitään (upotettuna)\",\n \"themeLabel\": \"Teema\",\n \"appearanceLabel\": \"Ulkoasu\",\n \"appearanceLightLabel\": \"Vaalea\",\n \"appearanceDarkLabel\": \"Tumma\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas korkea kontrasti\",\n \"includeDarkModeLabel\": \"Sisällytä tumma tila\",\n \"colorLabel\": \"Väriteema\",\n \"colorNavyLabel\": \"Laivastonsininen\",\n \"colorBlueLabel\": \"Sininen\",\n \"colorGreenLabel\": \"Vihreä\",\n \"colorRedLabel\": \"Punainen\",\n \"colorOrangeLabel\": \"Oranssi\",\n \"colorGreyLabel\": \"Harmaa\",\n \"colorPlumLabel\": \"Luumun\",\n \"colorVioletLabel\": \"Violetti\",\n \"colorStoneLabel\": \"Kivisävy\",\n \"colorSkyLabel\": \"Taivas\",\n \"colorHoneyLabel\": \"Hunaja\",\n \"colorSeaLabel\": \"Meri\",\n \"colorAuroraLabel\": \"Revontuli\",\n \"colorCustomLabel\": \"Mukautettu\",\n \"customColorInputLabel\": \"Brändin väri (hex)\",\n \"downloadCssLabel\": \"Lataa theme.css\",\n \"downloadJsLabel\": \"Lataa theme.js\",\n \"cssPanelHintLabel\": \"Lisää mukautettua CSS:ää tähän — se lisätään generoituun theme.css-tiedostoon esikatselussa ja latauksessa.\",\n \"jsPanelHintLabel\": \"Lisää mukautettua JS:ää tähän — se lisätään generoituun theme.js-tiedostoon esikatselussa ja latauksessa.\",\n \"helpModalTitle\": \"Kuinka tätä sivua käytetään\",\n \"helpModalBody1\": \"Valitse aloituspohja, muokkaa sitä kuten Canvas Rich Content Editorissa, napsauta sitten <strong>Copy HTML</strong> ja liitä tulos Canvas-sivulle (siirry ensin HTML-muokkaustilaan). Canvas puhdistaa liitetyn HTML:n palvelinpuolella — tämä esikatselu ei yritä jäljitellä sitä, joten varmista aina liitetty lopputulos Canvasissa.\",\n \"helpModalBody2\": \"Käytä <strong>Edit theme</strong> -toimintoa muuttaaksesi CDN-palvelua, teemaa tai tilaa sekä muokataksesi generoituja <code>theme.css</code>/<code>theme.js</code>-tiedostoja ennen latausta.\",\n \"closeLabel\": \"Sulje\"\n },\n \"fr\": {\n \"pageTitle\": \"Authoring de modèles RCE\",\n \"pageDescription\": \"Créer des modèles de page RCE Canvas stylés avec pantoken, avec aperçu en direct.\",\n \"editThemeLabel\": \"Modifier le thème\",\n \"layoutDirectionLabel\": \"Changer l’orientation de la disposition\",\n \"helpAriaLabel\": \"Aide\",\n \"appModeLabel\": \"Ouvrir l'application web\",\n \"copyHtmlLabel\": \"Copier le HTML\",\n \"downloadPackageLabel\": \"Télécharger le paquet\",\n \"previewFrameTitle\": \"Aperçu stylé\",\n \"previewWidthLargeLabel\": \"Grand\",\n \"previewWidthMediumLabel\": \"Moyen\",\n \"previewWidthSmallLabel\": \"Petit\",\n \"previewPopupLabel\": \"Ouvrir l'aperçu dans une fenêtre contextuelle\",\n \"previewPopupTitle\": \"Aperçu du contenu Canvas\",\n \"previewPopupBlockedMessage\": \"La fenêtre contextuelle d'aperçu a été bloquée. Autorisez les fenêtres contextuelles pour ce site et réessayez.\",\n \"previewFullscreenLabel\": \"Afficher l'aperçu en plein écran\",\n \"previewPopupReturnLabel\": \"Renvoyer l'aperçu à l'éditeur\",\n \"downloadHtmlLabel\": \"Télécharger le HTML\",\n \"themeTrayAriaLabel\": \"Paramètres du thème\",\n \"tabConfigLabel\": \"Configuration\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Fournisseur CDN\",\n \"localProviderLabel\": \"Aucun (intégré)\",\n \"themeLabel\": \"Thème\",\n \"appearanceLabel\": \"Apparence\",\n \"appearanceLightLabel\": \"Clair\",\n \"appearanceDarkLabel\": \"Sombre\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas à contraste élevé\",\n \"includeDarkModeLabel\": \"Inclure le mode sombre\",\n \"colorLabel\": \"Jeu de couleurs\",\n \"colorNavyLabel\": \"Bleu marine\",\n \"colorBlueLabel\": \"Bleu\",\n \"colorGreenLabel\": \"Vert\",\n \"colorRedLabel\": \"Rouge\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Gris\",\n \"colorPlumLabel\": \"Prune\",\n \"colorVioletLabel\": \"Violet\",\n \"colorStoneLabel\": \"Pierre\",\n \"colorSkyLabel\": \"Ciel\",\n \"colorHoneyLabel\": \"Miel\",\n \"colorSeaLabel\": \"Mer\",\n \"colorAuroraLabel\": \"Aurore\",\n \"colorCustomLabel\": \"Personnalisé\",\n \"customColorInputLabel\": \"Couleur de la marque (hex)\",\n \"downloadCssLabel\": \"Télécharger theme.css\",\n \"downloadJsLabel\": \"Télécharger theme.js\",\n \"cssPanelHintLabel\": \"Ajoutez ici du CSS personnalisé — il est ajouté au theme.css généré, dans l’aperçu et dans le téléchargement.\",\n \"jsPanelHintLabel\": \"Ajoutez ici du JS personnalisé — il est ajouté au theme.js généré, dans l’aperçu et dans le téléchargement.\",\n \"helpModalTitle\": \"Comment utiliser cette page\",\n \"helpModalBody1\": \"Choisissez un modèle de départ, éditez-le comme dans l’éditeur de contenu enrichi (RCE) de Canvas, puis cliquez sur <strong>Copier le HTML</strong> et collez le résultat dans une page Canvas (passez d’abord en vue éditeur HTML). Canvas assainit le HTML collé côté serveur — cet aperçu ne reproduit pas ce comportement, vérifiez donc toujours le résultat collé dans Canvas.\",\n \"helpModalBody2\": \"Utilisez <strong>Modifier le thème</strong> pour changer le fournisseur CDN, le thème ou le mode, et pour éditer manuellement les fichiers générés <code>theme.css</code>/<code>theme.js</code> avant de les télécharger.\",\n \"closeLabel\": \"Fermer\"\n },\n \"fr-CA\": {\n \"pageTitle\": \"Édition de modèles RCE\",\n \"pageDescription\": \"Créer des modèles de page RCE Canvas stylisés avec pantoken, avec aperçu en direct.\",\n \"editThemeLabel\": \"Modifier le thème\",\n \"layoutDirectionLabel\": \"Changer l'orientation de la mise en page\",\n \"helpAriaLabel\": \"Aide\",\n \"appModeLabel\": \"Ouvrir l'application web\",\n \"copyHtmlLabel\": \"Copier le HTML\",\n \"previewFrameTitle\": \"Aperçu stylisé\",\n \"previewWidthLargeLabel\": \"Grand\",\n \"previewWidthMediumLabel\": \"Moyen\",\n \"previewWidthSmallLabel\": \"Petit\",\n \"previewSchemeToggleLabel\": \"Aperçu du mode sombre\",\n \"previewPopupLabel\": \"Ouvrir l'aperçu dans une fenêtre contextuelle\",\n \"previewPopupTitle\": \"Aperçu du contenu du canevas\",\n \"previewPopupBlockedMessage\": \"La fenêtre contextuelle d'aperçu a été bloquée. Autorisez les fenêtres contextuelles pour ce site et réessayez.\",\n \"previewFullscreenLabel\": \"Afficher l'aperçu en plein écran\",\n \"previewPopupReturnLabel\": \"Retourner l'aperçu dans l'éditeur\",\n \"downloadHtmlLabel\": \"Télécharger le HTML\",\n \"themeTrayAriaLabel\": \"Paramètres du thème\",\n \"tabConfigLabel\": \"Configuration\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Fournisseur CDN\",\n \"localProviderLabel\": \"Aucun (en ligne)\",\n \"themeLabel\": \"Thème\",\n \"appearanceLabel\": \"Apparence\",\n \"appearanceLightLabel\": \"Clair\",\n \"appearanceDarkLabel\": \"Sombre\",\n \"themeCanvasLabel\": \"Canevas\",\n \"themeCanvasHighContrastLabel\": \"Canevas haute contraste\",\n \"includeDarkModeLabel\": \"Inclure le mode sombre\",\n \"colorLabel\": \"Schéma de couleurs\",\n \"colorNavyLabel\": \"Marine\",\n \"colorBlueLabel\": \"Bleu\",\n \"colorGreenLabel\": \"Vert\",\n \"colorRedLabel\": \"Rouge\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Gris\",\n \"colorPlumLabel\": \"Prune\",\n \"colorVioletLabel\": \"Violet\",\n \"colorStoneLabel\": \"Pierre\",\n \"colorSkyLabel\": \"Ciel\",\n \"colorHoneyLabel\": \"Miel\",\n \"colorSeaLabel\": \"Mer\",\n \"colorAuroraLabel\": \"Aurore\",\n \"colorCustomLabel\": \"Personnalisé\",\n \"customColorInputLabel\": \"Couleur de la marque (hexadécimal)\",\n \"downloadCssLabel\": \"Télécharger theme.css\",\n \"downloadJsLabel\": \"Télécharger theme.js\",\n \"cssPanelHintLabel\": \"Ajoutez du CSS personnalisé ici — il est ajouté au fichier theme.css généré, dans l'aperçu et le téléchargement.\",\n \"jsPanelHintLabel\": \"Ajoutez du JS personnalisé ici — il est ajouté au fichier theme.js généré, dans l'aperçu et le téléchargement.\",\n \"helpModalTitle\": \"Comment utiliser cette page\",\n \"helpModalBody1\": \"Choisissez un modèle de départ, modifiez-le comme dans l'éditeur de contenu enrichi de Canvas, puis cliquez sur <strong>Copier le HTML</strong> et collez le résultat dans une page Canvas (passez d'abord en vue éditeur HTML). Canvas nettoie le HTML collé côté serveur — cet aperçu ne reproduit pas ce nettoyage, donc vérifiez toujours le résultat collé dans Canvas.\",\n \"helpModalBody2\": \"Utilisez <strong>Modifier le thème</strong> pour changer le fournisseur CDN, le thème ou le mode, et pour éditer manuellement les fichiers générés <code>theme.css</code>/<code>theme.js</code> avant de les télécharger.\",\n \"closeLabel\": \"Fermer\"\n },\n \"ga\": {\n \"pageTitle\": \"Údarú téama RCE\",\n \"pageDescription\": \"Cruthaigh téamaí leathanach RCE do Canvas stíleáilte le pantoken, le réamhamharc beo.\",\n \"editThemeLabel\": \"Cuir in eagar an téama\",\n \"layoutDirectionLabel\": \"Athraigh treoshuíomh leagan amach\",\n \"helpAriaLabel\": \"Cabhair\",\n \"appModeLabel\": \"Oscail an fheidhmchlár gréasáin\",\n \"copyHtmlLabel\": \"Cóipeáil HTML\",\n \"previewFrameTitle\": \"Réamhamharc stílithe\",\n \"previewWidthLargeLabel\": \"Mór\",\n \"previewWidthMediumLabel\": \"Meánach\",\n \"previewWidthSmallLabel\": \"Beag\",\n \"previewSchemeToggleLabel\": \"Réamhamharc mód dorcha\",\n \"previewPopupLabel\": \"Oscail an réamhamharc i bpop-up\",\n \"previewPopupTitle\": \"Réamhamharc ábhar canbháis\",\n \"previewPopupBlockedMessage\": \"Bhí an pop-up réamhamhairc blocáilte. Ceadaigh pop-ups don suíomh seo agus déan iarracht arís.\",\n \"previewFullscreenLabel\": \"Taispeáin an réamhamharc lánscáileáin\",\n \"previewPopupReturnLabel\": \"Fill an réamhamharc ar ais chuig an eagarthóir\",\n \"downloadHtmlLabel\": \"Íoslódáil HTML\",\n \"themeTrayAriaLabel\": \"Socruithe téama\",\n \"tabConfigLabel\": \"Cumraíocht\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Soláthraí CDN\",\n \"localProviderLabel\": \"Níl (ionchlannaithe)\",\n \"themeLabel\": \"Téama\",\n \"appearanceLabel\": \"Cuma\",\n \"appearanceLightLabel\": \"Éadrom\",\n \"appearanceDarkLabel\": \"Dorcha\",\n \"themeCanvasLabel\": \"Canbhás\",\n \"themeCanvasHighContrastLabel\": \"Canbhás ardchoibhéiseach\",\n \"includeDarkModeLabel\": \"Cuimsigh mód dorcha\",\n \"colorLabel\": \"Scéim dathanna\",\n \"colorNavyLabel\": \"Naibhí\",\n \"colorBlueLabel\": \"Gorm\",\n \"colorGreenLabel\": \"Glas\",\n \"colorRedLabel\": \"Dearg\",\n \"colorOrangeLabel\": \"Oráiste\",\n \"colorGreyLabel\": \"Liath\",\n \"colorPlumLabel\": \"Plúm\",\n \"colorVioletLabel\": \"Corcra\",\n \"colorStoneLabel\": \"Cloch\",\n \"colorSkyLabel\": \"Neamh\",\n \"colorHoneyLabel\": \"Mil\",\n \"colorSeaLabel\": \"Muir\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Saincheaptha\",\n \"customColorInputLabel\": \"Dath branda (hex)\",\n \"downloadCssLabel\": \"Íoslódáil theme.css\",\n \"downloadJsLabel\": \"Íoslódáil theme.js\",\n \"cssPanelHintLabel\": \"Cuir CSS saincheaptha anseo — cuirtear é le theme.css a ghintear, sa réamhamharc agus san íoslódáil.\",\n \"jsPanelHintLabel\": \"Cuir JS saincheaptha anseo — cuirtear é le theme.js a ghintear, sa réamhamharc agus san íoslódáil.\",\n \"helpModalTitle\": \"Conas an leathanach seo a úsáid\",\n \"helpModalBody1\": \"Roghnaigh teimpléad tosaigh, eagair é mar a dhéanfá sa Eagarthóir Ábhar Saibhrithe Canvas, ansin cliceáil <strong>Cóipeáil HTML</strong> agus greamaigh an toradh isteach i leathanach Canvas (athraigh go radharc eagarthóra HTML ar dtús). Déanann Canvas HTML ghreamaithe a ghlanadh ar thaobh an fhreastalaí — ní dhéanann an réamhamharc seo iarracht é sin a athchruthú, mar sin déan seiceáil i gcónaí ar an toradh sa Canvas.\",\n \"helpModalBody2\": \"Bain úsáid as <strong>Cuir in eagar an téama</strong> chun athrú a dhéanamh ar an soláthraí CDN, téama, nó mód, agus chun <code>theme.css</code>/<code>theme.js</code> a cheartú de láimh sula n-íoslódaítear iad.\",\n \"closeLabel\": \"Dún\"\n },\n \"de\": {\n \"pageTitle\": \"RCE-Vorlagenbearbeitung\",\n \"pageDescription\": \"Erstelle Canvas RCE-Seitenvorlagen mit pantoken-Styling und Live-Vorschau.\",\n \"editThemeLabel\": \"Theme bearbeiten\",\n \"layoutDirectionLabel\": \"Layout-Ausrichtung wechseln\",\n \"helpAriaLabel\": \"Hilfe\",\n \"appModeLabel\": \"Web-App öffnen\",\n \"copyHtmlLabel\": \"HTML kopieren\",\n \"previewFrameTitle\": \"Gestylte Vorschau\",\n \"previewWidthLargeLabel\": \"Groß\",\n \"previewWidthMediumLabel\": \"Mittel\",\n \"previewWidthSmallLabel\": \"Klein\",\n \"previewSchemeToggleLabel\": \"Dunklen Modus in der Vorschau anzeigen\",\n \"previewPopupLabel\": \"Vorschau in einem Popup öffnen\",\n \"previewPopupTitle\": \"Vorschau des Canvas-Inhalts\",\n \"previewPopupBlockedMessage\": \"Das Vorschau-Popup wurde blockiert. Erlaube Popups für diese Seite und versuche es erneut.\",\n \"previewFullscreenLabel\": \"Vorschau im Vollbild anzeigen\",\n \"previewPopupReturnLabel\": \"Vorschau zurück in den Editor\",\n \"downloadHtmlLabel\": \"HTML herunterladen\",\n \"themeTrayAriaLabel\": \"Theme-Einstellungen\",\n \"tabConfigLabel\": \"Konfiguration\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN-Anbieter\",\n \"localProviderLabel\": \"Keine (inline)\",\n \"themeLabel\": \"Theme\",\n \"appearanceLabel\": \"Erscheinungsbild\",\n \"appearanceLightLabel\": \"Hell\",\n \"appearanceDarkLabel\": \"Dunkel\",\n \"themeCanvasLabel\": \"Leinwand\",\n \"themeCanvasHighContrastLabel\": \"Leinwand mit hohem Kontrast\",\n \"includeDarkModeLabel\": \"Dunkelmodus einbeziehen\",\n \"colorLabel\": \"Farbschema\",\n \"colorNavyLabel\": \"Marine\",\n \"colorBlueLabel\": \"Blau\",\n \"colorGreenLabel\": \"Grün\",\n \"colorRedLabel\": \"Rot\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Grau\",\n \"colorPlumLabel\": \"Pflaume\",\n \"colorVioletLabel\": \"Violett\",\n \"colorStoneLabel\": \"Stein\",\n \"colorSkyLabel\": \"Himmel\",\n \"colorHoneyLabel\": \"Honig\",\n \"colorSeaLabel\": \"Meer\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Benutzerdefiniert\",\n \"customColorInputLabel\": \"Markenfarbe (Hex)\",\n \"downloadCssLabel\": \"theme.css herunterladen\",\n \"downloadJsLabel\": \"theme.js herunterladen\",\n \"cssPanelHintLabel\": \"Füge hier benutzerdefiniertes CSS hinzu — es wird an das erzeugte theme.css angehängt, in der Vorschau und im Download.\",\n \"jsPanelHintLabel\": \"Füge hier benutzerdefiniertes JS hinzu — es wird an das erzeugte theme.js angehängt, in der Vorschau und im Download.\",\n \"helpModalTitle\": \"So verwendet man diese Seite\",\n \"helpModalBody1\": \"Wähle eine Starter-Vorlage, bearbeite sie wie im Canvas Rich Content Editor, klicke dann auf <strong>HTML kopieren</strong> und füge das Ergebnis in eine Canvas-Seite ein (zuerst in die HTML-Editoransicht wechseln). Canvas bereinigt eingefügtes HTML serverseitig — diese Vorschau versucht das nicht zu reproduzieren; überprüfe das eingefügte Ergebnis immer in Canvas.\",\n \"helpModalBody2\": \"Mit <strong>Theme bearbeiten</strong> lässt sich der CDN-Anbieter, das Theme oder der Modus ändern und die erzeugten <code>theme.css</code>/<code>theme.js</code> vor dem Herunterladen manuell bearbeiten.\",\n \"closeLabel\": \"Schließen\"\n },\n \"el\": {\n \"pageTitle\": \"Σύνταξη προτύπων RCE\",\n \"pageDescription\": \"Δημιουργήστε πρότυπα σελίδων Canvas RCE στιλιζαρισμένα με pantoken, με ζωντανή προεπισκόπηση.\",\n \"editThemeLabel\": \"Επεξεργασία θέματος\",\n \"layoutDirectionLabel\": \"Αλλαγή προσανατολισμού διάταξης\",\n \"helpAriaLabel\": \"Βοήθεια\",\n \"appModeLabel\": \"Άνοιγμα web εφαρμογής\",\n \"copyHtmlLabel\": \"Αντιγραφή HTML\",\n \"previewFrameTitle\": \"Στυλιζαρισμένη προεπισκόπηση\",\n \"previewWidthLargeLabel\": \"Μεγάλο\",\n \"previewWidthMediumLabel\": \"Μεσαίο\",\n \"previewWidthSmallLabel\": \"Μικρό\",\n \"previewSchemeToggleLabel\": \"Προεπισκόπηση σκοτεινής λειτουργίας\",\n \"previewPopupLabel\": \"Άνοιγμα προεπισκόπησης σε αναδυόμενο παράθυρο\",\n \"previewPopupTitle\": \"Προεπισκόπηση περιεχομένου καμβά\",\n \"previewPopupBlockedMessage\": \"Το αναδυόμενο παράθυρο προεπισκόπησης αποκλείστηκε. Επιτρέψτε αναδυόμενα παράθυρα για αυτήν την τοποθεσία και δοκιμάστε ξανά.\",\n \"previewFullscreenLabel\": \"Εμφάνιση προεπισκόπησης σε πλήρη οθόνη\",\n \"previewPopupReturnLabel\": \"Επαναφορά προεπισκόπησης στον επεξεργαστή\",\n \"downloadHtmlLabel\": \"Λήψη HTML\",\n \"themeTrayAriaLabel\": \"Ρυθμίσεις θέματος\",\n \"tabConfigLabel\": \"Ρυθμίσεις\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Πάροχος CDN\",\n \"localProviderLabel\": \"Καμία (ενσωματωμένη)\",\n \"themeLabel\": \"Θέμα\",\n \"appearanceLabel\": \"Εμφάνιση\",\n \"appearanceLightLabel\": \"Φωτεινό\",\n \"appearanceDarkLabel\": \"Σκούρο\",\n \"themeCanvasLabel\": \"Καμβάς\",\n \"themeCanvasHighContrastLabel\": \"Καμβάς υψηλής αντίθεσης\",\n \"includeDarkModeLabel\": \"Συμπερίληψη σκοτεινής λειτουργίας\",\n \"colorLabel\": \"Χρωματικό σχήμα\",\n \"colorNavyLabel\": \"Ναυτικό\",\n \"colorBlueLabel\": \"Μπλε\",\n \"colorGreenLabel\": \"Πράσινο\",\n \"colorRedLabel\": \"Κόκκινο\",\n \"colorOrangeLabel\": \"Πορτοκαλί\",\n \"colorGreyLabel\": \"Γκρι\",\n \"colorPlumLabel\": \"Δαμάσκηνο\",\n \"colorVioletLabel\": \"Βιολετί\",\n \"colorStoneLabel\": \"Πέτρα\",\n \"colorSkyLabel\": \"Ουρανός\",\n \"colorHoneyLabel\": \"Μέλι\",\n \"colorSeaLabel\": \"Θάλασσα\",\n \"colorAuroraLabel\": \"Αυγή\",\n \"colorCustomLabel\": \"Προσαρμοσμένο\",\n \"customColorInputLabel\": \"Χρώμα επωνυμίας (hex)\",\n \"downloadCssLabel\": \"Λήψη theme.css\",\n \"downloadJsLabel\": \"Λήψη theme.js\",\n \"cssPanelHintLabel\": \"Προσθέστε προσαρμοσμένο CSS εδώ — προστίθεται στο παραγόμενο theme.css, στην προεπισκόπηση και στη λήψη.\",\n \"jsPanelHintLabel\": \"Προσθέστε προσαρμοσμένο JS εδώ — προστίθεται στο παραγόμενο theme.js, στην προεπισκόπηση και στη λήψη.\",\n \"helpModalTitle\": \"Πώς να χρησιμοποιήσετε αυτή τη σελίδα\",\n \"helpModalBody1\": \"Επιλέξτε ένα αρχικό πρότυπο, επεξεργαστείτε το όπως θα κάνατε στον Canvas Rich Content Editor, μετά κάντε κλικ στο <strong>Αντιγραφή HTML</strong> και επικολλήστε το αποτέλεσμα σε σελίδα Canvas (πρώτα μεταβείτε στην προβολή HTML του επεξεργαστή). Το Canvas καθαρίζει το επικολλημένο HTML στον διακομιστή — αυτή η προεπισκόπηση δεν προσπαθεί να αναπαραγάγει αυτή τη συμπεριφορά, οπότε πάντα επαληθεύστε το αποτέλεσμα μέσα στο Canvas.\",\n \"helpModalBody2\": \"Χρησιμοποιήστε το <strong>Επεξεργασία θέματος</strong> για να αλλάξετε τον πάροχο CDN, το θέμα ή τη λειτουργία, και για να επεξεργαστείτε χειροκίνητα τα παραγόμενα <code>theme.css</code>/<code>theme.js</code> πριν τα κατεβάσετε.\",\n \"closeLabel\": \"Κλείσιμο\"\n },\n \"ht\": {\n \"pageTitle\": \"Otoring modèl paj RCE\",\n \"pageDescription\": \"Ekri modèl paj Canvas RCE estilize ak pantoken, ak yon aperçu an tan reyèl.\",\n \"editThemeLabel\": \"Modifye tèm\",\n \"layoutDirectionLabel\": \"Chanje oryantasyon dispozisyon\",\n \"helpAriaLabel\": \"Èd\",\n \"appModeLabel\": \"Louvri aplikasyon wèb\",\n \"copyHtmlLabel\": \"Kopi HTML\",\n \"previewFrameTitle\": \"Aperçu estilize\",\n \"previewWidthLargeLabel\": \"Gwo\",\n \"previewWidthMediumLabel\": \"Mwayen\",\n \"previewWidthSmallLabel\": \"Ti\",\n \"previewSchemeToggleLabel\": \"Gade mòd fènwa\",\n \"previewPopupLabel\": \"Louvri previ nan yon popup\",\n \"previewPopupTitle\": \"Previ kontni Canvas\",\n \"previewPopupBlockedMessage\": \"Fenèt popup previ a te bloke. Pèmèt popup pou sit sa a epi eseye ankò.\",\n \"previewFullscreenLabel\": \"Montre previ an plen ekran\",\n \"previewPopupReturnLabel\": \"Retounen previ a nan editè a\",\n \"downloadHtmlLabel\": \"Telechaje HTML\",\n \"themeTrayAriaLabel\": \"Anviwònman tèm\",\n \"tabConfigLabel\": \"Konfigirasyon\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Founisè CDN\",\n \"localProviderLabel\": \"Okenn (anliy)\",\n \"themeLabel\": \"Tèm\",\n \"appearanceLabel\": \"Aparans\",\n \"appearanceLightLabel\": \"Limyè\",\n \"appearanceDarkLabel\": \"Fènwa\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas kontrast wo\",\n \"includeDarkModeLabel\": \"Enkli mòd fènwa\",\n \"colorLabel\": \"Palèt koulè\",\n \"colorNavyLabel\": \"Ble fonse\",\n \"colorBlueLabel\": \"Ble\",\n \"colorGreenLabel\": \"Vèt\",\n \"colorRedLabel\": \"Wouj\",\n \"colorOrangeLabel\": \"Oranj\",\n \"colorGreyLabel\": \"Gri\",\n \"colorPlumLabel\": \"Plim\",\n \"colorVioletLabel\": \"Vyolèt\",\n \"colorStoneLabel\": \"Wòch\",\n \"colorSkyLabel\": \"Syèl\",\n \"colorHoneyLabel\": \"Myèl\",\n \"colorSeaLabel\": \"Lanmè\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Pèsonalize\",\n \"customColorInputLabel\": \"Koulè mak la (hex)\",\n \"downloadCssLabel\": \"Telechaje theme.css\",\n \"downloadJsLabel\": \"Telechaje theme.js\",\n \"cssPanelHintLabel\": \"Ajoute CSS koutim isit la — li ajoute nan theme.css ki jenere a, nan previ ak nan telechajman an.\",\n \"jsPanelHintLabel\": \"Ajoute JS koutim isit la — li ajoute nan theme.js ki jenere a, nan previ ak nan telechajman an.\",\n \"helpModalTitle\": \"Kijan pou itilize paj sa a\",\n \"helpModalBody1\": \"Chwazi yon modèl demaraj, modifye li tankou ou ta fè nan Canvas Rich Content Editor, epi klike <strong>Copy HTML</strong> epi kole rezilta a nan yon paj Canvas (chanje anvan nan vye wè editè HTML la). Canvas netwaye HTML kole sou sèvè a — aperçu sa a pa eseye repwodui sa, kidonk toujou verifye rezilta kole a nan Canvas.\",\n \"helpModalBody2\": \"Sèvi ak <strong>Edit theme</strong> pou chanje founisè CDN, tèm, oswa mòd, epi pou modifye manyèlman <code>theme.css</code>/<code>theme.js</code> ki jenere anvan ou telechaje yo.\",\n \"closeLabel\": \"Fèmen\"\n },\n \"he\": {\n \"pageTitle\": \"עריכת תבניות RCE\",\n \"pageDescription\": \"ערוך תבניות עמודי Canvas RCE מעוצבות עם pantoken, עם תצוגה מקדימה חיה.\",\n \"editThemeLabel\": \"ערוך ערכה\",\n \"layoutDirectionLabel\": \"החלפת כיוון הפריסה\",\n \"helpAriaLabel\": \"עזרה\",\n \"appModeLabel\": \"פתח את אפליקציית האינטרנט\",\n \"copyHtmlLabel\": \"העתק HTML\",\n \"previewFrameTitle\": \"תצוגה מעוצבת\",\n \"previewWidthLargeLabel\": \"גדול\",\n \"previewWidthMediumLabel\": \"בינוני\",\n \"previewWidthSmallLabel\": \"קטן\",\n \"previewSchemeToggleLabel\": \"תצוגה מקדימה של מצב כהה\",\n \"previewPopupLabel\": \"פתח תצוגה מקדימה בחלון קופץ\",\n \"previewPopupTitle\": \"תצוגה מקדימה של תוכן הקנבס\",\n \"previewPopupBlockedMessage\": \"חלון התצוגה המקדים נחסם. אפשר חלונות קופצים עבור אתר זה ונסה שוב.\",\n \"previewFullscreenLabel\": \"הצג תצוגה מקדימה במסך מלא\",\n \"previewPopupReturnLabel\": \"החזר את התצוגה המקדימה לעריכה\",\n \"downloadHtmlLabel\": \"הורד HTML\",\n \"themeTrayAriaLabel\": \"הגדרות ערכה\",\n \"tabConfigLabel\": \"תצורה\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"ספק CDN\",\n \"localProviderLabel\": \"ללא (מוטמע)\",\n \"themeLabel\": \"ערכה\",\n \"appearanceLabel\": \"מראה\",\n \"appearanceLightLabel\": \"בהיר\",\n \"appearanceDarkLabel\": \"כהה\",\n \"themeCanvasLabel\": \"קנבס\",\n \"themeCanvasHighContrastLabel\": \"קנבס ניגודיות גבוהה\",\n \"includeDarkModeLabel\": \"לכלול מצב כהה\",\n \"colorLabel\": \"סכמת צבעים\",\n \"colorNavyLabel\": \"כחול כהה\",\n \"colorBlueLabel\": \"כחול\",\n \"colorGreenLabel\": \"ירוק\",\n \"colorRedLabel\": \"אדום\",\n \"colorOrangeLabel\": \"כתום\",\n \"colorGreyLabel\": \"אפור\",\n \"colorPlumLabel\": \"שזיף\",\n \"colorVioletLabel\": \"סגול\",\n \"colorStoneLabel\": \"אבן\",\n \"colorSkyLabel\": \"תכלת\",\n \"colorHoneyLabel\": \"דבש\",\n \"colorSeaLabel\": \"ים\",\n \"colorAuroraLabel\": \"אורורה\",\n \"colorCustomLabel\": \"מותאם אישית\",\n \"customColorInputLabel\": \"צבע המותג (hex)\",\n \"downloadCssLabel\": \"הורד theme.css\",\n \"downloadJsLabel\": \"הורד theme.js\",\n \"cssPanelHintLabel\": \"הוסף CSS מותאם אישית כאן — הוא מצורף ל-theme.css שנוצר, בתצוגה המקדימה ובהורדה.\",\n \"jsPanelHintLabel\": \"הוסף JS מותאם אישית כאן — הוא מצורף ל-theme.js שנוצר, בתצוגה המקדימה ובהורדה.\",\n \"helpModalTitle\": \"כיצד להשתמש בעמוד זה\",\n \"helpModalBody1\": \"בחר תבנית התחל, ערוך אותה כמו ב־Canvas Rich Content Editor, ואז לחץ על <strong>העתק HTML</strong> והדבק את התוצאה בעמוד Canvas (העבר קודם למצב עורך ה‑HTML). Canvas מנקה HTML שהודבק בצד השרת — תצוגה מקדימה זו אינה מדמה זאת, לכן תמיד אשר את התוצאה ב‑Canvas.\",\n \"helpModalBody2\": \"השתמש ב־<strong>ערוך ערכה</strong> כדי לשנות את ספק ה‑CDN, הערכה או המצב, ולערוך ידנית את הקבצים הנוצרים <code>theme.css</code>/<code>theme.js</code> לפני הורדה.\",\n \"closeLabel\": \"סגור\"\n },\n \"hi\": {\n \"pageTitle\": \"RCE टेम्पलेट लेखन\",\n \"pageDescription\": \"Canvas RCE पृष्ठ टेम्पलेट बनाएं जिन्हें pantoken से स्टाइल किया गया है, साथ में लाइव प्रीव्यू।\",\n \"editThemeLabel\": \"थीम संपादित करें\",\n \"layoutDirectionLabel\": \"लेआउट अभिविन्यास बदलें\",\n \"helpAriaLabel\": \"सहायता\",\n \"appModeLabel\": \"वेब ऐप खोलें\",\n \"copyHtmlLabel\": \"HTML कॉपी करें\",\n \"previewFrameTitle\": \"स्टाइल्ड प्रीव्यू\",\n \"previewWidthLargeLabel\": \"बड़ा\",\n \"previewWidthMediumLabel\": \"मध्यम\",\n \"previewWidthSmallLabel\": \"छोटा\",\n \"previewSchemeToggleLabel\": \"डार्क मोड का पूर्वावलोकन\",\n \"previewPopupLabel\": \"पूर्वावलोकन पॉपअप में खोलें\",\n \"previewPopupTitle\": \"कैनवास सामग्री का पूर्वावलोकन\",\n \"previewPopupBlockedMessage\": \"पूर्वावलोकन पॉपअप को अवरुद्ध किया गया था। इस साइट के लिए पॉपअप की अनुमति दें और पुनः प्रयास करें।\",\n \"previewFullscreenLabel\": \"पूर्वावलोकन को पूरा-स्क्रीन दिखाएं\",\n \"previewPopupReturnLabel\": \"पूर्वावलोकन को संपादक में लौटाएं\",\n \"downloadHtmlLabel\": \"HTML डाउनलोड करें\",\n \"themeTrayAriaLabel\": \"थीम सेटिंग्स\",\n \"tabConfigLabel\": \"कॉन्फ़िग\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN प्रदाता\",\n \"localProviderLabel\": \"कोई नहीं (इनलाइन)\",\n \"themeLabel\": \"थीम\",\n \"appearanceLabel\": \"दिखावट\",\n \"appearanceLightLabel\": \"रोशनी\",\n \"appearanceDarkLabel\": \"अंधेरा\",\n \"themeCanvasLabel\": \"कैनवास\",\n \"themeCanvasHighContrastLabel\": \"कैनवास उच्च कंट्रास्ट\",\n \"includeDarkModeLabel\": \"डार्क मोड शामिल करें\",\n \"colorLabel\": \"रंग योजना\",\n \"colorNavyLabel\": \"नेवी\",\n \"colorBlueLabel\": \"नीला\",\n \"colorGreenLabel\": \"हरा\",\n \"colorRedLabel\": \"लाल\",\n \"colorOrangeLabel\": \"नारंगी\",\n \"colorGreyLabel\": \"ग्रे\",\n \"colorPlumLabel\": \"प्लम\",\n \"colorVioletLabel\": \"वायोलेट\",\n \"colorStoneLabel\": \"स्टोन\",\n \"colorSkyLabel\": \"स्काई\",\n \"colorHoneyLabel\": \"हनी\",\n \"colorSeaLabel\": \"सी\",\n \"colorAuroraLabel\": \"ऑरोरा\",\n \"colorCustomLabel\": \"कस्टम\",\n \"customColorInputLabel\": \"ब्रांड रंग (हेक्स)\",\n \"downloadCssLabel\": \"theme.css डाउनलोड करें\",\n \"downloadJsLabel\": \"theme.js डाउनलोड करें\",\n \"cssPanelHintLabel\": \"यहाँ कस्टम CSS जोड़ें — यह जनरेट की गई theme.css में जोड़ा जाएगा, पूर्वावलोकन और डाउनलोड दोनों में।\",\n \"jsPanelHintLabel\": \"यहाँ कस्टम JS जोड़ें — यह जनरेट की गई theme.js में जोड़ा जाएगा, पूर्वावलोकन और डाउनलोड दोनों में।\",\n \"helpModalTitle\": \"इस पृष्ठ का उपयोग कैसे करें\",\n \"helpModalBody1\": \"स्टार्टर टेम्पलेट चुनें, इसे Canvas Rich Content Editor में जैसा संपादित करेंगे वैसा संपादित करें, फिर <strong>Copy HTML</strong> पर क्लिक करें और परिणाम को Canvas पेज में पेस्ट करें (पहले HTML एडिटर व्यू पर स्विच करें). Canvas सर्वर-साइड पर पेस्ट किए गए HTML को सैनिटाइज़ करता है — यह प्रीव्यू उस व्यवहार की नकल नहीं करता, इसलिए पेस्ट परिणाम को Canvas में हमेशा सत्यापित करें।\",\n \"helpModalBody2\": \"<strong>Edit theme</strong> का उपयोग CDN प्रदाता, थीम या मोड बदलने के लिए करें, और डाउनलोड करने से पहले स्वचालित रूप से जनरेट किए गए <code>theme.css</code>/<code>theme.js</code> को हाथ से संपादित करें।\",\n \"closeLabel\": \"बंद करें\"\n },\n \"hu\": {\n \"pageTitle\": \"RCE sablon szerkesztés\",\n \"pageDescription\": \"Canvas RCE oldal sablonok készítése pantoken stílussal, élő előnézettel.\",\n \"editThemeLabel\": \"Téma szerkesztése\",\n \"layoutDirectionLabel\": \"Elrendezés tájolásának váltása\",\n \"helpAriaLabel\": \"Súgó\",\n \"appModeLabel\": \"Webalkalmazás megnyitása\",\n \"copyHtmlLabel\": \"HTML másolása\",\n \"previewFrameTitle\": \"Stilizált előnézet\",\n \"previewWidthLargeLabel\": \"Nagy\",\n \"previewWidthMediumLabel\": \"Közepes\",\n \"previewWidthSmallLabel\": \"Kicsi\",\n \"previewSchemeToggleLabel\": \"Sötét mód előnézete\",\n \"previewPopupLabel\": \"Előnézet megnyitása felugró ablakban\",\n \"previewPopupTitle\": \"Vászon tartalom előnézete\",\n \"previewPopupBlockedMessage\": \"Az előnézeti felugró ablak letiltva. Engedélyezd a felugró ablakokat ennél a webhelynél, majd próbáld újra.\",\n \"previewFullscreenLabel\": \"Előnézet megjelenítése teljes képernyőn\",\n \"previewPopupReturnLabel\": \"Előnézet visszaadása a szerkesztőnek\",\n \"downloadHtmlLabel\": \"HTML letöltése\",\n \"themeTrayAriaLabel\": \"Téma beállítások\",\n \"tabConfigLabel\": \"Konfiguráció\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN szolgáltató\",\n \"localProviderLabel\": \"Nincs (inline)\",\n \"themeLabel\": \"Téma\",\n \"appearanceLabel\": \"Megjelenés\",\n \"appearanceLightLabel\": \"Világos\",\n \"appearanceDarkLabel\": \"Sötét\",\n \"themeCanvasLabel\": \"Vászon\",\n \"themeCanvasHighContrastLabel\": \"Vászon — nagy kontraszt\",\n \"includeDarkModeLabel\": \"Sötét mód hozzáadása\",\n \"colorLabel\": \"Színséma\",\n \"colorNavyLabel\": \"Tengerészkék\",\n \"colorBlueLabel\": \"Kék\",\n \"colorGreenLabel\": \"Zöld\",\n \"colorRedLabel\": \"Piros\",\n \"colorOrangeLabel\": \"Narancssárga\",\n \"colorGreyLabel\": \"Szürke\",\n \"colorPlumLabel\": \"Szilva\",\n \"colorVioletLabel\": \"Ibolya\",\n \"colorStoneLabel\": \"Kőszín\",\n \"colorSkyLabel\": \"Égkék\",\n \"colorHoneyLabel\": \"Méz\",\n \"colorSeaLabel\": \"Tenger\",\n \"colorAuroraLabel\": \"Auróra\",\n \"colorCustomLabel\": \"Egyéni\",\n \"customColorInputLabel\": \"Márkaszín (hex)\",\n \"downloadCssLabel\": \"theme.css letöltése\",\n \"downloadJsLabel\": \"theme.js letöltése\",\n \"cssPanelHintLabel\": \"Itt adhatsz egyéni CSS-t — a generált theme.css-hez lesz fűzve, az előnézetben és a letöltésnél.\",\n \"jsPanelHintLabel\": \"Itt adhatsz egyéni JS-t — a generált theme.js-hez lesz fűzve, az előnézetben és a letöltésnél.\",\n \"helpModalTitle\": \"Hogyan használd ezt az oldalt\",\n \"helpModalBody1\": \"Válassz egy kezdősablont, szerkeszd úgy, mint a Canvas Rich Content Editorban, majd kattints a <strong>HTML másolása</strong> gombra és illeszd be az eredményt egy Canvas oldalba (előtte válts HTML szerkesztő nézetre). A Canvas szerveroldalon megtisztítja a beillesztett HTML-t — ez az előnézet nem próbálja reprodukálni ezt, ezért mindig ellenőrizd a beillesztett eredményt Canvasban.\",\n \"helpModalBody2\": \"Használd a <strong>Téma szerkesztése</strong> lehetőséget a CDN szolgáltató, téma vagy mód megváltoztatásához, illetve a generált <code>theme.css</code>/<code>theme.js</code> kézi szerkesztéséhez letöltés előtt.\",\n \"closeLabel\": \"Bezárás\"\n },\n \"is\": {\n \"pageTitle\": \"RCE sniðmátahöfundur\",\n \"pageDescription\": \"Höfundu Canvas RCE síðu­sniðmát stílað með pantoken, með lifandi forskoðun.\",\n \"editThemeLabel\": \"Breyta þema\",\n \"layoutDirectionLabel\": \"Skipta um útlitsstefnu\",\n \"helpAriaLabel\": \"Hjálp\",\n \"appModeLabel\": \"Opna vefforrit\",\n \"copyHtmlLabel\": \"Afrita HTML\",\n \"previewFrameTitle\": \"Stíluð forskoðun\",\n \"previewWidthLargeLabel\": \"Stórt\",\n \"previewWidthMediumLabel\": \"Miðlungs\",\n \"previewWidthSmallLabel\": \"Lítill\",\n \"previewSchemeToggleLabel\": \"Forskoða dökkan hátt\",\n \"previewPopupLabel\": \"Opna forskoðun í sprettiglugga\",\n \"previewPopupTitle\": \"Forskoðun á Canvas-efni\",\n \"previewPopupBlockedMessage\": \"Sprettiglugginn fyrir forskoðun var hindraður. Leyfðu sprettiglugga fyrir þessa síðu og reyndu aftur.\",\n \"previewFullscreenLabel\": \"Sýna forskoðun í fullri skjástærð\",\n \"previewPopupReturnLabel\": \"Færa forskoðun aftur í ritstjórann\",\n \"downloadHtmlLabel\": \"Sækja HTML\",\n \"themeTrayAriaLabel\": \"Þema-stillingar\",\n \"tabConfigLabel\": \"Stillingar\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN birgir\",\n \"localProviderLabel\": \"Ekkert (innfelldur)\",\n \"themeLabel\": \"Þema\",\n \"appearanceLabel\": \"Útlit\",\n \"appearanceLightLabel\": \"Ljóst\",\n \"appearanceDarkLabel\": \"Dökkt\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas hákontrast\",\n \"includeDarkModeLabel\": \"Innihalda dökkan hátt\",\n \"colorLabel\": \"Litasamsetning\",\n \"colorNavyLabel\": \"Dökkblár\",\n \"colorBlueLabel\": \"Blár\",\n \"colorGreenLabel\": \"Grænn\",\n \"colorRedLabel\": \"Rauður\",\n \"colorOrangeLabel\": \"Appelsínugulur\",\n \"colorGreyLabel\": \"Grár\",\n \"colorPlumLabel\": \"Plómulitur\",\n \"colorVioletLabel\": \"Fjólublár\",\n \"colorStoneLabel\": \"Steinlitur\",\n \"colorSkyLabel\": \"Himnublár\",\n \"colorHoneyLabel\": \"Hunangslitur\",\n \"colorSeaLabel\": \"Sjávarblár\",\n \"colorAuroraLabel\": \"Norðurljós\",\n \"colorCustomLabel\": \"Sérsniðinn\",\n \"customColorInputLabel\": \"Vörumerkislitur (hex)\",\n \"downloadCssLabel\": \"Sækja theme.css\",\n \"downloadJsLabel\": \"Sækja theme.js\",\n \"cssPanelHintLabel\": \"Bættu sérsniðnu CSS hér — það er bætt við myndaða theme.css, í forskoðuninni og í niðurhali.\",\n \"jsPanelHintLabel\": \"Bættu sérsniðnu JS hér — það er bætt við myndaða theme.js, í forskoðuninni og í niðurhali.\",\n \"helpModalTitle\": \"Hvernig á að nota þessa síðu\",\n \"helpModalBody1\": \"Veldu byrjunar­sniðmát, breyttu því eins og í Canvas Rich Content Editor, smelltu á <strong>Copy HTML</strong> og límdu niðurstöðuna inn í Canvas síðu (skiptðu í HTML ritillinn fyrst). Canvas hreinsar límt HTML á þjóninum — þessi forskoðun hermir það ekki, svo staðfestu alltaf útkomuna í Canvas.\",\n \"helpModalBody2\": \"Notaðu <strong>Edit theme</strong> til að breyta CDN birgja, þema eða ham, og til að breyta handvirkt mynduðu <code>theme.css</code>/<code>theme.js</code> áður en þú sækir þau.\",\n \"closeLabel\": \"Loka\"\n },\n \"id\": {\n \"pageTitle\": \"Pembuatan template RCE\",\n \"pageDescription\": \"Buat template halaman Canvas RCE yang distilasi dengan pantoken, dengan pratinjau langsung.\",\n \"editThemeLabel\": \"Sunting tema\",\n \"layoutDirectionLabel\": \"Beralih orientasi tata letak\",\n \"helpAriaLabel\": \"Bantuan\",\n \"appModeLabel\": \"Buka aplikasi web\",\n \"copyHtmlLabel\": \"Salin HTML\",\n \"previewFrameTitle\": \"Pratinjau bergaya\",\n \"previewWidthLargeLabel\": \"Besar\",\n \"previewWidthMediumLabel\": \"Sedang\",\n \"previewWidthSmallLabel\": \"Kecil\",\n \"previewSchemeToggleLabel\": \"Pratinjau mode gelap\",\n \"previewPopupLabel\": \"Buka pratinjau di popup\",\n \"previewPopupTitle\": \"Pratinjau konten kanvas\",\n \"previewPopupBlockedMessage\": \"Popup pratinjau diblokir. Izinkan popup untuk situs ini dan coba lagi.\",\n \"previewFullscreenLabel\": \"Tampilkan pratinjau layar penuh\",\n \"previewPopupReturnLabel\": \"Kembalikan pratinjau ke editor\",\n \"downloadHtmlLabel\": \"Unduh HTML\",\n \"themeTrayAriaLabel\": \"Pengaturan tema\",\n \"tabConfigLabel\": \"Konfigurasi\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Penyedia CDN\",\n \"localProviderLabel\": \"Tidak ada (inline)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Tampilan\",\n \"appearanceLightLabel\": \"Terang\",\n \"appearanceDarkLabel\": \"Gelap\",\n \"themeCanvasLabel\": \"Kanvas\",\n \"themeCanvasHighContrastLabel\": \"Kanvas kontras tinggi\",\n \"includeDarkModeLabel\": \"Sertakan mode gelap\",\n \"colorLabel\": \"Skema warna\",\n \"colorNavyLabel\": \"Biru Tua\",\n \"colorBlueLabel\": \"Biru\",\n \"colorGreenLabel\": \"Hijau\",\n \"colorRedLabel\": \"Merah\",\n \"colorOrangeLabel\": \"Oranye\",\n \"colorGreyLabel\": \"Abu-abu\",\n \"colorPlumLabel\": \"Plum\",\n \"colorVioletLabel\": \"Violet\",\n \"colorStoneLabel\": \"Batu\",\n \"colorSkyLabel\": \"Langit\",\n \"colorHoneyLabel\": \"Madu\",\n \"colorSeaLabel\": \"Laut\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Kustom\",\n \"customColorInputLabel\": \"Warna merek (hex)\",\n \"downloadCssLabel\": \"Unduh theme.css\",\n \"downloadJsLabel\": \"Unduh theme.js\",\n \"cssPanelHintLabel\": \"Tambahkan CSS kustom di sini — ini ditambahkan ke theme.css yang dihasilkan, di pratinjau dan unduhan.\",\n \"jsPanelHintLabel\": \"Tambahkan JS kustom di sini — ini ditambahkan ke theme.js yang dihasilkan, di pratinjau dan unduhan.\",\n \"helpModalTitle\": \"Cara menggunakan halaman ini\",\n \"helpModalBody1\": \"Pilih template awal, sunting seperti di Canvas Rich Content Editor, lalu klik <strong>Copy HTML</strong> dan tempel hasilnya ke halaman Canvas (alihkan ke tampilan editor HTML terlebih dahulu). Canvas menyanitasi HTML yang ditempel di sisi server — pratinjau ini tidak mencoba meniru itu, jadi selalu verifikasi hasil yang ditempel di Canvas.\",\n \"helpModalBody2\": \"Gunakan <strong>Edit theme</strong> untuk mengubah penyedia CDN, tema, atau mode, dan untuk menyunting <code>theme.css</code>/<code>theme.js</code> yang dihasilkan sebelum mengunduhnya.\",\n \"closeLabel\": \"Tutup\"\n },\n \"it\": {\n \"pageTitle\": \"Autore di template RCE\",\n \"pageDescription\": \"Crea template di pagina RCE per Canvas stilizzati con pantoken, con anteprima live.\",\n \"editThemeLabel\": \"Modifica tema\",\n \"layoutDirectionLabel\": \"Cambia orientamento del layout\",\n \"helpAriaLabel\": \"Guida\",\n \"appModeLabel\": \"Apri l'app web\",\n \"copyHtmlLabel\": \"Copia HTML\",\n \"previewFrameTitle\": \"Anteprima stilizzata\",\n \"previewWidthLargeLabel\": \"Grande\",\n \"previewWidthMediumLabel\": \"Medio\",\n \"previewWidthSmallLabel\": \"Piccolo\",\n \"previewSchemeToggleLabel\": \"Anteprima modalità scura\",\n \"previewPopupLabel\": \"Apri l'anteprima in un popup\",\n \"previewPopupTitle\": \"Anteprima del contenuto del Canvas\",\n \"previewPopupBlockedMessage\": \"Il popup di anteprima è stato bloccato. Consenti i popup per questo sito e riprova.\",\n \"previewFullscreenLabel\": \"Mostra l'anteprima a schermo intero\",\n \"previewPopupReturnLabel\": \"Riporta l'anteprima all'editor\",\n \"downloadHtmlLabel\": \"Scarica HTML\",\n \"themeTrayAriaLabel\": \"Impostazioni tema\",\n \"tabConfigLabel\": \"Configurazione\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Provider CDN\",\n \"localProviderLabel\": \"Nessuno (in linea)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Aspetto\",\n \"appearanceLightLabel\": \"Chiaro\",\n \"appearanceDarkLabel\": \"Scuro\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas ad alto contrasto\",\n \"includeDarkModeLabel\": \"Includi modalità scura\",\n \"colorLabel\": \"Schema dei colori\",\n \"colorNavyLabel\": \"Blu navy\",\n \"colorBlueLabel\": \"Blu\",\n \"colorGreenLabel\": \"Verde\",\n \"colorRedLabel\": \"Rosso\",\n \"colorOrangeLabel\": \"Arancione\",\n \"colorGreyLabel\": \"Grigio\",\n \"colorPlumLabel\": \"Prugna\",\n \"colorVioletLabel\": \"Viola\",\n \"colorStoneLabel\": \"Pietra\",\n \"colorSkyLabel\": \"Cielo\",\n \"colorHoneyLabel\": \"Miele\",\n \"colorSeaLabel\": \"Mare\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Personalizzato\",\n \"customColorInputLabel\": \"Colore del brand (hex)\",\n \"downloadCssLabel\": \"Scarica theme.css\",\n \"downloadJsLabel\": \"Scarica theme.js\",\n \"cssPanelHintLabel\": \"Aggiungi CSS personalizzato qui — viene aggiunto a theme.css generato, nell'anteprima e nel download.\",\n \"jsPanelHintLabel\": \"Aggiungi JS personalizzato qui — viene aggiunto a theme.js generato, nell'anteprima e nel download.\",\n \"helpModalTitle\": \"Come usare questa pagina\",\n \"helpModalBody1\": \"Scegli un template di partenza, modificalo come faresti nell'Editor di contenuti ricchi di Canvas, poi clicca <strong>Copia HTML</strong> e incolla il risultato in una pagina di Canvas (passa prima alla vista editor HTML). Canvas sanitizza l'HTML incollato lato server — questa anteprima non tenta di replicare quel comportamento, quindi verifica sempre il risultato incollato in Canvas.\",\n \"helpModalBody2\": \"Usa <strong>Modifica tema</strong> per cambiare il provider CDN, il tema o la modalità, e per modificare manualmente i file generati <code>theme.css</code>/<code>theme.js</code> prima di scaricarli.\",\n \"closeLabel\": \"Chiudi\"\n },\n \"ja\": {\n \"pageTitle\": \"RCE テンプレート作成\",\n \"pageDescription\": \"pantoken でスタイルした Canvas RCE ページテンプレートを作成し、ライブプレビューできます。\",\n \"editThemeLabel\": \"テーマを編集\",\n \"layoutDirectionLabel\": \"レイアウトの向きを切り替える\",\n \"helpAriaLabel\": \"ヘルプ\",\n \"appModeLabel\": \"ウェブアプリを開く\",\n \"copyHtmlLabel\": \"HTML をコピー\",\n \"previewFrameTitle\": \"スタイル済みプレビュー\",\n \"previewWidthLargeLabel\": \"大\",\n \"previewWidthMediumLabel\": \"中\",\n \"previewWidthSmallLabel\": \"小\",\n \"previewSchemeToggleLabel\": \"ダークモードをプレビュー\",\n \"previewPopupLabel\": \"プレビューをポップアップで開く\",\n \"previewPopupTitle\": \"キャンバスのコンテンツプレビュー\",\n \"previewPopupBlockedMessage\": \"プレビューポップアップがブロックされました。このサイトでポップアップを許可して、もう一度お試しください。\",\n \"previewFullscreenLabel\": \"プレビューを全画面表示\",\n \"previewPopupReturnLabel\": \"プレビューをエディタに戻す\",\n \"downloadHtmlLabel\": \"HTMLをダウンロード\",\n \"themeTrayAriaLabel\": \"テーマ設定\",\n \"tabConfigLabel\": \"設定\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN プロバイダ\",\n \"localProviderLabel\": \"なし(インライン)\",\n \"themeLabel\": \"テーマ\",\n \"appearanceLabel\": \"表示設定\",\n \"appearanceLightLabel\": \"ライト\",\n \"appearanceDarkLabel\": \"ダーク\",\n \"themeCanvasLabel\": \"キャンバス\",\n \"themeCanvasHighContrastLabel\": \"キャンバス(ハイコントラスト)\",\n \"includeDarkModeLabel\": \"ダークモードを含める\",\n \"colorLabel\": \"カラースキーム\",\n \"colorNavyLabel\": \"ネイビー\",\n \"colorBlueLabel\": \"ブルー\",\n \"colorGreenLabel\": \"グリーン\",\n \"colorRedLabel\": \"レッド\",\n \"colorOrangeLabel\": \"オレンジ\",\n \"colorGreyLabel\": \"グレー\",\n \"colorPlumLabel\": \"プラム\",\n \"colorVioletLabel\": \"バイオレット\",\n \"colorStoneLabel\": \"ストーン\",\n \"colorSkyLabel\": \"スカイ\",\n \"colorHoneyLabel\": \"ハニー\",\n \"colorSeaLabel\": \"シー\",\n \"colorAuroraLabel\": \"オーロラ\",\n \"colorCustomLabel\": \"カスタム\",\n \"customColorInputLabel\": \"ブランドカラー(16進数)\",\n \"downloadCssLabel\": \"theme.css をダウンロード\",\n \"downloadJsLabel\": \"theme.js をダウンロード\",\n \"cssPanelHintLabel\": \"ここにカスタムCSSを追加してください — 生成されたtheme.cssに追記され、プレビューとダウンロードに反映されます。\",\n \"jsPanelHintLabel\": \"ここにカスタムJSを追加してください — 生成されたtheme.jsに追記され、プレビューとダウンロードに反映されます。\",\n \"helpModalTitle\": \"このページの使い方\",\n \"helpModalBody1\": \"スターターテンプレートを選び、Canvas の Rich Content Editor のように編集してから <strong>HTML をコピー</strong> をクリックし、結果を Canvas のページに貼り付けてください(先に HTML エディタ表示に切り替えてください)。Canvas はサーバー側で貼り付けた HTML をサニタイズするため、このプレビューは同じ動作を再現しません。必ず Canvas 上で貼り付け結果を確認してください。\",\n \"helpModalBody2\": \"<strong>テーマを編集</strong> で CDN プロバイダ、テーマ、モードを変更したり、ダウンロード前に生成された <code>theme.css</code>/<code>theme.js</code> を手動編集できます。\",\n \"closeLabel\": \"閉じる\"\n },\n \"ko\": {\n \"pageTitle\": \"RCE 템플릿 작성\",\n \"pageDescription\": \"pantoken으로 스타일된 Canvas RCE 페이지 템플릿을 작성하고 실시간 미리보기를 확인합니다.\",\n \"editThemeLabel\": \"테마 편집\",\n \"layoutDirectionLabel\": \"레이아웃 방향 전환\",\n \"helpAriaLabel\": \"도움말\",\n \"appModeLabel\": \"웹 앱 열기\",\n \"copyHtmlLabel\": \"HTML 복사\",\n \"previewFrameTitle\": \"스타일된 미리보기\",\n \"previewWidthLargeLabel\": \"대형\",\n \"previewWidthMediumLabel\": \"중형\",\n \"previewWidthSmallLabel\": \"소형\",\n \"previewSchemeToggleLabel\": \"다크 모드 미리보기\",\n \"previewPopupLabel\": \"미리보기를 팝업으로 열기\",\n \"previewPopupTitle\": \"캔버스 콘텐츠 미리보기\",\n \"previewPopupBlockedMessage\": \"미리보기 팝업이 차단되었습니다. 이 사이트에서 팝업을 허용한 후 다시 시도하세요.\",\n \"previewFullscreenLabel\": \"전체 화면으로 미리보기 표시\",\n \"previewPopupReturnLabel\": \"미리보기를 편집기로 되돌리기\",\n \"downloadHtmlLabel\": \"HTML 다운로드\",\n \"themeTrayAriaLabel\": \"테마 설정\",\n \"tabConfigLabel\": \"구성\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN 제공자\",\n \"localProviderLabel\": \"없음(인라인)\",\n \"themeLabel\": \"테마\",\n \"appearanceLabel\": \"모양\",\n \"appearanceLightLabel\": \"라이트\",\n \"appearanceDarkLabel\": \"다크\",\n \"themeCanvasLabel\": \"캔버스\",\n \"themeCanvasHighContrastLabel\": \"캔버스 고대비\",\n \"includeDarkModeLabel\": \"다크 모드 포함\",\n \"colorLabel\": \"색상 구성표\",\n \"colorNavyLabel\": \"네이비\",\n \"colorBlueLabel\": \"파랑\",\n \"colorGreenLabel\": \"초록\",\n \"colorRedLabel\": \"빨강\",\n \"colorOrangeLabel\": \"오렌지\",\n \"colorGreyLabel\": \"회색\",\n \"colorPlumLabel\": \"자두색\",\n \"colorVioletLabel\": \"보라색\",\n \"colorStoneLabel\": \"스톤\",\n \"colorSkyLabel\": \"하늘색\",\n \"colorHoneyLabel\": \"허니\",\n \"colorSeaLabel\": \"바다색\",\n \"colorAuroraLabel\": \"오로라\",\n \"colorCustomLabel\": \"사용자 정의\",\n \"customColorInputLabel\": \"브랜드 색상 (16진수)\",\n \"downloadCssLabel\": \"theme.css 다운로드\",\n \"downloadJsLabel\": \"theme.js 다운로드\",\n \"cssPanelHintLabel\": \"여기에 사용자 정의 CSS를 추가하세요 — 미리보기와 다운로드에서 생성된 theme.css에 추가됩니다.\",\n \"jsPanelHintLabel\": \"여기에 사용자 정의 JS를 추가하세요 — 미리보기와 다운로드에서 생성된 theme.js에 추가됩니다.\",\n \"helpModalTitle\": \"이 페이지 사용 방법\",\n \"helpModalBody1\": \"시작 템플릿을 선택하고 Canvas의 리치 콘텐츠 편집기에서 편집하듯 템플릿을 수정한 다음 <strong>HTML 복사</strong>를 클릭하여 결과를 Canvas 페이지에 붙여넣으세요 (먼저 HTML 편집기 보기로 전환). Canvas는 서버 측에서 붙여넣은 HTML을 정리하므로 이 미리보기와 동작이 다를 수 있으니 Canvas에서 붙여넣은 결과를 항상 확인하세요.\",\n \"helpModalBody2\": \"<strong>테마 편집</strong>을 사용해 CDN 제공자, 테마 또는 모드를 변경하고, 다운로드하기 전에 생성된 <code>theme.css</code>/<code>theme.js</code>를 수동으로 편집할 수 있습니다.\",\n \"closeLabel\": \"닫기\"\n },\n \"mi\": {\n \"pageTitle\": \"Te tuhi tauira RCE\",\n \"pageDescription\": \"Tuhia ngā tauira whārangi RCE o Canvas kua āta hoahoa ki te pantoken, me tētahi matakitaki ora.\",\n \"editThemeLabel\": \"Whakatika kaupapa\",\n \"layoutDirectionLabel\": \"Huri i te aronga whakarite\",\n \"helpAriaLabel\": \"Āwhina\",\n \"appModeLabel\": \"Whakatuwheratia te taupānga tukutuku\",\n \"copyHtmlLabel\": \"Tāpiri HTML\",\n \"previewFrameTitle\": \"Tirohanga kua hōtaka\",\n \"previewWidthLargeLabel\": \"Nui\",\n \"previewWidthMediumLabel\": \"Waenga\",\n \"previewWidthSmallLabel\": \"Ititi\",\n \"previewSchemeToggleLabel\": \"Tirohia te aratau pōuri\",\n \"previewPopupLabel\": \"Whakatuwherahia te tirohanga i roto i tētahi matapihi pātata\",\n \"previewPopupTitle\": \"Tirohanga ihirangi papa toi\",\n \"previewPopupBlockedMessage\": \"I aukatia te matapihi pātata tirohanga. Whakaaetia ngā matapihi pātata mō tēnei pae ka whakamātau anō.\",\n \"previewFullscreenLabel\": \"Whakaatu te tirohanga i te mata-katoa\",\n \"previewPopupReturnLabel\": \"Whakahokia te tirohanga ki te etita\",\n \"downloadHtmlLabel\": \"Tikiake i te HTML\",\n \"themeTrayAriaLabel\": \"Tautuhinga kaupapa\",\n \"tabConfigLabel\": \"Kōwhiringa\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Kaiwhakarato CDN\",\n \"localProviderLabel\": \"Kore (tuara-roto)\",\n \"themeLabel\": \"Kaupapa\",\n \"appearanceLabel\": \"Āhua\",\n \"appearanceLightLabel\": \"Mārama\",\n \"appearanceDarkLabel\": \"Pōuri\",\n \"themeCanvasLabel\": \"Papa toi\",\n \"themeCanvasHighContrastLabel\": \"Papa toi — ōrite-nui\",\n \"includeDarkModeLabel\": \"Whakauru i te aratau pōuri\",\n \"colorLabel\": \"Aronga tae\",\n \"colorNavyLabel\": \"Kikorangi hōia\",\n \"colorBlueLabel\": \"Kikorangi\",\n \"colorGreenLabel\": \"Kākāriki\",\n \"colorRedLabel\": \"Whero\",\n \"colorOrangeLabel\": \"Karaka\",\n \"colorGreyLabel\": \"Kerei\",\n \"colorPlumLabel\": \"Poroporo\",\n \"colorVioletLabel\": \"Pūrū\",\n \"colorStoneLabel\": \"Kōhatu\",\n \"colorSkyLabel\": \"Rangi\",\n \"colorHoneyLabel\": \"Mīere\",\n \"colorSeaLabel\": \"Moana\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Whakarite\",\n \"customColorInputLabel\": \"Tae waitohu (hex)\",\n \"downloadCssLabel\": \"Tikiake theme.css\",\n \"downloadJsLabel\": \"Tikiake theme.js\",\n \"cssPanelHintLabel\": \"Tāpirihia te CSS ritenga ki konei — ka tapiritia ki te theme.css i hangaia, i te tirohanga me te tikiake.\",\n \"jsPanelHintLabel\": \"Tāpirihia te JS ritenga ki konei — ka tapiritia ki te theme.js i hangaia, i te tirohanga me te tikiake.\",\n \"helpModalTitle\": \"Me pēhea te whakamahi i tēnei whārangi\",\n \"helpModalBody1\": \"Tīpakohia he tauira tīmatanga, whakatikahia pēnei i roto i te Kaiwhakatika Ihirangi Rawa o Canvas, katahi ka pāwhiri <strong>Copy HTML</strong> ka whakapiri te hua ki tētahi whārangi Canvas (hurihia ki te tirohanga kaiwhakatika HTML i te tuatahi). Ka ārai a Canvas i te HTML i whakapirihia i te taha tūmau — kāore tēnei matakitaki e kopa i tērā, nō reira me whakamātau tonu i te hua kua whakapirihia i roto i Canvas.\",\n \"helpModalBody2\": \"Whakamahia te <strong>Edit theme</strong> ki te huri i te kaiwhakarato CDN, te kaupapa, te aratau, me te āta whakatika i ngā kōnae whakauru <code>theme.css</code>/<code>theme.js</code> i mua i te tikiake.\",\n \"closeLabel\": \"Katia\"\n },\n \"ms\": {\n \"pageTitle\": \"Penyunting templat RCE\",\n \"pageDescription\": \"Tulis templat halaman RCE Canvas yang bergaya dengan pantoken, dengan pratonton langsung.\",\n \"editThemeLabel\": \"Edit tema\",\n \"layoutDirectionLabel\": \"Alihkan orientasi susun atur\",\n \"helpAriaLabel\": \"Bantuan\",\n \"appModeLabel\": \"Buka aplikasi web\",\n \"copyHtmlLabel\": \"Salin HTML\",\n \"previewFrameTitle\": \"Pratonton berstail\",\n \"previewWidthLargeLabel\": \"Besar\",\n \"previewWidthMediumLabel\": \"Sederhana\",\n \"previewWidthSmallLabel\": \"Kecil\",\n \"previewSchemeToggleLabel\": \"Pratonton mod gelap\",\n \"previewPopupLabel\": \"Buka pratonton dalam popup\",\n \"previewPopupTitle\": \"Pratonton kandungan kanvas\",\n \"previewPopupBlockedMessage\": \"Popup pratonton disekat. Benarkan popup untuk laman ini dan cuba lagi.\",\n \"previewFullscreenLabel\": \"Paparkan pratonton skrin penuh\",\n \"previewPopupReturnLabel\": \"Kembalikan pratonton ke penyunting\",\n \"downloadHtmlLabel\": \"Muat turun HTML\",\n \"themeTrayAriaLabel\": \"Tetapan tema\",\n \"tabConfigLabel\": \"Konfigurasi\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Pembekal CDN\",\n \"localProviderLabel\": \"Tiada (sebaris)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Penampilan\",\n \"appearanceLightLabel\": \"Terang\",\n \"appearanceDarkLabel\": \"Gelap\",\n \"themeCanvasLabel\": \"Kanvas\",\n \"themeCanvasHighContrastLabel\": \"Kanvas kontras tinggi\",\n \"includeDarkModeLabel\": \"Sertakan mod gelap\",\n \"colorLabel\": \"Skema warna\",\n \"colorNavyLabel\": \"Biru laut\",\n \"colorBlueLabel\": \"Biru\",\n \"colorGreenLabel\": \"Hijau\",\n \"colorRedLabel\": \"Merah\",\n \"colorOrangeLabel\": \"Jingga\",\n \"colorGreyLabel\": \"Kelabu\",\n \"colorPlumLabel\": \"Plum\",\n \"colorVioletLabel\": \"Ungu\",\n \"colorStoneLabel\": \"Batu\",\n \"colorSkyLabel\": \"Langit\",\n \"colorHoneyLabel\": \"Madu\",\n \"colorSeaLabel\": \"Laut\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Tersuai\",\n \"customColorInputLabel\": \"Warna jenama (hex)\",\n \"downloadCssLabel\": \"Muat turun theme.css\",\n \"downloadJsLabel\": \"Muat turun theme.js\",\n \"cssPanelHintLabel\": \"Tambah CSS tersuai di sini — ia ditambahkan pada theme.css yang dijana, dalam pratonton dan muat turun.\",\n \"jsPanelHintLabel\": \"Tambah JS tersuai di sini — ia ditambahkan pada theme.js yang dijana, dalam pratonton dan muat turun.\",\n \"helpModalTitle\": \"Cara menggunakan halaman ini\",\n \"helpModalBody1\": \"Pilih templat permulaan, sunting seperti dalam Canvas Rich Content Editor, kemudian klik <strong>Copy HTML</strong> dan tampal hasil ke halaman Canvas (alih ke paparan penyunting HTML terlebih dahulu). Canvas menapis HTML yang ditampal di pelayan — pratonton ini tidak cuba menirunya, jadi sentiasa sahkan hasil tampalan dalam Canvas.\",\n \"helpModalBody2\": \"Gunakan <strong>Edit theme</strong> untuk menukar pembekal CDN, tema, atau mod, dan untuk sunting tangan <code>theme.css</code>/<code>theme.js</code> yang dijana sebelum memuat turunnya.\",\n \"closeLabel\": \"Tutup\"\n },\n \"se\": {\n \"pageTitle\": \"RCE-mallskapande\",\n \"pageDescription\": \"Skapa Canvas RCE-sidmallar stylade med pantoken, med en liveförhandsvisning.\",\n \"editThemeLabel\": \"Redigera tema\",\n \"layoutDirectionLabel\": \"Switch layout orientation\",\n \"helpAriaLabel\": \"Hjälp\",\n \"appModeLabel\": \"Open web app\",\n \"copyHtmlLabel\": \"Kopiera HTML\",\n \"previewFrameTitle\": \"Stylad förhandsvisning\",\n \"previewWidthLargeLabel\": \"Large\",\n \"previewWidthMediumLabel\": \"Medium\",\n \"previewWidthSmallLabel\": \"Small\",\n \"previewSchemeToggleLabel\": \"Preview dark mode\",\n \"previewPopupLabel\": \"Open preview in a popup\",\n \"previewPopupTitle\": \"Canvas content preview\",\n \"previewPopupBlockedMessage\": \"The preview popup was blocked. Allow popups for this site and try again.\",\n \"previewFullscreenLabel\": \"Show preview fullscreen\",\n \"previewPopupReturnLabel\": \"Return preview to the editor\",\n \"downloadHtmlLabel\": \"Download HTML\",\n \"themeTrayAriaLabel\": \"Temainställningar\",\n \"tabConfigLabel\": \"Konfiguration\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN-leverantör\",\n \"localProviderLabel\": \"None (inline)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Appearance\",\n \"appearanceLightLabel\": \"Light\",\n \"appearanceDarkLabel\": \"Dark\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas high contrast\",\n \"includeDarkModeLabel\": \"Include dark mode\",\n \"colorLabel\": \"Color scheme\",\n \"colorNavyLabel\": \"Navy\",\n \"colorBlueLabel\": \"Blue\",\n \"colorGreenLabel\": \"Green\",\n \"colorRedLabel\": \"Red\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Grey\",\n \"colorPlumLabel\": \"Plum\",\n \"colorVioletLabel\": \"Violet\",\n \"colorStoneLabel\": \"Stone\",\n \"colorSkyLabel\": \"Sky\",\n \"colorHoneyLabel\": \"Honey\",\n \"colorSeaLabel\": \"Sea\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Custom\",\n \"customColorInputLabel\": \"Brand color (hex)\",\n \"downloadCssLabel\": \"Ladda ner theme.css\",\n \"downloadJsLabel\": \"Ladda ner theme.js\",\n \"cssPanelHintLabel\": \"Add custom CSS here — it's appended to the generated theme.css, in the preview and the download.\",\n \"jsPanelHintLabel\": \"Add custom JS here — it's appended to the generated theme.js, in the preview and the download.\",\n \"helpModalTitle\": \"Hur man använder denna sida\",\n \"helpModalBody1\": \"Välj en startmall, redigera den som i Canvas Rich Content Editor, klicka sedan på <strong>Kopiera HTML</strong> och klistra in resultatet i en Canvas-sida (byt först till HTML-redigeringsvyn). Canvas sanerar inklistrad HTML server-side — denna förhandsvisning försöker inte efterlikna det, så verifiera alltid det inklistrade resultatet i Canvas.\",\n \"helpModalBody2\": \"Använd <strong>Redigera tema</strong> för att byta CDN-leverantör, tema eller läge, och för att handredigera genererade <code>theme.css</code>/<code>theme.js</code> innan nedladdning.\",\n \"closeLabel\": \"Stäng\"\n },\n \"nb\": {\n \"pageTitle\": \"RCE-malforfatting\",\n \"pageDescription\": \"Forfatt Canvas RCE-sidemaler stylet med pantoken, med levende forhåndsvisning.\",\n \"editThemeLabel\": \"Rediger tema\",\n \"layoutDirectionLabel\": \"Bytt layoutretning\",\n \"helpAriaLabel\": \"Hjelp\",\n \"appModeLabel\": \"Åpne webappen\",\n \"copyHtmlLabel\": \"Kopier HTML\",\n \"previewFrameTitle\": \"Stylet forhåndsvisning\",\n \"previewWidthLargeLabel\": \"Stor\",\n \"previewWidthMediumLabel\": \"Middels\",\n \"previewWidthSmallLabel\": \"Liten\",\n \"previewSchemeToggleLabel\": \"Forhåndsvis mørk modus\",\n \"previewPopupLabel\": \"Åpne forhåndsvisning i et popup-vindu\",\n \"previewPopupTitle\": \"Forhåndsvisning av lerretinnhold\",\n \"previewPopupBlockedMessage\": \"Forhåndsvisnings-popupen ble blokkert. Tillat popup-vinduer for dette nettstedet og prøv igjen.\",\n \"previewFullscreenLabel\": \"Vis forhåndsvisning i fullskjerm\",\n \"previewPopupReturnLabel\": \"Returner forhåndsvisningen til redigereren\",\n \"downloadHtmlLabel\": \"Last ned HTML\",\n \"themeTrayAriaLabel\": \"Temainnstillinger\",\n \"tabConfigLabel\": \"Konfig\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN-leverandør\",\n \"localProviderLabel\": \"Ingen (inline)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Utseende\",\n \"appearanceLightLabel\": \"Lys\",\n \"appearanceDarkLabel\": \"Mørk\",\n \"themeCanvasLabel\": \"Lerret\",\n \"themeCanvasHighContrastLabel\": \"Lerret høy kontrast\",\n \"includeDarkModeLabel\": \"Inkluder mørk modus\",\n \"colorLabel\": \"Fargeskjema\",\n \"colorNavyLabel\": \"Marineblå\",\n \"colorBlueLabel\": \"Blå\",\n \"colorGreenLabel\": \"Grønn\",\n \"colorRedLabel\": \"Rød\",\n \"colorOrangeLabel\": \"Oransje\",\n \"colorGreyLabel\": \"Grå\",\n \"colorPlumLabel\": \"Plomme\",\n \"colorVioletLabel\": \"Fiolett\",\n \"colorStoneLabel\": \"Stein\",\n \"colorSkyLabel\": \"Himmelblå\",\n \"colorHoneyLabel\": \"Honning\",\n \"colorSeaLabel\": \"Hav\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Egendefinert\",\n \"customColorInputLabel\": \"Merkevarefarge (heks)\",\n \"downloadCssLabel\": \"Last ned theme.css\",\n \"downloadJsLabel\": \"Last ned theme.js\",\n \"cssPanelHintLabel\": \"Legg til egendefinert CSS her — den legges til i den genererte theme.css, i forhåndsvisningen og nedlastingen.\",\n \"jsPanelHintLabel\": \"Legg til egendefinert JS her — den legges til i den genererte theme.js, i forhåndsvisningen og nedlastingen.\",\n \"helpModalTitle\": \"Hvordan bruke denne siden\",\n \"helpModalBody1\": \"Velg en startmal, rediger den som i Canvas Rich Content Editor, klikk <strong>Kopier HTML</strong> og lim resultatet inn i en Canvas-side (bytt først til HTML-redigeringsvisning). Canvas renser innlimt HTML på serversiden — denne forhåndsvisningen forsøker ikke å replikere det, så verifiser alltid det innlimte resultatet i Canvas.\",\n \"helpModalBody2\": \"Bruk <strong>Rediger tema</strong> for å endre CDN-leverandør, tema eller modus, og for å redigere generert <code>theme.css</code>/<code>theme.js</code> før nedlasting.\",\n \"closeLabel\": \"Lukk\"\n },\n \"nn\": {\n \"pageTitle\": \"RCE-malforfattning\",\n \"pageDescription\": \"Forfatt Canvas RCE-sidemalar stylede med pantoken, med live-forhandsvisning.\",\n \"editThemeLabel\": \"Rediger tema\",\n \"layoutDirectionLabel\": \"Bytt layoutretning\",\n \"helpAriaLabel\": \"Hjelp\",\n \"appModeLabel\": \"Opne nettapp\",\n \"copyHtmlLabel\": \"Kopier HTML\",\n \"previewFrameTitle\": \"Styla forhandsvisning\",\n \"previewWidthLargeLabel\": \"Stor\",\n \"previewWidthMediumLabel\": \"Middels\",\n \"previewWidthSmallLabel\": \"Liten\",\n \"previewSchemeToggleLabel\": \"Forhandsvis mørk modus\",\n \"previewPopupLabel\": \"Opne forhandsvising i popup-vindauge\",\n \"previewPopupTitle\": \"Forhandsvis av lerretinnhald\",\n \"previewPopupBlockedMessage\": \"Forhandsvisings-popupen blei blokkert. Tillat popup-vindauge for denne sida og prøv på nytt.\",\n \"previewFullscreenLabel\": \"Vis forhandsvising fullskjerm\",\n \"previewPopupReturnLabel\": \"Returner forhandsvisinga til redigeraren\",\n \"downloadHtmlLabel\": \"Last ned HTML\",\n \"themeTrayAriaLabel\": \"Temainnstillingar\",\n \"tabConfigLabel\": \"Konfig\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN-leverandør\",\n \"localProviderLabel\": \"Ingen (inline)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Utseende\",\n \"appearanceLightLabel\": \"Lys\",\n \"appearanceDarkLabel\": \"Mørk\",\n \"themeCanvasLabel\": \"Lerret\",\n \"themeCanvasHighContrastLabel\": \"Lerret høg kontrast\",\n \"includeDarkModeLabel\": \"Inkluder mørk modus\",\n \"colorLabel\": \"Fargeskjema\",\n \"colorNavyLabel\": \"Marineblå\",\n \"colorBlueLabel\": \"Blå\",\n \"colorGreenLabel\": \"Grøn\",\n \"colorRedLabel\": \"Raud\",\n \"colorOrangeLabel\": \"Oransje\",\n \"colorGreyLabel\": \"Grå\",\n \"colorPlumLabel\": \"Plomme\",\n \"colorVioletLabel\": \"Fiolett\",\n \"colorStoneLabel\": \"Stein\",\n \"colorSkyLabel\": \"Himmel\",\n \"colorHoneyLabel\": \"Honning\",\n \"colorSeaLabel\": \"Hav\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Tilpassa\",\n \"customColorInputLabel\": \"Varemerke-farge (hex)\",\n \"downloadCssLabel\": \"Last ned theme.css\",\n \"downloadJsLabel\": \"Last ned theme.js\",\n \"cssPanelHintLabel\": \"Legg til tilpassa CSS her — den blir lagt til i den genererte theme.css, i forhandsvisinga og i nedlastinga.\",\n \"jsPanelHintLabel\": \"Legg til tilpassa JS her — den blir lagt til i den genererte theme.js, i forhandsvisinga og i nedlastinga.\",\n \"helpModalTitle\": \"Korleis bruke denne sida\",\n \"helpModalBody1\": \"Vel ein startmal, rediger han som i Canvas Rich Content Editor, klikk <strong>Copy HTML</strong> og lim resultatet inn i ei Canvas-side (byt til HTML-editorvisning fyrst). Canvas saniterer innlimt HTML på serversida — denne forhandsvisninga prøver ikkje å replikere det, så ver alltid nøye med å verifisere det innlimte i Canvas.\",\n \"helpModalBody2\": \"Bruk <strong>Edit theme</strong> for å endre CDN-leverandør, tema eller modus, og for å handredigere den genererte <code>theme.css</code>/<code>theme.js</code> før nedlasting.\",\n \"closeLabel\": \"Lukk\"\n },\n \"fa\": {\n \"pageTitle\": \"نویسندگی قالب RCE\",\n \"pageDescription\": \"نوشتن قالب‌های صفحه RCE برای Canvas که با pantoken استایل داده شده و پیش‌نمایش زنده دارند.\",\n \"editThemeLabel\": \"ویرایش تم\",\n \"layoutDirectionLabel\": \"تغییر جهت‌بندی طرح\",\n \"helpAriaLabel\": \"راهنما\",\n \"appModeLabel\": \"باز کردن برنامه وب\",\n \"copyHtmlLabel\": \"کپی HTML\",\n \"previewFrameTitle\": \"پیش‌نمایش استایل‌خورده\",\n \"previewWidthLargeLabel\": \"بزرگ\",\n \"previewWidthMediumLabel\": \"متوسط\",\n \"previewWidthSmallLabel\": \"کوچک\",\n \"previewSchemeToggleLabel\": \"پیش‌نمایش حالت تاریک\",\n \"previewPopupLabel\": \"باز کردن پیش‌نمایش در پنجرهٔ پاپ‌آپ\",\n \"previewPopupTitle\": \"پیش‌نمایش محتوای بوم\",\n \"previewPopupBlockedMessage\": \"پنجرهٔ پاپ‌آپ پیش‌نمایش مسدود شد. برای این سایت پاپ‌آپ‌ها را مجاز کنید و دوباره تلاش کنید.\",\n \"previewFullscreenLabel\": \"نمایش پیش‌نمایش تمام‌صفحه\",\n \"previewPopupReturnLabel\": \"بازگرداندن پیش‌نمایش به ویرایشگر\",\n \"downloadHtmlLabel\": \"دانلود HTML\",\n \"themeTrayAriaLabel\": \"تنظیمات تم\",\n \"tabConfigLabel\": \"پیکربندی\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"ارائه‌دهنده CDN\",\n \"localProviderLabel\": \"هیچ‌کدام (درون‌خطی)\",\n \"themeLabel\": \"تم\",\n \"appearanceLabel\": \"ظاهر\",\n \"appearanceLightLabel\": \"روشن\",\n \"appearanceDarkLabel\": \"تاریک\",\n \"themeCanvasLabel\": \"بوم\",\n \"themeCanvasHighContrastLabel\": \"بوم با کنتراست بالا\",\n \"includeDarkModeLabel\": \"شامل حالت تاریک\",\n \"colorLabel\": \"پالت رنگ\",\n \"colorNavyLabel\": \"سرمه‌ای\",\n \"colorBlueLabel\": \"آبی\",\n \"colorGreenLabel\": \"سبز\",\n \"colorRedLabel\": \"قرمز\",\n \"colorOrangeLabel\": \"نارنجی\",\n \"colorGreyLabel\": \"خاکستری\",\n \"colorPlumLabel\": \"آلوئی\",\n \"colorVioletLabel\": \"بنفش\",\n \"colorStoneLabel\": \"سنگی\",\n \"colorSkyLabel\": \"آسمانی\",\n \"colorHoneyLabel\": \"عسلی\",\n \"colorSeaLabel\": \"دریایی\",\n \"colorAuroraLabel\": \"شفق\",\n \"colorCustomLabel\": \"سفارشی\",\n \"customColorInputLabel\": \"رنگ برند (هگز)\",\n \"downloadCssLabel\": \"دانلود theme.css\",\n \"downloadJsLabel\": \"دانلود theme.js\",\n \"cssPanelHintLabel\": \"اینجا CSS سفارشی اضافه کنید — به generated theme.css افزوده می‌شود، هم در پیش‌نمایش و هم در دانلود.\",\n \"jsPanelHintLabel\": \"اینجا JS سفارشی اضافه کنید — به generated theme.js افزوده می‌شود، هم در پیش‌نمایش و هم در دانلود.\",\n \"helpModalTitle\": \"نحوه استفاده از این صفحه\",\n \"helpModalBody1\": \"یک قالب شروع انتخاب کنید، آن را مانند ویرایشگر محتوای غنی Canvas ویرایش کنید، سپس روی <strong>کپی HTML</strong> کلیک کرده و نتیجه را در یک صفحه Canvas جای‌گذاری کنید (ابتدا به نمای ویرایش HTML سوئیچ کنید). Canvas محتوای HTML الصاق‌شده را سمت سرور پاک‌سازی می‌کند — این پیش‌نمایش تلاش نمی‌کند آن را شبیه‌سازی کند؛ پس همیشه نتیجه الصاق‌شده را در Canvas بررسی کنید.\",\n \"helpModalBody2\": \"از <strong>ویرایش تم</strong> برای تغییر ارائه‌دهنده CDN، تم یا حالت و ویرایش دستی فایل‌های تولیدشده <code>theme.css</code>/<code>theme.js</code> قبل از دانلود استفاده کنید.\",\n \"closeLabel\": \"بستن\"\n },\n \"pl\": {\n \"pageTitle\": \"Tworzenie szablonów RCE\",\n \"pageDescription\": \"Twórz szablony stron Canvas RCE stylizowane za pomocą pantoken z podglądem na żywo.\",\n \"editThemeLabel\": \"Edytuj motyw\",\n \"layoutDirectionLabel\": \"Zmień orientację układu\",\n \"helpAriaLabel\": \"Pomoc\",\n \"appModeLabel\": \"Otwórz aplikację webową\",\n \"copyHtmlLabel\": \"Kopiuj HTML\",\n \"previewFrameTitle\": \"Stylizowany podgląd\",\n \"previewWidthLargeLabel\": \"Duży\",\n \"previewWidthMediumLabel\": \"Średni\",\n \"previewWidthSmallLabel\": \"Mały\",\n \"previewSchemeToggleLabel\": \"Podgląd trybu ciemnego\",\n \"previewPopupLabel\": \"Otwórz podgląd w wyskakującym oknie\",\n \"previewPopupTitle\": \"Podgląd zawartości kanwy\",\n \"previewPopupBlockedMessage\": \"Wyskakujące okno podglądu zostało zablokowane. Zezwól na wyskakujące okna dla tej witryny i spróbuj ponownie.\",\n \"previewFullscreenLabel\": \"Pokaż podgląd na pełnym ekranie\",\n \"previewPopupReturnLabel\": \"Przywróć podgląd do edytora\",\n \"downloadHtmlLabel\": \"Pobierz HTML\",\n \"themeTrayAriaLabel\": \"Ustawienia motywu\",\n \"tabConfigLabel\": \"Konfiguracja\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Dostawca CDN\",\n \"localProviderLabel\": \"Brak (w linii)\",\n \"themeLabel\": \"Motyw\",\n \"appearanceLabel\": \"Wygląd\",\n \"appearanceLightLabel\": \"Jasny\",\n \"appearanceDarkLabel\": \"Ciemny\",\n \"themeCanvasLabel\": \"Kanwa\",\n \"themeCanvasHighContrastLabel\": \"Kanwa (wysoki kontrast)\",\n \"includeDarkModeLabel\": \"Uwzględnij tryb ciemny\",\n \"colorLabel\": \"Schemat kolorów\",\n \"colorNavyLabel\": \"Granatowy\",\n \"colorBlueLabel\": \"Niebieski\",\n \"colorGreenLabel\": \"Zielony\",\n \"colorRedLabel\": \"Czerwony\",\n \"colorOrangeLabel\": \"Pomarańczowy\",\n \"colorGreyLabel\": \"Szary\",\n \"colorPlumLabel\": \"Śliwkowy\",\n \"colorVioletLabel\": \"Fioletowy\",\n \"colorStoneLabel\": \"Kamienny\",\n \"colorSkyLabel\": \"Błękitny\",\n \"colorHoneyLabel\": \"Miodowy\",\n \"colorSeaLabel\": \"Morski\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Niestandardowy\",\n \"customColorInputLabel\": \"Kolor marki (hex)\",\n \"downloadCssLabel\": \"Pobierz theme.css\",\n \"downloadJsLabel\": \"Pobierz theme.js\",\n \"cssPanelHintLabel\": \"Dodaj niestandardowy CSS tutaj — zostanie on dopisany do wygenerowanego theme.css, w podglądzie i w pobranym pliku.\",\n \"jsPanelHintLabel\": \"Dodaj niestandardowy JS tutaj — zostanie on dopisany do wygenerowanego theme.js, w podglądzie i w pobranym pliku.\",\n \"helpModalTitle\": \"Jak korzystać z tej strony\",\n \"helpModalBody1\": \"Wybierz szablon startowy, edytuj go jak w Canvas Rich Content Editor, następnie kliknij <strong>Kopiuj HTML</strong> i wklej wynik na stronę Canvas (najpierw przejdź do widoku edytora HTML). Canvas sanitizuje wklejany HTML po stronie serwera — ten podgląd tego nie naśladuje, więc zawsze zweryfikuj efekt w Canvas.\",\n \"helpModalBody2\": \"Użyj <strong>Edytuj motyw</strong>, aby zmienić dostawcę CDN, motyw lub tryb oraz ręcznie edytować wygenerowane <code>theme.css</code>/<code>theme.js</code> przed ich pobraniem.\",\n \"closeLabel\": \"Zamknij\"\n },\n \"pt\": {\n \"pageTitle\": \"Criação de templates RCE\",\n \"pageDescription\": \"Crie templates de página RCE do Canvas estilizados com pantoken, com pré-visualização ao vivo.\",\n \"editThemeLabel\": \"Editar tema\",\n \"layoutDirectionLabel\": \"Alternar orientação do layout\",\n \"helpAriaLabel\": \"Ajuda\",\n \"appModeLabel\": \"Abrir aplicativo web\",\n \"copyHtmlLabel\": \"Copiar HTML\",\n \"previewFrameTitle\": \"Pré-visualização estilizada\",\n \"previewWidthLargeLabel\": \"Grande\",\n \"previewWidthMediumLabel\": \"Médio\",\n \"previewWidthSmallLabel\": \"Pequeno\",\n \"previewSchemeToggleLabel\": \"Visualizar modo escuro\",\n \"previewPopupLabel\": \"Abrir visualização em um popup\",\n \"previewPopupTitle\": \"Pré-visualização do conteúdo do canvas\",\n \"previewPopupBlockedMessage\": \"O popup de visualização foi bloqueado. Permita popups para este site e tente novamente.\",\n \"previewFullscreenLabel\": \"Exibir visualização em tela cheia\",\n \"previewPopupReturnLabel\": \"Retornar visualização para o editor\",\n \"downloadHtmlLabel\": \"Baixar HTML\",\n \"themeTrayAriaLabel\": \"Configurações do tema\",\n \"tabConfigLabel\": \"Configuração\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Provedor CDN\",\n \"localProviderLabel\": \"Nenhum (inline)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Aparência\",\n \"appearanceLightLabel\": \"Claro\",\n \"appearanceDarkLabel\": \"Escuro\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas alto contraste\",\n \"includeDarkModeLabel\": \"Incluir modo escuro\",\n \"colorLabel\": \"Esquema de cores\",\n \"colorNavyLabel\": \"Azul-marinho\",\n \"colorBlueLabel\": \"Azul\",\n \"colorGreenLabel\": \"Verde\",\n \"colorRedLabel\": \"Vermelho\",\n \"colorOrangeLabel\": \"Laranja\",\n \"colorGreyLabel\": \"Cinza\",\n \"colorPlumLabel\": \"Ameixa\",\n \"colorVioletLabel\": \"Violeta\",\n \"colorStoneLabel\": \"Pedra\",\n \"colorSkyLabel\": \"Céu\",\n \"colorHoneyLabel\": \"Mel\",\n \"colorSeaLabel\": \"Mar\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Personalizado\",\n \"customColorInputLabel\": \"Cor da marca (hex)\",\n \"downloadCssLabel\": \"Baixar theme.css\",\n \"downloadJsLabel\": \"Baixar theme.js\",\n \"cssPanelHintLabel\": \"Adicione CSS personalizado aqui — ele é anexado ao generated theme.css, na visualização e no download.\",\n \"jsPanelHintLabel\": \"Adicione JS personalizado aqui — ele é anexado ao generated theme.js, na visualização e no download.\",\n \"helpModalTitle\": \"Como usar esta página\",\n \"helpModalBody1\": \"Escolha um template inicial, edite-o como faria no Rich Content Editor do Canvas e clique em <strong>Copiar HTML</strong>, então cole o resultado em uma página do Canvas (troque primeiro para a visualização do editor HTML). O Canvas sanitiza o HTML colado no servidor — esta pré-visualização não tenta replicar isso, portanto sempre verifique o resultado colado no Canvas.\",\n \"helpModalBody2\": \"Use <strong>Editar tema</strong> para alterar o provedor CDN, o tema ou o modo, e para editar manualmente o gerado <code>theme.css</code>/<code>theme.js</code> antes de baixá-los.\",\n \"closeLabel\": \"Fechar\"\n },\n \"pt-BR\": {\n \"pageTitle\": \"Criação de templates RCE\",\n \"pageDescription\": \"Crie templates de página RCE do Canvas estilizados com pantoken, com pré-visualização ao vivo.\",\n \"editThemeLabel\": \"Editar tema\",\n \"layoutDirectionLabel\": \"Alternar orientação do layout\",\n \"helpAriaLabel\": \"Ajuda\",\n \"appModeLabel\": \"Abrir aplicativo web\",\n \"copyHtmlLabel\": \"Copiar HTML\",\n \"previewFrameTitle\": \"Pré-visualização estilizada\",\n \"previewWidthLargeLabel\": \"Grande\",\n \"previewWidthMediumLabel\": \"Médio\",\n \"previewWidthSmallLabel\": \"Pequeno\",\n \"previewSchemeToggleLabel\": \"Visualizar modo escuro\",\n \"previewPopupLabel\": \"Abrir visualização em um popup\",\n \"previewPopupTitle\": \"Visualização do conteúdo do Canvas\",\n \"previewPopupBlockedMessage\": \"O popup de visualização foi bloqueado. Permita popups para este site e tente novamente.\",\n \"previewFullscreenLabel\": \"Mostrar visualização em tela cheia\",\n \"previewPopupReturnLabel\": \"Retornar visualização para o editor\",\n \"downloadHtmlLabel\": \"Baixar HTML\",\n \"themeTrayAriaLabel\": \"Configurações do tema\",\n \"tabConfigLabel\": \"Configuração\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Provedor CDN\",\n \"localProviderLabel\": \"Nenhum (inline)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Aparência\",\n \"appearanceLightLabel\": \"Claro\",\n \"appearanceDarkLabel\": \"Escuro\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas de alto contraste\",\n \"includeDarkModeLabel\": \"Incluir modo escuro\",\n \"colorLabel\": \"Esquema de cores\",\n \"colorNavyLabel\": \"Azul-marinho\",\n \"colorBlueLabel\": \"Azul\",\n \"colorGreenLabel\": \"Verde\",\n \"colorRedLabel\": \"Vermelho\",\n \"colorOrangeLabel\": \"Laranja\",\n \"colorGreyLabel\": \"Cinza\",\n \"colorPlumLabel\": \"Ameixa\",\n \"colorVioletLabel\": \"Violeta\",\n \"colorStoneLabel\": \"Pedra\",\n \"colorSkyLabel\": \"Céu\",\n \"colorHoneyLabel\": \"Mel\",\n \"colorSeaLabel\": \"Mar\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Personalizado\",\n \"customColorInputLabel\": \"Cor da marca (hex)\",\n \"downloadCssLabel\": \"Baixar theme.css\",\n \"downloadJsLabel\": \"Baixar theme.js\",\n \"cssPanelHintLabel\": \"Adicione CSS personalizado aqui — ele é anexado ao theme.css gerado, na visualização e no download.\",\n \"jsPanelHintLabel\": \"Adicione JS personalizado aqui — ele é anexado ao theme.js gerado, na visualização e no download.\",\n \"helpModalTitle\": \"Como usar esta página\",\n \"helpModalBody1\": \"Escolha um template inicial, edite-o como faria no Rich Content Editor do Canvas, então clique em <strong>Copiar HTML</strong> e cole o resultado em uma página do Canvas (mude para a visualização do editor HTML primeiro). O Canvas sanitiza o HTML colado no servidor — esta pré-visualização não tenta replicar isso, então sempre verifique o resultado colado no Canvas.\",\n \"helpModalBody2\": \"Use <strong>Editar tema</strong> para alterar o provedor CDN, o tema ou o modo, e para editar manualmente o <code>theme.css</code>/<code>theme.js</code> gerado antes de baixá-los.\",\n \"closeLabel\": \"Fechar\"\n },\n \"ru\": {\n \"pageTitle\": \"Создание шаблонов RCE\",\n \"pageDescription\": \"Создавайте шаблоны страниц Canvas RCE, стилизованные с помощью pantoken, с живым предварительным просмотром.\",\n \"editThemeLabel\": \"Редактировать тему\",\n \"layoutDirectionLabel\": \"Поменять ориентацию макета\",\n \"helpAriaLabel\": \"Справка\",\n \"appModeLabel\": \"Открыть веб-приложение\",\n \"copyHtmlLabel\": \"Копировать HTML\",\n \"previewFrameTitle\": \"Стилизация — предпросмотр\",\n \"previewWidthLargeLabel\": \"Большой\",\n \"previewWidthMediumLabel\": \"Средний\",\n \"previewWidthSmallLabel\": \"Маленький\",\n \"previewSchemeToggleLabel\": \"Предпросмотр тёмной темы\",\n \"previewPopupLabel\": \"Открыть предпросмотр в всплывающем окне\",\n \"previewPopupTitle\": \"Предпросмотр содержимого холста\",\n \"previewPopupBlockedMessage\": \"Всплывающее окно предпросмотра было заблокировано. Разрешите всплывающие окна для этого сайта и попробуйте снова.\",\n \"previewFullscreenLabel\": \"Показать предпросмотр на весь экран\",\n \"previewPopupReturnLabel\": \"Вернуть предпросмотр в редактор\",\n \"downloadHtmlLabel\": \"Скачать HTML\",\n \"themeTrayAriaLabel\": \"Настройки темы\",\n \"tabConfigLabel\": \"Конфигурация\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Провайдер CDN\",\n \"localProviderLabel\": \"Нет (встроенный)\",\n \"themeLabel\": \"Тема\",\n \"appearanceLabel\": \"Внешний вид\",\n \"appearanceLightLabel\": \"Светлая\",\n \"appearanceDarkLabel\": \"Тёмная\",\n \"themeCanvasLabel\": \"Холст\",\n \"themeCanvasHighContrastLabel\": \"Холст высокой контрастности\",\n \"includeDarkModeLabel\": \"Включить тёмную тему\",\n \"colorLabel\": \"Цветовая схема\",\n \"colorNavyLabel\": \"Тёмно-синий\",\n \"colorBlueLabel\": \"Синий\",\n \"colorGreenLabel\": \"Зелёный\",\n \"colorRedLabel\": \"Красный\",\n \"colorOrangeLabel\": \"Оранжевый\",\n \"colorGreyLabel\": \"Серый\",\n \"colorPlumLabel\": \"Сливовый\",\n \"colorVioletLabel\": \"Фиолетовый\",\n \"colorStoneLabel\": \"Каменный\",\n \"colorSkyLabel\": \"Небесный\",\n \"colorHoneyLabel\": \"Медовый\",\n \"colorSeaLabel\": \"Морской\",\n \"colorAuroraLabel\": \"Аврора\",\n \"colorCustomLabel\": \"Пользовательский\",\n \"customColorInputLabel\": \"Цвет бренда (hex)\",\n \"downloadCssLabel\": \"Скачать theme.css\",\n \"downloadJsLabel\": \"Скачать theme.js\",\n \"cssPanelHintLabel\": \"Добавьте здесь пользовательский CSS — он добавляется в сгенерированный theme.css, в предпросмотре и в скачиваемом файле.\",\n \"jsPanelHintLabel\": \"Добавьте здесь пользовательский JS — он добавляется в сгенерированный theme.js, в предпросмотре и в скачиваемом файле.\",\n \"helpModalTitle\": \"Как пользоваться этой страницей\",\n \"helpModalBody1\": \"Выберите стартовый шаблон, отредактируйте его как в Canvas Rich Content Editor, затем нажмите <strong>Копировать HTML</strong> и вставьте результат в страницу Canvas (сначала переключитесь в режим редактирования HTML). Canvas очищает вставляемый HTML на сервере — этот предпросмотр не пытается это воспроизвести, поэтому обязательно проверьте вставленный результат в Canvas.\",\n \"helpModalBody2\": \"Используйте <strong>Редактировать тему</strong>, чтобы изменить провайдера CDN, тему или режим, а также вручную отредактировать сгенерированные <code>theme.css</code>/<code>theme.js</code> перед их загрузкой.\",\n \"closeLabel\": \"Закрыть\"\n },\n \"zh-Hans\": {\n \"pageTitle\": \"RCE 模板创作\",\n \"pageDescription\": \"创作使用 pantoken 样式的 Canvas RCE 页面模板,并提供实时预览。\",\n \"editThemeLabel\": \"编辑主题\",\n \"layoutDirectionLabel\": \"切换布局方向\",\n \"helpAriaLabel\": \"帮助\",\n \"appModeLabel\": \"打开 Web 应用\",\n \"copyHtmlLabel\": \"复制 HTML\",\n \"previewFrameTitle\": \"样式化预览\",\n \"previewWidthLargeLabel\": \"大\",\n \"previewWidthMediumLabel\": \"中\",\n \"previewWidthSmallLabel\": \"小\",\n \"previewSchemeToggleLabel\": \"预览深色模式\",\n \"previewPopupLabel\": \"在弹出窗口中打开预览\",\n \"previewPopupTitle\": \"画布内容预览\",\n \"previewPopupBlockedMessage\": \"预览弹出窗口被阻止。允许此站点弹出窗口后重试。\",\n \"previewFullscreenLabel\": \"全屏显示预览\",\n \"previewPopupReturnLabel\": \"将预览返回到编辑器\",\n \"downloadHtmlLabel\": \"下载 HTML\",\n \"themeTrayAriaLabel\": \"主题设置\",\n \"tabConfigLabel\": \"配置\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN 提供商\",\n \"localProviderLabel\": \"无(内联)\",\n \"themeLabel\": \"主题\",\n \"appearanceLabel\": \"外观\",\n \"appearanceLightLabel\": \"亮色\",\n \"appearanceDarkLabel\": \"暗色\",\n \"themeCanvasLabel\": \"画布\",\n \"themeCanvasHighContrastLabel\": \"画布高对比\",\n \"includeDarkModeLabel\": \"包含深色模式\",\n \"colorLabel\": \"颜色方案\",\n \"colorNavyLabel\": \"藏青\",\n \"colorBlueLabel\": \"蓝色\",\n \"colorGreenLabel\": \"绿色\",\n \"colorRedLabel\": \"红色\",\n \"colorOrangeLabel\": \"橙色\",\n \"colorGreyLabel\": \"灰色\",\n \"colorPlumLabel\": \"梅紫\",\n \"colorVioletLabel\": \"紫罗兰\",\n \"colorStoneLabel\": \"石色\",\n \"colorSkyLabel\": \"天蓝\",\n \"colorHoneyLabel\": \"蜂蜜色\",\n \"colorSeaLabel\": \"海色\",\n \"colorAuroraLabel\": \"极光\",\n \"colorCustomLabel\": \"自定义\",\n \"customColorInputLabel\": \"品牌色(十六进制)\",\n \"downloadCssLabel\": \"下载 theme.css\",\n \"downloadJsLabel\": \"下载 theme.js\",\n \"cssPanelHintLabel\": \"在此添加自定义 CSS — 它将被附加到生成的 theme.css 中,在预览和下载中生效。\",\n \"jsPanelHintLabel\": \"在此添加自定义 JS — 它将被附加到生成的 theme.js 中,在预览和下载中生效。\",\n \"helpModalTitle\": \"如何使用此页面\",\n \"helpModalBody1\": \"选择一个入门模板,像在 Canvas 富文本编辑器中那样编辑,然后点击 <strong>复制 HTML</strong> 并将结果粘贴到 Canvas 页面(请先切换到 HTML 编辑视图)。Canvas 会在服务器端清理粘贴的 HTML——此预览不会尝试完全复现该行为,因此务必在 Canvas 中验证粘贴结果。\",\n \"helpModalBody2\": \"使用 <strong>编辑主题</strong> 可以更改 CDN 提供商、主题或模式,并在下载前手动编辑生成的 <code>theme.css</code>/<code>theme.js</code>。\",\n \"closeLabel\": \"关闭\"\n },\n \"sl\": {\n \"pageTitle\": \"Ustvarjanje RCE predlog\",\n \"pageDescription\": \"Ustvarjajte Canvas RCE predloge strani, oblikovane s pantokenom, z živim predogledom.\",\n \"editThemeLabel\": \"Uredi temo\",\n \"layoutDirectionLabel\": \"Preklopi usmerjenost postavitve\",\n \"helpAriaLabel\": \"Pomoč\",\n \"appModeLabel\": \"Odpri spletno aplikacijo\",\n \"copyHtmlLabel\": \"Kopiraj HTML\",\n \"previewFrameTitle\": \"Oblikovan predogled\",\n \"previewWidthLargeLabel\": \"Veliko\",\n \"previewWidthMediumLabel\": \"Srednje\",\n \"previewWidthSmallLabel\": \"Majhno\",\n \"previewSchemeToggleLabel\": \"Predogled temnega načina\",\n \"previewPopupLabel\": \"Odpri predogled v pojavnem oknu\",\n \"previewPopupTitle\": \"Predogled vsebine platna\",\n \"previewPopupBlockedMessage\": \"Pojavno okno s predogledom je bilo blokirano. Dovolite pojavna okna za to spletno mesto in poskusite znova.\",\n \"previewFullscreenLabel\": \"Pokaži predogled čez celoten zaslon\",\n \"previewPopupReturnLabel\": \"Vrni predogled v urejevalnik\",\n \"downloadHtmlLabel\": \"Prenesi HTML\",\n \"themeTrayAriaLabel\": \"Nastavitve teme\",\n \"tabConfigLabel\": \"Konfiguracija\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Ponudnik CDN\",\n \"localProviderLabel\": \"Brez (v vrstici)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Videz\",\n \"appearanceLightLabel\": \"Svetlo\",\n \"appearanceDarkLabel\": \"Temno\",\n \"themeCanvasLabel\": \"Platno\",\n \"themeCanvasHighContrastLabel\": \"Platno z visokim kontrastom\",\n \"includeDarkModeLabel\": \"Vključi temni način\",\n \"colorLabel\": \"Barvna shema\",\n \"colorNavyLabel\": \"Temno modra\",\n \"colorBlueLabel\": \"Modra\",\n \"colorGreenLabel\": \"Zelena\",\n \"colorRedLabel\": \"Rdeča\",\n \"colorOrangeLabel\": \"Oranžna\",\n \"colorGreyLabel\": \"Siva\",\n \"colorPlumLabel\": \"Šljivasta\",\n \"colorVioletLabel\": \"Vijolična\",\n \"colorStoneLabel\": \"Kamnata\",\n \"colorSkyLabel\": \"Nebesno modra\",\n \"colorHoneyLabel\": \"Medena\",\n \"colorSeaLabel\": \"Morska\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Po meri\",\n \"customColorInputLabel\": \"Barva blagovne znamke (hex)\",\n \"downloadCssLabel\": \"Prenesi theme.css\",\n \"downloadJsLabel\": \"Prenesi theme.js\",\n \"cssPanelHintLabel\": \"Add custom CSS here — it's appended to the generated theme.css, in the preview and the download.\",\n \"jsPanelHintLabel\": \"Add custom JS here — it's appended to the generated theme.js, in the preview and the download.\",\n \"helpModalTitle\": \"Kako uporabljati to stran\",\n \"helpModalBody1\": \"Izberite začetno predlogo, jo uredite, kot bi v Canvas Rich Content Editorju, nato kliknite <strong>Copy HTML</strong> in prilepite rezultat na Canvas stran (pred tem preklopite v pogled urejevalnika HTML). Canvas obdeluje prilepljen HTML na strežniku — ta predogled tega ne poskuša posnemati, zato vedno preverite prilepljen rezultat v Canvasu.\",\n \"helpModalBody2\": \"Uporabite <strong>Edit theme</strong> za spreminjanje ponudnika CDN, teme ali načina ter za ročno urejanje generiranih <code>theme.css</code>/<code>theme.js</code> pred prenosom.\",\n \"closeLabel\": \"Zapri\"\n },\n \"es\": {\n \"pageTitle\": \"Creación de plantillas RCE\",\n \"pageDescription\": \"Cree plantillas de páginas RCE de Canvas con estilo pantoken y vista previa en tiempo real.\",\n \"editThemeLabel\": \"Editar tema\",\n \"layoutDirectionLabel\": \"Cambiar orientación del diseño\",\n \"helpAriaLabel\": \"Ayuda\",\n \"appModeLabel\": \"Abrir aplicación web\",\n \"copyHtmlLabel\": \"Copiar HTML\",\n \"previewFrameTitle\": \"Vista previa con estilo\",\n \"previewWidthLargeLabel\": \"Grande\",\n \"previewWidthMediumLabel\": \"Mediano\",\n \"previewWidthSmallLabel\": \"Pequeño\",\n \"previewSchemeToggleLabel\": \"Previsualizar modo oscuro\",\n \"previewPopupLabel\": \"Abrir vista previa en una ventana emergente\",\n \"previewPopupTitle\": \"Vista previa del contenido del lienzo\",\n \"previewPopupBlockedMessage\": \"La ventana emergente de vista previa fue bloqueada. Permite ventanas emergentes para este sitio e inténtalo de nuevo.\",\n \"previewFullscreenLabel\": \"Mostrar vista previa en pantalla completa\",\n \"previewPopupReturnLabel\": \"Devolver la vista previa al editor\",\n \"downloadHtmlLabel\": \"Descargar HTML\",\n \"themeTrayAriaLabel\": \"Ajustes del tema\",\n \"tabConfigLabel\": \"Configuración\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Proveedor CDN\",\n \"localProviderLabel\": \"Ninguno (en línea)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Apariencia\",\n \"appearanceLightLabel\": \"Claro\",\n \"appearanceDarkLabel\": \"Oscuro\",\n \"themeCanvasLabel\": \"Lienzo\",\n \"themeCanvasHighContrastLabel\": \"Lienzo de alto contraste\",\n \"includeDarkModeLabel\": \"Incluir modo oscuro\",\n \"colorLabel\": \"Esquema de color\",\n \"colorNavyLabel\": \"Azul marino\",\n \"colorBlueLabel\": \"Azul\",\n \"colorGreenLabel\": \"Verde\",\n \"colorRedLabel\": \"Rojo\",\n \"colorOrangeLabel\": \"Naranja\",\n \"colorGreyLabel\": \"Gris\",\n \"colorPlumLabel\": \"Ciruela\",\n \"colorVioletLabel\": \"Violeta\",\n \"colorStoneLabel\": \"Piedra\",\n \"colorSkyLabel\": \"Cielo\",\n \"colorHoneyLabel\": \"Miel\",\n \"colorSeaLabel\": \"Mar\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Personalizado\",\n \"customColorInputLabel\": \"Color de la marca (hex)\",\n \"downloadCssLabel\": \"Descargar theme.css\",\n \"downloadJsLabel\": \"Descargar theme.js\",\n \"cssPanelHintLabel\": \"Añade CSS personalizado aquí — se añade al theme.css generado, en la vista previa y la descarga.\",\n \"jsPanelHintLabel\": \"Añade JS personalizado aquí — se añade al theme.js generado, en la vista previa y la descarga.\",\n \"helpModalTitle\": \"Cómo usar esta página\",\n \"helpModalBody1\": \"Elija una plantilla inicial, edítela como lo haría en el Rich Content Editor de Canvas, luego haga clic en <strong>Copy HTML</strong> y pegue el resultado en una página de Canvas (cambie primero a la vista del editor HTML). Canvas sanitiza el HTML pegado en el servidor — esta vista previa no intenta replicar eso, así que siempre verifique el resultado pegado en Canvas.\",\n \"helpModalBody2\": \"Use <strong>Edit theme</strong> para cambiar el proveedor CDN, el tema o el modo, y para editar manualmente los archivos generados <code>theme.css</code>/<code>theme.js</code> antes de descargarlos.\",\n \"closeLabel\": \"Cerrar\"\n },\n \"sv\": {\n \"pageTitle\": \"RCE-mallskapande\",\n \"pageDescription\": \"Skapa Canvas RCE-sidemallar stylade med pantoken, med en liveförhandsvisning.\",\n \"editThemeLabel\": \"Redigera tema\",\n \"layoutDirectionLabel\": \"Byt layoutorientering\",\n \"helpAriaLabel\": \"Hjälp\",\n \"appModeLabel\": \"Öppna webbapp\",\n \"copyHtmlLabel\": \"Kopiera HTML\",\n \"previewFrameTitle\": \"Stiliserad förhandsvisning\",\n \"previewWidthLargeLabel\": \"Stor\",\n \"previewWidthMediumLabel\": \"Mellan\",\n \"previewWidthSmallLabel\": \"Liten\",\n \"previewSchemeToggleLabel\": \"Förhandsgranska mörkt läge\",\n \"previewPopupLabel\": \"Öppna förhandsvisning i ett popup-fönster\",\n \"previewPopupTitle\": \"Förhandsvisning av canvasinnehåll\",\n \"previewPopupBlockedMessage\": \"Förhandsvisningspopupen blockerades. Tillåt popup-fönster för den här webbplatsen och försök igen.\",\n \"previewFullscreenLabel\": \"Visa förhandsvisning i helskärm\",\n \"previewPopupReturnLabel\": \"Återför förhandsvisningen till redigeraren\",\n \"downloadHtmlLabel\": \"Ladda ner HTML\",\n \"themeTrayAriaLabel\": \"Temainställningar\",\n \"tabConfigLabel\": \"Konfig\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN-leverantör\",\n \"localProviderLabel\": \"Ingen (inbäddad)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Utseende\",\n \"appearanceLightLabel\": \"Ljus\",\n \"appearanceDarkLabel\": \"Mörk\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas med hög kontrast\",\n \"includeDarkModeLabel\": \"Inkludera mörkt läge\",\n \"colorLabel\": \"Färgschema\",\n \"colorNavyLabel\": \"Marin\",\n \"colorBlueLabel\": \"Blå\",\n \"colorGreenLabel\": \"Grön\",\n \"colorRedLabel\": \"Röd\",\n \"colorOrangeLabel\": \"Orange\",\n \"colorGreyLabel\": \"Grå\",\n \"colorPlumLabel\": \"Plommon\",\n \"colorVioletLabel\": \"Violett\",\n \"colorStoneLabel\": \"Sten\",\n \"colorSkyLabel\": \"Himmelsblå\",\n \"colorHoneyLabel\": \"Honung\",\n \"colorSeaLabel\": \"Hav\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Anpassad\",\n \"customColorInputLabel\": \"Varumärkesfärg (hex)\",\n \"downloadCssLabel\": \"Ladda ner theme.css\",\n \"downloadJsLabel\": \"Ladda ner theme.js\",\n \"cssPanelHintLabel\": \"Lägg till egendefinierad CSS här — den läggs till i den genererade theme.css, i förhandsvisningen och i nedladdningen.\",\n \"jsPanelHintLabel\": \"Lägg till egendefinierad JS här — den läggs till i den genererade theme.js, i förhandsvisningen och i nedladdningen.\",\n \"helpModalTitle\": \"Hur man använder denna sida\",\n \"helpModalBody1\": \"Välj en startmall, redigera den som i Canvas Rich Content Editor, klicka sedan på <strong>Kopiera HTML</strong> och klistra in resultatet i en Canvas-sida (byt först till HTML-redigeraren). Canvas sanerar inklistrad HTML på serversidan — denna förhandsvisning efterliknar inte det, så verifiera alltid det inklistrade resultatet i Canvas.\",\n \"helpModalBody2\": \"Använd <strong>Redigera tema</strong> för att ändra CDN-leverantör, tema eller läge, och för att manuellt redigera den genererade <code>theme.css</code>/<code>theme.js</code> innan nedladdning.\",\n \"closeLabel\": \"Stäng\"\n },\n \"th\": {\n \"pageTitle\": \"การเขียนเทมเพลต RCE\",\n \"pageDescription\": \"เขียนเทมเพลตหน้า Canvas RCE ที่จัดสไตล์ด้วย pantoken พร้อมตัวอย่างแสดงผลสด.\",\n \"editThemeLabel\": \"แก้ไขธีม\",\n \"layoutDirectionLabel\": \"สลับทิศทางการจัดวาง\",\n \"helpAriaLabel\": \"ช่วยเหลือ\",\n \"appModeLabel\": \"เปิดเว็บแอป\",\n \"copyHtmlLabel\": \"คัดลอก HTML\",\n \"previewFrameTitle\": \"ตัวอย่างที่จัดสไตล์\",\n \"previewWidthLargeLabel\": \"ใหญ่\",\n \"previewWidthMediumLabel\": \"กลาง\",\n \"previewWidthSmallLabel\": \"เล็ก\",\n \"previewSchemeToggleLabel\": \"แสดงตัวอย่างโหมดมืด\",\n \"previewPopupLabel\": \"เปิดตัวอย่างในป๊อปอัพ\",\n \"previewPopupTitle\": \"ตัวอย่างเนื้อหาแคนวาส\",\n \"previewPopupBlockedMessage\": \"ป๊อปอัพการแสดงตัวอย่างถูกบล็อก โปรดอนุญาตป๊อปอัพสำหรับไซต์นี้แล้วลองอีกครั้ง.\",\n \"previewFullscreenLabel\": \"แสดงตัวอย่างแบบเต็มหน้าจอ\",\n \"previewPopupReturnLabel\": \"คืนการแสดงตัวอย่างกลับไปยังตัวแก้ไข\",\n \"downloadHtmlLabel\": \"ดาวน์โหลด HTML\",\n \"themeTrayAriaLabel\": \"การตั้งค่าธีม\",\n \"tabConfigLabel\": \"การกำหนดค่า\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"ผู้ให้บริการ CDN\",\n \"localProviderLabel\": \"ไม่มี (อินไลน์)\",\n \"themeLabel\": \"ธีม\",\n \"appearanceLabel\": \"ลักษณะ\",\n \"appearanceLightLabel\": \"สว่าง\",\n \"appearanceDarkLabel\": \"มืด\",\n \"themeCanvasLabel\": \"แคนวาส\",\n \"themeCanvasHighContrastLabel\": \"แคนวาสความเปรียบต่างสูง\",\n \"includeDarkModeLabel\": \"รวมโหมดมืด\",\n \"colorLabel\": \"ชุดสี\",\n \"colorNavyLabel\": \"กรมท่า\",\n \"colorBlueLabel\": \"น้ำเงิน\",\n \"colorGreenLabel\": \"เขียว\",\n \"colorRedLabel\": \"แดง\",\n \"colorOrangeLabel\": \"ส้ม\",\n \"colorGreyLabel\": \"เทา\",\n \"colorPlumLabel\": \"พลัม\",\n \"colorVioletLabel\": \"ม่วง\",\n \"colorStoneLabel\": \"หิน\",\n \"colorSkyLabel\": \"ฟ้า\",\n \"colorHoneyLabel\": \"น้ำผึ้ง\",\n \"colorSeaLabel\": \"ทะเล\",\n \"colorAuroraLabel\": \"ออโรร่า\",\n \"colorCustomLabel\": \"กำหนดเอง\",\n \"customColorInputLabel\": \"สีแบรนด์ (hex)\",\n \"downloadCssLabel\": \"ดาวน์โหลด theme.css\",\n \"downloadJsLabel\": \"ดาวน์โหลด theme.js\",\n \"cssPanelHintLabel\": \"เพิ่ม CSS แบบกำหนดเองที่นี่ — จะถูกต่อท้ายไปยังไฟล์ theme.css ที่สร้างขึ้น, ในตัวอย่างและในการดาวน์โหลด.\",\n \"jsPanelHintLabel\": \"เพิ่ม JS แบบกำหนดเองที่นี่ — จะถูกต่อท้ายไปยังไฟล์ theme.js ที่สร้างขึ้น, ในตัวอย่างและในการดาวน์โหลด.\",\n \"helpModalTitle\": \"วิธีใช้หน้านี้\",\n \"helpModalBody1\": \"เลือกเทมเพลตเริ่มต้น แก้ไขเหมือนที่ทำใน Canvas Rich Content Editor แล้วคลิก <strong>คัดลอก HTML</strong> และนำผลลัพธ์ไปวางในหน้า Canvas (สลับไปที่มุมมอง HTML editor ก่อน). Canvas จะ sanitize HTML บนเซิร์ฟเวอร์ — ตัวอย่างนี้ไม่ได้จำลองพฤติกรรมดังกล่าว จึงควรตรวจสอบผลลัพธ์ที่วางใน Canvas เสมอ.\",\n \"helpModalBody2\": \"ใช้ <strong>แก้ไขธีม</strong> เพื่อเปลี่ยนผู้ให้บริการ CDN, ธีม หรือโหมด และแก้ไข <code>theme.css</code>/<code>theme.js</code> ที่สร้างขึ้นด้วยตนเองก่อนดาวน์โหลด.\",\n \"closeLabel\": \"ปิด\"\n },\n \"zh-Hant\": {\n \"pageTitle\": \"RCE 範本撰寫\",\n \"pageDescription\": \"撰寫使用 pantoken 樣式的 Canvas RCE 頁面範本,並提供即時預覽。\",\n \"editThemeLabel\": \"編輯主題\",\n \"layoutDirectionLabel\": \"切換佈局方向\",\n \"helpAriaLabel\": \"說明\",\n \"appModeLabel\": \"開啟網頁應用程式\",\n \"copyHtmlLabel\": \"複製 HTML\",\n \"previewFrameTitle\": \"樣式化預覽\",\n \"previewWidthLargeLabel\": \"大\",\n \"previewWidthMediumLabel\": \"中\",\n \"previewWidthSmallLabel\": \"小\",\n \"previewSchemeToggleLabel\": \"預覽深色模式\",\n \"previewPopupLabel\": \"在彈出視窗中開啟預覽\",\n \"previewPopupTitle\": \"畫布內容預覽\",\n \"previewPopupBlockedMessage\": \"預覽彈出視窗已被阻擋。請允許此網站的彈出視窗後再試一次。\",\n \"previewFullscreenLabel\": \"以全螢幕顯示預覽\",\n \"previewPopupReturnLabel\": \"將預覽返回編輯器\",\n \"downloadHtmlLabel\": \"下載 HTML\",\n \"themeTrayAriaLabel\": \"主題設定\",\n \"tabConfigLabel\": \"設定\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN 提供者\",\n \"localProviderLabel\": \"無(內嵌)\",\n \"themeLabel\": \"主題\",\n \"appearanceLabel\": \"外觀\",\n \"appearanceLightLabel\": \"淺色\",\n \"appearanceDarkLabel\": \"深色\",\n \"themeCanvasLabel\": \"畫布\",\n \"themeCanvasHighContrastLabel\": \"畫布(高對比)\",\n \"includeDarkModeLabel\": \"包含深色模式\",\n \"colorLabel\": \"配色方案\",\n \"colorNavyLabel\": \"藏青\",\n \"colorBlueLabel\": \"藍色\",\n \"colorGreenLabel\": \"綠色\",\n \"colorRedLabel\": \"紅色\",\n \"colorOrangeLabel\": \"橙色\",\n \"colorGreyLabel\": \"灰色\",\n \"colorPlumLabel\": \"梅紫\",\n \"colorVioletLabel\": \"紫羅蘭\",\n \"colorStoneLabel\": \"石色\",\n \"colorSkyLabel\": \"天藍\",\n \"colorHoneyLabel\": \"蜂蜜色\",\n \"colorSeaLabel\": \"海色\",\n \"colorAuroraLabel\": \"極光\",\n \"colorCustomLabel\": \"自訂\",\n \"customColorInputLabel\": \"品牌顏色 (十六進位)\",\n \"downloadCssLabel\": \"下載 theme.css\",\n \"downloadJsLabel\": \"下載 theme.js\",\n \"cssPanelHintLabel\": \"在此新增自訂 CSS — 會附加到生成的 theme.css 中,並會出現在預覽與下載中。\",\n \"jsPanelHintLabel\": \"在此新增自訂 JS — 會附加到生成的 theme.js 中,並會出現在預覽與下載中。\",\n \"helpModalTitle\": \"如何使用此頁面\",\n \"helpModalBody1\": \"選擇一個起始範本,像在 Canvas 富文本編輯器中編輯,然後點選 <strong>複製 HTML</strong> 並將結果貼到 Canvas 頁面(先切換到 HTML 編輯檢視)。Canvas 會在伺服器端清理貼上的 HTML — 此預覽不會嘗試複製該流程,請務必在 Canvas 中驗證貼上的結果。\",\n \"helpModalBody2\": \"使用 <strong>編輯主題</strong> 來變更 CDN 提供者、主題或模式,並在下載前手動編輯產生的 <code>theme.css</code>/<code>theme.js</code>。\",\n \"closeLabel\": \"關閉\"\n },\n \"tr\": {\n \"pageTitle\": \"RCE şablon hazırlama\",\n \"pageDescription\": \"Pantoken ile stil verilmiş Canvas RCE sayfa şablonları hazırlayın; canlı önizleme içerir.\",\n \"editThemeLabel\": \"Temayı düzenle\",\n \"layoutDirectionLabel\": \"Düzen yönünü değiştir\",\n \"helpAriaLabel\": \"Yardım\",\n \"appModeLabel\": \"Web uygulamasını aç\",\n \"copyHtmlLabel\": \"HTML'i kopyala\",\n \"previewFrameTitle\": \"Stil verilmiş önizleme\",\n \"previewWidthLargeLabel\": \"Büyük\",\n \"previewWidthMediumLabel\": \"Orta\",\n \"previewWidthSmallLabel\": \"Küçük\",\n \"previewSchemeToggleLabel\": \"Karanlık modu önizle\",\n \"previewPopupLabel\": \"Önizlemeyi açılır pencerede aç\",\n \"previewPopupTitle\": \"Tuval içerik önizlemesi\",\n \"previewPopupBlockedMessage\": \"Önizleme açılır penceresi engellendi. Bu site için açılır pencerelere izin verin ve tekrar deneyin.\",\n \"previewFullscreenLabel\": \"Önizlemeyi tam ekranda göster\",\n \"previewPopupReturnLabel\": \"Önizlemeyi düzenleyiciye geri getir\",\n \"downloadHtmlLabel\": \"HTML indir\",\n \"themeTrayAriaLabel\": \"Tema ayarları\",\n \"tabConfigLabel\": \"Yapılandırma\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN sağlayıcısı\",\n \"localProviderLabel\": \"Yok (satır içi)\",\n \"themeLabel\": \"Tema\",\n \"appearanceLabel\": \"Görünüm\",\n \"appearanceLightLabel\": \"Açık\",\n \"appearanceDarkLabel\": \"Koyu\",\n \"themeCanvasLabel\": \"Tuval\",\n \"themeCanvasHighContrastLabel\": \"Tuval yüksek kontrast\",\n \"includeDarkModeLabel\": \"Karanlık modu dahil et\",\n \"colorLabel\": \"Renk düzeni\",\n \"colorNavyLabel\": \"Lacivert\",\n \"colorBlueLabel\": \"Mavi\",\n \"colorGreenLabel\": \"Yeşil\",\n \"colorRedLabel\": \"Kırmızı\",\n \"colorOrangeLabel\": \"Turuncu\",\n \"colorGreyLabel\": \"Gri\",\n \"colorPlumLabel\": \"Eflatun\",\n \"colorVioletLabel\": \"Eflatun\",\n \"colorStoneLabel\": \"Taş\",\n \"colorSkyLabel\": \"Gökyüzü\",\n \"colorHoneyLabel\": \"Bal\",\n \"colorSeaLabel\": \"Deniz\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Özel\",\n \"customColorInputLabel\": \"Marka rengi (hex)\",\n \"downloadCssLabel\": \"theme.css indir\",\n \"downloadJsLabel\": \"theme.js indir\",\n \"cssPanelHintLabel\": \"Özel CSS'i buraya ekleyin — oluşturulan theme.css'e eklenir, önizlemede ve indirmede yer alır.\",\n \"jsPanelHintLabel\": \"Özel JS'i buraya ekleyin — oluşturulan theme.js'e eklenir, önizlemede ve indirmede yer alır.\",\n \"helpModalTitle\": \"Bu sayfa nasıl kullanılır\",\n \"helpModalBody1\": \"Bir başlangıç şablonu seçin, Canvas Zengin İçerik Düzenleyicisindeymiş gibi düzenleyin, ardından <strong>HTML'i kopyala</strong>'ya tıklayın ve sonucu bir Canvas sayfasına yapıştırın (önce HTML düzenleyici görünümüne geçin). Canvas, yapıştırılan HTML'i sunucu tarafında temizler — bu önizleme bunu taklit etmeye çalışmaz; bu yüzden yapıştırılan sonucu Canvas'ta her zaman doğrulayın.\",\n \"helpModalBody2\": \"<strong>Temayı düzenle</strong>'yi kullanarak CDN sağlayıcısını, temayı veya modu değiştirin ve indirmeden önce oluşturulan <code>theme.css</code>/<code>theme.js</code>'i elle düzenleyin.\",\n \"closeLabel\": \"Kapat\"\n },\n \"uk\": {\n \"pageTitle\": \"Авторинг шаблонів RCE\",\n \"pageDescription\": \"Створюйте шаблони сторінок Canvas RCE, стилізовані за допомогою pantoken, з живим попереднім переглядом.\",\n \"editThemeLabel\": \"Редагувати тему\",\n \"layoutDirectionLabel\": \"Змінити орієнтацію макета\",\n \"helpAriaLabel\": \"Допомога\",\n \"appModeLabel\": \"Відкрити веб-застосунок\",\n \"copyHtmlLabel\": \"Копіювати HTML\",\n \"previewFrameTitle\": \"Стилізований попередній перегляд\",\n \"previewWidthLargeLabel\": \"Великий\",\n \"previewWidthMediumLabel\": \"Середній\",\n \"previewWidthSmallLabel\": \"Малий\",\n \"previewSchemeToggleLabel\": \"Попередній перегляд темного режиму\",\n \"previewPopupLabel\": \"Відкрити попередній перегляд у спливаючому вікні\",\n \"previewPopupTitle\": \"Попередній перегляд вмісту полотна\",\n \"previewPopupBlockedMessage\": \"Спливаюче вікно попереднього перегляду було заблоковано. Дозвольте спливаючі вікна для цього сайту та спробуйте знову.\",\n \"previewFullscreenLabel\": \"Показати попередній перегляд на весь екран\",\n \"previewPopupReturnLabel\": \"Повернути попередній перегляд у редактор\",\n \"downloadHtmlLabel\": \"Завантажити HTML\",\n \"themeTrayAriaLabel\": \"Налаштування теми\",\n \"tabConfigLabel\": \"Конфіг\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Постачальник CDN\",\n \"localProviderLabel\": \"Немає (вбудовано)\",\n \"themeLabel\": \"Тема\",\n \"appearanceLabel\": \"Вигляд\",\n \"appearanceLightLabel\": \"Світла\",\n \"appearanceDarkLabel\": \"Темна\",\n \"themeCanvasLabel\": \"Полотно\",\n \"themeCanvasHighContrastLabel\": \"Полотно з високою контрастністю\",\n \"includeDarkModeLabel\": \"Включити темний режим\",\n \"colorLabel\": \"Кольорова схема\",\n \"colorNavyLabel\": \"Темно-синій\",\n \"colorBlueLabel\": \"Синій\",\n \"colorGreenLabel\": \"Зелений\",\n \"colorRedLabel\": \"Червоний\",\n \"colorOrangeLabel\": \"Оранжевий\",\n \"colorGreyLabel\": \"Сірий\",\n \"colorPlumLabel\": \"Сливовий\",\n \"colorVioletLabel\": \"Фіолетовий\",\n \"colorStoneLabel\": \"Кам'яний\",\n \"colorSkyLabel\": \"Небесний\",\n \"colorHoneyLabel\": \"Медовий\",\n \"colorSeaLabel\": \"Морський\",\n \"colorAuroraLabel\": \"Аврора\",\n \"colorCustomLabel\": \"Користувацький\",\n \"customColorInputLabel\": \"Фірмовий колір (hex)\",\n \"downloadCssLabel\": \"Завантажити theme.css\",\n \"downloadJsLabel\": \"Завантажити theme.js\",\n \"cssPanelHintLabel\": \"Додайте тут користувацький CSS — він додається в кінець згенерованого theme.css, у попередньому перегляді та в завантаженні.\",\n \"jsPanelHintLabel\": \"Додайте тут користувацький JS — він додається в кінець згенерованого theme.js, у попередньому перегляді та в завантаженні.\",\n \"helpModalTitle\": \"Як користуватися цією сторінкою\",\n \"helpModalBody1\": \"Оберіть стартовий шаблон, редагуйте його як у Canvas Rich Content Editor, потім натисніть <strong>Копіювати HTML</strong> і вставте результат у сторінку Canvas (спочатку переключіться в HTML‑редактор). Canvas очищує вставлений HTML на боці сервера — цей попередній перегляд цього не імітує, тому завжди перевіряйте вставлений результат у Canvas.\",\n \"helpModalBody2\": \"Використовуйте <strong>Редагувати тему</strong>, щоб змінити CDN‑провайдера, тему або режим, а також вручну відредагувати згенеровані <code>theme.css</code>/<code>theme.js</code> перед їхнім завантаженням.\",\n \"closeLabel\": \"Закрити\"\n },\n \"vi\": {\n \"pageTitle\": \"Soạn mẫu RCE\",\n \"pageDescription\": \"Soạn mẫu trang Canvas RCE được style bằng pantoken, kèm bản xem trước trực tiếp.\",\n \"editThemeLabel\": \"Chỉnh sửa theme\",\n \"layoutDirectionLabel\": \"Chuyển hướng bố cục\",\n \"helpAriaLabel\": \"Trợ giúp\",\n \"appModeLabel\": \"Mở ứng dụng web\",\n \"copyHtmlLabel\": \"Sao chép HTML\",\n \"previewFrameTitle\": \"Bản xem trước đã style\",\n \"previewWidthLargeLabel\": \"Lớn\",\n \"previewWidthMediumLabel\": \"Vừa\",\n \"previewWidthSmallLabel\": \"Nhỏ\",\n \"previewSchemeToggleLabel\": \"Xem trước chế độ tối\",\n \"previewPopupLabel\": \"Mở xem trước trong cửa sổ bật lên\",\n \"previewPopupTitle\": \"Xem trước nội dung Canvas\",\n \"previewPopupBlockedMessage\": \"Cửa sổ xem trước đã bị chặn. Cho phép cửa sổ bật lên cho trang này và thử lại.\",\n \"previewFullscreenLabel\": \"Hiển thị xem trước toàn màn hình\",\n \"previewPopupReturnLabel\": \"Trả xem trước về trình soạn thảo\",\n \"downloadHtmlLabel\": \"Tải xuống HTML\",\n \"themeTrayAriaLabel\": \"Cài đặt theme\",\n \"tabConfigLabel\": \"Cấu hình\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Nhà cung cấp CDN\",\n \"localProviderLabel\": \"Không (nội tuyến)\",\n \"themeLabel\": \"Giao diện\",\n \"appearanceLabel\": \"Giao diện\",\n \"appearanceLightLabel\": \"Sáng\",\n \"appearanceDarkLabel\": \"Tối\",\n \"themeCanvasLabel\": \"Canvas\",\n \"themeCanvasHighContrastLabel\": \"Canvas độ tương phản cao\",\n \"includeDarkModeLabel\": \"Bao gồm chế độ tối\",\n \"colorLabel\": \"Bảng màu\",\n \"colorNavyLabel\": \"Xanh hải quân\",\n \"colorBlueLabel\": \"Xanh dương\",\n \"colorGreenLabel\": \"Xanh lá\",\n \"colorRedLabel\": \"Đỏ\",\n \"colorOrangeLabel\": \"Cam\",\n \"colorGreyLabel\": \"Xám\",\n \"colorPlumLabel\": \"Mận\",\n \"colorVioletLabel\": \"Tím\",\n \"colorStoneLabel\": \"Đá\",\n \"colorSkyLabel\": \"Bầu trời\",\n \"colorHoneyLabel\": \"Mật ong\",\n \"colorSeaLabel\": \"Biển\",\n \"colorAuroraLabel\": \"Cực quang\",\n \"colorCustomLabel\": \"Tùy chỉnh\",\n \"customColorInputLabel\": \"Màu thương hiệu (hex)\",\n \"downloadCssLabel\": \"Tải xuống theme.css\",\n \"downloadJsLabel\": \"Tải xuống theme.js\",\n \"cssPanelHintLabel\": \"Thêm CSS tùy chỉnh tại đây — nó được nối vào theme.css được tạo, trong phần xem trước và tệp tải xuống.\",\n \"jsPanelHintLabel\": \"Thêm JS tùy chỉnh tại đây — nó được nối vào theme.js được tạo, trong phần xem trước và tệp tải xuống.\",\n \"helpModalTitle\": \"Cách sử dụng trang này\",\n \"helpModalBody1\": \"Chọn mẫu bắt đầu, chỉnh sửa giống như trong Canvas Rich Content Editor, rồi nhấp <strong>Sao chép HTML</strong> và dán vào trang Canvas (chuyển sang chế độ trình chỉnh sửa HTML trước). Canvas sẽ làm sạch HTML ở phía máy chủ — bản xem trước này không mô phỏng bước đó, nên luôn kiểm tra kết quả đã dán trong Canvas.\",\n \"helpModalBody2\": \"Dùng <strong>Chỉnh sửa theme</strong> để thay đổi nhà cung cấp CDN, theme, hoặc chế độ, và chỉnh tay <code>theme.css</code>/<code>theme.js</code> trước khi tải xuống.\",\n \"closeLabel\": \"Đóng\"\n },\n \"cy\": {\n \"pageTitle\": \"Awdurdod templedi RCE\",\n \"pageDescription\": \"Awdurdewch dempledi tudalen Canvas RCE wedi'u steilio gyda pantoken, gyda rhagolwg byw.\",\n \"editThemeLabel\": \"Golygu thema\",\n \"layoutDirectionLabel\": \"Newid orientiad y cynllun\",\n \"helpAriaLabel\": \"Cymorth\",\n \"appModeLabel\": \"Agor yr ap gwe\",\n \"copyHtmlLabel\": \"Copïo HTML\",\n \"previewFrameTitle\": \"Rhagolwg wedi'i steilio\",\n \"previewWidthLargeLabel\": \"Mawr\",\n \"previewWidthMediumLabel\": \"Canolig\",\n \"previewWidthSmallLabel\": \"Bach\",\n \"previewSchemeToggleLabel\": \"Rhagolwg ar fodd tywyll\",\n \"previewPopupLabel\": \"Agor y rhagolwg mewn pop-up\",\n \"previewPopupTitle\": \"Rhagolwg cynnwys canfas\",\n \"previewPopupBlockedMessage\": \"Cafodd y pop-up rhagolwg ei rwystro. Caniatewch pop-ups ar gyfer y safle hwn a cheisiwch eto.\",\n \"previewFullscreenLabel\": \"Dangos rhagolwg yn sgrin lawn\",\n \"previewPopupReturnLabel\": \"Dychwelyd y rhagolwg i'r golygydd\",\n \"downloadHtmlLabel\": \"Lawrlwytho HTML\",\n \"themeTrayAriaLabel\": \"Gosodiadau thema\",\n \"tabConfigLabel\": \"Ffurfweddiad\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"Darparwr CDN\",\n \"localProviderLabel\": \"Dim (mewnlin)\",\n \"themeLabel\": \"Thema\",\n \"appearanceLabel\": \"Ymddangosiad\",\n \"appearanceLightLabel\": \"Ysgafn\",\n \"appearanceDarkLabel\": \"Tywyll\",\n \"themeCanvasLabel\": \"Canfas\",\n \"themeCanvasHighContrastLabel\": \"Canfas gyda chyferbyniad uchel\",\n \"includeDarkModeLabel\": \"Cynnwys modd tywyll\",\n \"colorLabel\": \"Cynllun lliw\",\n \"colorNavyLabel\": \"Las llynges\",\n \"colorBlueLabel\": \"Glas\",\n \"colorGreenLabel\": \"Gwyrdd\",\n \"colorRedLabel\": \"Coch\",\n \"colorOrangeLabel\": \"Oren\",\n \"colorGreyLabel\": \"Llwyd\",\n \"colorPlumLabel\": \"Plwm\",\n \"colorVioletLabel\": \"Fioled\",\n \"colorStoneLabel\": \"Carreg\",\n \"colorSkyLabel\": \"Awyr\",\n \"colorHoneyLabel\": \"Mêl\",\n \"colorSeaLabel\": \"Môr\",\n \"colorAuroraLabel\": \"Aurora\",\n \"colorCustomLabel\": \"Personol\",\n \"customColorInputLabel\": \"Lliw brand (hex)\",\n \"downloadCssLabel\": \"Lawrlwytho theme.css\",\n \"downloadJsLabel\": \"Lawrlwytho theme.js\",\n \"cssPanelHintLabel\": \"Ychwanegu CSS wedi'i addasu yma — fe'i ychwanegir at y theme.css a gynhyrchir, yn y rhagolwg ac yn y lawrlwythiad.\",\n \"jsPanelHintLabel\": \"Ychwanegu JS wedi'i addasu yma — fe'i ychwanegir at y theme.js a gynhyrchir, yn y rhagolwg ac yn y lawrlwythiad.\",\n \"helpModalTitle\": \"Sut i ddefnyddio'r dudalen hon\",\n \"helpModalBody1\": \"Dewiswch dempled cychwyn, golygu ef fel pe baech yn y Canvas Rich Content Editor, yna clicio <strong>Copïo HTML</strong> a gludo'r canlyniad i dudalen Canvas (newid i olygydd HTML yn gyntaf). Mae Canvas yn glanhau HTML a gludir ar y gweinydd — nid yw'r rhagolwg hwn yn ceisio efelychu hynny, felly gwirio bob amser y canlyniad a gludir yn Canvas.\",\n \"helpModalBody2\": \"Defnyddiwch <strong>Golygu thema</strong> i newid y darparwr CDN, y thema neu'r modd, ac i olygu'r <code>theme.css</code>/<code>theme.js</code> a gynhyrchir yn llaw cyn eu lawrlwytho.\",\n \"closeLabel\": \"Cau\"\n }\n};\n",
38
41
  "src/locale-dirs.ts": "// GENERATED by scripts/generate.ts — do not edit by hand.\n/** Text direction per supported BCP47 tag. */\nexport const LOCALE_DIRS: Record<string, \"ltr\" | \"rtl\"> = {\n \"ar\": \"rtl\",\n \"hy\": \"ltr\",\n \"ca\": \"ltr\",\n \"da\": \"ltr\",\n \"nl\": \"ltr\",\n \"en-AU\": \"ltr\",\n \"en-CA\": \"ltr\",\n \"en-GB\": \"ltr\",\n \"en\": \"ltr\",\n \"fi\": \"ltr\",\n \"fr\": \"ltr\",\n \"fr-CA\": \"ltr\",\n \"ga\": \"ltr\",\n \"de\": \"ltr\",\n \"el\": \"ltr\",\n \"ht\": \"ltr\",\n \"he\": \"rtl\",\n \"hi\": \"ltr\",\n \"hu\": \"ltr\",\n \"is\": \"ltr\",\n \"id\": \"ltr\",\n \"it\": \"ltr\",\n \"ja\": \"ltr\",\n \"ko\": \"ltr\",\n \"mi\": \"ltr\",\n \"ms\": \"ltr\",\n \"se\": \"ltr\",\n \"nb\": \"ltr\",\n \"nn\": \"ltr\",\n \"fa\": \"rtl\",\n \"pl\": \"ltr\",\n \"pt\": \"ltr\",\n \"pt-BR\": \"ltr\",\n \"ru\": \"ltr\",\n \"zh-Hans\": \"ltr\",\n \"sl\": \"ltr\",\n \"es\": \"ltr\",\n \"sv\": \"ltr\",\n \"th\": \"ltr\",\n \"zh-Hant\": \"ltr\",\n \"tr\": \"ltr\",\n \"uk\": \"ltr\",\n \"vi\": \"ltr\",\n \"cy\": \"ltr\"\n};\n",
39
42
  "src/tinymce-locale-strings.ts": "// GENERATED by scripts/generate.ts — do not edit by hand.\n/** Translated TinyMCE plugin strings; missing entries use the plugins' English defaults. */\nexport const TINYMCE_LOCALE_STRINGS: Record<string, Record<string, string>> = {\n \"ar\": {\n \"autocompleteModifierDetail\": \"modifier\",\n \"classValidationIncompleteComponent\": \"اسم المكون غير مكتمل بعد '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"يجب أن يبدأ الرمز بـ '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"مكون/أداة غير معروفة: '{{componentName}}'\",\n \"componentsDialogTitle\": \"إدراج مكوّن\",\n \"componentsListLabel\": \"مكونات\",\n \"componentsMenuText\": \"مكوّن\",\n \"componentsToolbarText\": \"مكونات\",\n \"componentsToolbarTooltip\": \"إدراج مكوّن pantoken\",\n \"componentModifiersDefault\": \"افتراضي\",\n \"componentModifiersOptions\": \"خيارات\",\n \"componentModifiersTooltip\": \"تغيير معدِّلات المكوّن\",\n \"componentModifiersUtilities\": \"الأدوات\",\n \"iconLabelDialogTitle\": \"تسمية الأيقونة\",\n \"iconLabelInputLabel\": \"تسمية لقارئ الشاشة\",\n \"iconsMenuText\": \"أيقونة\",\n \"iconsSearchPlaceholder\": \"البحث عن الأيقونات…\",\n \"iconsSearchLabel\": \"ابحث عن الأيقونات\",\n \"iconsAllSources\": \"الكل\",\n \"iconsResultCount\": \"{{count}} أيقونات\",\n \"iconsNoResults\": \"لا توجد أيقونات تطابق بحثك.\",\n \"iconsToolbarText\": \"أيقونات\",\n \"iconsToolbarTooltip\": \"إدراج أيقونة\",\n \"iconContextSizeSmall\": \"صغير\",\n \"iconContextSizeMedium\": \"متوسط\",\n \"iconContextSizeLarge\": \"كبير\",\n \"iconContextSizeExtraLarge\": \"كبير جدًا\",\n \"layoutsConfirmReplace\": \"استبدال المحتوى الحالي بتخطيط \\\"{{title}}\\\"؟\",\n \"layoutsDialogTitle\": \"إدراج تخطيط\",\n \"layoutsMenuText\": \"تخطيط…\",\n \"layoutsSelectLabel\": \"تخطيط مبدئي\",\n \"layoutsToolbarText\": \"تخطيطات\",\n \"layoutsToolbarTooltip\": \"إدراج تخطيط مبدئي\",\n \"logosToolbarText\": \"شعارات\",\n \"logosToolbarTooltip\": \"إدراج شعار\",\n \"logosMenuText\": \"شعار\",\n \"logosDialogTitle\": \"إدراج شعار\",\n \"insertButton\": \"إدراج\",\n \"replaceButton\": \"استبدال\",\n \"cancelButton\": \"إلغاء\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"استبدال المحتوى الحالي بالقالب \\\"{{title}}\\\"؟\",\n \"templatesDialogTitle\": \"إدراج قالب\",\n \"templatesMenuText\": \"إدراج قالب…\",\n \"templatesSelectLabel\": \"قالب مبدئي\",\n \"templatesToolbarText\": \"قوالب\",\n \"placeholdToolbarText\": \"عنصر نائب\",\n \"placeholdToolbarTooltip\": \"إدراج صورة عنصر نائب\",\n \"placeholdMenuText\": \"صورة عنصر نائب…\",\n \"placeholdDialogTitle\": \"إدراج صورة عنصر نائب\",\n \"placeholdWidthLabel\": \"العرض\",\n \"placeholdHeightLabel\": \"الارتفاع\",\n \"placeholdBackgroundColorLabel\": \"لون الخلفية\",\n \"placeholdTextColorLabel\": \"لون النص\",\n \"placeholdTextLabel\": \"نص\",\n \"placeholdAltTextLabel\": \"نص بديل\",\n \"placeholdInsertButton\": \"إدراج\",\n \"placeholdCancelButton\": \"إلغاء\",\n \"placeholdInvalidDimensions\": \"يجب أن يكون العرض والارتفاع أعدادًا صحيحة من 10 إلى 4000.\",\n \"placeholdInvalidColor\": \"يجب أن تستخدم الألوان قيمًا سداسية عشرية مكونة من ثلاثة أو ستة أرقام.\",\n \"placeholdAltFallback\": \"{{width}} × {{height}} صورة عنصر نائب\",\n \"a11yToolbarText\": \"تحقق من إمكانية الوصول\",\n \"a11yToolbarTooltip\": \"تحقق من المحتوى بحثًا عن مشكلات إمكانية الوصول\",\n \"a11yMenuText\": \"تحقق من إمكانية الوصول\",\n \"a11yDialogTitle\": \"مدقق إمكانية الوصول\",\n \"a11yNoIssues\": \"لم يتم العثور على مشكلات في إمكانية الوصول.\",\n \"a11yIssueCount\": \"تم العثور على {{count}} مشكلة/مشكلات في إمكانية الوصول.\",\n \"a11yStatusbarIssueCount\": \"{{count}} مشكلات إمكانية الوصول\",\n \"a11yIssueLabel\": \"مشكلة\",\n \"a11yCloseButton\": \"إغلاق\",\n \"a11yImageAltMessage\": \"يجب أن تحتوي الصور على نص بديل.\",\n \"a11yImageAltWhy\": \"تحتاج برامج قراءة الشاشة إلى سمة alt لوصف الصورة أو لتحديدها كعناصر زخرفية.\",\n \"a11yImageAltFilenameMessage\": \"يجب أن يصف النص البديل للصورة الصورة، ولا يكرر اسم الملف.\",\n \"a11yImageAltFilenameWhy\": \"نادراً ما يقدم اسم الملف معلومات مفيدة لمستخدمي قارئ الشاشة حول الصورة.\",\n \"a11yImageAltLengthMessage\": \"يجب أن يكون النص البديل للصورة 125 حرفًا أو أقل.\",\n \"a11yImageAltLengthWhy\": \"الأوصاف القصيرة أسهل في الفهم والملاحة باستخدام تقنيات المساعدة.\",\n \"a11yHeadingSequenceMessage\": \"يجب ألا تتخطى مستويات العناوين مستويات أخرى.\",\n \"a11yHeadingSequenceWhy\": \"يساعد مخطط العناوين المنطقي الأشخاص في التنقل عبر المحتوى باستخدام تقنيات المساعدة.\",\n \"a11yTableHeaderMessage\": \"يجب أن تتضمن الجداول خلايا رؤوس.\",\n \"a11yTableHeaderWhy\": \"توفر خلايا الرأس لسماعات الشاشة السياق اللازم لفهم بيانات الجدول.\",\n \"a11yTableCaptionMessage\": \"يجب أن تتضمن الجداول تسمية توضيحية (caption).\",\n \"a11yTableCaptionWhy\": \"تُعرّف التسمية توضيح غرض الجدول قبل أن تدخل قارئات الشاشة في خلاياه.\",\n \"a11yTableHeaderScopeMessage\": \"يجب أن تُعلن خلايا رأس الجدول عن نطاقها.\",\n \"a11yTableHeaderScopeWhy\": \"تسمح سمة النطاق لتقنيات المساعدة بربط الرؤوس بخلايا البيانات.\",\n \"a11yAdjacentLinksMessage\": \"ينبغي دمج الروابط المتجاورة التي تؤدي إلى نفس الوجهة.\",\n \"a11yAdjacentLinksWhy\": \"تُنشئ الروابط المكررة توقفات غير ضرورية لمستخدمي لوحة المفاتيح وقارئات الشاشة.\",\n \"a11yHeadingStartMessage\": \"يجب أن يكون العنوان الأول h2.\",\n \"a11yHeadingStartWhy\": \"يتم توفير عنوان المستند في المحرر خارج المحتوى القابل للتحرير.\",\n \"a11yListStructureMessage\": \"يجب أن تكون عناصر القائمة محاطة بقائمة مرتبة أو غير مرتبة.\",\n \"a11yListStructureWhy\": \"تعتمد تقنيات المساعدة على بنية القائمة لإعلان عدد العناصر وموقعها.\",\n \"sourceToggleTooltip\": \"شفرة المصدر\",\n \"sourceFormatErrorMessage\": \"تعذر تنسيق شفرة المصدر — تحقق من وجود وسوم غير مغلقة أو أخطاء نحوية أخرى.\",\n \"saveToolbarText\": \"الإعدادات المسبقة\",\n \"saveToolbarTooltip\": \"إدارة الإعدادات المسبقة المحفوظة\",\n \"saveAction\": \"حفظ\",\n \"saveAsAction\": \"حفظ كـ...\",\n \"openAction\": \"فتح...\",\n \"deleteAction\": \"حذف...\",\n \"newAction\": \"جديد\",\n \"exportAction\": \"تصدير...\",\n \"importAction\": \"استيراد...\",\n \"saveAsDialogTitle\": \"حفظ الإعداد المسبق\",\n \"presetNameLabel\": \"الاسم\",\n \"openDialogTitle\": \"فتح الإعداد المسبق\",\n \"deleteDialogTitle\": \"حذف الإعداد المسبق\",\n \"newDialogTitle\": \"مستند جديد\",\n \"newDialogMessage\": \"هذا يمسح محتوى المحرر الحالي والتكوين. هل تريد حفظ العمل الحالي أولاً؟\",\n \"newDialogSaveButton\": \"حفظ ومسح\",\n \"newDialogDiscardButton\": \"تجاهل\",\n \"presetLabel\": \"إعداد مسبق\",\n \"confirmOverwrite\": \"يوجد بالفعل إعداد مسبق باسم “{{name}}”. هل ترغب في استبداله؟\",\n \"confirmDiscard\": \"فتح “{{name}}” والتخلّي عن التغييرات الحالية غير المحفوظة؟\",\n \"confirmDelete\": \"حذف “{{name}}”؟ لا يمكن التراجع عن هذا.\",\n \"emptyPresets\": \"لا توجد إعدادات مسبقة محفوظة متاحة.\",\n \"invalidName\": \"أدخل اسمًا للإعداد المسبق.\",\n \"invalidPreset\": \"هذا الإعداد المسبق غير صالح ولم يمكن فتحه.\",\n \"importInvalidFile\": \"الملف المحدد ليس تصدير pantoken TinyMCE صالحًا.\",\n \"storageReadError\": \"لم يمكن قراءة الإعدادات المسبقة المحفوظة من هذا المتصفح.\",\n \"storageWriteError\": \"لم يمكن حفظ الإعداد المسبق في هذا المتصفح.\",\n \"storageDeleteError\": \"لم يمكن حذف الإعداد المسبق من هذا المتصفح.\",\n \"exportDefaultName\": \"بدون عنوان\",\n \"presetSaveButton\": \"حفظ\",\n \"presetOpenButton\": \"فتح\",\n \"presetDeleteButton\": \"حذف\"\n },\n \"hy\": {\n \"autocompleteModifierDetail\": \"մոդիֆիկատոր\",\n \"classValidationIncompleteComponent\": \"Կոմպոնենտի անունը '{{prefix}}'-ից հետո ամբողջական չէ\",\n \"classValidationTokenPrefix\": \"Տոկենը պետք է սկսվի '{{prefix}}'-ով\",\n \"classValidationUnknownComponent\": \"Անհայտ կոմպոնենտ/օգտակարություն՝ '{{componentName}}'\",\n \"componentsDialogTitle\": \"Ավելացնել կոմպոնենտ\",\n \"componentsListLabel\": \"Կոմպոնենտներ\",\n \"componentsMenuText\": \"Կոմպոնենտ\",\n \"componentsToolbarText\": \"Կոմպոնենտներ\",\n \"componentsToolbarTooltip\": \"Ավելացնել pantoken կոմպոնենտ\",\n \"componentModifiersDefault\": \"Նախնական\",\n \"componentModifiersOptions\": \"Ընտրանքներ\",\n \"componentModifiersTooltip\": \"Փոխել կոմպոնենտի մոդիֆիկատորները\",\n \"componentModifiersUtilities\": \"Օգտակար գործիքներ\",\n \"iconLabelDialogTitle\": \"Պատկերակի պիտակ\",\n \"iconLabelInputLabel\": \"Էկրանի ընթերցողի պիտակ\",\n \"iconsMenuText\": \"Պատկերակ\",\n \"iconsSearchPlaceholder\": \"Փնտրել պատկերակները…\",\n \"iconsSearchLabel\": \"Փնտրել պատկերակները\",\n \"iconsAllSources\": \"Բոլորը\",\n \"iconsResultCount\": \"{{count}} պատկերակ(ներ)\",\n \"iconsNoResults\": \"Ձեր որոնմանը համապատասխանող պատկերակներ չկան։\",\n \"iconsToolbarText\": \"Պատկերակներ\",\n \"iconsToolbarTooltip\": \"Ավելացնել պատկերակ\",\n \"iconContextSizeSmall\": \"Փոքր\",\n \"iconContextSizeMedium\": \"Միջին\",\n \"iconContextSizeLarge\": \"Մեծ\",\n \"iconContextSizeExtraLarge\": \"Առավել մեծ\",\n \"layoutsConfirmReplace\": \"Փոխարինե՞լ ընթացիկ բովանդակությունը \\\"{{title}}\\\" դասավորությամբ?\",\n \"layoutsDialogTitle\": \"Ավելացնել դասավորություն\",\n \"layoutsMenuText\": \"Դասավորություն…\",\n \"layoutsSelectLabel\": \"Սկզբնական դասավորություն\",\n \"layoutsToolbarText\": \"Դասավորություններ\",\n \"layoutsToolbarTooltip\": \"Ավելացնել սկզբնական դասավորություն\",\n \"logosToolbarText\": \"Լոգոտիպներ\",\n \"logosToolbarTooltip\": \"Ավելացնել լոգոտիպ\",\n \"logosMenuText\": \"Լոգոտիպ\",\n \"logosDialogTitle\": \"Ավելացնել լոգոտիպ\",\n \"insertButton\": \"Ավելացնել\",\n \"replaceButton\": \"Փոխարինել\",\n \"cancelButton\": \"Չեղարկել\",\n \"logoAltSuffix\": \"լոգոտիպ\",\n \"templatesConfirmReplace\": \"Փոխարինե՞լ ընթացիկ բովանդակությունը \\\"{{title}}\\\" տեմպլատով?\",\n \"templatesDialogTitle\": \"Ավելացնել տեմպլատ\",\n \"templatesMenuText\": \"Ավելացնել տեմպլատ…\",\n \"templatesSelectLabel\": \"Սկզբնական տեմպլատ\",\n \"templatesToolbarText\": \"Տեմպլատներ\",\n \"placeholdToolbarText\": \"Պլեյսհոլդեր\",\n \"placeholdToolbarTooltip\": \"Ավելացնել պլեյսհոլդեր պատկեր\",\n \"placeholdMenuText\": \"Պլեյսհոլդեր պատկեր…\",\n \"placeholdDialogTitle\": \"Ավելացնել պլեյսհոլդեր պատկեր\",\n \"placeholdWidthLabel\": \"Լայնություն\",\n \"placeholdHeightLabel\": \"Բարձրություն\",\n \"placeholdBackgroundColorLabel\": \"Ֆոնի գույն\",\n \"placeholdTextColorLabel\": \"Տեքստի գույն\",\n \"placeholdTextLabel\": \"Տեքստ\",\n \"placeholdAltTextLabel\": \"Alt տեքստ\",\n \"placeholdInsertButton\": \"Ավելացնել\",\n \"placeholdCancelButton\": \"Չեղարկել\",\n \"placeholdInvalidDimensions\": \"Լայնությունն ու բարձրությունը պետք է ամբողջ թվեր լինեն 10–ից մինչև 4000.\",\n \"placeholdInvalidColor\": \"Գույները պետք է օգտագործեն երեք- կամ վեցանիշ հեքսադեցիմալ արժեքներ.\",\n \"placeholdAltFallback\": \"{{width}} x {{height}} պլեյսհոլդեր պատկեր\",\n \"a11yToolbarText\": \"Ստուգել մատչելիությունը\",\n \"a11yToolbarTooltip\": \"Ստուգել բովանդակությունը մատչելիության խնդիրների համար\",\n \"a11yMenuText\": \"Ստուգել մատչելիությունը\",\n \"a11yDialogTitle\": \"Մատչելիության ստուգիչ\",\n \"a11yNoIssues\": \"Մատչելիության խնդիրներ չհայտնաբերվեցին։\",\n \"a11yIssueCount\": \"{{count}} մատչելիության խնդիր(ներ) հայտնաբերվեցին։\",\n \"a11yStatusbarIssueCount\": \"{{count}} մատչելիության խնդիր(ներ)\",\n \"a11yIssueLabel\": \"Խնդիր\",\n \"a11yCloseButton\": \"Փակել\",\n \"a11yImageAltMessage\": \"Նկարները պետք է ունենան այլընտրանքային տեքստ։\",\n \"a11yImageAltWhy\": \"Էկրան կարդացողներին անհրաժեշտ է alt հատկությունը՝ նկարն նկարագրելու կամ այն որպես զարդանախշող նշելու համար։\",\n \"a11yImageAltFilenameMessage\": \"Ալտ տեքստը պետք է նկարագրի նկարը, ոչ թե կրկնի ֆայլի անունը։\",\n \"a11yImageAltFilenameWhy\": \"Ֆայլի անունն հազվադեպ է օգտակար տեղեկություններ տալիս էկրան կարդացողների համար։\",\n \"a11yImageAltLengthMessage\": \"Ալտ տեքստը պետք է լինի 125 կամ ավելի քիչ նիշ։\",\n \"a11yImageAltLengthWhy\": \"Կարճ նկարագրությունները ավելի հեշտ են հասկանալու և նավարկելու աջակցող տեխնոլոգիաներով։\",\n \"a11yHeadingSequenceMessage\": \"Վերնագրերի մակարդակները չպետք է ցատկեն։\",\n \"a11yHeadingSequenceWhy\": \"Լոգիկական վերնագրերի կառուցվածքը օգնում է մարդկանց նավարկել բովանդակությունը աջակցող տեխնոլոգիաներով։\",\n \"a11yTableHeaderMessage\": \"Աղյուսակները պետք է ունենան վերնագրային բջիջներ։\",\n \"a11yTableHeaderWhy\": \"Վերնագրային բջիջները տալիս են էկրան կարդացողների համար անհրաժեշտ համատեքստը աղյուսակի տվյալները հասկանալու համար։\",\n \"a11yTableCaptionMessage\": \"Աղյուսակները պետք է ունենան նկարագիր։\",\n \"a11yTableCaptionWhy\": \"Նկարագիրը սահմանում է աղյուսակի նպատակը նախքան էկրան կարդացողը մտնի նրա բջիջները։\",\n \"a11yTableHeaderScopeMessage\": \"Աղյուսակի վերնագրային բջիջները պետք է հայտարարեն իրենց scope-ը։\",\n \"a11yTableHeaderScopeWhy\": \"scope հատկությունը թույլ է տալիս աջակցող տեխնոլոգիային կապել վերնագրերը տվյալ բջիջների հետ։\",\n \"a11yAdjacentLinksMessage\": \"Մոտակա նույն նպատակ ունեցող հղումները պետք է միատեղվեն։\",\n \"a11yAdjacentLinksWhy\": \"Կրկնվող հղումները ստեղծում են ավելորդ կանգառներ ստեղնաշարի և էկրան կարդացողների համար։\",\n \"a11yHeadingStartMessage\": \"Առաջին վերնագիրը պետք է լինի h2։\",\n \"a11yHeadingStartWhy\": \"Խմբագրի փաստաթղթի վերնագիրը տրամադրվում է խմբագրելի բովանդակությունից դուրս։\",\n \"a11yListStructureMessage\": \"Ցանկի տարրերը պետք է ընդգրկվեն թվարկված կամ անթվարկված ցանկի մեջ։\",\n \"a11yListStructureWhy\": \"Աջակցող տեխնոլոգիան կախված է ցանկի կառուցվածքից՝ հայտարարելու համար տարրերի քանակը և դիրքը։\",\n \"sourceToggleTooltip\": \"Աղբյուր կոդ\",\n \"sourceFormatErrorMessage\": \"Չհաջողվեց ձևավորել աղբյուրի կոդը — ստուգեք՝ չբացված տեգերի կամ այլ نحوային սխալների առկայությունը։\",\n \"saveToolbarText\": \"Պրեսետներ\",\n \"saveToolbarTooltip\": \"Կառավարել պահպանված պրեսետները\",\n \"saveAction\": \"Պահպանել\",\n \"saveAsAction\": \"Պահպանել որպես...\",\n \"openAction\": \"Բացել...\",\n \"deleteAction\": \"Ջնջել...\",\n \"newAction\": \"Նոր\",\n \"exportAction\": \"Արտահանել...\",\n \"importAction\": \"Ներմուծել...\",\n \"saveAsDialogTitle\": \"Պահպանել պրեսետը\",\n \"presetNameLabel\": \"Անուն\",\n \"openDialogTitle\": \"Բացել պրեսետը\",\n \"deleteDialogTitle\": \"Ջնջել պրեսետը\",\n \"newDialogTitle\": \"Նոր փաստաթուղթ\",\n \"newDialogMessage\": \"Սա մաքրում է ընթացիկ խմբագրի պարունակությունը և կարգավորումները։ Նախ պահպանե՞լ արդյոք ընթացիկ աշխատանքը։\",\n \"newDialogSaveButton\": \"Պահպանել և մաքրել\",\n \"newDialogDiscardButton\": \"Չեղարկել\",\n \"presetLabel\": \"Պրեսետ\",\n \"confirmOverwrite\": \"«{{name}}» անվամբ պրեսետը արդեն գոյություն ունի։ Փոխարինե՞լ այն։\",\n \"confirmDiscard\": \"Բացել «{{name}}»-ն և կորցնել ընթացիկ չպահպանված փոփոխությունները՞\",\n \"confirmDelete\": \"Ջնջե՞լ «{{name}}»-ը։ Սա վերադարձնելն անհնար է։\",\n \"emptyPresets\": \"Պահպանված պրեսետներ չեն գտնվել։\",\n \"invalidName\": \"Մուտքագրեք պրեսետի անունը։\",\n \"invalidPreset\": \"Այս պրեսետը անվավեր է և չի բացվում։\",\n \"importInvalidFile\": \"Ընտրված ֆայլը վավեր pantoken TinyMCE արտահանում չէ։\",\n \"storageReadError\": \"Պահպանված պրեսետները չկարդացվեցին այս զննարկչից։\",\n \"storageWriteError\": \"Պրեսետը չի կարող պահպանվել այս զննարկչում։\",\n \"storageDeleteError\": \"Պրեսետը չի կարող ջնջվել այս զննարկչից։\",\n \"exportDefaultName\": \"անանուն\",\n \"presetSaveButton\": \"Պահպանել\",\n \"presetOpenButton\": \"Բացել\",\n \"presetDeleteButton\": \"Ջնջել\"\n },\n \"ca\": {\n \"autocompleteModifierDetail\": \"modificador\",\n \"classValidationIncompleteComponent\": \"Nom de component incomplet després de '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"El token ha de començar per '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Component/utility desconegut: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Insereix component\",\n \"componentsListLabel\": \"Components\",\n \"componentsMenuText\": \"Component\",\n \"componentsToolbarText\": \"Components\",\n \"componentsToolbarTooltip\": \"Insereix un component pantoken\",\n \"componentModifiersDefault\": \"Predeterminat\",\n \"componentModifiersOptions\": \"Opcions\",\n \"componentModifiersTooltip\": \"Canvia els modificadors del component\",\n \"componentModifiersUtilities\": \"Utilitats\",\n \"iconLabelDialogTitle\": \"Etiqueta de la icona\",\n \"iconLabelInputLabel\": \"Etiqueta per lectors de pantalla\",\n \"iconsMenuText\": \"Icona\",\n \"iconsSearchPlaceholder\": \"Cercar icones…\",\n \"iconsSearchLabel\": \"Cercar icones\",\n \"iconsAllSources\": \"Tots\",\n \"iconsResultCount\": \"{{count}} icones\",\n \"iconsNoResults\": \"Cap icona coincideix amb la teva cerca.\",\n \"iconsToolbarText\": \"Icones\",\n \"iconsToolbarTooltip\": \"Insereix una icona\",\n \"iconContextSizeSmall\": \"Petit\",\n \"iconContextSizeMedium\": \"Mitjà\",\n \"iconContextSizeLarge\": \"Gran\",\n \"iconContextSizeExtraLarge\": \"Extra gran\",\n \"layoutsConfirmReplace\": \"Substitueix el contingut actual pel disseny \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Insereix disseny\",\n \"layoutsMenuText\": \"Disseny…\",\n \"layoutsSelectLabel\": \"Disseny inicial\",\n \"layoutsToolbarText\": \"Dissenys\",\n \"layoutsToolbarTooltip\": \"Insereix un disseny inicial\",\n \"logosToolbarText\": \"Logotips\",\n \"logosToolbarTooltip\": \"Insereix un logotip\",\n \"logosMenuText\": \"Logotip\",\n \"logosDialogTitle\": \"Insereix logotip\",\n \"insertButton\": \"Insereix\",\n \"replaceButton\": \"Substituir\",\n \"cancelButton\": \"Cancel·la\",\n \"logoAltSuffix\": \"logotip\",\n \"templatesConfirmReplace\": \"Substitueix el contingut actual per la plantilla \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Insereix plantilla\",\n \"templatesMenuText\": \"Insereix plantilla…\",\n \"templatesSelectLabel\": \"Plantilla inicial\",\n \"templatesToolbarText\": \"Plantilles\",\n \"placeholdToolbarText\": \"Marcador de posició\",\n \"placeholdToolbarTooltip\": \"Insereix una imatge de marcador de posició\",\n \"placeholdMenuText\": \"Imatge de marcador de posició…\",\n \"placeholdDialogTitle\": \"Insereix imatge de marcador de posició\",\n \"placeholdWidthLabel\": \"Amplada\",\n \"placeholdHeightLabel\": \"Alçada\",\n \"placeholdBackgroundColorLabel\": \"Color de fons\",\n \"placeholdTextColorLabel\": \"Color del text\",\n \"placeholdTextLabel\": \"Text\",\n \"placeholdAltTextLabel\": \"Text alternatiu\",\n \"placeholdInsertButton\": \"Insereix\",\n \"placeholdCancelButton\": \"Cancel·la\",\n \"placeholdInvalidDimensions\": \"L'amplada i l'alçada han de ser nombres enters entre 10 i 4000.\",\n \"placeholdInvalidColor\": \"Els colors han d'utilitzar valors hexadecimals de tres o sis dígits.\",\n \"placeholdAltFallback\": \"{{width}} per {{height}} imatge de marcador de posició\",\n \"a11yToolbarText\": \"Comprovar accessibilitat\",\n \"a11yToolbarTooltip\": \"Comproveu el contingut per detectar problemes d'accessibilitat\",\n \"a11yMenuText\": \"Comprovar accessibilitat\",\n \"a11yDialogTitle\": \"Comprovador d'accessibilitat\",\n \"a11yNoIssues\": \"No s'han trobat problemes d'accessibilitat.\",\n \"a11yIssueCount\": \"{{count}} problemes d'accessibilitat trobats.\",\n \"a11yStatusbarIssueCount\": \"{{count}} problemes d'accessibilitat\",\n \"a11yIssueLabel\": \"Problema\",\n \"a11yCloseButton\": \"Tancar\",\n \"a11yImageAltMessage\": \"Les imatges han de tenir text alternatiu.\",\n \"a11yImageAltWhy\": \"Els lectors de pantalla necessiten un atribut alt per descriure una imatge o identificar-la com a decorativa.\",\n \"a11yImageAltFilenameMessage\": \"El text alternatiu de la imatge ha de descriure la imatge, no repetir el nom del fitxer.\",\n \"a11yImageAltFilenameWhy\": \"Un nom de fitxer rarament aporta informació útil sobre una imatge als usuaris de lectors de pantalla.\",\n \"a11yImageAltLengthMessage\": \"El text alternatiu de la imatge ha de tenir 125 caràcters o menys.\",\n \"a11yImageAltLengthWhy\": \"Les descripcions curtes són més fàcils d'entendre i de navegar amb tecnologia d'assistència.\",\n \"a11yHeadingSequenceMessage\": \"Els nivells de títol no han de saltar-se nivells.\",\n \"a11yHeadingSequenceWhy\": \"Una estructura lògica de títols ajuda les persones a navegar pel contingut amb tecnologia d'assistència.\",\n \"a11yTableHeaderMessage\": \"Les taules han d'incloure cel·les d'encapçalament.\",\n \"a11yTableHeaderWhy\": \"Les cel·les d'encapçalament proporcionen als lectors de pantalla el context necessari per entendre les dades de la taula.\",\n \"a11yTableCaptionMessage\": \"Les taules haurien d'incloure una llegenda.\",\n \"a11yTableCaptionWhy\": \"Una llegenda identifica la finalitat d'una taula abans que un lector de pantalla accedeixi a les seves cel·les.\",\n \"a11yTableHeaderScopeMessage\": \"Les cel·les d'encapçalament de taula han de declarar el seu àmbit.\",\n \"a11yTableHeaderScopeWhy\": \"L'atribut scope permet a la tecnologia d'assistència associar els encapçalaments amb les cel·les de dades.\",\n \"a11yAdjacentLinksMessage\": \"Els enllaços adjacents amb la mateixa destinació s'han de combinar.\",\n \"a11yAdjacentLinksWhy\": \"Els enllaços repetits creen parades innecessàries per als usuaris de teclat i lectors de pantalla.\",\n \"a11yHeadingStartMessage\": \"El primer títol ha de ser un h2.\",\n \"a11yHeadingStartWhy\": \"El títol del document de l'editor s'ha proporcionat fora del contingut editable.\",\n \"a11yListStructureMessage\": \"Els elements de llista han d'estar continguts en una llista ordenada o desordenada.\",\n \"a11yListStructureWhy\": \"La tecnologia d'assistència es basa en l'estructura de la llista per anunciar el nombre d'elements i la posició.\",\n \"sourceToggleTooltip\": \"Codi font\",\n \"sourceFormatErrorMessage\": \"No s'ha pogut formatar el codi font — comprova si hi ha etiquetes sense tancar o altres errors de sintaxi.\",\n \"saveToolbarText\": \"Predefinits\",\n \"saveToolbarTooltip\": \"Gestionar predefinits desats\",\n \"saveAction\": \"Desar\",\n \"saveAsAction\": \"Desar com...\",\n \"openAction\": \"Obrir...\",\n \"deleteAction\": \"Eliminar...\",\n \"newAction\": \"Nou\",\n \"exportAction\": \"Exportar...\",\n \"importAction\": \"Importar...\",\n \"saveAsDialogTitle\": \"Desar predefinit\",\n \"presetNameLabel\": \"Nom\",\n \"openDialogTitle\": \"Obrir predefinit\",\n \"deleteDialogTitle\": \"Eliminar predefinit\",\n \"newDialogTitle\": \"Nou document\",\n \"newDialogMessage\": \"Això esborra el contingut i la configuració de l'editor actual. Vols desar la feina actual primer?\",\n \"newDialogSaveButton\": \"Desa i esborra\",\n \"newDialogDiscardButton\": \"Descarta\",\n \"presetLabel\": \"Predefinit\",\n \"confirmOverwrite\": \"Ja existeix un predefinit anomenat “{{name}}”. Vols substituir-lo?\",\n \"confirmDiscard\": \"Obrir “{{name}}” i descartar els canvis no desats actuals?\",\n \"confirmDelete\": \"Eliminar “{{name}}”? Això no es pot desfer.\",\n \"emptyPresets\": \"No hi ha predefinits desats disponibles.\",\n \"invalidName\": \"Introduïu un nom de predefinit.\",\n \"invalidPreset\": \"Aquest predefinit no és vàlid i no s'ha pogut obrir.\",\n \"importInvalidFile\": \"El fitxer seleccionat no és una exportació de pantoken TinyMCE vàlida.\",\n \"storageReadError\": \"No s'han pogut llegir els predefinits desats des d'aquest navegador.\",\n \"storageWriteError\": \"El predefinit no s'ha pogut desar en aquest navegador.\",\n \"storageDeleteError\": \"El predefinit no s'ha pogut eliminar d'aquest navegador.\",\n \"exportDefaultName\": \"sense títol\",\n \"presetSaveButton\": \"Desar\",\n \"presetOpenButton\": \"Obrir\",\n \"presetDeleteButton\": \"Eliminar\"\n },\n \"da\": {\n \"autocompleteModifierDetail\": \"modifikator\",\n \"classValidationIncompleteComponent\": \"Ufuldstændigt komponentnavn efter '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token skal starte med '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Ukendt komponent/utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Indsæt komponent\",\n \"componentsListLabel\": \"Komponenter\",\n \"componentsMenuText\": \"Komponent\",\n \"componentsToolbarText\": \"Komponenter\",\n \"componentsToolbarTooltip\": \"Indsæt en pantoken-komponent\",\n \"componentModifiersDefault\": \"Standard\",\n \"componentModifiersOptions\": \"Indstillinger\",\n \"componentModifiersTooltip\": \"Skift komponentmodifikatorer\",\n \"componentModifiersUtilities\": \"Værktøjer\",\n \"iconLabelDialogTitle\": \"Ikonetiket\",\n \"iconLabelInputLabel\": \"Etiket til skærmlæser\",\n \"iconsMenuText\": \"Ikon\",\n \"iconsSearchPlaceholder\": \"Søg efter ikoner…\",\n \"iconsSearchLabel\": \"Søg ikoner\",\n \"iconsAllSources\": \"Alle\",\n \"iconsResultCount\": \"{{count}} ikoner\",\n \"iconsNoResults\": \"Ingen ikoner matcher din søgning.\",\n \"iconsToolbarText\": \"Ikoner\",\n \"iconsToolbarTooltip\": \"Indsæt et ikon\",\n \"iconContextSizeSmall\": \"Lille\",\n \"iconContextSizeMedium\": \"Mellem\",\n \"iconContextSizeLarge\": \"Stor\",\n \"iconContextSizeExtraLarge\": \"Ekstra stor\",\n \"layoutsConfirmReplace\": \"Erstat det nuværende indhold med layoutet \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Indsæt layout\",\n \"layoutsMenuText\": \"Layout…\",\n \"layoutsSelectLabel\": \"Startlayout\",\n \"layoutsToolbarText\": \"Layouts\",\n \"layoutsToolbarTooltip\": \"Indsæt et startlayout\",\n \"logosToolbarText\": \"Logoer\",\n \"logosToolbarTooltip\": \"Indsæt et logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Indsæt logo\",\n \"insertButton\": \"Indsæt\",\n \"replaceButton\": \"Erstat\",\n \"cancelButton\": \"Annuller\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Erstat det nuværende indhold med skabelonen \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Indsæt skabelon\",\n \"templatesMenuText\": \"Indsæt skabelon…\",\n \"templatesSelectLabel\": \"Startskabelon\",\n \"templatesToolbarText\": \"Skabeloner\",\n \"placeholdToolbarText\": \"Pladsholder\",\n \"placeholdToolbarTooltip\": \"Indsæt et pladsholderbillede\",\n \"placeholdMenuText\": \"Pladsholderbillede…\",\n \"placeholdDialogTitle\": \"Indsæt pladsholderbillede\",\n \"placeholdWidthLabel\": \"Bredde\",\n \"placeholdHeightLabel\": \"Højde\",\n \"placeholdBackgroundColorLabel\": \"Baggrundsfarve\",\n \"placeholdTextColorLabel\": \"Tekstfarve\",\n \"placeholdTextLabel\": \"Tekst\",\n \"placeholdAltTextLabel\": \"Alt-tekst\",\n \"placeholdInsertButton\": \"Indsæt\",\n \"placeholdCancelButton\": \"Annuller\",\n \"placeholdInvalidDimensions\": \"Bredde og højde skal være hele tal fra 10 til 4000.\",\n \"placeholdInvalidColor\": \"Farver skal bruge tre- eller sekscifrede hexadecimale værdier.\",\n \"placeholdAltFallback\": \"{{width}} × {{height}} pladsholderbillede\",\n \"a11yToolbarText\": \"Kontrollér tilgængelighed\",\n \"a11yToolbarTooltip\": \"Kontrollér indholdet for tilgængelighedsproblemer\",\n \"a11yMenuText\": \"Kontrollér tilgængelighed\",\n \"a11yDialogTitle\": \"Tilgængelighedstjekker\",\n \"a11yNoIssues\": \"Ingen tilgængelighedsproblemer fundet.\",\n \"a11yIssueCount\": \"{{count}} tilgængelighedsproblem(er) fundet.\",\n \"a11yStatusbarIssueCount\": \"{{count}} tilgængelighedsproblemer\",\n \"a11yIssueLabel\": \"Problem\",\n \"a11yCloseButton\": \"Luk\",\n \"a11yImageAltMessage\": \"Billeder skal have alternativ tekst.\",\n \"a11yImageAltWhy\": \"Skærmlæsere har brug for et alt-attribut for at beskrive et billede eller identificere det som dekorativt.\",\n \"a11yImageAltFilenameMessage\": \"Billeders alternative tekst bør beskrive billedet, ikke gentage filnavnet.\",\n \"a11yImageAltFilenameWhy\": \"Et filnavn giver sjældent skærmlæserbrugere nyttig information om et billede.\",\n \"a11yImageAltLengthMessage\": \"Billeders alternative tekst bør være 125 tegn eller færre.\",\n \"a11yImageAltLengthWhy\": \"Korte beskrivelser er nemmere at forstå og navigere med hjælpemidler.\",\n \"a11yHeadingSequenceMessage\": \"Overskriftsniveauer bør ikke springe niveauer over.\",\n \"a11yHeadingSequenceWhy\": \"En logisk overskriftsstruktur hjælper folk med at navigere indholdet med hjælpemidler.\",\n \"a11yTableHeaderMessage\": \"Tabeller skal inkludere header-celler.\",\n \"a11yTableHeaderWhy\": \"Header-celler giver skærmlæsere den kontekst, der er nødvendig for at forstå tabeldata.\",\n \"a11yTableCaptionMessage\": \"Tabeller bør inkludere en billedtekst (caption).\",\n \"a11yTableCaptionWhy\": \"En billedtekst identificerer en tabels formål, før en skærmlæser går ind i dens celler.\",\n \"a11yTableHeaderScopeMessage\": \"Tabel-headerceller bør erklære deres scope.\",\n \"a11yTableHeaderScopeWhy\": \"Scope-attributten lader hjælpemidler knytte overskrifter til dataceller.\",\n \"a11yAdjacentLinksMessage\": \"Nabo-links med samme destination bør slås sammen.\",\n \"a11yAdjacentLinksWhy\": \"Gentagne links skaber unødvendige stop for tastatur- og skærmlæserbrugere.\",\n \"a11yHeadingStartMessage\": \"Den første overskrift bør være en h2.\",\n \"a11yHeadingStartWhy\": \"Editorens dokumenttitel leveres uden for det redigerbare indhold.\",\n \"a11yListStructureMessage\": \"Listeelementer skal være indeholdt i en ordnet eller uordnet liste.\",\n \"a11yListStructureWhy\": \"Hjælpemidler er afhængige af listestrukturen for at annoncere elementantal og position.\",\n \"sourceToggleTooltip\": \"Kildekode\",\n \"sourceFormatErrorMessage\": \"Kunne ikke formatere kildeteksten — tjek for uafsluttede tags eller andre syntaksfejl.\",\n \"saveToolbarText\": \"Forudindstillinger\",\n \"saveToolbarTooltip\": \"Administrer gemte forudindstillinger\",\n \"saveAction\": \"Gem\",\n \"saveAsAction\": \"Gem som...\",\n \"openAction\": \"Åbn...\",\n \"deleteAction\": \"Slet...\",\n \"newAction\": \"Ny\",\n \"exportAction\": \"Eksporter...\",\n \"importAction\": \"Importer...\",\n \"saveAsDialogTitle\": \"Gem forudindstilling\",\n \"presetNameLabel\": \"Navn\",\n \"openDialogTitle\": \"Åbn forudindstilling\",\n \"deleteDialogTitle\": \"Slet forudindstilling\",\n \"newDialogTitle\": \"Nyt dokument\",\n \"newDialogMessage\": \"Dette rydder det aktuelle redigeringsindhold og konfiguration. Gem det aktuelle arbejde først?\",\n \"newDialogSaveButton\": \"Gem & ryd\",\n \"newDialogDiscardButton\": \"Forkast\",\n \"presetLabel\": \"Forudindstilling\",\n \"confirmOverwrite\": \"En forudindstilling med navnet “{{name}}” findes allerede. Erstat den?\",\n \"confirmDiscard\": \"Åbn “{{name}}” og kassér de nuværende ikke-gemte ændringer?\",\n \"confirmDelete\": \"Slet “{{name}}”? Dette kan ikke fortrydes.\",\n \"emptyPresets\": \"Der er ingen gemte forudindstillinger tilgængelige.\",\n \"invalidName\": \"Angiv et navn til forudindstillingen.\",\n \"invalidPreset\": \"Denne forudindstilling er ugyldig og kunne ikke åbnes.\",\n \"importInvalidFile\": \"Den valgte fil er ikke en gyldig pantoken TinyMCE-eksport.\",\n \"storageReadError\": \"Gemt forudindstillinger kunne ikke læses fra denne browser.\",\n \"storageWriteError\": \"Forudindstillingen kunne ikke gemmes i denne browser.\",\n \"storageDeleteError\": \"Forudindstillingen kunne ikke slettes fra denne browser.\",\n \"exportDefaultName\": \"uden titel\",\n \"presetSaveButton\": \"Gem\",\n \"presetOpenButton\": \"Åbn\",\n \"presetDeleteButton\": \"Slet\"\n },\n \"nl\": {\n \"autocompleteModifierDetail\": \"modifier\",\n \"classValidationIncompleteComponent\": \"Onvolledige componentnaam na '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token moet beginnen met '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Onbekende component/utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Component invoegen\",\n \"componentsListLabel\": \"Componenten\",\n \"componentsMenuText\": \"Component\",\n \"componentsToolbarText\": \"Componenten\",\n \"componentsToolbarTooltip\": \"Voeg een pantoken-component in\",\n \"componentModifiersDefault\": \"Standaard\",\n \"componentModifiersOptions\": \"Opties\",\n \"componentModifiersTooltip\": \"Wijzig componentmodifiers\",\n \"componentModifiersUtilities\": \"Hulpprogramma's\",\n \"iconLabelDialogTitle\": \"Pictogramlabel\",\n \"iconLabelInputLabel\": \"Label voor schermlezer\",\n \"iconsMenuText\": \"Pictogram\",\n \"iconsSearchPlaceholder\": \"Zoek iconen…\",\n \"iconsSearchLabel\": \"Zoek iconen\",\n \"iconsAllSources\": \"Alles\",\n \"iconsResultCount\": \"{{count}} iconen\",\n \"iconsNoResults\": \"Geen iconen komen overeen met je zoekopdracht.\",\n \"iconsToolbarText\": \"Pictogrammen\",\n \"iconsToolbarTooltip\": \"Voeg een pictogram in\",\n \"iconContextSizeSmall\": \"Klein\",\n \"iconContextSizeMedium\": \"Middelgroot\",\n \"iconContextSizeLarge\": \"Groot\",\n \"iconContextSizeExtraLarge\": \"Extra groot\",\n \"layoutsConfirmReplace\": \"Huidige inhoud vervangen door de lay-out \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Lay-out invoegen\",\n \"layoutsMenuText\": \"Lay-out…\",\n \"layoutsSelectLabel\": \"Startlay-out\",\n \"layoutsToolbarText\": \"Lay-outs\",\n \"layoutsToolbarTooltip\": \"Voeg een startlay-out in\",\n \"logosToolbarText\": \"Logo's\",\n \"logosToolbarTooltip\": \"Voeg een logo in\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Logo invoegen\",\n \"insertButton\": \"Invoegen\",\n \"replaceButton\": \"Vervangen\",\n \"cancelButton\": \"Annuleren\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Huidige inhoud vervangen door het sjabloon \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Sjabloon invoegen\",\n \"templatesMenuText\": \"Sjabloon invoegen…\",\n \"templatesSelectLabel\": \"Startsjabloon\",\n \"templatesToolbarText\": \"Sjablonen\",\n \"placeholdToolbarText\": \"Plaatsaanduiding\",\n \"placeholdToolbarTooltip\": \"Voeg een plaatsaanduidingsafbeelding in\",\n \"placeholdMenuText\": \"Plaatsaanduidingsafbeelding…\",\n \"placeholdDialogTitle\": \"Plaatsaanduidingsafbeelding invoegen\",\n \"placeholdWidthLabel\": \"Breedte\",\n \"placeholdHeightLabel\": \"Hoogte\",\n \"placeholdBackgroundColorLabel\": \"Achtergrondkleur\",\n \"placeholdTextColorLabel\": \"Tekstkleur\",\n \"placeholdTextLabel\": \"Tekst\",\n \"placeholdAltTextLabel\": \"Alt-tekst\",\n \"placeholdInsertButton\": \"Invoegen\",\n \"placeholdCancelButton\": \"Annuleren\",\n \"placeholdInvalidDimensions\": \"Breedte en hoogte moeten gehele getallen zijn tussen 10 en 4000.\",\n \"placeholdInvalidColor\": \"Kleuren moeten drie- of zescijferige hexadecimale waarden gebruiken.\",\n \"placeholdAltFallback\": \"{{width}} bij {{height}} plaatsaanduidingsafbeelding\",\n \"a11yToolbarText\": \"Controleer toegankelijkheid\",\n \"a11yToolbarTooltip\": \"Controleer de inhoud op toegankelijkheidsproblemen\",\n \"a11yMenuText\": \"Controleer toegankelijkheid\",\n \"a11yDialogTitle\": \"Toegankelijkheidscontrole\",\n \"a11yNoIssues\": \"Geen toegankelijkheidsproblemen gevonden.\",\n \"a11yIssueCount\": \"{{count}} toegankelijkheidsprobleem(en) gevonden.\",\n \"a11yStatusbarIssueCount\": \"{{count}} toegankelijkheidsproblemen\",\n \"a11yIssueLabel\": \"Probleem\",\n \"a11yCloseButton\": \"Sluiten\",\n \"a11yImageAltMessage\": \"Afbeeldingen moeten alternatieve tekst hebben.\",\n \"a11yImageAltWhy\": \"Schermlezers hebben een alt-attribuut nodig om een afbeelding te beschrijven of aan te geven dat deze decoratief is.\",\n \"a11yImageAltFilenameMessage\": \"Alternatieve tekst voor afbeeldingen moet de afbeelding beschrijven, niet de bestandsnaam herhalen.\",\n \"a11yImageAltFilenameWhy\": \"Een bestandsnaam geeft schermlezergebruikers zelden nuttige informatie over een afbeelding.\",\n \"a11yImageAltLengthMessage\": \"Alternatieve tekst voor afbeeldingen moet maximaal 125 tekens bevatten.\",\n \"a11yImageAltLengthWhy\": \"Korte beschrijvingen zijn gemakkelijker te begrijpen en te navigeren met ondersteunende technologieën.\",\n \"a11yHeadingSequenceMessage\": \"Kopniveaus mogen geen niveaus overslaan.\",\n \"a11yHeadingSequenceWhy\": \"Een logische kopstructuur helpt mensen te navigeren met ondersteunende technologie.\",\n \"a11yTableHeaderMessage\": \"Tabellen moeten kopcellen bevatten.\",\n \"a11yTableHeaderWhy\": \"Kopcellen geven schermlezers de context die nodig is om tabelgegevens te begrijpen.\",\n \"a11yTableCaptionMessage\": \"Tabellen moeten een bijschrift bevatten.\",\n \"a11yTableCaptionWhy\": \"Een bijschrift geeft het doel van een tabel aan voordat een schermlezer de cellen betreedt.\",\n \"a11yTableHeaderScopeMessage\": \"Tabelkopcellen moeten hun scope declareren.\",\n \"a11yTableHeaderScopeWhy\": \"Het scope-attribuut laat ondersteunende technologie toe koppen te koppelen aan gegevenscellen.\",\n \"a11yAdjacentLinksMessage\": \"Aangrenzende links met dezelfde bestemming moeten worden samengevoegd.\",\n \"a11yAdjacentLinksWhy\": \"Herhaalde links zorgen voor onnodige stops voor toetsenbord- en schermlezergebruikers.\",\n \"a11yHeadingStartMessage\": \"De eerste kop moet een h2 zijn.\",\n \"a11yHeadingStartWhy\": \"De documenttitel van de editor wordt buiten de bewerkbare inhoud geleverd.\",\n \"a11yListStructureMessage\": \"Lijstitems moeten binnen een geordende of ongeordende lijst staan.\",\n \"a11yListStructureWhy\": \"Ondersteunende technologie vertrouwt op lijststructuur om het aantal items en de positie aan te kondigen.\",\n \"sourceToggleTooltip\": \"Broncode\",\n \"sourceFormatErrorMessage\": \"Kon de broncode niet formatteren — controleer op niet afgesloten tags of andere syntaxisfouten.\",\n \"saveToolbarText\": \"Voorinstellingen\",\n \"saveToolbarTooltip\": \"Beheer opgeslagen voorinstellingen\",\n \"saveAction\": \"Opslaan\",\n \"saveAsAction\": \"Opslaan als...\",\n \"openAction\": \"Openen...\",\n \"deleteAction\": \"Verwijderen...\",\n \"newAction\": \"Nieuw\",\n \"exportAction\": \"Exporteren...\",\n \"importAction\": \"Importeren...\",\n \"saveAsDialogTitle\": \"Voorinstelling opslaan\",\n \"presetNameLabel\": \"Naam\",\n \"openDialogTitle\": \"Voorinstelling openen\",\n \"deleteDialogTitle\": \"Voorinstelling verwijderen\",\n \"newDialogTitle\": \"Nieuw document\",\n \"newDialogMessage\": \"Dit wist de huidige inhoud en configuratie van de editor. Eerst het huidige werk opslaan?\",\n \"newDialogSaveButton\": \"Opslaan & wissen\",\n \"newDialogDiscardButton\": \"Verwerpen\",\n \"presetLabel\": \"Voorinstelling\",\n \"confirmOverwrite\": \"Er bestaat al een voorinstelling met de naam “{{name}}”. Vervangen?\",\n \"confirmDiscard\": \"“{{name}}” openen en de huidige niet-opgeslagen wijzigingen negeren?\",\n \"confirmDelete\": \"“{{name}}” verwijderen? Dit kan niet ongedaan worden gemaakt.\",\n \"emptyPresets\": \"Er zijn geen opgeslagen voorinstellingen beschikbaar.\",\n \"invalidName\": \"Voer een naam voor de voorinstelling in.\",\n \"invalidPreset\": \"Deze voorinstelling is ongeldig en kon niet worden geopend.\",\n \"importInvalidFile\": \"Het geselecteerde bestand is geen geldige pantoken TinyMCE-export.\",\n \"storageReadError\": \"Opgeslagen voorinstellingen konden niet worden gelezen door deze browser.\",\n \"storageWriteError\": \"De voorinstelling kon niet in deze browser worden opgeslagen.\",\n \"storageDeleteError\": \"De voorinstelling kon niet uit deze browser worden verwijderd.\",\n \"exportDefaultName\": \"ongetiteld\",\n \"presetSaveButton\": \"Opslaan\",\n \"presetOpenButton\": \"Openen\",\n \"presetDeleteButton\": \"Verwijderen\"\n },\n \"en-AU\": {\n \"autocompleteModifierDetail\": \"modifier\",\n \"classValidationIncompleteComponent\": \"Incomplete component name after '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token must start with '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Unknown component/utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Insert Component\",\n \"componentsListLabel\": \"Components\",\n \"componentsMenuText\": \"Component\",\n \"componentsToolbarText\": \"Components\",\n \"componentsToolbarTooltip\": \"Insert a pantoken component\",\n \"componentModifiersDefault\": \"Default\",\n \"componentModifiersOptions\": \"Options\",\n \"componentModifiersTooltip\": \"Change component modifiers\",\n \"componentModifiersUtilities\": \"Utilities\",\n \"iconLabelDialogTitle\": \"Icon label\",\n \"iconLabelInputLabel\": \"Screen reader label\",\n \"iconsMenuText\": \"Icon\",\n \"iconsSearchPlaceholder\": \"Search icons…\",\n \"iconsSearchLabel\": \"Search icons\",\n \"iconsAllSources\": \"All\",\n \"iconsResultCount\": \"{{count}} icons\",\n \"iconsNoResults\": \"No icons match your search.\",\n \"iconsToolbarText\": \"Icons\",\n \"iconsToolbarTooltip\": \"Insert an icon\",\n \"iconContextSizeSmall\": \"Small\",\n \"iconContextSizeMedium\": \"Medium\",\n \"iconContextSizeLarge\": \"Large\",\n \"iconContextSizeExtraLarge\": \"Extra large\",\n \"layoutsConfirmReplace\": \"Replace the current content with the \\\"{{title}}\\\" layout?\",\n \"layoutsDialogTitle\": \"Insert layout\",\n \"layoutsMenuText\": \"Layout…\",\n \"layoutsSelectLabel\": \"Starter layout\",\n \"layoutsToolbarText\": \"Layouts\",\n \"layoutsToolbarTooltip\": \"Insert a starter layout\",\n \"logosToolbarText\": \"Logos\",\n \"logosToolbarTooltip\": \"Insert a logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Insert Logo\",\n \"insertButton\": \"Insert\",\n \"replaceButton\": \"Replace\",\n \"cancelButton\": \"Cancel\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Replace the current content with the \\\"{{title}}\\\" template?\",\n \"templatesDialogTitle\": \"Insert template\",\n \"templatesMenuText\": \"Insert template…\",\n \"templatesSelectLabel\": \"Starter template\",\n \"templatesToolbarText\": \"Templates\",\n \"placeholdToolbarText\": \"Placeholder\",\n \"placeholdToolbarTooltip\": \"Insert a placeholder image\",\n \"placeholdMenuText\": \"Placeholder image…\",\n \"placeholdDialogTitle\": \"Insert placeholder image\",\n \"placeholdWidthLabel\": \"Width\",\n \"placeholdHeightLabel\": \"Height\",\n \"placeholdBackgroundColorLabel\": \"Background colour\",\n \"placeholdTextColorLabel\": \"Text colour\",\n \"placeholdTextLabel\": \"Text\",\n \"placeholdAltTextLabel\": \"Alt text\",\n \"placeholdInsertButton\": \"Insert\",\n \"placeholdCancelButton\": \"Cancel\",\n \"placeholdInvalidDimensions\": \"Width and height must be whole numbers from 10 to 4000.\",\n \"placeholdInvalidColor\": \"Colours must use three- or six-digit hexadecimal values.\",\n \"placeholdAltFallback\": \"{{width}} by {{height}} placeholder image\",\n \"a11yToolbarText\": \"Check accessibility\",\n \"a11yToolbarTooltip\": \"Check the content for accessibility issues\",\n \"a11yMenuText\": \"Check accessibility\",\n \"a11yDialogTitle\": \"Accessibility checker\",\n \"a11yNoIssues\": \"No accessibility issues found.\",\n \"a11yIssueCount\": \"{{count}} accessibility issue(s) found.\",\n \"a11yStatusbarIssueCount\": \"{{count}} accessibility issues\",\n \"a11yIssueLabel\": \"Issue\",\n \"a11yCloseButton\": \"Close\",\n \"a11yImageAltMessage\": \"Images must have alternative text.\",\n \"a11yImageAltWhy\": \"Screen readers need an alt attribute to describe an image or identify it as decorative.\",\n \"a11yImageAltFilenameMessage\": \"Image alternative text should describe the image, not repeat its filename.\",\n \"a11yImageAltFilenameWhy\": \"A filename rarely gives screen reader users useful information about an image.\",\n \"a11yImageAltLengthMessage\": \"Image alternative text should be 125 characters or fewer.\",\n \"a11yImageAltLengthWhy\": \"Short descriptions are easier to understand and navigate with assistive technology.\",\n \"a11yHeadingSequenceMessage\": \"Heading levels should not skip levels.\",\n \"a11yHeadingSequenceWhy\": \"A logical heading outline helps people navigate content with assistive technology.\",\n \"a11yTableHeaderMessage\": \"Tables must include header cells.\",\n \"a11yTableHeaderWhy\": \"Header cells give screen readers the context needed to understand table data.\",\n \"a11yTableCaptionMessage\": \"Tables should include a caption.\",\n \"a11yTableCaptionWhy\": \"A caption identifies a table's purpose before a screen reader enters its cells.\",\n \"a11yTableHeaderScopeMessage\": \"Table header cells should declare their scope.\",\n \"a11yTableHeaderScopeWhy\": \"The scope attribute lets assistive technology associate headers with data cells.\",\n \"a11yAdjacentLinksMessage\": \"Adjacent links with the same destination should be combined.\",\n \"a11yAdjacentLinksWhy\": \"Repeated links create unnecessary stops for keyboard and screen reader users.\",\n \"a11yHeadingStartMessage\": \"The first heading should be an h2.\",\n \"a11yHeadingStartWhy\": \"The editor's document title is supplied outside the editable content.\",\n \"a11yListStructureMessage\": \"List items must be contained by an ordered or unordered list.\",\n \"a11yListStructureWhy\": \"Assistive technology relies on list structure to announce item counts and position.\",\n \"sourceToggleTooltip\": \"Source code\",\n \"sourceFormatErrorMessage\": \"Couldn't format the source code — check for unclosed tags or other syntax errors.\",\n \"saveToolbarText\": \"Presets\",\n \"saveToolbarTooltip\": \"Manage saved presets\",\n \"saveAction\": \"Save\",\n \"saveAsAction\": \"Save as...\",\n \"openAction\": \"Open...\",\n \"deleteAction\": \"Delete...\",\n \"newAction\": \"New\",\n \"exportAction\": \"Export...\",\n \"importAction\": \"Import...\",\n \"saveAsDialogTitle\": \"Save preset\",\n \"presetNameLabel\": \"Name\",\n \"openDialogTitle\": \"Open preset\",\n \"deleteDialogTitle\": \"Delete preset\",\n \"newDialogTitle\": \"New document\",\n \"newDialogMessage\": \"This clears the current editor content and config. Save your current work first?\",\n \"newDialogSaveButton\": \"Save & clear\",\n \"newDialogDiscardButton\": \"Discard\",\n \"presetLabel\": \"Preset\",\n \"confirmOverwrite\": \"A preset named “{{name}}” already exists. Replace it?\",\n \"confirmDiscard\": \"Open “{{name}}” and discard the current unsaved changes?\",\n \"confirmDelete\": \"Delete “{{name}}”? This cannot be undone.\",\n \"emptyPresets\": \"No saved presets are available.\",\n \"invalidName\": \"Enter a preset name.\",\n \"invalidPreset\": \"This preset is invalid and could not be opened.\",\n \"importInvalidFile\": \"The selected file is not a valid pantoken TinyMCE export.\",\n \"storageReadError\": \"Saved presets could not be read from this browser.\",\n \"storageWriteError\": \"The preset could not be saved in this browser.\",\n \"storageDeleteError\": \"The preset could not be deleted from this browser.\",\n \"exportDefaultName\": \"untitled\",\n \"presetSaveButton\": \"Save\",\n \"presetOpenButton\": \"Open\",\n \"presetDeleteButton\": \"Delete\"\n },\n \"en-CA\": {\n \"autocompleteModifierDetail\": \"modifier\",\n \"classValidationIncompleteComponent\": \"Incomplete component name after '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token must start with '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Unknown component/utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Insert Component\",\n \"componentsListLabel\": \"Components\",\n \"componentsMenuText\": \"Component\",\n \"componentsToolbarText\": \"Components\",\n \"componentsToolbarTooltip\": \"Insert a pantoken component\",\n \"componentModifiersDefault\": \"Default\",\n \"componentModifiersOptions\": \"Options\",\n \"componentModifiersTooltip\": \"Change component modifiers\",\n \"componentModifiersUtilities\": \"Utilities\",\n \"iconLabelDialogTitle\": \"Icon label\",\n \"iconLabelInputLabel\": \"Screen reader label\",\n \"iconsMenuText\": \"Icon\",\n \"iconsSearchPlaceholder\": \"Search icons…\",\n \"iconsSearchLabel\": \"Search icons\",\n \"iconsAllSources\": \"All\",\n \"iconsResultCount\": \"{{count}} icons\",\n \"iconsNoResults\": \"No icons match your search.\",\n \"iconsToolbarText\": \"Icons\",\n \"iconsToolbarTooltip\": \"Insert an icon\",\n \"iconContextSizeSmall\": \"Small\",\n \"iconContextSizeMedium\": \"Medium\",\n \"iconContextSizeLarge\": \"Large\",\n \"iconContextSizeExtraLarge\": \"Extra large\",\n \"layoutsConfirmReplace\": \"Replace the current content with the \\\"{{title}}\\\" layout?\",\n \"layoutsDialogTitle\": \"Insert layout\",\n \"layoutsMenuText\": \"Layout…\",\n \"layoutsSelectLabel\": \"Starter layout\",\n \"layoutsToolbarText\": \"Layouts\",\n \"layoutsToolbarTooltip\": \"Insert a starter layout\",\n \"logosToolbarText\": \"Logos\",\n \"logosToolbarTooltip\": \"Insert a logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Insert Logo\",\n \"insertButton\": \"Insert\",\n \"replaceButton\": \"Replace\",\n \"cancelButton\": \"Cancel\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Replace the current content with the \\\"{{title}}\\\" template?\",\n \"templatesDialogTitle\": \"Insert template\",\n \"templatesMenuText\": \"Insert template…\",\n \"templatesSelectLabel\": \"Starter template\",\n \"templatesToolbarText\": \"Templates\",\n \"placeholdToolbarText\": \"Placeholder\",\n \"placeholdToolbarTooltip\": \"Insert a placeholder image\",\n \"placeholdMenuText\": \"Placeholder image…\",\n \"placeholdDialogTitle\": \"Insert placeholder image\",\n \"placeholdWidthLabel\": \"Width\",\n \"placeholdHeightLabel\": \"Height\",\n \"placeholdBackgroundColorLabel\": \"Background colour\",\n \"placeholdTextColorLabel\": \"Text colour\",\n \"placeholdTextLabel\": \"Text\",\n \"placeholdAltTextLabel\": \"Alt text\",\n \"placeholdInsertButton\": \"Insert\",\n \"placeholdCancelButton\": \"Cancel\",\n \"placeholdInvalidDimensions\": \"Width and height must be whole numbers from 10 through 4000.\",\n \"placeholdInvalidColor\": \"Colours must use three- or six-digit hexadecimal values.\",\n \"placeholdAltFallback\": \"{{width}} by {{height}} placeholder image\",\n \"a11yToolbarText\": \"Check accessibility\",\n \"a11yToolbarTooltip\": \"Check the content for accessibility issues\",\n \"a11yMenuText\": \"Check accessibility\",\n \"a11yDialogTitle\": \"Accessibility checker\",\n \"a11yNoIssues\": \"No accessibility issues found.\",\n \"a11yIssueCount\": \"{{count}} accessibility issue(s) found.\",\n \"a11yStatusbarIssueCount\": \"{{count}} accessibility issues\",\n \"a11yIssueLabel\": \"Issue\",\n \"a11yCloseButton\": \"Close\",\n \"a11yImageAltMessage\": \"Images must have alternative text.\",\n \"a11yImageAltWhy\": \"Screen readers need an alt attribute to describe an image or identify it as decorative.\",\n \"a11yImageAltFilenameMessage\": \"Image alternative text should describe the image, not repeat its filename.\",\n \"a11yImageAltFilenameWhy\": \"A filename rarely gives screen reader users useful information about an image.\",\n \"a11yImageAltLengthMessage\": \"Image alternative text should be 125 characters or fewer.\",\n \"a11yImageAltLengthWhy\": \"Short descriptions are easier to understand and navigate with assistive technology.\",\n \"a11yHeadingSequenceMessage\": \"Heading levels should not skip levels.\",\n \"a11yHeadingSequenceWhy\": \"A logical heading outline helps people navigate content with assistive technology.\",\n \"a11yTableHeaderMessage\": \"Tables must include header cells.\",\n \"a11yTableHeaderWhy\": \"Header cells give screen readers the context needed to understand table data.\",\n \"a11yTableCaptionMessage\": \"Tables should include a caption.\",\n \"a11yTableCaptionWhy\": \"A caption identifies a table's purpose before a screen reader enters its cells.\",\n \"a11yTableHeaderScopeMessage\": \"Table header cells should declare their scope.\",\n \"a11yTableHeaderScopeWhy\": \"The scope attribute lets assistive technology associate headers with data cells.\",\n \"a11yAdjacentLinksMessage\": \"Adjacent links with the same destination should be combined.\",\n \"a11yAdjacentLinksWhy\": \"Repeated links create unnecessary stops for keyboard and screen reader users.\",\n \"a11yHeadingStartMessage\": \"The first heading should be an h2.\",\n \"a11yHeadingStartWhy\": \"The editor's document title is supplied outside the editable content.\",\n \"a11yListStructureMessage\": \"List items must be contained by an ordered or unordered list.\",\n \"a11yListStructureWhy\": \"Assistive technology relies on list structure to announce item counts and position.\",\n \"sourceToggleTooltip\": \"Source code\",\n \"sourceFormatErrorMessage\": \"Couldn't format the source code — check for unclosed tags or other syntax errors.\",\n \"saveToolbarText\": \"Presets\",\n \"saveToolbarTooltip\": \"Manage saved presets\",\n \"saveAction\": \"Save\",\n \"saveAsAction\": \"Save as...\",\n \"openAction\": \"Open...\",\n \"deleteAction\": \"Delete...\",\n \"newAction\": \"New\",\n \"exportAction\": \"Export...\",\n \"importAction\": \"Import...\",\n \"saveAsDialogTitle\": \"Save preset\",\n \"presetNameLabel\": \"Name\",\n \"openDialogTitle\": \"Open preset\",\n \"deleteDialogTitle\": \"Delete preset\",\n \"newDialogTitle\": \"New document\",\n \"newDialogMessage\": \"This clears the current editor content and config. Save the current work first?\",\n \"newDialogSaveButton\": \"Save & clear\",\n \"newDialogDiscardButton\": \"Discard\",\n \"presetLabel\": \"Preset\",\n \"confirmOverwrite\": \"A preset named “{{name}}” already exists. Replace it?\",\n \"confirmDiscard\": \"Open “{{name}}” and discard the current unsaved changes?\",\n \"confirmDelete\": \"Delete “{{name}}”? This cannot be undone.\",\n \"emptyPresets\": \"No saved presets are available.\",\n \"invalidName\": \"Enter a preset name.\",\n \"invalidPreset\": \"This preset is invalid and could not be opened.\",\n \"importInvalidFile\": \"The selected file is not a valid pantoken TinyMCE export.\",\n \"storageReadError\": \"Saved presets could not be read from this browser.\",\n \"storageWriteError\": \"The preset could not be saved in this browser.\",\n \"storageDeleteError\": \"The preset could not be deleted from this browser.\",\n \"exportDefaultName\": \"untitled\",\n \"presetSaveButton\": \"Save\",\n \"presetOpenButton\": \"Open\",\n \"presetDeleteButton\": \"Delete\"\n },\n \"en-GB\": {\n \"autocompleteModifierDetail\": \"modifier\",\n \"classValidationIncompleteComponent\": \"Incomplete component name after '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token must start with '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Unknown component/utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Insert Component\",\n \"componentsListLabel\": \"Components\",\n \"componentsMenuText\": \"Component\",\n \"componentsToolbarText\": \"Components\",\n \"componentsToolbarTooltip\": \"Insert a pantoken component\",\n \"componentModifiersDefault\": \"Default\",\n \"componentModifiersOptions\": \"Options\",\n \"componentModifiersTooltip\": \"Change component modifiers\",\n \"componentModifiersUtilities\": \"Utilities\",\n \"iconLabelDialogTitle\": \"Icon label\",\n \"iconLabelInputLabel\": \"Screen reader label\",\n \"iconsMenuText\": \"Icon\",\n \"iconsSearchPlaceholder\": \"Search icons…\",\n \"iconsSearchLabel\": \"Search icons\",\n \"iconsAllSources\": \"All\",\n \"iconsResultCount\": \"{{count}} icons\",\n \"iconsNoResults\": \"No icons match your search.\",\n \"iconsToolbarText\": \"Icons\",\n \"iconsToolbarTooltip\": \"Insert an icon\",\n \"iconContextSizeSmall\": \"Small\",\n \"iconContextSizeMedium\": \"Medium\",\n \"iconContextSizeLarge\": \"Large\",\n \"iconContextSizeExtraLarge\": \"Extra large\",\n \"layoutsConfirmReplace\": \"Replace the current content with the \\\"{{title}}\\\" layout?\",\n \"layoutsDialogTitle\": \"Insert layout\",\n \"layoutsMenuText\": \"Layout…\",\n \"layoutsSelectLabel\": \"Starter layout\",\n \"layoutsToolbarText\": \"Layouts\",\n \"layoutsToolbarTooltip\": \"Insert a starter layout\",\n \"logosToolbarText\": \"Logos\",\n \"logosToolbarTooltip\": \"Insert a logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Insert Logo\",\n \"insertButton\": \"Insert\",\n \"replaceButton\": \"Replace\",\n \"cancelButton\": \"Cancel\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Replace the current content with the \\\"{{title}}\\\" template?\",\n \"templatesDialogTitle\": \"Insert template\",\n \"templatesMenuText\": \"Insert template…\",\n \"templatesSelectLabel\": \"Starter template\",\n \"templatesToolbarText\": \"Templates\",\n \"placeholdToolbarText\": \"Placeholder\",\n \"placeholdToolbarTooltip\": \"Insert a placeholder image\",\n \"placeholdMenuText\": \"Placeholder image…\",\n \"placeholdDialogTitle\": \"Insert placeholder image\",\n \"placeholdWidthLabel\": \"Width\",\n \"placeholdHeightLabel\": \"Height\",\n \"placeholdBackgroundColorLabel\": \"Background colour\",\n \"placeholdTextColorLabel\": \"Text colour\",\n \"placeholdTextLabel\": \"Text\",\n \"placeholdAltTextLabel\": \"Alt text\",\n \"placeholdInsertButton\": \"Insert\",\n \"placeholdCancelButton\": \"Cancel\",\n \"placeholdInvalidDimensions\": \"Width and height must be whole numbers from 10 to 4000.\",\n \"placeholdInvalidColor\": \"Colours must use three- or six-digit hexadecimal values.\",\n \"placeholdAltFallback\": \"{{width}} by {{height}} placeholder image\",\n \"a11yToolbarText\": \"Check accessibility\",\n \"a11yToolbarTooltip\": \"Check the content for accessibility issues\",\n \"a11yMenuText\": \"Check accessibility\",\n \"a11yDialogTitle\": \"Accessibility checker\",\n \"a11yNoIssues\": \"No accessibility issues found.\",\n \"a11yIssueCount\": \"{{count}} accessibility issue(s) found.\",\n \"a11yStatusbarIssueCount\": \"{{count}} accessibility issues\",\n \"a11yIssueLabel\": \"Issue\",\n \"a11yCloseButton\": \"Close\",\n \"a11yImageAltMessage\": \"Images must have alternative text.\",\n \"a11yImageAltWhy\": \"Screen readers need an alt attribute to describe an image or identify it as decorative.\",\n \"a11yImageAltFilenameMessage\": \"Image alternative text should describe the image, not repeat its filename.\",\n \"a11yImageAltFilenameWhy\": \"A filename rarely gives screen reader users useful information about an image.\",\n \"a11yImageAltLengthMessage\": \"Image alternative text should be 125 characters or fewer.\",\n \"a11yImageAltLengthWhy\": \"Short descriptions are easier to understand and navigate with assistive technology.\",\n \"a11yHeadingSequenceMessage\": \"Heading levels should not skip levels.\",\n \"a11yHeadingSequenceWhy\": \"A logical heading outline helps people navigate content with assistive technology.\",\n \"a11yTableHeaderMessage\": \"Tables must include header cells.\",\n \"a11yTableHeaderWhy\": \"Header cells give screen readers the context needed to understand table data.\",\n \"a11yTableCaptionMessage\": \"Tables should include a caption.\",\n \"a11yTableCaptionWhy\": \"A caption identifies a table's purpose before a screen reader enters its cells.\",\n \"a11yTableHeaderScopeMessage\": \"Table header cells should declare their scope.\",\n \"a11yTableHeaderScopeWhy\": \"The scope attribute lets assistive technology associate headers with data cells.\",\n \"a11yAdjacentLinksMessage\": \"Adjacent links with the same destination should be combined.\",\n \"a11yAdjacentLinksWhy\": \"Repeated links create unnecessary stops for keyboard and screen reader users.\",\n \"a11yHeadingStartMessage\": \"The first heading should be an h2.\",\n \"a11yHeadingStartWhy\": \"The editor's document title is supplied outside the editable content.\",\n \"a11yListStructureMessage\": \"List items must be contained by an ordered or unordered list.\",\n \"a11yListStructureWhy\": \"Assistive technology relies on list structure to announce item counts and position.\",\n \"sourceToggleTooltip\": \"Source code\",\n \"sourceFormatErrorMessage\": \"Couldn't format the source code — check for unclosed tags or other syntax errors.\",\n \"saveToolbarText\": \"Presets\",\n \"saveToolbarTooltip\": \"Manage saved presets\",\n \"saveAction\": \"Save\",\n \"saveAsAction\": \"Save as...\",\n \"openAction\": \"Open...\",\n \"deleteAction\": \"Delete...\",\n \"newAction\": \"New\",\n \"exportAction\": \"Export...\",\n \"importAction\": \"Import...\",\n \"saveAsDialogTitle\": \"Save preset\",\n \"presetNameLabel\": \"Name\",\n \"openDialogTitle\": \"Open preset\",\n \"deleteDialogTitle\": \"Delete preset\",\n \"newDialogTitle\": \"New document\",\n \"newDialogMessage\": \"This clears the current editor content and configuration. Save the current work first?\",\n \"newDialogSaveButton\": \"Save & clear\",\n \"newDialogDiscardButton\": \"Discard\",\n \"presetLabel\": \"Preset\",\n \"confirmOverwrite\": \"A preset named “{{name}}” already exists. Replace it?\",\n \"confirmDiscard\": \"Open “{{name}}” and discard the current unsaved changes?\",\n \"confirmDelete\": \"Delete “{{name}}”? This cannot be undone.\",\n \"emptyPresets\": \"No saved presets are available.\",\n \"invalidName\": \"Enter a preset name.\",\n \"invalidPreset\": \"This preset is invalid and could not be opened.\",\n \"importInvalidFile\": \"The selected file is not a valid pantoken TinyMCE export.\",\n \"storageReadError\": \"Saved presets could not be read from this browser.\",\n \"storageWriteError\": \"The preset could not be saved in this browser.\",\n \"storageDeleteError\": \"The preset could not be deleted from this browser.\",\n \"exportDefaultName\": \"untitled\",\n \"presetSaveButton\": \"Save\",\n \"presetOpenButton\": \"Open\",\n \"presetDeleteButton\": \"Delete\"\n },\n \"fi\": {\n \"autocompleteModifierDetail\": \"modifikaattori\",\n \"classValidationIncompleteComponent\": \"Komponentin nimi on epätäydellinen kohdan '{{prefix}}' jälkeen\",\n \"classValidationTokenPrefix\": \"Tokenin on aloitettava '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Tuntematon komponentti/utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Lisää komponentti\",\n \"componentsListLabel\": \"Komponentit\",\n \"componentsMenuText\": \"Komponentti\",\n \"componentsToolbarText\": \"Komponentit\",\n \"componentsToolbarTooltip\": \"Lisää pantoken-komponentti\",\n \"componentModifiersDefault\": \"Oletus\",\n \"componentModifiersOptions\": \"Asetukset\",\n \"componentModifiersTooltip\": \"Vaihda komponentin modifikaattoreita\",\n \"componentModifiersUtilities\": \"Apuohjelmat\",\n \"iconLabelDialogTitle\": \"Kuvakkeen etiketti\",\n \"iconLabelInputLabel\": \"Näytönlukijan etiketti\",\n \"iconsMenuText\": \"Kuvake\",\n \"iconsSearchPlaceholder\": \"Hae kuvakkeita…\",\n \"iconsSearchLabel\": \"Hae kuvakkeita\",\n \"iconsAllSources\": \"Kaikki\",\n \"iconsResultCount\": \"{{count}} kuvaketta\",\n \"iconsNoResults\": \"Haku ei löytänyt kuvakkeita.\",\n \"iconsToolbarText\": \"Kuvakkeet\",\n \"iconsToolbarTooltip\": \"Lisää kuvake\",\n \"iconContextSizeSmall\": \"Pieni\",\n \"iconContextSizeMedium\": \"Keskikokoinen\",\n \"iconContextSizeLarge\": \"Suuri\",\n \"iconContextSizeExtraLarge\": \"Erittäin suuri\",\n \"layoutsConfirmReplace\": \"Korvataanko nykyinen sisältö asetelmalla \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Lisää asettelu\",\n \"layoutsMenuText\": \"Asettelu…\",\n \"layoutsSelectLabel\": \"Aloitusasettelu\",\n \"layoutsToolbarText\": \"Asettelut\",\n \"layoutsToolbarTooltip\": \"Lisää aloitusasettelu\",\n \"logosToolbarText\": \"Logot\",\n \"logosToolbarTooltip\": \"Lisää logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Lisää logo\",\n \"insertButton\": \"Lisää\",\n \"replaceButton\": \"Korvaa\",\n \"cancelButton\": \"Peruuta\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Korvataanko nykyinen sisältö mallilla \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Lisää malli\",\n \"templatesMenuText\": \"Lisää malli…\",\n \"templatesSelectLabel\": \"Aloitusmalli\",\n \"templatesToolbarText\": \"Mallit\",\n \"placeholdToolbarText\": \"Paikkamerkki\",\n \"placeholdToolbarTooltip\": \"Lisää paikkamerkkikuva\",\n \"placeholdMenuText\": \"Paikkamerkkikuva…\",\n \"placeholdDialogTitle\": \"Lisää paikkamerkkikuva\",\n \"placeholdWidthLabel\": \"Leveys\",\n \"placeholdHeightLabel\": \"Korkeus\",\n \"placeholdBackgroundColorLabel\": \"Taustaväri\",\n \"placeholdTextColorLabel\": \"Tekstin väri\",\n \"placeholdTextLabel\": \"Teksti\",\n \"placeholdAltTextLabel\": \"Alt-teksti\",\n \"placeholdInsertButton\": \"Lisää\",\n \"placeholdCancelButton\": \"Peruuta\",\n \"placeholdInvalidDimensions\": \"Leveyden ja korkeuden on oltava kokonaislukuja välillä 10–4000.\",\n \"placeholdInvalidColor\": \"Värien on oltava kolmi- tai kuusinumeroisia heksadesimaaliarvoja.\",\n \"placeholdAltFallback\": \"{{width}} × {{height}} paikkamerkkikuva\",\n \"a11yToolbarText\": \"Tarkista saavutettavuus\",\n \"a11yToolbarTooltip\": \"Tarkista sisältö saavutettavuusongelmien varalta\",\n \"a11yMenuText\": \"Tarkista saavutettavuus\",\n \"a11yDialogTitle\": \"Saavutettavuustarkistin\",\n \"a11yNoIssues\": \"Ei löydetty saavutettavuusongelmia.\",\n \"a11yIssueCount\": \"{{count}} saavutettavuusongelmaa löydetty.\",\n \"a11yStatusbarIssueCount\": \"{{count}} saavutettavuusongelmaa\",\n \"a11yIssueLabel\": \"Ongelma\",\n \"a11yCloseButton\": \"Sulje\",\n \"a11yImageAltMessage\": \"Kuvilla on oltava vaihtoehtoinen teksti.\",\n \"a11yImageAltWhy\": \"Ruudunlukijat tarvitsevat alt-attribuutin kuvan kuvaamiseen tai sen tunnistamiseen koristeelliseksi.\",\n \"a11yImageAltFilenameMessage\": \"Kuvan vaihtoehtoinen teksti kannattaa kuvata kuvaa, ei toistaa tiedostonimeä.\",\n \"a11yImageAltFilenameWhy\": \"Tiedostonimi harvoin antaa hyödyllistä tietoa ruudunlukijoille.\",\n \"a11yImageAltLengthMessage\": \"Kuvan vaihtoehtoisen tekstin tulisi olla enintään 125 merkkiä.\",\n \"a11yImageAltLengthWhy\": \"Lyhyet kuvaukset ovat helpommin ymmärrettäviä ja navigoitavia apuvälineillä.\",\n \"a11yHeadingSequenceMessage\": \"Otsikkotasoja ei tule hypätä yli.\",\n \"a11yHeadingSequenceWhy\": \"Looginen otsikkorakenne auttaa apuvälineiden käyttäjiä navigoimaan sisällössä.\",\n \"a11yTableHeaderMessage\": \"Taulukoissa on oltava otsikkosoluja.\",\n \"a11yTableHeaderWhy\": \"Otsikkosolut antavat ruudunlukijoille tarvittavan kontekstin taulukkotiedon ymmärtämiseen.\",\n \"a11yTableCaptionMessage\": \"Taulukoissa tulisi olla kuvateksti.\",\n \"a11yTableCaptionWhy\": \"Kuvateksti kertoo taulukon tarkoituksen ennen kuin ruudunlukija siirtyy sen soluihin.\",\n \"a11yTableHeaderScopeMessage\": \"Taulukon otsikkosolujen tulisi määrittää scope-attribuutti.\",\n \"a11yTableHeaderScopeWhy\": \"Scope-attribuutti sallii apuvälineiden yhdistää otsikot datasoluihin.\",\n \"a11yAdjacentLinksMessage\": \"Saman kohteen vierekkäiset linkit kannattaa yhdistää.\",\n \"a11yAdjacentLinksWhy\": \"Toistuvat linkit aiheuttavat turhia pysähdyksiä näppäimistö- ja ruudunlukijakäyttäjille.\",\n \"a11yHeadingStartMessage\": \"Ensimmäisen otsikon tulisi olla h2.\",\n \"a11yHeadingStartWhy\": \"Muokkaimen asiakirjan otsikko annetaan muokattavan sisällön ulkopuolella.\",\n \"a11yListStructureMessage\": \"Listan kohteet on sijoitettava järjestettyyn tai järjestämättömään listaan.\",\n \"a11yListStructureWhy\": \"Apuvälineet luottavat listan rakenteeseen ilmoittaakseen kohteiden lukumäärän ja sijainnin.\",\n \"sourceToggleTooltip\": \"Lähdekoodi\",\n \"sourceFormatErrorMessage\": \"Lähdekoodia ei voitu muotoilla — tarkista, ettei tageja ole jäänyt sulkematta tai esiinny muita syntaksivirheitä.\",\n \"saveToolbarText\": \"Esiasetukset\",\n \"saveToolbarTooltip\": \"Hallitse tallennettuja esiasetuksia\",\n \"saveAction\": \"Tallenna\",\n \"saveAsAction\": \"Tallenna nimellä...\",\n \"openAction\": \"Avaa...\",\n \"deleteAction\": \"Poista...\",\n \"newAction\": \"Uusi\",\n \"exportAction\": \"Vie...\",\n \"importAction\": \"Tuo...\",\n \"saveAsDialogTitle\": \"Tallenna esiasetus\",\n \"presetNameLabel\": \"Nimi\",\n \"openDialogTitle\": \"Avaa esiasetus\",\n \"deleteDialogTitle\": \"Poista esiasetus\",\n \"newDialogTitle\": \"Uusi asiakirja\",\n \"newDialogMessage\": \"Tämä tyhjentää nykyisen editorin sisällön ja asetukset. Tallenna nykyinen työ ensin?\",\n \"newDialogSaveButton\": \"Tallenna ja tyhjennä\",\n \"newDialogDiscardButton\": \"Hylkää\",\n \"presetLabel\": \"Esiasetus\",\n \"confirmOverwrite\": \"Esiasetus nimeltä “{{name}}” on jo olemassa. Korvataanko se?\",\n \"confirmDiscard\": \"Avaa “{{name}}” ja hylkää muutokset, joita ei ole tallennettu?\",\n \"confirmDelete\": \"Poistetaanko “{{name}}”? Tätä ei voi peruuttaa.\",\n \"emptyPresets\": \"Tallennettuja esiasetuksia ei ole saatavilla.\",\n \"invalidName\": \"Syötä esiasetuksen nimi.\",\n \"invalidPreset\": \"Tätä esiasetusta ei voi avata — se on virheellinen.\",\n \"importInvalidFile\": \"Valittu tiedosto ei ole kelvollinen pantoken TinyMCE -vientitiedosto.\",\n \"storageReadError\": \"Tallennettuja esiasetuksia ei voitu lukea tästä selaimesta.\",\n \"storageWriteError\": \"Esiasetusta ei voitu tallentaa tähän selaimeen.\",\n \"storageDeleteError\": \"Esiasetusta ei voitu poistaa tästä selaimesta.\",\n \"exportDefaultName\": \"nimetön\",\n \"presetSaveButton\": \"Tallenna\",\n \"presetOpenButton\": \"Avaa\",\n \"presetDeleteButton\": \"Poista\"\n },\n \"fr\": {\n \"autocompleteModifierDetail\": \"modifier\",\n \"classValidationIncompleteComponent\": \"Nom de composant incomplet après '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Le jeton doit commencer par '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Composant/utilitaire inconnu : '{{componentName}}'\",\n \"componentsDialogTitle\": \"Insérer le composant\",\n \"componentsListLabel\": \"Composants\",\n \"componentsMenuText\": \"Composant\",\n \"componentsToolbarText\": \"Composants\",\n \"componentsToolbarTooltip\": \"Insérer un composant pantoken\",\n \"componentModifiersDefault\": \"Par défaut\",\n \"componentModifiersOptions\": \"Options\",\n \"componentModifiersTooltip\": \"Modifier les modificateurs du composant\",\n \"componentModifiersUtilities\": \"Utilitaires\",\n \"iconLabelDialogTitle\": \"Étiquette d'icône\",\n \"iconLabelInputLabel\": \"Étiquette pour lecteur d'écran\",\n \"iconsMenuText\": \"Icône\",\n \"iconsSearchPlaceholder\": \"Rechercher des icônes…\",\n \"iconsSearchLabel\": \"Rechercher des icônes\",\n \"iconsAllSources\": \"Tout\",\n \"iconsResultCount\": \"{{count}} icônes\",\n \"iconsNoResults\": \"Aucune icône ne correspond à votre recherche.\",\n \"iconsToolbarText\": \"Icônes\",\n \"iconsToolbarTooltip\": \"Insérer une icône\",\n \"iconContextSizeSmall\": \"Petit\",\n \"iconContextSizeMedium\": \"Moyen\",\n \"iconContextSizeLarge\": \"Grand\",\n \"iconContextSizeExtraLarge\": \"Très grand\",\n \"layoutsConfirmReplace\": \"Remplacer le contenu actuel par la mise en page \\\"{{title}}\\\" ?\",\n \"layoutsDialogTitle\": \"Insérer la mise en page\",\n \"layoutsMenuText\": \"Mise en page…\",\n \"layoutsSelectLabel\": \"Mise en page de démarrage\",\n \"layoutsToolbarText\": \"Mises en page\",\n \"layoutsToolbarTooltip\": \"Insérer une mise en page de démarrage\",\n \"logosToolbarText\": \"Logos\",\n \"logosToolbarTooltip\": \"Insérer un logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Insérer le logo\",\n \"insertButton\": \"Insérer\",\n \"replaceButton\": \"Remplacer\",\n \"cancelButton\": \"Annuler\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Remplacer le contenu actuel par le modèle \\\"{{title}}\\\" ?\",\n \"templatesDialogTitle\": \"Insérer le modèle\",\n \"templatesMenuText\": \"Insérer le modèle…\",\n \"templatesSelectLabel\": \"Modèle de démarrage\",\n \"templatesToolbarText\": \"Modèles\",\n \"placeholdToolbarText\": \"Espace réservé\",\n \"placeholdToolbarTooltip\": \"Insérer une image d'espace réservé\",\n \"placeholdMenuText\": \"Image d'espace réservé…\",\n \"placeholdDialogTitle\": \"Insérer l'image d'espace réservé\",\n \"placeholdWidthLabel\": \"Largeur\",\n \"placeholdHeightLabel\": \"Hauteur\",\n \"placeholdBackgroundColorLabel\": \"Couleur d'arrière-plan\",\n \"placeholdTextColorLabel\": \"Couleur du texte\",\n \"placeholdTextLabel\": \"Texte\",\n \"placeholdAltTextLabel\": \"Texte alternatif\",\n \"placeholdInsertButton\": \"Insérer\",\n \"placeholdCancelButton\": \"Annuler\",\n \"placeholdInvalidDimensions\": \"La largeur et la hauteur doivent être des nombres entiers compris entre 10 et 4000.\",\n \"placeholdInvalidColor\": \"Les couleurs doivent utiliser des valeurs hexadécimales à trois ou six chiffres.\",\n \"placeholdAltFallback\": \"{{width}} par {{height}} image d'espace réservé\",\n \"a11yToolbarText\": \"Vérifier l'accessibilité\",\n \"a11yToolbarTooltip\": \"Vérifier le contenu pour des problèmes d'accessibilité\",\n \"a11yMenuText\": \"Vérifier l'accessibilité\",\n \"a11yDialogTitle\": \"Vérificateur d'accessibilité\",\n \"a11yNoIssues\": \"Aucun problème d'accessibilité trouvé.\",\n \"a11yIssueCount\": \"{{count}} problème(s) d'accessibilité trouvé(s).\",\n \"a11yStatusbarIssueCount\": \"{{count}} problèmes d'accessibilité\",\n \"a11yIssueLabel\": \"Problème\",\n \"a11yCloseButton\": \"Fermer\",\n \"a11yImageAltMessage\": \"Les images doivent avoir un texte alternatif.\",\n \"a11yImageAltWhy\": \"Les lecteurs d'écran ont besoin d'un attribut alt pour décrire une image ou l'identifier comme décorative.\",\n \"a11yImageAltFilenameMessage\": \"Le texte alternatif d'une image doit décrire l'image, pas répéter son nom de fichier.\",\n \"a11yImageAltFilenameWhy\": \"Un nom de fichier donne rarement des informations utiles sur une image aux utilisateurs de lecteurs d'écran.\",\n \"a11yImageAltLengthMessage\": \"Le texte alternatif d'une image doit contenir 125 caractères ou moins.\",\n \"a11yImageAltLengthWhy\": \"Les descriptions courtes sont plus faciles à comprendre et à parcourir avec une technologie d'assistance.\",\n \"a11yHeadingSequenceMessage\": \"Les niveaux de titre ne doivent pas sauter de niveaux.\",\n \"a11yHeadingSequenceWhy\": \"Une structure logique des titres aide les personnes à naviguer dans le contenu avec une technologie d'assistance.\",\n \"a11yTableHeaderMessage\": \"Les tableaux doivent inclure des cellules d'en-tête.\",\n \"a11yTableHeaderWhy\": \"Les cellules d'en-tête donnent aux lecteurs d'écran le contexte nécessaire pour comprendre les données du tableau.\",\n \"a11yTableCaptionMessage\": \"Les tableaux devraient inclure une légende.\",\n \"a11yTableCaptionWhy\": \"Une légende identifie l'objectif d'un tableau avant qu'un lecteur d'écran n'entre dans ses cellules.\",\n \"a11yTableHeaderScopeMessage\": \"Les cellules d'en-tête de tableau devraient déclarer leur portée.\",\n \"a11yTableHeaderScopeWhy\": \"L'attribut scope permet à la technologie d'assistance d'associer les en-têtes aux cellules de données.\",\n \"a11yAdjacentLinksMessage\": \"Les liens adjacents pointant vers la même destination devraient être combinés.\",\n \"a11yAdjacentLinksWhy\": \"Les liens répétés créent des arrêts inutiles pour les utilisateurs au clavier et aux lecteurs d'écran.\",\n \"a11yHeadingStartMessage\": \"Le premier titre devrait être un h2.\",\n \"a11yHeadingStartWhy\": \"Le titre du document de l'éditeur est fourni en dehors du contenu modifiable.\",\n \"a11yListStructureMessage\": \"Les éléments de liste doivent être contenus par une liste ordonnée ou non ordonnée.\",\n \"a11yListStructureWhy\": \"La technologie d'assistance s'appuie sur la structure des listes pour annoncer le nombre d'éléments et la position.\",\n \"sourceToggleTooltip\": \"Code source\",\n \"sourceFormatErrorMessage\": \"Impossible de formater le code source — vérifiez les balises non fermées ou d'autres erreurs de syntaxe.\",\n \"saveToolbarText\": \"Préréglages\",\n \"saveToolbarTooltip\": \"Gérer les préréglages enregistrés\",\n \"saveAction\": \"Enregistrer\",\n \"saveAsAction\": \"Enregistrer sous...\",\n \"openAction\": \"Ouvrir...\",\n \"deleteAction\": \"Supprimer...\",\n \"newAction\": \"Nouveau\",\n \"exportAction\": \"Exporter...\",\n \"importAction\": \"Importer...\",\n \"saveAsDialogTitle\": \"Enregistrer le préréglage\",\n \"presetNameLabel\": \"Nom\",\n \"openDialogTitle\": \"Ouvrir le préréglage\",\n \"deleteDialogTitle\": \"Supprimer le préréglage\",\n \"newDialogTitle\": \"Nouveau document\",\n \"newDialogMessage\": \"Cela efface le contenu et la configuration de l'éditeur actuel. Enregistrer le travail en cours d'abord ?\",\n \"newDialogSaveButton\": \"Enregistrer & effacer\",\n \"newDialogDiscardButton\": \"Abandonner\",\n \"presetLabel\": \"Préréglage\",\n \"confirmOverwrite\": \"Un préréglage nommé «\xA0{{name}}\xA0» existe déjà. Le remplacer ?\",\n \"confirmDiscard\": \"Ouvrir «\xA0{{name}}\xA0» et abandonner les modifications non enregistrées actuelles ?\",\n \"confirmDelete\": \"Supprimer «\xA0{{name}}\xA0» ? Cela ne peut pas être annulé.\",\n \"emptyPresets\": \"Aucun préréglage enregistré disponible.\",\n \"invalidName\": \"Entrez un nom de préréglage.\",\n \"invalidPreset\": \"Ce préréglage est invalide et n'a pas pu être ouvert.\",\n \"importInvalidFile\": \"Le fichier sélectionné n'est pas une exportation pantoken TinyMCE valide.\",\n \"storageReadError\": \"Les préréglages enregistrés n'ont pas pu être lus depuis ce navigateur.\",\n \"storageWriteError\": \"Le préréglage n'a pas pu être enregistré dans ce navigateur.\",\n \"storageDeleteError\": \"Le préréglage n'a pas pu être supprimé de ce navigateur.\",\n \"exportDefaultName\": \"sans titre\",\n \"presetSaveButton\": \"Enregistrer\",\n \"presetOpenButton\": \"Ouvrir\",\n \"presetDeleteButton\": \"Supprimer\"\n },\n \"fr-CA\": {\n \"autocompleteModifierDetail\": \"modifier\",\n \"classValidationIncompleteComponent\": \"Nom de composant incomplet après '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Le jeton doit commencer par '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Composant/outil inconnu : '{{componentName}}'\",\n \"componentsDialogTitle\": \"Insérer un composant\",\n \"componentsListLabel\": \"Composants\",\n \"componentsMenuText\": \"Composant\",\n \"componentsToolbarText\": \"Composants\",\n \"componentsToolbarTooltip\": \"Insérer un composant pantoken\",\n \"componentModifiersDefault\": \"Par défaut\",\n \"componentModifiersOptions\": \"Options\",\n \"componentModifiersTooltip\": \"Modifier les modificateurs du composant\",\n \"componentModifiersUtilities\": \"Utilitaires\",\n \"iconLabelDialogTitle\": \"Libellé de l'icône\",\n \"iconLabelInputLabel\": \"Libellé pour lecteur d'écran\",\n \"iconsMenuText\": \"Icône\",\n \"iconsSearchPlaceholder\": \"Rechercher des icônes…\",\n \"iconsSearchLabel\": \"Rechercher des icônes\",\n \"iconsAllSources\": \"Tous\",\n \"iconsResultCount\": \"{{count}} icônes\",\n \"iconsNoResults\": \"Aucune icône ne correspond à votre recherche.\",\n \"iconsToolbarText\": \"Icônes\",\n \"iconsToolbarTooltip\": \"Insérer une icône\",\n \"iconContextSizeSmall\": \"Petit\",\n \"iconContextSizeMedium\": \"Moyen\",\n \"iconContextSizeLarge\": \"Grand\",\n \"iconContextSizeExtraLarge\": \"Très grand\",\n \"layoutsConfirmReplace\": \"Remplacer le contenu actuel par la mise en page \\\"{{title}}\\\" ?\",\n \"layoutsDialogTitle\": \"Insérer une mise en page\",\n \"layoutsMenuText\": \"Mise en page…\",\n \"layoutsSelectLabel\": \"Mise en page de démarrage\",\n \"layoutsToolbarText\": \"Mises en page\",\n \"layoutsToolbarTooltip\": \"Insérer une mise en page de démarrage\",\n \"logosToolbarText\": \"Logos\",\n \"logosToolbarTooltip\": \"Insérer un logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Insérer le logo\",\n \"insertButton\": \"Insérer\",\n \"replaceButton\": \"Remplacer\",\n \"cancelButton\": \"Annuler\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Remplacer le contenu actuel par le modèle \\\"{{title}}\\\" ?\",\n \"templatesDialogTitle\": \"Insérer un modèle\",\n \"templatesMenuText\": \"Insérer le modèle…\",\n \"templatesSelectLabel\": \"Modèle de démarrage\",\n \"templatesToolbarText\": \"Modèles\",\n \"placeholdToolbarText\": \"Espace réservé\",\n \"placeholdToolbarTooltip\": \"Insérer une image d'espace réservé\",\n \"placeholdMenuText\": \"Image d'espace réservé…\",\n \"placeholdDialogTitle\": \"Insérer une image d'espace réservé\",\n \"placeholdWidthLabel\": \"Largeur\",\n \"placeholdHeightLabel\": \"Hauteur\",\n \"placeholdBackgroundColorLabel\": \"Couleur d'arrière-plan\",\n \"placeholdTextColorLabel\": \"Couleur du texte\",\n \"placeholdTextLabel\": \"Texte\",\n \"placeholdAltTextLabel\": \"Texte alternatif\",\n \"placeholdInsertButton\": \"Insérer\",\n \"placeholdCancelButton\": \"Annuler\",\n \"placeholdInvalidDimensions\": \"La largeur et la hauteur doivent être des nombres entiers compris entre 10 et 4000.\",\n \"placeholdInvalidColor\": \"Les couleurs doivent utiliser des valeurs hexadécimales à trois ou six chiffres.\",\n \"placeholdAltFallback\": \"{{width}} par {{height}} image d'espace réservé\",\n \"a11yToolbarText\": \"Vérifier l'accessibilité\",\n \"a11yToolbarTooltip\": \"Vérifier le contenu pour des problèmes d'accessibilité\",\n \"a11yMenuText\": \"Vérifier l'accessibilité\",\n \"a11yDialogTitle\": \"Vérificateur d'accessibilité\",\n \"a11yNoIssues\": \"Aucun problème d'accessibilité trouvé.\",\n \"a11yIssueCount\": \"{{count}} problème(s) d'accessibilité trouvé(s).\",\n \"a11yStatusbarIssueCount\": \"{{count}} problèmes d'accessibilité\",\n \"a11yIssueLabel\": \"Problème\",\n \"a11yCloseButton\": \"Fermer\",\n \"a11yImageAltMessage\": \"Les images doivent avoir un texte de remplacement.\",\n \"a11yImageAltWhy\": \"Les lecteurs d'écran ont besoin d'un attribut alt pour décrire une image ou l'identifier comme décorative.\",\n \"a11yImageAltFilenameMessage\": \"Le texte alternatif de l'image doit décrire l'image, et non répéter son nom de fichier.\",\n \"a11yImageAltFilenameWhy\": \"Un nom de fichier donne rarement des informations utiles aux utilisateurs de lecteurs d'écran.\",\n \"a11yImageAltLengthMessage\": \"Le texte alternatif d'une image doit comporter 125 caractères ou moins.\",\n \"a11yImageAltLengthWhy\": \"Les courtes descriptions sont plus faciles à comprendre et à naviguer avec une technologie d'assistance.\",\n \"a11yHeadingSequenceMessage\": \"Les niveaux de titres ne doivent pas sauter de niveau.\",\n \"a11yHeadingSequenceWhy\": \"Une hiérarchie logique des titres aide les personnes utilisant des technologies d'assistance à naviguer dans le contenu.\",\n \"a11yTableHeaderMessage\": \"Les tableaux doivent inclure des cellules d'en-tête.\",\n \"a11yTableHeaderWhy\": \"Les cellules d'en-tête fournissent aux lecteurs d'écran le contexte nécessaire pour comprendre les données du tableau.\",\n \"a11yTableCaptionMessage\": \"Les tableaux devraient inclure une légende.\",\n \"a11yTableCaptionWhy\": \"Une légende identifie l'objet d'un tableau avant que le lecteur d'écran n'accède à ses cellules.\",\n \"a11yTableHeaderScopeMessage\": \"Les cellules d'en-tête de tableau devraient déclarer leur portée.\",\n \"a11yTableHeaderScopeWhy\": \"L'attribut scope permet aux technologies d'assistance d'associer les en-têtes aux cellules de données.\",\n \"a11yAdjacentLinksMessage\": \"Les liens adjacents ayant la même destination devraient être combinés.\",\n \"a11yAdjacentLinksWhy\": \"Les liens répétés créent des arrêts inutiles pour les utilisateurs au clavier et les lecteurs d'écran.\",\n \"a11yHeadingStartMessage\": \"Le premier titre devrait être un h2.\",\n \"a11yHeadingStartWhy\": \"Le titre du document de l'éditeur est fourni en dehors du contenu modifiable.\",\n \"a11yListStructureMessage\": \"Les éléments de liste doivent être contenus dans une liste ordonnée ou non ordonnée.\",\n \"a11yListStructureWhy\": \"Les technologies d'assistance s'appuient sur la structure des listes pour annoncer le nombre d'éléments et leur position.\",\n \"sourceToggleTooltip\": \"Code source\",\n \"sourceFormatErrorMessage\": \"Impossible de formater le code source — vérifiez s'il y a des balises non fermées ou d'autres erreurs de syntaxe.\",\n \"saveToolbarText\": \"Préréglages\",\n \"saveToolbarTooltip\": \"Gérer les préréglages enregistrés\",\n \"saveAction\": \"Enregistrer\",\n \"saveAsAction\": \"Enregistrer sous…\",\n \"openAction\": \"Ouvrir…\",\n \"deleteAction\": \"Supprimer…\",\n \"newAction\": \"Nouveau\",\n \"exportAction\": \"Exporter...\",\n \"importAction\": \"Importer...\",\n \"saveAsDialogTitle\": \"Enregistrer le préréglage\",\n \"presetNameLabel\": \"Nom\",\n \"openDialogTitle\": \"Ouvrir le préréglage\",\n \"deleteDialogTitle\": \"Supprimer le préréglage\",\n \"newDialogTitle\": \"Nouveau document\",\n \"newDialogMessage\": \"Cela effacera le contenu et la configuration de l'éditeur actuel. Enregistrer le travail en cours d'abord ?\",\n \"newDialogSaveButton\": \"Enregistrer & effacer\",\n \"newDialogDiscardButton\": \"Abandonner\",\n \"presetLabel\": \"Préréglage\",\n \"confirmOverwrite\": \"Un préréglage nommé “{{name}}” existe déjà. Le remplacer ?\",\n \"confirmDiscard\": \"Ouvrir “{{name}}” et supprimer les modifications non enregistrées en cours ?\",\n \"confirmDelete\": \"Supprimer “{{name}}”? Cette action est irréversible.\",\n \"emptyPresets\": \"Aucun préréglage enregistré n'est disponible.\",\n \"invalidName\": \"Entrez un nom de préréglage.\",\n \"invalidPreset\": \"Ce préréglage est invalide et n'a pas pu être ouvert.\",\n \"importInvalidFile\": \"Le fichier sélectionné n'est pas une exportation pantoken TinyMCE valide.\",\n \"storageReadError\": \"Les préréglages enregistrés n'ont pas pu être lus depuis ce navigateur.\",\n \"storageWriteError\": \"Le préréglage n'a pas pu être enregistré dans ce navigateur.\",\n \"storageDeleteError\": \"Le préréglage n'a pas pu être supprimé de ce navigateur.\",\n \"exportDefaultName\": \"sans titre\",\n \"presetSaveButton\": \"Enregistrer\",\n \"presetOpenButton\": \"Ouvrir\",\n \"presetDeleteButton\": \"Supprimer\"\n },\n \"ga\": {\n \"autocompleteModifierDetail\": \"modhnóir\",\n \"classValidationIncompleteComponent\": \"Ainm comhlachta gan críochnú tar éis '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Caithfidh an t-token tosú le '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Comhpháirt/úirlis anaithnid: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Iontráil Comhpháirt\",\n \"componentsListLabel\": \"Comhpháirteanna\",\n \"componentsMenuText\": \"Comhpháirt\",\n \"componentsToolbarText\": \"Comhpháirteanna\",\n \"componentsToolbarTooltip\": \"Iontráil comhpháirt pantoken\",\n \"componentModifiersDefault\": \"Réamhshocraithe\",\n \"componentModifiersOptions\": \"Roghanna\",\n \"componentModifiersTooltip\": \"Athraigh modhnóirí comhpháirte\",\n \"componentModifiersUtilities\": \"Uirlisí\",\n \"iconLabelDialogTitle\": \"Lipéad deilbhín\",\n \"iconLabelInputLabel\": \"Lipéad do léitheoir scáileáin\",\n \"iconsMenuText\": \"Deilbhín\",\n \"iconsSearchPlaceholder\": \"Ag cuardach deilbhíní…\",\n \"iconsSearchLabel\": \"Cuardaigh deilbhíní\",\n \"iconsAllSources\": \"Gach\",\n \"iconsResultCount\": \"{{count}} deilbhíní\",\n \"iconsNoResults\": \"Níl aon deilbhíní a oireann do d'chuardach.\",\n \"iconsToolbarText\": \"Deilbhíní\",\n \"iconsToolbarTooltip\": \"Iontráil deilbhín\",\n \"iconContextSizeSmall\": \"Beag\",\n \"iconContextSizeMedium\": \"Meán\",\n \"iconContextSizeLarge\": \"Mór\",\n \"iconContextSizeExtraLarge\": \"An-mhór\",\n \"layoutsConfirmReplace\": \"An ionadóidh tú an t-ábhar reatha leis an leagan amach \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Iontráil leagan amach\",\n \"layoutsMenuText\": \"Leagan amach…\",\n \"layoutsSelectLabel\": \"Leagan amach tosaigh\",\n \"layoutsToolbarText\": \"Leaganacha\",\n \"layoutsToolbarTooltip\": \"Iontráil leagan tosaigh\",\n \"logosToolbarText\": \"Lógónna\",\n \"logosToolbarTooltip\": \"Iontráil lógó\",\n \"logosMenuText\": \"Lógó\",\n \"logosDialogTitle\": \"Iontráil Lógó\",\n \"insertButton\": \"Iontráil\",\n \"replaceButton\": \"Athsholáthar\",\n \"cancelButton\": \"Cealaigh\",\n \"logoAltSuffix\": \"lógó\",\n \"templatesConfirmReplace\": \"An ionadóidh tú an t-ábhar reatha leis an teimpléad \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Iontráil teimpléad\",\n \"templatesMenuText\": \"Iontráil teimpléad…\",\n \"templatesSelectLabel\": \"Teimpléad tosaigh\",\n \"templatesToolbarText\": \"Teimpléid\",\n \"placeholdToolbarText\": \"Áitsholáthar\",\n \"placeholdToolbarTooltip\": \"Iontráil íomhá áitsholáthair\",\n \"placeholdMenuText\": \"Íomhá áitsholáthair…\",\n \"placeholdDialogTitle\": \"Iontráil íomhá áitsholáthair\",\n \"placeholdWidthLabel\": \"Leithead\",\n \"placeholdHeightLabel\": \"Airde\",\n \"placeholdBackgroundColorLabel\": \"Dath cúlra\",\n \"placeholdTextColorLabel\": \"Dath téacs\",\n \"placeholdTextLabel\": \"Téacs\",\n \"placeholdAltTextLabel\": \"Alt téacs\",\n \"placeholdInsertButton\": \"Iontráil\",\n \"placeholdCancelButton\": \"Cealaigh\",\n \"placeholdInvalidDimensions\": \"Caithfidh leithead agus airde a bheith ina n-uimhreacha iomlána ó 10 go 4000.\",\n \"placeholdInvalidColor\": \"Caithfidh dathanna luachanna heicsidéach trí- nó sé-dhigit a úsáid.\",\n \"placeholdAltFallback\": \"{{width}} faoi {{height}} íomhá áitsholáthair\",\n \"a11yToolbarText\": \"Seiceáil inrochtaineachta\",\n \"a11yToolbarTooltip\": \"Seiceáil an t-ábhar le haghaidh fadhbanna inrochtaineachta\",\n \"a11yMenuText\": \"Seiceáil inrochtaineachta\",\n \"a11yDialogTitle\": \"Seiceálaí inrochtaineachta\",\n \"a11yNoIssues\": \"Níor aimsíodh fadhbanna inrochtaineachta.\",\n \"a11yIssueCount\": \"{{count}} fhadhb inrochtaineachta aimsithe.\",\n \"a11yStatusbarIssueCount\": \"{{count}} fadhb inrochtaineachta\",\n \"a11yIssueLabel\": \"Fadhb\",\n \"a11yCloseButton\": \"Dún\",\n \"a11yImageAltMessage\": \"Ní mór téacs malartach a bheith ag íomhánna.\",\n \"a11yImageAltWhy\": \"Teastaíonn tréith `alt` ó léitheoirí scáileáin chun íomhá a chur síos nó í a aithint mar mhaisiúchán.\",\n \"a11yImageAltFilenameMessage\": \"Ba chóir go ndéanfaidh téacs malartach na híomhá cur síos ar an íomhá, ní a ainm comhaid a athrá.\",\n \"a11yImageAltFilenameWhy\": \"Is annamh a thugann ainm comhaid faisnéis úsáideach do léitheoirí scáileáin faoi íomhá.\",\n \"a11yImageAltLengthMessage\": \"Ba chóir go mbeadh téacs malartach na híomhá 125 carachtar nó níos lú.\",\n \"a11yImageAltLengthWhy\": \"Tá tuairiscí gonta níos éasca le tuiscint agus le nascleanúint le teicneolaíochtaí cúnta.\",\n \"a11yHeadingSequenceMessage\": \"Níor chóir leibhéil teidil a scipeáil.\",\n \"a11yHeadingSequenceWhy\": \"Cuidíonn struchtúr loighciúil teidil le daoine nascleanúint a dhéanamh ar ábhar ag úsáid teicneolaíochtaí cúnta.\",\n \"a11yTableHeaderMessage\": \"Ní mór cilleanna ceanntásca a bheith i dtáblaí.\",\n \"a11yTableHeaderWhy\": \"Tugann cilleanna ceanntásc an comhthéacs atá ag teastáil ó léitheoirí scáileáin chun sonraí tábla a thuiscint.\",\n \"a11yTableCaptionMessage\": \"Ba chóir go mbeadh fotheideal ag táblaí.\",\n \"a11yTableCaptionWhy\": \"Aithníonn fotheideal cuspóir an tábla sular iontrálfaidh léitheoir scáileáin a chillí.\",\n \"a11yTableHeaderScopeMessage\": \"Ba chóir do chill cheanntásca tábla an tréith `scope` a shonrú.\",\n \"a11yTableHeaderScopeWhy\": \"Ligeann an tréith `scope` do theicneolaíochtaí cúnta ceanntáscanna a chur i dteagmháil le cillí sonraí.\",\n \"a11yAdjacentLinksMessage\": \"Ba chóir nascanna in aice lena chéile le ceann scríbe céanna a chomhcheangal.\",\n \"a11yAdjacentLinksWhy\": \"Cruthaíonn naisc athráite stadanna neamhghánta do bhaill úsáideora méarchláir agus léitheoirí scáileáin.\",\n \"a11yHeadingStartMessage\": \"Ba chóir go mbeadh an chéad theideal mar h2.\",\n \"a11yHeadingStartWhy\": \"Tugtar teideal an doiciméid eagarthóra lasmuigh den ábhar inathraithe.\",\n \"a11yListStructureMessage\": \"Ní mór míreanna liosta a bheith laistigh de liosta ordaithe nó neamhrordaithe.\",\n \"a11yListStructureWhy\": \"Braitheann teicneolaíochtaí cúnta ar struchtúr liosta chun líon agus suíomh na míreanna a fhógairt.\",\n \"sourceToggleTooltip\": \"Cód foinse\",\n \"sourceFormatErrorMessage\": \"Níorbh fhéidir an cód foinse a fhormáidiú — seiceáil an bhfuil clibeanna neamh-dhúntha nó earráidí sintéise eile.\",\n \"saveToolbarText\": \"Réamhshocruithe\",\n \"saveToolbarTooltip\": \"Bainistigh réamhshocruithe sábháilte\",\n \"saveAction\": \"Sábháil\",\n \"saveAsAction\": \"Sábháil mar...\",\n \"openAction\": \"Oscail...\",\n \"deleteAction\": \"Scrios...\",\n \"newAction\": \"Nua\",\n \"exportAction\": \"Easpórtáil...\",\n \"importAction\": \"Iompórtáil...\",\n \"saveAsDialogTitle\": \"Sábháil réamhshocrú\",\n \"presetNameLabel\": \"Ainm\",\n \"openDialogTitle\": \"Oscail réamhshocrú\",\n \"deleteDialogTitle\": \"Scrios réamhshocrú\",\n \"newDialogTitle\": \"Doiciméad nua\",\n \"newDialogMessage\": \"Scriosann sé seo ábhar agus cumraíocht an eagarthóra reatha. An sábháilfá an obair reatha ar dtús?\",\n \"newDialogSaveButton\": \"Sábháil & glan\",\n \"newDialogDiscardButton\": \"Scartaigh\",\n \"presetLabel\": \"Réamhshocrú\",\n \"confirmOverwrite\": \"Tá réamhshocrú darb ainm “{{name}}” ann cheana. An gcuirfí ina áit é?\",\n \"confirmDiscard\": \"Oscail “{{name}}” agus diúltaigh na hathruithe reatha nach bhfuil sábháilte?\",\n \"confirmDelete\": \"Scrios “{{name}}”? Ní féidir seo a chealú.\",\n \"emptyPresets\": \"Níl aon réamhshocruithe sábháilte ar fáil.\",\n \"invalidName\": \"Cuir isteach ainm réamhshocrú.\",\n \"invalidPreset\": \"Tá an réamhshocrú seo neamhdhleathach agus níorbh fhéidir é a oscailt.\",\n \"importInvalidFile\": \"Níl an comhad roghnaithe ina easpórtáil pantoken TinyMCE bailí.\",\n \"storageReadError\": \"Níorbh fhéidir réamhshocruithe sábháilte a léamh ón mbrabhsálaí seo.\",\n \"storageWriteError\": \"Níorbh fhéidir an réamhshocrú a shábháil sa bhrabhsálaí seo.\",\n \"storageDeleteError\": \"Níorbh fhéidir an réamhshocrú a scriosadh ón mbrabhsálaí seo.\",\n \"exportDefaultName\": \"gan teideal\",\n \"presetSaveButton\": \"Sábháil\",\n \"presetOpenButton\": \"Oscail\",\n \"presetDeleteButton\": \"Scrios\"\n },\n \"de\": {\n \"autocompleteModifierDetail\": \"modifier\",\n \"classValidationIncompleteComponent\": \"Unvollständiger Komponentenname nach '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token muss mit '{{prefix}}' beginnen\",\n \"classValidationUnknownComponent\": \"Unbekannte Komponente/Utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Komponente einfügen\",\n \"componentsListLabel\": \"Komponenten\",\n \"componentsMenuText\": \"Komponente\",\n \"componentsToolbarText\": \"Komponenten\",\n \"componentsToolbarTooltip\": \"Eine pantoken-Komponente einfügen\",\n \"componentModifiersDefault\": \"Standard\",\n \"componentModifiersOptions\": \"Optionen\",\n \"componentModifiersTooltip\": \"Komponentenmodifikatoren ändern\",\n \"componentModifiersUtilities\": \"Dienstprogramme\",\n \"iconLabelDialogTitle\": \"Icon-Beschriftung\",\n \"iconLabelInputLabel\": \"Screenreader-Beschriftung\",\n \"iconsMenuText\": \"Symbol\",\n \"iconsSearchPlaceholder\": \"Symbole durchsuchen…\",\n \"iconsSearchLabel\": \"Symbole durchsuchen\",\n \"iconsAllSources\": \"Alle\",\n \"iconsResultCount\": \"{{count}} Symbole\",\n \"iconsNoResults\": \"Keine Symbole entsprechen Ihrer Suche.\",\n \"iconsToolbarText\": \"Symbole\",\n \"iconsToolbarTooltip\": \"Ein Symbol einfügen\",\n \"iconContextSizeSmall\": \"Klein\",\n \"iconContextSizeMedium\": \"Mittel\",\n \"iconContextSizeLarge\": \"Groß\",\n \"iconContextSizeExtraLarge\": \"Extra groß\",\n \"layoutsConfirmReplace\": \"Den aktuellen Inhalt durch das \\\"{{title}}\\\"-Layout ersetzen?\",\n \"layoutsDialogTitle\": \"Layout einfügen\",\n \"layoutsMenuText\": \"Layout…\",\n \"layoutsSelectLabel\": \"Starter-Layout\",\n \"layoutsToolbarText\": \"Layouts\",\n \"layoutsToolbarTooltip\": \"Ein Starter-Layout einfügen\",\n \"logosToolbarText\": \"Logos\",\n \"logosToolbarTooltip\": \"Ein Logo einfügen\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Logo einfügen\",\n \"insertButton\": \"Einfügen\",\n \"replaceButton\": \"Ersetzen\",\n \"cancelButton\": \"Abbrechen\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Den aktuellen Inhalt durch die \\\"{{title}}\\\"-Vorlage ersetzen?\",\n \"templatesDialogTitle\": \"Vorlage einfügen\",\n \"templatesMenuText\": \"Vorlage einfügen…\",\n \"templatesSelectLabel\": \"Starter-Vorlage\",\n \"templatesToolbarText\": \"Vorlagen\",\n \"placeholdToolbarText\": \"Platzhalter\",\n \"placeholdToolbarTooltip\": \"Ein Platzhalterbild einfügen\",\n \"placeholdMenuText\": \"Platzhalterbild…\",\n \"placeholdDialogTitle\": \"Platzhalterbild einfügen\",\n \"placeholdWidthLabel\": \"Breite\",\n \"placeholdHeightLabel\": \"Höhe\",\n \"placeholdBackgroundColorLabel\": \"Hintergrundfarbe\",\n \"placeholdTextColorLabel\": \"Textfarbe\",\n \"placeholdTextLabel\": \"Text\",\n \"placeholdAltTextLabel\": \"Alternativtext\",\n \"placeholdInsertButton\": \"Einfügen\",\n \"placeholdCancelButton\": \"Abbrechen\",\n \"placeholdInvalidDimensions\": \"Breite und Höhe müssen ganze Zahlen zwischen 10 und 4000 sein.\",\n \"placeholdInvalidColor\": \"Farben müssen drei- oder sechsstellige hexadezimale Werte verwenden.\",\n \"placeholdAltFallback\": \"{{width}} × {{height}} Platzhalterbild\",\n \"a11yToolbarText\": \"Barrierefreiheit prüfen\",\n \"a11yToolbarTooltip\": \"Inhalte auf Barrierefreiheitsprobleme prüfen\",\n \"a11yMenuText\": \"Barrierefreiheit prüfen\",\n \"a11yDialogTitle\": \"Barrierefreiheitsprüfer\",\n \"a11yNoIssues\": \"Keine Barrierefreiheitsprobleme gefunden.\",\n \"a11yIssueCount\": \"{{count}} Barrierefreiheitsproblem(e) gefunden.\",\n \"a11yStatusbarIssueCount\": \"{{count}} Barrierefreiheitsprobleme\",\n \"a11yIssueLabel\": \"Problem\",\n \"a11yCloseButton\": \"Schließen\",\n \"a11yImageAltMessage\": \"Bilder müssen einen Alternativtext haben.\",\n \"a11yImageAltWhy\": \"Screenreader benötigen ein alt-Attribut, um ein Bild zu beschreiben oder als dekorativ zu kennzeichnen.\",\n \"a11yImageAltFilenameMessage\": \"Der Alternativtext eines Bildes sollte das Bild beschreiben und nicht den Dateinamen wiederholen.\",\n \"a11yImageAltFilenameWhy\": \"Ein Dateiname liefert Screenreader-Nutzern selten nützliche Informationen über ein Bild.\",\n \"a11yImageAltLengthMessage\": \"Der Alternativtext eines Bildes sollte 125 Zeichen oder weniger lang sein.\",\n \"a11yImageAltLengthWhy\": \"Kurze Beschreibungen sind mit unterstützender Technologie leichter zu verstehen und zu navigieren.\",\n \"a11yHeadingSequenceMessage\": \"Überschriftenebenen sollten nicht übersprungen werden.\",\n \"a11yHeadingSequenceWhy\": \"Eine logische Gliederung der Überschriften hilft Menschen, Inhalte mit unterstützender Technologie zu navigieren.\",\n \"a11yTableHeaderMessage\": \"Tabellen müssen Kopfzellen enthalten.\",\n \"a11yTableHeaderWhy\": \"Kopfzellen geben Screenreadern den nötigen Kontext, um Tabellendaten zu verstehen.\",\n \"a11yTableCaptionMessage\": \"Tabellen sollten eine Beschriftung enthalten.\",\n \"a11yTableCaptionWhy\": \"Eine Beschriftung benennt den Zweck einer Tabelle, bevor ein Screenreader ihre Zellen ausliest.\",\n \"a11yTableHeaderScopeMessage\": \"Tabellenkopfzellen sollten ihren Scope angeben.\",\n \"a11yTableHeaderScopeWhy\": \"Das scope-Attribut ermöglicht unterstützenden Technologien, Kopfzeilen mit Datenzellen zu verknüpfen.\",\n \"a11yAdjacentLinksMessage\": \"Nebeneinanderstehende Links mit demselben Ziel sollten zusammengeführt werden.\",\n \"a11yAdjacentLinksWhy\": \"Wiederholte Links erzeugen unnötige Stopps für Tastatur- und Screenreader-Nutzer.\",\n \"a11yHeadingStartMessage\": \"Die erste Überschrift sollte ein h2 sein.\",\n \"a11yHeadingStartWhy\": \"Der Dokumenttitel des Editors wird außerhalb des editierbaren Inhalts bereitgestellt.\",\n \"a11yListStructureMessage\": \"Listenelemente müssen in einer geordneten oder ungeordneten Liste enthalten sein.\",\n \"a11yListStructureWhy\": \"Assistive Technologien sind auf die Listenstruktur angewiesen, um Anzahl und Position der Elemente anzusagen.\",\n \"sourceToggleTooltip\": \"Quellcode\",\n \"sourceFormatErrorMessage\": \"Konnte den Quellcode nicht formatieren — prüfen Sie auf nicht geschlossene Tags oder andere Syntaxfehler.\",\n \"saveToolbarText\": \"Voreinstellungen\",\n \"saveToolbarTooltip\": \"Gespeicherte Voreinstellungen verwalten\",\n \"saveAction\": \"Speichern\",\n \"saveAsAction\": \"Speichern als...\",\n \"openAction\": \"Öffnen...\",\n \"deleteAction\": \"Löschen...\",\n \"newAction\": \"Neu\",\n \"exportAction\": \"Exportieren...\",\n \"importAction\": \"Importieren...\",\n \"saveAsDialogTitle\": \"Voreinstellung speichern\",\n \"presetNameLabel\": \"Name\",\n \"openDialogTitle\": \"Voreinstellung öffnen\",\n \"deleteDialogTitle\": \"Voreinstellung löschen\",\n \"newDialogTitle\": \"Neues Dokument\",\n \"newDialogMessage\": \"Dadurch werden der aktuelle Inhalt und die Konfiguration des Editors gelöscht. Zuerst die aktuelle Arbeit speichern?\",\n \"newDialogSaveButton\": \"Speichern & löschen\",\n \"newDialogDiscardButton\": \"Verwerfen\",\n \"presetLabel\": \"Voreinstellung\",\n \"confirmOverwrite\": \"Eine Voreinstellung mit dem Namen “{{name}}” existiert bereits. Ersetzen?\",\n \"confirmDiscard\": \"Öffnen “{{name}}” und die aktuellen nicht gespeicherten Änderungen verwerfen?\",\n \"confirmDelete\": \"“{{name}}” löschen? Dies kann nicht rückgängig gemacht werden.\",\n \"emptyPresets\": \"Keine gespeicherten Voreinstellungen verfügbar.\",\n \"invalidName\": \"Geben Sie einen Namen für die Voreinstellung ein.\",\n \"invalidPreset\": \"Diese Voreinstellung ist ungültig und konnte nicht geöffnet werden.\",\n \"importInvalidFile\": \"Die ausgewählte Datei ist kein gültiger pantoken TinyMCE-Export.\",\n \"storageReadError\": \"Gespeicherte Voreinstellungen konnten nicht aus diesem Browser gelesen werden.\",\n \"storageWriteError\": \"Die Voreinstellung konnte nicht in diesem Browser gespeichert werden.\",\n \"storageDeleteError\": \"Die Voreinstellung konnte nicht aus diesem Browser gelöscht werden.\",\n \"exportDefaultName\": \"Unbenannt\",\n \"presetSaveButton\": \"Speichern\",\n \"presetOpenButton\": \"Öffnen\",\n \"presetDeleteButton\": \"Löschen\"\n },\n \"el\": {\n \"autocompleteModifierDetail\": \"τροποποιητής\",\n \"classValidationIncompleteComponent\": \"Ελλιπές όνομα συνιστώσας μετά το '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Το token πρέπει να ξεκινά με '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Άγνωστη συνιστώσα/βοηθητικό: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Εισαγωγή Συνιστώσας\",\n \"componentsListLabel\": \"Συνιστώσες\",\n \"componentsMenuText\": \"Συνιστώσα\",\n \"componentsToolbarText\": \"Συνιστώσες\",\n \"componentsToolbarTooltip\": \"Εισαγωγή συνιστώσας pantoken\",\n \"componentModifiersDefault\": \"Προεπιλογή\",\n \"componentModifiersOptions\": \"Επιλογές\",\n \"componentModifiersTooltip\": \"Αλλαγή τροποποιητών συστατικού\",\n \"componentModifiersUtilities\": \"Βοηθητικά\",\n \"iconLabelDialogTitle\": \"Ετικέτα εικονιδίου\",\n \"iconLabelInputLabel\": \"Ετικέτα για αναγνώστη οθόνης\",\n \"iconsMenuText\": \"Εικονίδιο\",\n \"iconsSearchPlaceholder\": \"Αναζήτηση εικονιδίων…\",\n \"iconsSearchLabel\": \"Αναζήτηση εικονιδίων\",\n \"iconsAllSources\": \"Όλα\",\n \"iconsResultCount\": \"{{count}} εικονίδια\",\n \"iconsNoResults\": \"Κανένα εικονίδιο δεν ταιριάζει στην αναζήτησή σας.\",\n \"iconsToolbarText\": \"Εικονίδια\",\n \"iconsToolbarTooltip\": \"Εισαγωγή εικονιδίου\",\n \"iconContextSizeSmall\": \"Μικρό\",\n \"iconContextSizeMedium\": \"Μεσαίο\",\n \"iconContextSizeLarge\": \"Μεγάλο\",\n \"iconContextSizeExtraLarge\": \"Εξτρα μεγάλο\",\n \"layoutsConfirmReplace\": \"Να αντικατασταθεί το τρέχον περιεχόμενο με τη διάταξη \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Εισαγωγή διάταξης\",\n \"layoutsMenuText\": \"Διάταξη…\",\n \"layoutsSelectLabel\": \"Διάταξη εκκίνησης\",\n \"layoutsToolbarText\": \"Διατάξεις\",\n \"layoutsToolbarTooltip\": \"Εισαγωγή διάταξης εκκίνησης\",\n \"logosToolbarText\": \"Λογότυπα\",\n \"logosToolbarTooltip\": \"Εισαγωγή λογότυπου\",\n \"logosMenuText\": \"Λογότυπο\",\n \"logosDialogTitle\": \"Εισαγωγή λογότυπου\",\n \"insertButton\": \"Εισαγωγή\",\n \"replaceButton\": \"Αντικατάσταση\",\n \"cancelButton\": \"Ακύρωση\",\n \"logoAltSuffix\": \"λογότυπο\",\n \"templatesConfirmReplace\": \"Να αντικατασταθεί το τρέχον περιεχόμενο με το πρότυπο \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Εισαγωγή προτύπου\",\n \"templatesMenuText\": \"Εισαγωγή προτύπου…\",\n \"templatesSelectLabel\": \"Πρότυπο εκκίνησης\",\n \"templatesToolbarText\": \"Πρότυπα\",\n \"placeholdToolbarText\": \"Δείκτης κράτησης\",\n \"placeholdToolbarTooltip\": \"Εισαγωγή εικόνας δείκτη κράτησης\",\n \"placeholdMenuText\": \"Εικόνα δείκτη κράτησης…\",\n \"placeholdDialogTitle\": \"Εισαγωγή εικόνας δείκτη κράτησης\",\n \"placeholdWidthLabel\": \"Πλάτος\",\n \"placeholdHeightLabel\": \"Ύψος\",\n \"placeholdBackgroundColorLabel\": \"Χρώμα φόντου\",\n \"placeholdTextColorLabel\": \"Χρώμα κειμένου\",\n \"placeholdTextLabel\": \"Κείμενο\",\n \"placeholdAltTextLabel\": \"Εναλλακτικό κείμενο\",\n \"placeholdInsertButton\": \"Εισαγωγή\",\n \"placeholdCancelButton\": \"Ακύρωση\",\n \"placeholdInvalidDimensions\": \"Το πλάτος και το ύψος πρέπει να είναι ακέραιοι αριθμοί από 10 έως 4000.\",\n \"placeholdInvalidColor\": \"Τα χρώματα πρέπει να χρησιμοποιούν δεκαεξαδικές τιμές τριών ή έξι ψηφίων.\",\n \"placeholdAltFallback\": \"{{width}} επί {{height}} εικόνα δείκτη κράτησης\",\n \"a11yToolbarText\": \"Έλεγχος προσβασιμότητας\",\n \"a11yToolbarTooltip\": \"Έλεγχος του περιεχομένου για προβλήματα προσβασιμότητας\",\n \"a11yMenuText\": \"Έλεγχος προσβασιμότητας\",\n \"a11yDialogTitle\": \"Ελεγκτής προσβασιμότητας\",\n \"a11yNoIssues\": \"Δεν βρέθηκαν προβλήματα προσβασιμότητας.\",\n \"a11yIssueCount\": \"Βρέθηκε {{count}} θέμα(τα) προσβασιμότητας.\",\n \"a11yStatusbarIssueCount\": \"{{count}} ζητήματα προσβασιμότητας\",\n \"a11yIssueLabel\": \"Πρόβλημα\",\n \"a11yCloseButton\": \"Κλείσιμο\",\n \"a11yImageAltMessage\": \"Οι εικόνες πρέπει να έχουν εναλλακτικό κείμενο.\",\n \"a11yImageAltWhy\": \"Οι αναγνώστες οθόνης χρειάζονται το attribute alt για να περιγράψουν μια εικόνα ή να την αναγνωρίσουν ως διακοσμητική.\",\n \"a11yImageAltFilenameMessage\": \"Το εναλλακτικό κείμενο εικόνας πρέπει να περιγράφει την εικόνα, όχι να επαναλαμβάνει το όνομα αρχείου της.\",\n \"a11yImageAltFilenameWhy\": \"Ένα όνομα αρχείου σπάνια δίνει χρήσιμη πληροφορία για τις εικόνες στους χρήστες αναγνωστών οθόνης.\",\n \"a11yImageAltLengthMessage\": \"Το εναλλακτικό κείμενο εικόνας πρέπει να έχει 125 χαρακτήρες ή λιγότερους.\",\n \"a11yImageAltLengthWhy\": \"Σύντομες περιγραφές είναι ευκολότερες στην κατανόηση και την πλοήγηση με βοηθητική τεχνολογία.\",\n \"a11yHeadingSequenceMessage\": \"Τα επίπεδα επικεφαλίδων δεν πρέπει να παραλείπουν επίπεδα.\",\n \"a11yHeadingSequenceWhy\": \"Ένα λογικό περίγραμμα επικεφαλίδων βοηθάει τους ανθρώπους να πλοηγηθούν στο περιεχόμενο με βοηθητική τεχνολογία.\",\n \"a11yTableHeaderMessage\": \"Οι πίνακες πρέπει να περιλαμβάνουν κελια κεφαλίδων.\",\n \"a11yTableHeaderWhy\": \"Τα κελιά κεφαλίδας δίνουν στους αναγνώστες οθόνης το πλαίσιο που χρειάζονται για να κατανοήσουν τα δεδομένα του πίνακα.\",\n \"a11yTableCaptionMessage\": \"Οι πίνακες θα πρέπει να περιλαμβάνουν υπότιτλο (caption).\",\n \"a11yTableCaptionWhy\": \"Ένας υπότιτλος προσδιορίζει τον σκοπό ενός πίνακα πριν ένας αναγνώστης οθόνης εισέλθει στα κελιά του.\",\n \"a11yTableHeaderScopeMessage\": \"Τα κελιά κεφαλίδας πίνακα θα πρέπει να δηλώνουν το scope τους.\",\n \"a11yTableHeaderScopeWhy\": \"Το attribute scope επιτρέπει στην βοηθητική τεχνολογία να συσχετίζει τις κεφαλίδες με τα κελιά δεδομένων.\",\n \"a11yAdjacentLinksMessage\": \"Γειτονικοί σύνδεσμοι με τον ίδιο προορισμό θα πρέπει να συνενώνονται.\",\n \"a11yAdjacentLinksWhy\": \"Οι επαναλαμβανόμενοι σύνδεσμοι δημιουργούν περιττές στάσεις για χρήστες πληκτρολογίου και αναγνωστών οθόνης.\",\n \"a11yHeadingStartMessage\": \"Η πρώτη επικεφαλίδα θα πρέπει να είναι h2.\",\n \"a11yHeadingStartWhy\": \"Ο τίτλος του εγγράφου του επεξεργαστή παρέχεται εκτός του επεξεργάσιμου περιεχομένου.\",\n \"a11yListStructureMessage\": \"Τα στοιχεία λίστας πρέπει να περιέχονται σε διατεταγμένη ή αδιάτακτη λίστα.\",\n \"a11yListStructureWhy\": \"Η βοηθητική τεχνολογία βασίζεται στη δομή λίστας για να ανακοινώνει τον αριθμό των στοιχείων και τη θέση τους.\",\n \"sourceToggleTooltip\": \"Πηγαίος κώδικας\",\n \"sourceFormatErrorMessage\": \"Δεν ήταν δυνατή η μορφοποίηση του πηγαίου κώδικα — ελέγξτε για μη κλειστές ετικέτες ή άλλα σφάλματα σύνταξης.\",\n \"saveToolbarText\": \"Προεπιλογές\",\n \"saveToolbarTooltip\": \"Διαχείριση αποθηκευμένων προεπιλογών\",\n \"saveAction\": \"Αποθήκευση\",\n \"saveAsAction\": \"Αποθήκευση ως...\",\n \"openAction\": \"Άνοιγμα...\",\n \"deleteAction\": \"Διαγραφή...\",\n \"newAction\": \"Νέο\",\n \"exportAction\": \"Εξαγωγή...\",\n \"importAction\": \"Εισαγωγή...\",\n \"saveAsDialogTitle\": \"Αποθήκευση προεπιλογής\",\n \"presetNameLabel\": \"Όνομα\",\n \"openDialogTitle\": \"Άνοιγμα προεπιλογής\",\n \"deleteDialogTitle\": \"Διαγραφή προεπιλογής\",\n \"newDialogTitle\": \"Νέο έγγραφο\",\n \"newDialogMessage\": \"Αυτό θα διαγράψει το τρέχον περιεχόμενο και τις ρυθμίσεις του επεξεργαστή. Να αποθηκευτεί πρώτα η τρέχουσα εργασία;\",\n \"newDialogSaveButton\": \"Αποθήκευση & εκκαθάριση\",\n \"newDialogDiscardButton\": \"Απόρριψη\",\n \"presetLabel\": \"Προεπιλογή\",\n \"confirmOverwrite\": \"Υπάρχει ήδη μια προεπιλογή με όνομα “{{name}}”. Να την αντικαταστήσει;\",\n \"confirmDiscard\": \"Να ανοίξει η “{{name}}” και να απορριφθούν οι τρέχουσες μη αποθηκευμένες αλλαγές;\",\n \"confirmDelete\": \"Διαγραφή της “{{name}}”; Αυτό δεν μπορεί να αναιρεθεί.\",\n \"emptyPresets\": \"Δεν υπάρχουν διαθέσιμες αποθηκευμένες προεπιλογές.\",\n \"invalidName\": \"Εισάγετε ένα όνομα προεπιλογής.\",\n \"invalidPreset\": \"Αυτή η προεπιλογή είναι άκυρη και δεν μπόρεσε να ανοιχτεί.\",\n \"importInvalidFile\": \"Το επιλεγμένο αρχείο δεν είναι έγκυρη εξαγωγή pantoken TinyMCE.\",\n \"storageReadError\": \"Οι αποθηκευμένες προεπιλογές δεν μπόρεσαν να διαβαστούν από αυτόν τον περιηγητή.\",\n \"storageWriteError\": \"Η προεπιλογή δεν μπόρεσε να αποθηκευτεί σε αυτόν τον περιηγητή.\",\n \"storageDeleteError\": \"Η προεπιλογή δεν μπόρεσε να διαγραφεί από αυτόν τον περιηγητή.\",\n \"exportDefaultName\": \"χωρίς τίτλο\",\n \"presetSaveButton\": \"Αποθήκευση\",\n \"presetOpenButton\": \"Άνοιγμα\",\n \"presetDeleteButton\": \"Διαγραφή\"\n },\n \"ht\": {\n \"autocompleteModifierDetail\": \"modifikatè\",\n \"classValidationIncompleteComponent\": \"Non konpozan an pa konplè apre '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token an dwe kòmanse ak '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Konpozan/itilite enkoni: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Mete Konpozan\",\n \"componentsListLabel\": \"Konpozan\",\n \"componentsMenuText\": \"Konpozan\",\n \"componentsToolbarText\": \"Konpozan\",\n \"componentsToolbarTooltip\": \"Mete yon konpozan pantoken\",\n \"componentModifiersDefault\": \"Pa default\",\n \"componentModifiersOptions\": \"Opsyon\",\n \"componentModifiersTooltip\": \"Chanje modifikatè konpozan yo\",\n \"componentModifiersUtilities\": \"Itilite\",\n \"iconLabelDialogTitle\": \"Etikèt ikon\",\n \"iconLabelInputLabel\": \"Etikèt pou lektè ekran\",\n \"iconsMenuText\": \"Ikon\",\n \"iconsSearchPlaceholder\": \"Chèche ikon…\",\n \"iconsSearchLabel\": \"Chèche ikon\",\n \"iconsAllSources\": \"Tout\",\n \"iconsResultCount\": \"{{count}} ikon\",\n \"iconsNoResults\": \"Pa gen ikon ki matche ak rechèch ou a.\",\n \"iconsToolbarText\": \"Ikon\",\n \"iconsToolbarTooltip\": \"Mete yon ikon\",\n \"iconContextSizeSmall\": \"Ti\",\n \"iconContextSizeMedium\": \"Mwayen\",\n \"iconContextSizeLarge\": \"Gwo\",\n \"iconContextSizeExtraLarge\": \"Ekstra gwo\",\n \"layoutsConfirmReplace\": \"Ranplase kontni aktyèl la ak aranjman \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Mete aranjman\",\n \"layoutsMenuText\": \"Aranjman…\",\n \"layoutsSelectLabel\": \"Aranjman demaraj\",\n \"layoutsToolbarText\": \"Aranjman\",\n \"layoutsToolbarTooltip\": \"Mete yon aranjman demaraj\",\n \"logosToolbarText\": \"Logo\",\n \"logosToolbarTooltip\": \"Mete yon logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Mete Logo\",\n \"insertButton\": \"Mete\",\n \"replaceButton\": \"Ranplase\",\n \"cancelButton\": \"Anile\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Ranplase kontni aktyèl la ak modèl \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Mete modèl\",\n \"templatesMenuText\": \"Mete modèl…\",\n \"templatesSelectLabel\": \"Modèl demaraj\",\n \"templatesToolbarText\": \"Modèl\",\n \"placeholdToolbarText\": \"Ranplasan\",\n \"placeholdToolbarTooltip\": \"Mete yon imaj ranplasan\",\n \"placeholdMenuText\": \"Imaj ranplasan…\",\n \"placeholdDialogTitle\": \"Mete imaj ranplasan\",\n \"placeholdWidthLabel\": \"Lajè\",\n \"placeholdHeightLabel\": \"Wotè\",\n \"placeholdBackgroundColorLabel\": \"Koulè fon\",\n \"placeholdTextColorLabel\": \"Koulè tèks\",\n \"placeholdTextLabel\": \"Tèks\",\n \"placeholdAltTextLabel\": \"Tèks alt\",\n \"placeholdInsertButton\": \"Mete\",\n \"placeholdCancelButton\": \"Anile\",\n \"placeholdInvalidDimensions\": \"Lajè ak wotè dwe nimewo antye ant 10 ak 4000.\",\n \"placeholdInvalidColor\": \"Koulè yo dwe itilize valè hexadesimal twa oswa sis chif.\",\n \"placeholdAltFallback\": \"{{width}} pa {{height}} imaj ranplasan\",\n \"a11yToolbarText\": \"Tcheke aksè\",\n \"a11yToolbarTooltip\": \"Tcheke kontni an pou pwoblèm aksè\",\n \"a11yMenuText\": \"Tcheke aksè\",\n \"a11yDialogTitle\": \"Tès aksè\",\n \"a11yNoIssues\": \"Pa jwenn pwoblèm aksè.\",\n \"a11yIssueCount\": \"{{count}} pwoblèm aksè jwenn.\",\n \"a11yStatusbarIssueCount\": \"{{count}} pwoblèm aksè\",\n \"a11yIssueLabel\": \"Pwoblèm\",\n \"a11yCloseButton\": \"Fèmen\",\n \"a11yImageAltMessage\": \"Imaj yo dwe gen tèks altènatif.\",\n \"a11yImageAltWhy\": \"Lektè ekran yo bezwen yon atribi alt pou dekri yon imaj oswa idantifye li kòm dekoratif.\",\n \"a11yImageAltFilenameMessage\": \"Tèks alt imaj la ta dwe dekri imaj la, pa repete non fichye li.\",\n \"a11yImageAltFilenameWhy\": \"Yon non fichye raman bay itilizatè lektè ekran enfòmasyon itil sou yon imaj.\",\n \"a11yImageAltLengthMessage\": \"Tèks alt imaj la ta dwe 125 karaktè oswa mwens.\",\n \"a11yImageAltLengthWhy\": \"Deskripsyon kout pi fasil pou konprann ak navige ak teknoloji asistif.\",\n \"a11yHeadingSequenceMessage\": \"Nivo tit yo pa ta dwe sote nivo.\",\n \"a11yHeadingSequenceWhy\": \"Yon estrikti tit lojik ede moun navige kontni ak teknoloji asistif.\",\n \"a11yTableHeaderMessage\": \"Tablo dwe gen selil tèt.\",\n \"a11yTableHeaderWhy\": \"Selil tèt bay lektè ekran kontèks ki nesesè pou konprann done tab la.\",\n \"a11yTableCaptionMessage\": \"Tablo yo ta dwe gen yon caption.\",\n \"a11yTableCaptionWhy\": \"Yon caption idantifye objektif yon tablo anvan yon lektè ekran antre nan selil li yo.\",\n \"a11yTableHeaderScopeMessage\": \"Selil tèt tablo yo ta dwe deklare sijè yo (scope).\",\n \"a11yTableHeaderScopeWhy\": \"Atribi scope pèmèt teknoloji asistif asosye tèt yo ak selil done yo.\",\n \"a11yAdjacentLinksMessage\": \"Lyens ki toupre youn ak lòt ki mennen sou menm destinasyon ta dwe konbine.\",\n \"a11yAdjacentLinksWhy\": \"Lyens repete kreye arè nesesè pou itilizatè klavye ak lektè ekran.\",\n \"a11yHeadingStartMessage\": \"Premye tit la ta dwe yon h2.\",\n \"a11yHeadingStartWhy\": \"Tit dokiman editè a bay deyò kontni ki editab la.\",\n \"a11yListStructureMessage\": \"Atik lis yo dwe plase nan yon lis òdone oswa enòdone.\",\n \"a11yListStructureWhy\": \"Teknoloji asistif konte sou estrikti lis la pou anonse kantite atik ak pozisyon.\",\n \"sourceToggleTooltip\": \"Kòd sous\",\n \"sourceFormatErrorMessage\": \"Pa t kapab fòma kòd sous la — tcheke pou etikèt ki pa fèmen oswa lòt erè sentaks.\",\n \"saveToolbarText\": \"Predefini\",\n \"saveToolbarTooltip\": \"Jere predefini sove yo\",\n \"saveAction\": \"Sove\",\n \"saveAsAction\": \"Sove kòm...\",\n \"openAction\": \"Louvri...\",\n \"deleteAction\": \"Efase...\",\n \"newAction\": \"Nouvo\",\n \"exportAction\": \"Ekspòte...\",\n \"importAction\": \"Enpòte...\",\n \"saveAsDialogTitle\": \"Sove predefini\",\n \"presetNameLabel\": \"Non\",\n \"openDialogTitle\": \"Louvri predefini\",\n \"deleteDialogTitle\": \"Efase predefini\",\n \"newDialogTitle\": \"Nouvo dokiman\",\n \"newDialogMessage\": \"Sa a ap efase kontni ak konfigirasyon editè aktyèl la. Sove travay aktyèl la anvan?\",\n \"newDialogSaveButton\": \"Sove & efase\",\n \"newDialogDiscardButton\": \"Rejete\",\n \"presetLabel\": \"Predefini\",\n \"confirmOverwrite\": \"Yon predefini ki rele “{{name}}” deja egziste. Ranplase li?\",\n \"confirmDiscard\": \"Louvri “{{name}}” epi rejte chanjman aktyèl ki pa sove yo?\",\n \"confirmDelete\": \"Efase “{{name}}”? Sa pa ka anile.\",\n \"emptyPresets\": \"Pa gen predefini sove ki disponib.\",\n \"invalidName\": \"Antre yon non predefini.\",\n \"invalidPreset\": \"Predefini sa a pa valab e li pa t ka louvri.\",\n \"importInvalidFile\": \"Fichye chwazi a pa yon ekspòtasyon pantoken TinyMCE valab.\",\n \"storageReadError\": \"Predefini sove yo pa t ka li soti nan navigatè sa a.\",\n \"storageWriteError\": \"Predefini a pa t ka sove nan navigatè sa a.\",\n \"storageDeleteError\": \"Predefini a pa t ka efase soti nan navigatè sa a.\",\n \"exportDefaultName\": \"san tit\",\n \"presetSaveButton\": \"Sove\",\n \"presetOpenButton\": \"Louvri\",\n \"presetDeleteButton\": \"Efase\"\n },\n \"he\": {\n \"autocompleteModifierDetail\": \"משתנה\",\n \"classValidationIncompleteComponent\": \"שם הרכיב אינו שלם לאחר '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"הטוקן חייב להתחיל ב-'{{prefix}}'\",\n \"classValidationUnknownComponent\": \"רכיב/עזר לא ידוע: '{{componentName}}'\",\n \"componentsDialogTitle\": \"הכנס רכיב\",\n \"componentsListLabel\": \"רכיבים\",\n \"componentsMenuText\": \"רכיב\",\n \"componentsToolbarText\": \"רכיבים\",\n \"componentsToolbarTooltip\": \"הכנס רכיב של pantoken\",\n \"componentModifiersDefault\": \"ברירת המחדל\",\n \"componentModifiersOptions\": \"אפשרויות\",\n \"componentModifiersTooltip\": \"שנה את המודיפיירים של הרכיב\",\n \"componentModifiersUtilities\": \"כלים\",\n \"iconLabelDialogTitle\": \"תווית אייקון\",\n \"iconLabelInputLabel\": \"תווית לקורא מסך\",\n \"iconsMenuText\": \"אייקון\",\n \"iconsSearchPlaceholder\": \"חפש אייקונים…\",\n \"iconsSearchLabel\": \"חפש אייקונים\",\n \"iconsAllSources\": \"הכל\",\n \"iconsResultCount\": \"{{count}} אייקונים\",\n \"iconsNoResults\": \"אין אייקונים התואמים לחיפוש שלך.\",\n \"iconsToolbarText\": \"אייקונים\",\n \"iconsToolbarTooltip\": \"הכנס אייקון\",\n \"iconContextSizeSmall\": \"קטן\",\n \"iconContextSizeMedium\": \"בינוני\",\n \"iconContextSizeLarge\": \"גדול\",\n \"iconContextSizeExtraLarge\": \"גדול במיוחד\",\n \"layoutsConfirmReplace\": \"להחליף את התוכן הנוכחי בפריסת \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"הכנס פריסה\",\n \"layoutsMenuText\": \"פריסה…\",\n \"layoutsSelectLabel\": \"פריסת התחלה\",\n \"layoutsToolbarText\": \"פריסות\",\n \"layoutsToolbarTooltip\": \"הכנס פריסת התחלה\",\n \"logosToolbarText\": \"לוגואים\",\n \"logosToolbarTooltip\": \"הכנס לוגו\",\n \"logosMenuText\": \"לוגו\",\n \"logosDialogTitle\": \"הכנס לוגו\",\n \"insertButton\": \"הכנס\",\n \"replaceButton\": \"החלף\",\n \"cancelButton\": \"בטל\",\n \"logoAltSuffix\": \"לוגו\",\n \"templatesConfirmReplace\": \"להחליף את התוכן הנוכחי בתבנית \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"הכנס תבנית\",\n \"templatesMenuText\": \"הכנס תבנית…\",\n \"templatesSelectLabel\": \"תבנית התחלה\",\n \"templatesToolbarText\": \"תבניות\",\n \"placeholdToolbarText\": \"ממלא מקום\",\n \"placeholdToolbarTooltip\": \"הכנס תמונת ממלא מקום\",\n \"placeholdMenuText\": \"תמונת ממלא מקום…\",\n \"placeholdDialogTitle\": \"הכנס תמונת ממלא מקום\",\n \"placeholdWidthLabel\": \"רוחב\",\n \"placeholdHeightLabel\": \"גובה\",\n \"placeholdBackgroundColorLabel\": \"צבע רקע\",\n \"placeholdTextColorLabel\": \"צבע טקסט\",\n \"placeholdTextLabel\": \"טקסט\",\n \"placeholdAltTextLabel\": \"טקסט חלופי\",\n \"placeholdInsertButton\": \"הכנס\",\n \"placeholdCancelButton\": \"בטל\",\n \"placeholdInvalidDimensions\": \"הרוחב והגובה חייבים להיות מספרים שלמים בטווח 10 עד 4000.\",\n \"placeholdInvalidColor\": \"הצבעים חייבים להיות בערכי הקסדצימל של 3 או 6 ספרות.\",\n \"placeholdAltFallback\": \"{{width}} על ידי {{height}} תמונת ממלא מקום\",\n \"a11yToolbarText\": \"בדוק הנגשה\",\n \"a11yToolbarTooltip\": \"בדוק את התוכן לאיתור בעיות הנגשה\",\n \"a11yMenuText\": \"בדוק הנגשה\",\n \"a11yDialogTitle\": \"בודק הנגשה\",\n \"a11yNoIssues\": \"לא נמצאו בעיות הנגשה.\",\n \"a11yIssueCount\": \"נמצאה/נמצאו {{count}} בעיית/בעיות הנגשה.\",\n \"a11yStatusbarIssueCount\": \"{{count}} בעיות הנגשה\",\n \"a11yIssueLabel\": \"בעיה\",\n \"a11yCloseButton\": \"סגור\",\n \"a11yImageAltMessage\": \"לתמונות חייב להיות טקסט חלופי.\",\n \"a11yImageAltWhy\": \"קוראי מסך זקוקים לתכונת alt כדי לתאר תמונה או לזהותה כתוספת דקורטיבית.\",\n \"a11yImageAltFilenameMessage\": \"הטקסט החלופי של התמונה צריך לתאר את התמונה, ולא לחזור על שם הקובץ שלה.\",\n \"a11yImageAltFilenameWhy\": \"שם קובץ נדיר מספק מידע שימושי למשתמשי קוראי מסך לגבי תמונה.\",\n \"a11yImageAltLengthMessage\": \"הטקסט החלופי של התמונה צריך להיות של 125 תווים או פחות.\",\n \"a11yImageAltLengthWhy\": \"תיאורים קצרים קלים יותר להבנה ולניווט בעזרת טכנולוגיות מסייעות.\",\n \"a11yHeadingSequenceMessage\": \"כותרות לא אמורות לדלג על רמות.\",\n \"a11yHeadingSequenceWhy\": \"מבנה כותרות לוגי מסייע לאנשים לנווט בתוכן בעזרת טכנולוגיות מסייעות.\",\n \"a11yTableHeaderMessage\": \"טבלאות חייבות לכלול תאי כותרת.\",\n \"a11yTableHeaderWhy\": \"תאי כותרת נותנים לקוראי מסך את ההקשר הדרוש כדי להבין את נתוני הטבלה.\",\n \"a11yTableCaptionMessage\": \"טבלאות צריכות לכלול כיתוב.\",\n \"a11yTableCaptionWhy\": \"כיתוב מזהה את מטרת הטבלה לפני שקורא המסך נכנס לתאים שלה.\",\n \"a11yTableHeaderScopeMessage\": \"תאי כותרת בטבלה צריכים להצהיר על ה-scope שלהם.\",\n \"a11yTableHeaderScopeWhy\": \"תכונת ה-scope מאפשרת לטכנולוגיות מסייעות לקשר בין כותרות לתאי נתונים.\",\n \"a11yAdjacentLinksMessage\": \"קישורים סמוכים עם אותו יעד צריכים להיות משולבים.\",\n \"a11yAdjacentLinksWhy\": \"קישורים חוזרים יוצרים עצירות מיותרות למשתמשי מקלדת וקוראי מסך.\",\n \"a11yHeadingStartMessage\": \"הכותרת הראשונה צריכה להיות h2.\",\n \"a11yHeadingStartWhy\": \"כותרת המסמך של העורך מסופקת מחוץ לתוכן הניתן לעריכה.\",\n \"a11yListStructureMessage\": \"פריטי רשימה חייבים להיות כלולים ברשימה מסודרת או לא מסודרת.\",\n \"a11yListStructureWhy\": \"טכנולוגיות מסייעות מסתמכות על מבנה הרשימה כדי להכריז על מספר הפריטים והמיקום.\",\n \"sourceToggleTooltip\": \"קוד מקור\",\n \"sourceFormatErrorMessage\": \"לא ניתן לעצב את קוד המקור — בדוק אם יש תגיות שלא נסגרו או שגיאות תחביר אחרות.\",\n \"saveToolbarText\": \"תבניות\",\n \"saveToolbarTooltip\": \"נהל תבניות שמורות\",\n \"saveAction\": \"שמור\",\n \"saveAsAction\": \"שמור בשם...\",\n \"openAction\": \"פתח...\",\n \"deleteAction\": \"מחק...\",\n \"newAction\": \"חדש\",\n \"exportAction\": \"ייצוא...\",\n \"importAction\": \"ייבוא...\",\n \"saveAsDialogTitle\": \"שמור תבנית\",\n \"presetNameLabel\": \"שם\",\n \"openDialogTitle\": \"פתח תבנית\",\n \"deleteDialogTitle\": \"מחק תבנית\",\n \"newDialogTitle\": \"מסמך חדש\",\n \"newDialogMessage\": \"פעולה זו תנקה את תכני העורך וההגדרות הנוכחיות. לשמור את העבודה הנוכחית קודם?\",\n \"newDialogSaveButton\": \"שמור ונקה\",\n \"newDialogDiscardButton\": \"בטל\",\n \"presetLabel\": \"תבנית\",\n \"confirmOverwrite\": \"כבר קיימת תבנית בשם “{{name}}”. להחליף אותה?\",\n \"confirmDiscard\": \"לפתוח את “{{name}}” ולבטל את השינויים הנוכחיים שלא נשמרו?\",\n \"confirmDelete\": \"למחוק את “{{name}}”? אין אפשרות לביטול פעולה זו.\",\n \"emptyPresets\": \"אין תבניות שמורות זמינות.\",\n \"invalidName\": \"הזן שם תבנית.\",\n \"invalidPreset\": \"התבנית לא חוקית ולא ניתן לפתוח אותה.\",\n \"importInvalidFile\": \"הקובץ הנבחר אינו ייצוא תקין של pantoken TinyMCE.\",\n \"storageReadError\": \"לא ניתן לקרוא תבניות שמורות מדפדפן זה.\",\n \"storageWriteError\": \"לא ניתן לשמור את התבנית בדפדפן זה.\",\n \"storageDeleteError\": \"לא ניתן למחוק את התבנית מדפדפן זה.\",\n \"exportDefaultName\": \"ללא כותרת\",\n \"presetSaveButton\": \"שמור\",\n \"presetOpenButton\": \"פתח\",\n \"presetDeleteButton\": \"מחק\"\n },\n \"hi\": {\n \"autocompleteModifierDetail\": \"मॉडिफ़ायर\",\n \"classValidationIncompleteComponent\": \"'{{prefix}}' के बाद घटक का नाम अधूरा है\",\n \"classValidationTokenPrefix\": \"टोकन '{{prefix}}' से शुरू होना चाहिए\",\n \"classValidationUnknownComponent\": \"अज्ञात घटक/उपयोगिता: '{{componentName}}'\",\n \"componentsDialogTitle\": \"घटक डालें\",\n \"componentsListLabel\": \"घटक\",\n \"componentsMenuText\": \"घटक\",\n \"componentsToolbarText\": \"घटक\",\n \"componentsToolbarTooltip\": \"एक pantoken घटक डालें\",\n \"componentModifiersDefault\": \"डिफ़ॉल्ट\",\n \"componentModifiersOptions\": \"विकल्प\",\n \"componentModifiersTooltip\": \"कंपोनेंट संशोधकों को बदलें\",\n \"componentModifiersUtilities\": \"उपयोगिताएँ\",\n \"iconLabelDialogTitle\": \"आइकन लेबल\",\n \"iconLabelInputLabel\": \"स्क्रीन रीडर लेबल\",\n \"iconsMenuText\": \"आइकन\",\n \"iconsSearchPlaceholder\": \"आइकन खोजें…\",\n \"iconsSearchLabel\": \"आइकन खोजें\",\n \"iconsAllSources\": \"सभी\",\n \"iconsResultCount\": \"{{count}} आइकन\",\n \"iconsNoResults\": \"आपकी खोज से कोई आइकन मेल नहीं खाते।\",\n \"iconsToolbarText\": \"आइकन\",\n \"iconsToolbarTooltip\": \"एक आइकन डालें\",\n \"iconContextSizeSmall\": \"छोटा\",\n \"iconContextSizeMedium\": \"मध्यम\",\n \"iconContextSizeLarge\": \"बड़ा\",\n \"iconContextSizeExtraLarge\": \"अतिरिक्त बड़ा\",\n \"layoutsConfirmReplace\": \"क्या वर्तमान सामग्री को \\\"{{title}}\\\" लेआउट से प्रतिस्थापित करना है?\",\n \"layoutsDialogTitle\": \"लेआउट डालें\",\n \"layoutsMenuText\": \"लेआउट…\",\n \"layoutsSelectLabel\": \"स्टार्टर लेआउट\",\n \"layoutsToolbarText\": \"लेआउट्स\",\n \"layoutsToolbarTooltip\": \"एक स्टार्टर लेआउट डालें\",\n \"logosToolbarText\": \"लोगो\",\n \"logosToolbarTooltip\": \"एक लोगो डालें\",\n \"logosMenuText\": \"लोगो\",\n \"logosDialogTitle\": \"लोगो डालें\",\n \"insertButton\": \"डालें\",\n \"replaceButton\": \"बदलें\",\n \"cancelButton\": \"रद्द करें\",\n \"logoAltSuffix\": \"लोगो\",\n \"templatesConfirmReplace\": \"क्या वर्तमान सामग्री को \\\"{{title}}\\\" टेम्पलेट से प्रतिस्थापित किया जाए?\",\n \"templatesDialogTitle\": \"टेम्पलेट डालें\",\n \"templatesMenuText\": \"टेम्पलेट डालें…\",\n \"templatesSelectLabel\": \"स्टार्टर टेम्पलेट\",\n \"templatesToolbarText\": \"टेम्पलेट्स\",\n \"placeholdToolbarText\": \"प्लेसहोल्डर\",\n \"placeholdToolbarTooltip\": \"एक प्लेसहोल्डर छवि डालें\",\n \"placeholdMenuText\": \"प्लेसहोल्डर छवि…\",\n \"placeholdDialogTitle\": \"प्लेसहोल्डर छवि डालें\",\n \"placeholdWidthLabel\": \"चौड़ाई\",\n \"placeholdHeightLabel\": \"ऊँचाई\",\n \"placeholdBackgroundColorLabel\": \"पृष्ठभूमि रंग\",\n \"placeholdTextColorLabel\": \"पाठ का रंग\",\n \"placeholdTextLabel\": \"पाठ\",\n \"placeholdAltTextLabel\": \"Alt टेक्स्ट\",\n \"placeholdInsertButton\": \"डालें\",\n \"placeholdCancelButton\": \"रद्द करें\",\n \"placeholdInvalidDimensions\": \"चौड़ाई और ऊँचाई 10 से 4000 के बीच पूर्ण संख्या होनी चाहिए।\",\n \"placeholdInvalidColor\": \"रंगों में तीन या छह अंकों के हेक्साडेसिमल मान होने चाहिए।\",\n \"placeholdAltFallback\": \"{{width}} बाय {{height}} प्लेसहोल्डर छवि\",\n \"a11yToolbarText\": \"सुलभता जांचें\",\n \"a11yToolbarTooltip\": \"सामग्री को सुलभता मुद्दों के लिए जांचें\",\n \"a11yMenuText\": \"सुलभता जांचें\",\n \"a11yDialogTitle\": \"सुलभता चेकर\",\n \"a11yNoIssues\": \"कोई सुलभता समस्या नहीं मिली।\",\n \"a11yIssueCount\": \"{{count}} सुलभता समस्या(एं) मिलीं।\",\n \"a11yStatusbarIssueCount\": \"{{count}} सुलभता समस्याएँ\",\n \"a11yIssueLabel\": \"समस्या\",\n \"a11yCloseButton\": \"बंद करें\",\n \"a11yImageAltMessage\": \"चित्रों में वैकल्पिक पाठ होना चाहिए।\",\n \"a11yImageAltWhy\": \"स्क्रीन रीडर्स को किसी चित्र का वर्णन करने या इसे सजावटी बताने के लिए alt गुण चाहिए।\",\n \"a11yImageAltFilenameMessage\": \"चित्र का वैकल्पिक पाठ चित्र का वर्णन करना चाहिए, फ़ाइलनाम को दोहराना नहीं चाहिए।\",\n \"a11yImageAltFilenameWhy\": \"फ़ाइलनाम अक्सर स्क्रीन रीडर उपयोगकर्ताओं को उपयोगी जानकारी नहीं देता।\",\n \"a11yImageAltLengthMessage\": \"चित्र के वैकल्पिक पाठ में 125 अक्षर या उससे कम होने चाहिए।\",\n \"a11yImageAltLengthWhy\": \"संक्षिप्त विवरण सहायक तकनीक के साथ समझने और नेविगेट करने में आसान होते हैं।\",\n \"a11yHeadingSequenceMessage\": \"हेडिंग स्तरों को छोड़कर नहीं जाना चाहिए।\",\n \"a11yHeadingSequenceWhy\": \"एक तार्किक हेडिंग रूपरेखा लोगों को सहायक तकनीक के साथ सामग्री नेविगेट करने में मदद करती है।\",\n \"a11yTableHeaderMessage\": \"तालिकाओं में हेडर सेल होने चाहिए।\",\n \"a11yTableHeaderWhy\": \"हेडर सेल स्क्रीन रीडर्स को तालिका डेटा समझने का संदर्भ देते हैं।\",\n \"a11yTableCaptionMessage\": \"तालिकाओं में एक कैप्शन होना चाहिए।\",\n \"a11yTableCaptionWhy\": \"एक कैप्शन तालिका के उद्देश्य की पहचान करता है इससे पहले कि स्क्रीन रीडर उसकी कोशिकाओं में जाए।\",\n \"a11yTableHeaderScopeMessage\": \"तालिका हेडर सेल्स को अपनी स्कोप घोषणा करनी चाहिए।\",\n \"a11yTableHeaderScopeWhy\": \"scope एट्रिब्यूट सहायक तकनीक को हेडर्स को डेटा सेल्स से जोड़ने देता है।\",\n \"a11yAdjacentLinksMessage\": \"एक ही गंतव्य वाले निकटवर्ती लिंक मिलाने चाहिए।\",\n \"a11yAdjacentLinksWhy\": \"दोहराए गए लिंक कीबोर्ड और स्क्रीन रीडर उपयोगकर्ताओं के लिए अनावश्यक रुकावटें बनाते हैं।\",\n \"a11yHeadingStartMessage\": \"पहला हेडिंग h2 होना चाहिए।\",\n \"a11yHeadingStartWhy\": \"संपादक का दस्तावेज़ शीर्षक संपादन योग्य सामग्री के बाहर प्रदान किया गया है।\",\n \"a11yListStructureMessage\": \"सूची आइटम को क्रमबद्ध या अनक्रमबद्ध सूची में होना चाहिए।\",\n \"a11yListStructureWhy\": \"सहायक तकनीक सूची संरचना पर निर्भर करती है ताकि आइटम की गिनती और स्थिति घोषित कर सके।\",\n \"sourceToggleTooltip\": \"स्रोत कोड\",\n \"sourceFormatErrorMessage\": \"स्रोत कोड को स्वरूपित नहीं किया जा सका — बिना बंद हुए टैग या अन्य सिंटैक्स त्रुटियों की जांच करें।\",\n \"saveToolbarText\": \"पूर्व-निर्धारित सेट\",\n \"saveToolbarTooltip\": \"सहेजे गए प्रीसेट प्रबंधित करें\",\n \"saveAction\": \"सहेजें\",\n \"saveAsAction\": \"इसके रूप में सहेजें...\",\n \"openAction\": \"खोलें...\",\n \"deleteAction\": \"हटाएँ...\",\n \"newAction\": \"नया\",\n \"exportAction\": \"निर्यात...\",\n \"importAction\": \"आयात...\",\n \"saveAsDialogTitle\": \"प्रीसेट सहेजें\",\n \"presetNameLabel\": \"नाम\",\n \"openDialogTitle\": \"प्रीसेट खोलें\",\n \"deleteDialogTitle\": \"प्रीसेट हटाएँ\",\n \"newDialogTitle\": \"नया दस्तावेज़\",\n \"newDialogMessage\": \"यह वर्तमान संपादक की सामग्री और कॉन्फ़िगरेशन को साफ़ कर देता है। क्या पहले वर्तमान कार्य सहेजना चाहेंगे?\",\n \"newDialogSaveButton\": \"सहेजें और साफ़ करें\",\n \"newDialogDiscardButton\": \"खारिज करें\",\n \"presetLabel\": \"प्रीसेट\",\n \"confirmOverwrite\": \"“{{name}}” नाम का एक प्रीसेट पहले से मौजूद है। क्या इसे बदलना है?\",\n \"confirmDiscard\": \"“{{name}}” खोलें और वर्तमान अनसहेजे परिवर्तनों को छोड़ दें?\",\n \"confirmDelete\": \"“{{name}}” हटाएँ? यह पूर्ववत नहीं किया जा सकता।\",\n \"emptyPresets\": \"कोई सहेजा गया प्रीसेट उपलब्ध नहीं है।\",\n \"invalidName\": \"एक प्रीसेट नाम दर्ज करें।\",\n \"invalidPreset\": \"यह प्रीसेट अमान्य है और खोली नहीं जा सकी।\",\n \"importInvalidFile\": \"चयनित फ़ाइल एक वैध pantoken TinyMCE निर्यात नहीं है।\",\n \"storageReadError\": \"इस ब्राउज़र से सहेजे गए प्रीसेट पढ़े नहीं जा सके।\",\n \"storageWriteError\": \"यह प्रीसेट इस ब्राउज़र में सहेजा नहीं जा सका।\",\n \"storageDeleteError\": \"यह प्रीसेट इस ब्राउज़र से हटाया नहीं जा सका।\",\n \"exportDefaultName\": \"शीर्षकहीन\",\n \"presetSaveButton\": \"सहेजें\",\n \"presetOpenButton\": \"खोलें\",\n \"presetDeleteButton\": \"हटाएँ\"\n },\n \"hu\": {\n \"autocompleteModifierDetail\": \"módosító\",\n \"classValidationIncompleteComponent\": \"Hiányos komponensnév a '{{prefix}}' után\",\n \"classValidationTokenPrefix\": \"A tokennek '{{prefix}}' előtaggal kell kezdődnie\",\n \"classValidationUnknownComponent\": \"Ismeretlen komponens/segéd: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Komponens beszúrása\",\n \"componentsListLabel\": \"Komponensek\",\n \"componentsMenuText\": \"Komponens\",\n \"componentsToolbarText\": \"Komponensek\",\n \"componentsToolbarTooltip\": \"Pantoken-komponens beszúrása\",\n \"componentModifiersDefault\": \"Alapértelmezett\",\n \"componentModifiersOptions\": \"Opciók\",\n \"componentModifiersTooltip\": \"Komponens módosítóinak megváltoztatása\",\n \"componentModifiersUtilities\": \"Segédprogramok\",\n \"iconLabelDialogTitle\": \"Ikon címke\",\n \"iconLabelInputLabel\": \"Képernyőolvasó címke\",\n \"iconsMenuText\": \"Ikon\",\n \"iconsSearchPlaceholder\": \"Ikonok keresése…\",\n \"iconsSearchLabel\": \"Ikonok keresése\",\n \"iconsAllSources\": \"Mind\",\n \"iconsResultCount\": \"{{count}} ikon\",\n \"iconsNoResults\": \"Egyik ikon sem felel meg a keresésnek.\",\n \"iconsToolbarText\": \"Ikonok\",\n \"iconsToolbarTooltip\": \"Ikon beszúrása\",\n \"iconContextSizeSmall\": \"Kicsi\",\n \"iconContextSizeMedium\": \"Közepes\",\n \"iconContextSizeLarge\": \"Nagy\",\n \"iconContextSizeExtraLarge\": \"Extra nagy\",\n \"layoutsConfirmReplace\": \"A jelenlegi tartalmat lecseréljük a \\\"{{title}}\\\" elrendezésre?\",\n \"layoutsDialogTitle\": \"Elrendezés beszúrása\",\n \"layoutsMenuText\": \"Elrendezés…\",\n \"layoutsSelectLabel\": \"Kezdő elrendezés\",\n \"layoutsToolbarText\": \"Elrendezések\",\n \"layoutsToolbarTooltip\": \"Kezdő elrendezés beszúrása\",\n \"logosToolbarText\": \"Logók\",\n \"logosToolbarTooltip\": \"Logó beszúrása\",\n \"logosMenuText\": \"Logó\",\n \"logosDialogTitle\": \"Logó beszúrása\",\n \"insertButton\": \"Beszúrás\",\n \"replaceButton\": \"Cserél\",\n \"cancelButton\": \"Mégse\",\n \"logoAltSuffix\": \"logó\",\n \"templatesConfirmReplace\": \"A jelenlegi tartalmat lecseréljük a \\\"{{title}}\\\" sablonra?\",\n \"templatesDialogTitle\": \"Sablon beszúrása\",\n \"templatesMenuText\": \"Sablon beszúrása…\",\n \"templatesSelectLabel\": \"Kezdő sablon\",\n \"templatesToolbarText\": \"Sablonok\",\n \"placeholdToolbarText\": \"Helyőrző\",\n \"placeholdToolbarTooltip\": \"Helyőrző kép beszúrása\",\n \"placeholdMenuText\": \"Helyőrző kép…\",\n \"placeholdDialogTitle\": \"Helyőrző kép beszúrása\",\n \"placeholdWidthLabel\": \"Szélesség\",\n \"placeholdHeightLabel\": \"Magasság\",\n \"placeholdBackgroundColorLabel\": \"Háttérszín\",\n \"placeholdTextColorLabel\": \"Szövegszín\",\n \"placeholdTextLabel\": \"Szöveg\",\n \"placeholdAltTextLabel\": \"Alternatív szöveg\",\n \"placeholdInsertButton\": \"Beszúrás\",\n \"placeholdCancelButton\": \"Mégse\",\n \"placeholdInvalidDimensions\": \"A szélességnek és magasságnak egész számnak kell lennie 10 és 4000 között.\",\n \"placeholdInvalidColor\": \"A színeknek három- vagy hatjegyű hexadecimális értékeket kell használniuk.\",\n \"placeholdAltFallback\": \"{{width}} × {{height}} helyőrző kép\",\n \"a11yToolbarText\": \"Akadálymentesség ellenőrzése\",\n \"a11yToolbarTooltip\": \"Ellenőrizze a tartalmat akadálymentességi problémák szempontjából\",\n \"a11yMenuText\": \"Akadálymentesség ellenőrzése\",\n \"a11yDialogTitle\": \"Akadálymentesség-ellenőrző\",\n \"a11yNoIssues\": \"Nem találtunk akadálymentességi problémát.\",\n \"a11yIssueCount\": \"{{count}} akadálymentességi probléma található.\",\n \"a11yStatusbarIssueCount\": \"{{count}} akadálymentességi probléma\",\n \"a11yIssueLabel\": \"Probléma\",\n \"a11yCloseButton\": \"Bezárás\",\n \"a11yImageAltMessage\": \"A képeknek alternatív szövegüknek kell lennie.\",\n \"a11yImageAltWhy\": \"A képernyőolvasóknak alt attribútumra van szükségük a kép leírásához vagy dekoratív jellegének megjelöléséhez.\",\n \"a11yImageAltFilenameMessage\": \"Az alternatív szövegnek a képet kell leírnia, nem ismételnie a fájlnevet.\",\n \"a11yImageAltFilenameWhy\": \"Egy fájlnév ritkán ad hasznos információt a képernyőolvasó felhasználói számára a képről.\",\n \"a11yImageAltLengthMessage\": \"Az alternatív szöveg legfeljebb 125 karakter hosszú legyen.\",\n \"a11yImageAltLengthWhy\": \"A rövid leírások könnyebben érthetők és navigálhatók segítő technológiákkal.\",\n \"a11yHeadingSequenceMessage\": \"A címszinteknek nem szabad kihagyniuk szinteket.\",\n \"a11yHeadingSequenceWhy\": \"A logikus címsorvázlat segíti a tartalom navigálását segítő technológiákat használókat.\",\n \"a11yTableHeaderMessage\": \"A táblázatoknak fejléc cellákat kell tartalmazniuk.\",\n \"a11yTableHeaderWhy\": \"A fejléc cellák kontextust adnak a képernyőolvasóknak a táblázat adataival kapcsolatban.\",\n \"a11yTableCaptionMessage\": \"A táblázatoknak felirattal kell rendelkezniük.\",\n \"a11yTableCaptionWhy\": \"A felirat meghatározza a táblázat célját, mielőtt a képernyőolvasó belépne a celláiba.\",\n \"a11yTableHeaderScopeMessage\": \"A táblázat fejléc celláinak meg kell határozniuk a scope attribútumot.\",\n \"a11yTableHeaderScopeWhy\": \"A scope attribútum lehetővé teszi a segítő technológiák számára, hogy a fejlécet társítsák az adatok celláihoz.\",\n \"a11yAdjacentLinksMessage\": \"Az egymás melletti, ugyanoda mutató hivatkozásokat össze kell vonni.\",\n \"a11yAdjacentLinksWhy\": \"Az ismétlődő hivatkozások felesleges megállókat okoznak billentyűzetet és képernyőolvasót használóknak.\",\n \"a11yHeadingStartMessage\": \"Az első címsornak h2-nek kell lennie.\",\n \"a11yHeadingStartWhy\": \"A szerkesztő dokumentumcíme a szerkeszthető tartalmon kívül van megadva.\",\n \"a11yListStructureMessage\": \"A listaelemeket rendezett vagy rendezetlen listába kell helyezni.\",\n \"a11yListStructureWhy\": \"A segítő technológia a lista szerkezetére támaszkodik az elemek számának és pozíciójának bejelentéséhez.\",\n \"sourceToggleTooltip\": \"Forráskód\",\n \"sourceFormatErrorMessage\": \"Nem sikerült formázni a forráskódot — ellenőrizze a lezáratlan tageket vagy egyéb szintaxishibákat.\",\n \"saveToolbarText\": \"Előbeállítások\",\n \"saveToolbarTooltip\": \"Mentett előbeállítások kezelése\",\n \"saveAction\": \"Mentés\",\n \"saveAsAction\": \"Mentés másként...\",\n \"openAction\": \"Megnyitás...\",\n \"deleteAction\": \"Törlés...\",\n \"newAction\": \"Új\",\n \"exportAction\": \"Exportálás...\",\n \"importAction\": \"Importálás...\",\n \"saveAsDialogTitle\": \"Előbeállítás mentése\",\n \"presetNameLabel\": \"Név\",\n \"openDialogTitle\": \"Előbeállítás megnyitása\",\n \"deleteDialogTitle\": \"Előbeállítás törlése\",\n \"newDialogTitle\": \"Új dokumentum\",\n \"newDialogMessage\": \"Ez törli a jelenlegi szerkesztő tartalmát és konfigurációját. Előbb mentse a jelenlegi munkát?\",\n \"newDialogSaveButton\": \"Mentés és törlés\",\n \"newDialogDiscardButton\": \"Elvetés\",\n \"presetLabel\": \"Előbeállítás\",\n \"confirmOverwrite\": \"Már létezik egy „{{name}}” nevű előbeállítás. Felülírja?\",\n \"confirmDiscard\": \"Megnyitja a „{{name}}” előbeállítást és elveti a jelenlegi, nem mentett módosításokat?\",\n \"confirmDelete\": \"Törli a „{{name}}”-t? Ez nem visszavonható.\",\n \"emptyPresets\": \"Nincsenek elérhető mentett előbeállítások.\",\n \"invalidName\": \"Adjon meg egy előbeállítás nevet.\",\n \"invalidPreset\": \"Ez az előbeállítás érvénytelen, és nem nyitható meg.\",\n \"importInvalidFile\": \"A kiválasztott fájl nem érvényes pantoken TinyMCE export.\",\n \"storageReadError\": \"A mentett előbeállítások nem olvashatók ebből a böngészőből.\",\n \"storageWriteError\": \"Az előbeállítást nem sikerült menteni ebben a böngészőben.\",\n \"storageDeleteError\": \"Az előbeállítást nem sikerült törölni ebben a böngészőben.\",\n \"exportDefaultName\": \"Névtelen\",\n \"presetSaveButton\": \"Mentés\",\n \"presetOpenButton\": \"Megnyitás\",\n \"presetDeleteButton\": \"Törlés\"\n },\n \"is\": {\n \"autocompleteModifierDetail\": \"breytir\",\n \"classValidationIncompleteComponent\": \"Ófullkomið íhlutanfn eftir '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token verður að byrja á '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Óþekktur íhluti/aðgerð: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Setja inn íhluta\",\n \"componentsListLabel\": \"Íhlutir\",\n \"componentsMenuText\": \"Íhluti\",\n \"componentsToolbarText\": \"Íhlutir\",\n \"componentsToolbarTooltip\": \"Setja inn pantoken-íhluta\",\n \"componentModifiersDefault\": \"Sjálfgefið\",\n \"componentModifiersOptions\": \"Valkostir\",\n \"componentModifiersTooltip\": \"Breyta breytum íhluta\",\n \"componentModifiersUtilities\": \"Hjálparforrit\",\n \"iconLabelDialogTitle\": \"Táknmerking\",\n \"iconLabelInputLabel\": \"Merkimiði fyrir skjálesara\",\n \"iconsMenuText\": \"Tákn\",\n \"iconsSearchPlaceholder\": \"Leita að táknum…\",\n \"iconsSearchLabel\": \"Leita að táknum\",\n \"iconsAllSources\": \"Allt\",\n \"iconsResultCount\": \"{{count}} tákn\",\n \"iconsNoResults\": \"Engin tákn passa leitina þína.\",\n \"iconsToolbarText\": \"Tákn\",\n \"iconsToolbarTooltip\": \"Setja inn tákn\",\n \"iconContextSizeSmall\": \"Lítil\",\n \"iconContextSizeMedium\": \"Miðlungs\",\n \"iconContextSizeLarge\": \"Stór\",\n \"iconContextSizeExtraLarge\": \"Óvenju stór\",\n \"layoutsConfirmReplace\": \"Skipta núverandi efni út fyrir \\\"{{title}}\\\" uppsetningu?\",\n \"layoutsDialogTitle\": \"Setja inn uppsetningu\",\n \"layoutsMenuText\": \"Uppsetning…\",\n \"layoutsSelectLabel\": \"Upphafsuppsetning\",\n \"layoutsToolbarText\": \"Uppsetningar\",\n \"layoutsToolbarTooltip\": \"Setja inn upphafsuppsetningu\",\n \"logosToolbarText\": \"Lógó\",\n \"logosToolbarTooltip\": \"Setja inn lógó\",\n \"logosMenuText\": \"Lógó\",\n \"logosDialogTitle\": \"Setja inn lógó\",\n \"insertButton\": \"Setja inn\",\n \"replaceButton\": \"Skipta út\",\n \"cancelButton\": \"Hætta við\",\n \"logoAltSuffix\": \"lógó\",\n \"templatesConfirmReplace\": \"Skipta núverandi efni út fyrir sniðmátið \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Setja inn sniðmát\",\n \"templatesMenuText\": \"Setja inn sniðmát…\",\n \"templatesSelectLabel\": \"Upphafssniðmát\",\n \"templatesToolbarText\": \"Sniðmát\",\n \"placeholdToolbarText\": \"Staðgengill\",\n \"placeholdToolbarTooltip\": \"Setja inn staðgengilsmynd\",\n \"placeholdMenuText\": \"Staðgengilsmynd…\",\n \"placeholdDialogTitle\": \"Setja inn staðgengilsmynd\",\n \"placeholdWidthLabel\": \"Breidd\",\n \"placeholdHeightLabel\": \"Hæð\",\n \"placeholdBackgroundColorLabel\": \"Bakgrunnslitur\",\n \"placeholdTextColorLabel\": \"Textalitur\",\n \"placeholdTextLabel\": \"Texti\",\n \"placeholdAltTextLabel\": \"Alt-texti\",\n \"placeholdInsertButton\": \"Setja inn\",\n \"placeholdCancelButton\": \"Hætta við\",\n \"placeholdInvalidDimensions\": \"Breidd og hæð verða að vera heiltölur frá 10 til 4000.\",\n \"placeholdInvalidColor\": \"Litir verða að nota þrjár- eða sex stafa hexadecimal-gildi.\",\n \"placeholdAltFallback\": \"{{width}} x {{height}} staðgengilsmynd\",\n \"a11yToolbarText\": \"Athuga aðgengi\",\n \"a11yToolbarTooltip\": \"Athuga efnið fyrir aðgengismál\",\n \"a11yMenuText\": \"Athuga aðgengi\",\n \"a11yDialogTitle\": \"Aðgengismatsverkfæri\",\n \"a11yNoIssues\": \"Engin aðgengismál fundust.\",\n \"a11yIssueCount\": \"{{count}} aðgengismál fundust.\",\n \"a11yStatusbarIssueCount\": \"{{count}} aðgengismál\",\n \"a11yIssueLabel\": \"Vandamál\",\n \"a11yCloseButton\": \"Loka\",\n \"a11yImageAltMessage\": \"Myndir verða að hafa alt-texta.\",\n \"a11yImageAltWhy\": \"Lestrarforrit fyrir sjónskerta þurfa alt-eiginleika til að lýsa mynd eða merkja hana sem skraut.\",\n \"a11yImageAltFilenameMessage\": \"Alt-texti myndar ætti að lýsa myndinni, ekki endurtaka skráarnafn hennar.\",\n \"a11yImageAltFilenameWhy\": \"Skráarnafn gefur sjaldan notendum skjálesara gagnlegar upplýsingar um mynd.\",\n \"a11yImageAltLengthMessage\": \"Alt-texti myndar ætti að vera 125 stafir eða færri.\",\n \"a11yImageAltLengthWhy\": \"Stuttar lýsingar eru auðveldari í skilningi og leiðsögn með hjálpartækjum.\",\n \"a11yHeadingSequenceMessage\": \"Yfirskriftarstigin ættu ekki að sleppa stigum.\",\n \"a11yHeadingSequenceWhy\": \"Rökrétt yfirlit yfir yfirskriftir hjálpar fólki að sigla efni með hjálpartækjum.\",\n \"a11yTableHeaderMessage\": \"Töflur verða að innihalda hausfrumur.\",\n \"a11yTableHeaderWhy\": \"Hausfrumur gefa skjálesurum samhengi sem þarf til að skilja taflagögn.\",\n \"a11yTableCaptionMessage\": \"Töflur ættu að hafa skýringu.\",\n \"a11yTableCaptionWhy\": \"Skýring auðkennir tilgang töflu áður en skjálesari fer inn í frumur hennar.\",\n \"a11yTableHeaderScopeMessage\": \"Hausfrumur töflu ættu að tilkynna umfang sitt.\",\n \"a11yTableHeaderScopeWhy\": \"Scope-eiginleikinn leyfir hjálpartækjum að tengja haus við gagnafrumur.\",\n \"a11yAdjacentLinksMessage\": \"Nálægir tenglar með sama áfangastað ætti að sameina.\",\n \"a11yAdjacentLinksWhy\": \"Endurteknir tenglar skapa óþarfa stopp fyrir notendur lyklaborðs og skjálesara.\",\n \"a11yHeadingStartMessage\": \"Fyrsta yfirskriftin ætti að vera h2.\",\n \"a11yHeadingStartWhy\": \"Titill skjalsins í ritlinum er gefinn utan ritstjóranlegs innihalds.\",\n \"a11yListStructureMessage\": \"Atriði í lista verða að vera í raðaðan eða óraðaðan lista.\",\n \"a11yListStructureWhy\": \"Hjálpartæki treystir á listaskipan til að tilkynna fjölda atriða og stöðu.\",\n \"sourceToggleTooltip\": \"Upprunakóði\",\n \"sourceFormatErrorMessage\": \"Gat ekki sniðið upprunakóðann — athugaðu hvort einhver ólokin merki séu til eða aðrar sintaksvillur.\",\n \"saveToolbarText\": \"Fyrirstillingar\",\n \"saveToolbarTooltip\": \"Stjórna vistaðri fyrirstillingum\",\n \"saveAction\": \"Vista\",\n \"saveAsAction\": \"Vista sem...\",\n \"openAction\": \"Opna...\",\n \"deleteAction\": \"Eyða...\",\n \"newAction\": \"Nýtt\",\n \"exportAction\": \"Flytja út...\",\n \"importAction\": \"Flytja inn...\",\n \"saveAsDialogTitle\": \"Vista fyrirstillingu\",\n \"presetNameLabel\": \"Nafn\",\n \"openDialogTitle\": \"Opna fyrirstillingu\",\n \"deleteDialogTitle\": \"Eyða fyrirstillingu\",\n \"newDialogTitle\": \"Nýr skjal\",\n \"newDialogMessage\": \"Þetta tæmir núverandi efni ritilsins og uppsetningu. Vista núverandi verk fyrst?\",\n \"newDialogSaveButton\": \"Vista og hreinsa\",\n \"newDialogDiscardButton\": \"Henda\",\n \"presetLabel\": \"Fyrirstilling\",\n \"confirmOverwrite\": \"Fyrirstilling með nafni “{{name}}” er þegar til. Yfirskrifa hana?\",\n \"confirmDiscard\": \"Opna “{{name}}” og henda núverandi óvistaðar breytingum?\",\n \"confirmDelete\": \"Eyða “{{name}}”? Þetta er ekki hægt að afturkalla.\",\n \"emptyPresets\": \"Engar vistaðar fyrirstillingar eru í boði.\",\n \"invalidName\": \"Slá inn nafn fyrirstillingar.\",\n \"invalidPreset\": \"Þessi fyrirstilling er ógild og gat ekki verið opnuð.\",\n \"importInvalidFile\": \"Valið skjal er ekki gilt pantoken TinyMCE útflutningsskjal.\",\n \"storageReadError\": \"Gat ekki lesið vistaðar fyrirstillingar úr þessum vafra.\",\n \"storageWriteError\": \"Fyrirstillingin gat ekki verið vistuð í þessum vafra.\",\n \"storageDeleteError\": \"Fyrirstillingin gat ekki verið eytt úr þessum vafra.\",\n \"exportDefaultName\": \"Ótitlað\",\n \"presetSaveButton\": \"Vista\",\n \"presetOpenButton\": \"Opna\",\n \"presetDeleteButton\": \"Eyða\"\n },\n \"id\": {\n \"autocompleteModifierDetail\": \"modifikator\",\n \"classValidationIncompleteComponent\": \"Nama komponen tidak lengkap setelah '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token harus dimulai dengan '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Komponen/utilitas tidak dikenal: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Sisipkan Komponen\",\n \"componentsListLabel\": \"Komponen\",\n \"componentsMenuText\": \"Komponen\",\n \"componentsToolbarText\": \"Komponen\",\n \"componentsToolbarTooltip\": \"Sisipkan komponen pantoken\",\n \"componentModifiersDefault\": \"Bawaan\",\n \"componentModifiersOptions\": \"Opsi\",\n \"componentModifiersTooltip\": \"Ubah pengubah komponen\",\n \"componentModifiersUtilities\": \"Utilitas\",\n \"iconLabelDialogTitle\": \"Label ikon\",\n \"iconLabelInputLabel\": \"Label pembaca layar\",\n \"iconsMenuText\": \"Ikon\",\n \"iconsSearchPlaceholder\": \"Cari ikon…\",\n \"iconsSearchLabel\": \"Cari ikon\",\n \"iconsAllSources\": \"Semua\",\n \"iconsResultCount\": \"{{count}} ikon\",\n \"iconsNoResults\": \"Tidak ada ikon yang cocok dengan pencarian Anda.\",\n \"iconsToolbarText\": \"Ikon\",\n \"iconsToolbarTooltip\": \"Sisipkan ikon\",\n \"iconContextSizeSmall\": \"Kecil\",\n \"iconContextSizeMedium\": \"Sedang\",\n \"iconContextSizeLarge\": \"Besar\",\n \"iconContextSizeExtraLarge\": \"Ekstra besar\",\n \"layoutsConfirmReplace\": \"Ganti konten saat ini dengan tata letak \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Sisipkan tata letak\",\n \"layoutsMenuText\": \"Tata letak…\",\n \"layoutsSelectLabel\": \"Tata letak awal\",\n \"layoutsToolbarText\": \"Tata letak\",\n \"layoutsToolbarTooltip\": \"Sisipkan tata letak awal\",\n \"logosToolbarText\": \"Logo\",\n \"logosToolbarTooltip\": \"Sisipkan logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Sisipkan Logo\",\n \"insertButton\": \"Sisipkan\",\n \"replaceButton\": \"Ganti\",\n \"cancelButton\": \"Batal\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Ganti konten saat ini dengan templat \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Sisipkan templat\",\n \"templatesMenuText\": \"Sisipkan templat…\",\n \"templatesSelectLabel\": \"Templat awal\",\n \"templatesToolbarText\": \"Templat\",\n \"placeholdToolbarText\": \"Pengganti\",\n \"placeholdToolbarTooltip\": \"Sisipkan gambar pengganti\",\n \"placeholdMenuText\": \"Gambar pengganti…\",\n \"placeholdDialogTitle\": \"Sisipkan gambar pengganti\",\n \"placeholdWidthLabel\": \"Lebar\",\n \"placeholdHeightLabel\": \"Tinggi\",\n \"placeholdBackgroundColorLabel\": \"Warna latar belakang\",\n \"placeholdTextColorLabel\": \"Warna teks\",\n \"placeholdTextLabel\": \"Teks\",\n \"placeholdAltTextLabel\": \"Teks alternatif\",\n \"placeholdInsertButton\": \"Sisipkan\",\n \"placeholdCancelButton\": \"Batal\",\n \"placeholdInvalidDimensions\": \"Lebar dan tinggi harus berupa bilangan bulat dari 10 hingga 4000.\",\n \"placeholdInvalidColor\": \"Warna harus menggunakan nilai heksadesimal tiga atau enam digit.\",\n \"placeholdAltFallback\": \"{{width}} kali {{height}} gambar pengganti\",\n \"a11yToolbarText\": \"Periksa aksesibilitas\",\n \"a11yToolbarTooltip\": \"Periksa konten untuk masalah aksesibilitas\",\n \"a11yMenuText\": \"Periksa aksesibilitas\",\n \"a11yDialogTitle\": \"Pemeriksa aksesibilitas\",\n \"a11yNoIssues\": \"Tidak ditemukan masalah aksesibilitas.\",\n \"a11yIssueCount\": \"{{count}} masalah aksesibilitas ditemukan.\",\n \"a11yStatusbarIssueCount\": \"{{count}} masalah aksesibilitas\",\n \"a11yIssueLabel\": \"Masalah\",\n \"a11yCloseButton\": \"Tutup\",\n \"a11yImageAltMessage\": \"Gambar harus memiliki teks alternatif.\",\n \"a11yImageAltWhy\": \"Pembaca layar memerlukan atribut alt untuk mendeskripsikan gambar atau menandainya sebagai dekoratif.\",\n \"a11yImageAltFilenameMessage\": \"Teks alternatif gambar harus mendeskripsikan gambar, bukan mengulangi nama berkasnya.\",\n \"a11yImageAltFilenameWhy\": \"Nama berkas jarang memberi informasi berguna bagi pengguna pembaca layar tentang sebuah gambar.\",\n \"a11yImageAltLengthMessage\": \"Teks alternatif gambar sebaiknya 125 karakter atau kurang.\",\n \"a11yImageAltLengthWhy\": \"Deskripsi singkat lebih mudah dipahami dan dinavigasi dengan teknologi bantu.\",\n \"a11yHeadingSequenceMessage\": \"Tingkat heading tidak boleh melewatkan level.\",\n \"a11yHeadingSequenceWhy\": \"Garis besar heading yang logis membantu orang menavigasi konten dengan teknologi bantu.\",\n \"a11yTableHeaderMessage\": \"Tabel harus menyertakan sel header.\",\n \"a11yTableHeaderWhy\": \"Sel header memberi pembaca layar konteks yang diperlukan untuk memahami data tabel.\",\n \"a11yTableCaptionMessage\": \"Tabel sebaiknya menyertakan keterangan.\",\n \"a11yTableCaptionWhy\": \"Keterangan mengidentifikasi tujuan tabel sebelum pembaca layar memasuki sel-selnya.\",\n \"a11yTableHeaderScopeMessage\": \"Sel header tabel harus mendeklarasikan cakupannya.\",\n \"a11yTableHeaderScopeWhy\": \"Atribut scope memungkinkan teknologi bantu mengaitkan header dengan sel data.\",\n \"a11yAdjacentLinksMessage\": \"Tautan yang bersebelahan dengan tujuan yang sama sebaiknya digabungkan.\",\n \"a11yAdjacentLinksWhy\": \"Tautan yang diulang membuat pemberhentian yang tidak perlu bagi pengguna keyboard dan pembaca layar.\",\n \"a11yHeadingStartMessage\": \"Heading pertama sebaiknya berupa h2.\",\n \"a11yHeadingStartWhy\": \"Judul dokumen editor disediakan di luar konten yang dapat diedit.\",\n \"a11yListStructureMessage\": \"Item daftar harus berada di dalam daftar berurutan atau tidak berurutan.\",\n \"a11yListStructureWhy\": \"Teknologi bantu mengandalkan struktur daftar untuk mengumumkan jumlah item dan posisinya.\",\n \"sourceToggleTooltip\": \"Kode sumber\",\n \"sourceFormatErrorMessage\": \"Tidak dapat memformat kode sumber — periksa tag yang belum ditutup atau kesalahan sintaks lainnya.\",\n \"saveToolbarText\": \"Preset\",\n \"saveToolbarTooltip\": \"Kelola preset tersimpan\",\n \"saveAction\": \"Simpan\",\n \"saveAsAction\": \"Simpan sebagai...\",\n \"openAction\": \"Buka...\",\n \"deleteAction\": \"Hapus...\",\n \"newAction\": \"Baru\",\n \"exportAction\": \"Ekspor...\",\n \"importAction\": \"Impor...\",\n \"saveAsDialogTitle\": \"Simpan preset\",\n \"presetNameLabel\": \"Nama\",\n \"openDialogTitle\": \"Buka preset\",\n \"deleteDialogTitle\": \"Hapus preset\",\n \"newDialogTitle\": \"Dokumen baru\",\n \"newDialogMessage\": \"Ini akan menghapus konten dan konfigurasi editor saat ini. Simpan pekerjaan saat ini terlebih dahulu?\",\n \"newDialogSaveButton\": \"Simpan & kosongkan\",\n \"newDialogDiscardButton\": \"Buang\",\n \"presetLabel\": \"Preset\",\n \"confirmOverwrite\": \"Preset bernama “{{name}}” sudah ada. Ganti?\",\n \"confirmDiscard\": \"Buka “{{name}}” dan buang perubahan yang belum disimpan saat ini?\",\n \"confirmDelete\": \"Hapus “{{name}}”? Tindakan ini tidak dapat dibatalkan.\",\n \"emptyPresets\": \"Tidak ada preset tersimpan yang tersedia.\",\n \"invalidName\": \"Masukkan nama preset.\",\n \"invalidPreset\": \"Preset ini tidak valid dan tidak dapat dibuka.\",\n \"importInvalidFile\": \"File yang dipilih bukan ekspor pantoken TinyMCE yang valid.\",\n \"storageReadError\": \"Preset tersimpan tidak dapat dibaca dari peramban ini.\",\n \"storageWriteError\": \"Preset tidak dapat disimpan di peramban ini.\",\n \"storageDeleteError\": \"Preset tidak dapat dihapus dari peramban ini.\",\n \"exportDefaultName\": \"tanpa judul\",\n \"presetSaveButton\": \"Simpan\",\n \"presetOpenButton\": \"Buka\",\n \"presetDeleteButton\": \"Hapus\"\n },\n \"it\": {\n \"autocompleteModifierDetail\": \"modificatore\",\n \"classValidationIncompleteComponent\": \"Nome del componente incompleto dopo '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Il token deve iniziare con '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Componente/utility sconosciuto: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Inserisci componente\",\n \"componentsListLabel\": \"Componenti\",\n \"componentsMenuText\": \"Componente\",\n \"componentsToolbarText\": \"Componenti\",\n \"componentsToolbarTooltip\": \"Inserisci un componente pantoken\",\n \"componentModifiersDefault\": \"Predefinito\",\n \"componentModifiersOptions\": \"Opzioni\",\n \"componentModifiersTooltip\": \"Modifica i modificatori del componente\",\n \"componentModifiersUtilities\": \"Utilità\",\n \"iconLabelDialogTitle\": \"Etichetta dell'icona\",\n \"iconLabelInputLabel\": \"Etichetta per lettore di schermo\",\n \"iconsMenuText\": \"Icona\",\n \"iconsSearchPlaceholder\": \"Cerca icone…\",\n \"iconsSearchLabel\": \"Cerca icone\",\n \"iconsAllSources\": \"Tutte\",\n \"iconsResultCount\": \"{{count}} icone\",\n \"iconsNoResults\": \"Nessuna icona corrisponde alla tua ricerca.\",\n \"iconsToolbarText\": \"Icone\",\n \"iconsToolbarTooltip\": \"Inserisci un'icona\",\n \"iconContextSizeSmall\": \"Piccolo\",\n \"iconContextSizeMedium\": \"Medio\",\n \"iconContextSizeLarge\": \"Grande\",\n \"iconContextSizeExtraLarge\": \"Extra grande\",\n \"layoutsConfirmReplace\": \"Sostituire il contenuto corrente con il layout \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Inserisci layout\",\n \"layoutsMenuText\": \"Layout…\",\n \"layoutsSelectLabel\": \"Layout iniziale\",\n \"layoutsToolbarText\": \"Layout\",\n \"layoutsToolbarTooltip\": \"Inserisci un layout iniziale\",\n \"logosToolbarText\": \"Loghi\",\n \"logosToolbarTooltip\": \"Inserisci un logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Inserisci logo\",\n \"insertButton\": \"Inserisci\",\n \"replaceButton\": \"Sostituisci\",\n \"cancelButton\": \"Annulla\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Sostituire il contenuto corrente con il template \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Inserisci template\",\n \"templatesMenuText\": \"Inserisci template…\",\n \"templatesSelectLabel\": \"Template iniziale\",\n \"templatesToolbarText\": \"Template\",\n \"placeholdToolbarText\": \"Segnaposto\",\n \"placeholdToolbarTooltip\": \"Inserisci un'immagine segnaposto\",\n \"placeholdMenuText\": \"Immagine segnaposto…\",\n \"placeholdDialogTitle\": \"Inserisci immagine segnaposto\",\n \"placeholdWidthLabel\": \"Larghezza\",\n \"placeholdHeightLabel\": \"Altezza\",\n \"placeholdBackgroundColorLabel\": \"Colore di sfondo\",\n \"placeholdTextColorLabel\": \"Colore del testo\",\n \"placeholdTextLabel\": \"Testo\",\n \"placeholdAltTextLabel\": \"Testo alternativo\",\n \"placeholdInsertButton\": \"Inserisci\",\n \"placeholdCancelButton\": \"Annulla\",\n \"placeholdInvalidDimensions\": \"La larghezza e l'altezza devono essere numeri interi da 10 a 4000.\",\n \"placeholdInvalidColor\": \"I colori devono usare valori esadecimali a tre o sei cifre.\",\n \"placeholdAltFallback\": \"{{width}} per {{height}} immagine segnaposto\",\n \"a11yToolbarText\": \"Controlla accessibilità\",\n \"a11yToolbarTooltip\": \"Controlla il contenuto per problemi di accessibilità\",\n \"a11yMenuText\": \"Controlla accessibilità\",\n \"a11yDialogTitle\": \"Controllore di accessibilità\",\n \"a11yNoIssues\": \"Nessun problema di accessibilità rilevato.\",\n \"a11yIssueCount\": \"{{count}} problema(i) di accessibilità rilevato(i).\",\n \"a11yStatusbarIssueCount\": \"{{count}} problemi di accessibilità\",\n \"a11yIssueLabel\": \"Problema\",\n \"a11yCloseButton\": \"Chiudi\",\n \"a11yImageAltMessage\": \"Le immagini devono avere un testo alternativo.\",\n \"a11yImageAltWhy\": \"I lettori di schermo necessitano di un attributo alt per descrivere un'immagine o identificarla come decorativa.\",\n \"a11yImageAltFilenameMessage\": \"Il testo alternativo dell'immagine dovrebbe descriverla, non ripetere il nome del file.\",\n \"a11yImageAltFilenameWhy\": \"Un nome file raramente fornisce informazioni utili agli utenti di lettori di schermo.\",\n \"a11yImageAltLengthMessage\": \"Il testo alternativo dell'immagine dovrebbe essere di 125 caratteri o meno.\",\n \"a11yImageAltLengthWhy\": \"Le descrizioni brevi sono più facili da comprendere e navigare con tecnologie assistive.\",\n \"a11yHeadingSequenceMessage\": \"I livelli dei titoli non devono saltare livelli.\",\n \"a11yHeadingSequenceWhy\": \"Una struttura logica dei titoli aiuta le persone a navigare il contenuto con tecnologie assistive.\",\n \"a11yTableHeaderMessage\": \"Le tabelle devono includere celle di intestazione.\",\n \"a11yTableHeaderWhy\": \"Le celle di intestazione forniscono ai lettori di schermo il contesto necessario per comprendere i dati della tabella.\",\n \"a11yTableCaptionMessage\": \"Le tabelle dovrebbero includere una didascalia.\",\n \"a11yTableCaptionWhy\": \"Una didascalia identifica lo scopo di una tabella prima che un lettore di schermo entri nelle sue celle.\",\n \"a11yTableHeaderScopeMessage\": \"Le celle di intestazione della tabella dovrebbero dichiarare il loro ambito.\",\n \"a11yTableHeaderScopeWhy\": \"L'attributo scope permette alla tecnologia assistiva di associare le intestazioni alle celle dei dati.\",\n \"a11yAdjacentLinksMessage\": \"I link adiacenti con la stessa destinazione dovrebbero essere combinati.\",\n \"a11yAdjacentLinksWhy\": \"I link ripetuti creano soste inutili per gli utenti da tastiera e per i lettori di schermo.\",\n \"a11yHeadingStartMessage\": \"Il primo titolo dovrebbe essere un h2.\",\n \"a11yHeadingStartWhy\": \"Il titolo del documento dell'editor è fornito al di fuori del contenuto modificabile.\",\n \"a11yListStructureMessage\": \"Gli elementi di elenco devono essere contenuti in un elenco ordinato o non ordinato.\",\n \"a11yListStructureWhy\": \"La tecnologia assistiva si basa sulla struttura degli elenchi per annunciare il numero di elementi e la posizione.\",\n \"sourceToggleTooltip\": \"Codice sorgente\",\n \"sourceFormatErrorMessage\": \"Impossibile formattare il codice sorgente — controlla che non ci siano tag non chiusi o altri errori di sintassi.\",\n \"saveToolbarText\": \"Preimpostazioni\",\n \"saveToolbarTooltip\": \"Gestisci le preimpostazioni salvate\",\n \"saveAction\": \"Salva\",\n \"saveAsAction\": \"Salva come...\",\n \"openAction\": \"Apri...\",\n \"deleteAction\": \"Elimina...\",\n \"newAction\": \"Nuovo\",\n \"exportAction\": \"Esporta...\",\n \"importAction\": \"Importa...\",\n \"saveAsDialogTitle\": \"Salva preimpostazione\",\n \"presetNameLabel\": \"Nome\",\n \"openDialogTitle\": \"Apri preimpostazione\",\n \"deleteDialogTitle\": \"Elimina preimpostazione\",\n \"newDialogTitle\": \"Nuovo documento\",\n \"newDialogMessage\": \"Questo cancella il contenuto e la configurazione dell'editor corrente. Salvare prima il lavoro corrente?\",\n \"newDialogSaveButton\": \"Salva e cancella\",\n \"newDialogDiscardButton\": \"Scarta\",\n \"presetLabel\": \"Preimpostazione\",\n \"confirmOverwrite\": \"Esiste già una preimpostazione chiamata “{{name}}”. Sostituirla?\",\n \"confirmDiscard\": \"Aprire “{{name}}” e scartare le modifiche non salvate correnti?\",\n \"confirmDelete\": \"Eliminare “{{name}}”? Questa operazione non può essere annullata.\",\n \"emptyPresets\": \"Non sono disponibili preimpostazioni salvate.\",\n \"invalidName\": \"Inserisci un nome per la preimpostazione.\",\n \"invalidPreset\": \"Questa preimpostazione non è valida e non può essere aperta.\",\n \"importInvalidFile\": \"Il file selezionato non è un'esportazione pantoken TinyMCE valida.\",\n \"storageReadError\": \"Le preimpostazioni salvate non possono essere lette da questo browser.\",\n \"storageWriteError\": \"La preimpostazione non può essere salvata in questo browser.\",\n \"storageDeleteError\": \"La preimpostazione non può essere eliminata da questo browser.\",\n \"exportDefaultName\": \"senza titolo\",\n \"presetSaveButton\": \"Salva\",\n \"presetOpenButton\": \"Apri\",\n \"presetDeleteButton\": \"Elimina\"\n },\n \"ja\": {\n \"autocompleteModifierDetail\": \"修飾子\",\n \"classValidationIncompleteComponent\": \"'{{prefix}}' の後のコンポーネント名が不完全です\",\n \"classValidationTokenPrefix\": \"トークンは '{{prefix}}' で始まる必要があります\",\n \"classValidationUnknownComponent\": \"不明なコンポーネント/ユーティリティ: '{{componentName}}'\",\n \"componentsDialogTitle\": \"コンポーネントを挿入\",\n \"componentsListLabel\": \"コンポーネント\",\n \"componentsMenuText\": \"コンポーネント\",\n \"componentsToolbarText\": \"コンポーネント\",\n \"componentsToolbarTooltip\": \"pantoken コンポーネントを挿入\",\n \"componentModifiersDefault\": \"デフォルト\",\n \"componentModifiersOptions\": \"オプション\",\n \"componentModifiersTooltip\": \"コンポーネントの修飾子を変更する\",\n \"componentModifiersUtilities\": \"ユーティリティ\",\n \"iconLabelDialogTitle\": \"アイコンラベル\",\n \"iconLabelInputLabel\": \"スクリーンリーダー用ラベル\",\n \"iconsMenuText\": \"アイコン\",\n \"iconsSearchPlaceholder\": \"アイコンを検索…\",\n \"iconsSearchLabel\": \"アイコンを検索\",\n \"iconsAllSources\": \"すべて\",\n \"iconsResultCount\": \"{{count}} 個のアイコン\",\n \"iconsNoResults\": \"検索に一致するアイコンはありません。\",\n \"iconsToolbarText\": \"アイコン\",\n \"iconsToolbarTooltip\": \"アイコンを挿入\",\n \"iconContextSizeSmall\": \"小\",\n \"iconContextSizeMedium\": \"中\",\n \"iconContextSizeLarge\": \"大\",\n \"iconContextSizeExtraLarge\": \"特大\",\n \"layoutsConfirmReplace\": \"現在のコンテンツを \\\"{{title}}\\\" レイアウトに置き換えますか?\",\n \"layoutsDialogTitle\": \"レイアウトを挿入\",\n \"layoutsMenuText\": \"レイアウト…\",\n \"layoutsSelectLabel\": \"スターターレイアウト\",\n \"layoutsToolbarText\": \"レイアウト\",\n \"layoutsToolbarTooltip\": \"スターターレイアウトを挿入\",\n \"logosToolbarText\": \"ロゴ\",\n \"logosToolbarTooltip\": \"ロゴを挿入\",\n \"logosMenuText\": \"ロゴ\",\n \"logosDialogTitle\": \"ロゴを挿入\",\n \"insertButton\": \"挿入\",\n \"replaceButton\": \"置換\",\n \"cancelButton\": \"キャンセル\",\n \"logoAltSuffix\": \"ロゴ\",\n \"templatesConfirmReplace\": \"現在のコンテンツを \\\"{{title}}\\\" テンプレートに置き換えますか?\",\n \"templatesDialogTitle\": \"テンプレートを挿入\",\n \"templatesMenuText\": \"テンプレートを挿入…\",\n \"templatesSelectLabel\": \"スターターテンプレート\",\n \"templatesToolbarText\": \"テンプレート\",\n \"placeholdToolbarText\": \"プレースホルダー\",\n \"placeholdToolbarTooltip\": \"プレースホルダー画像を挿入\",\n \"placeholdMenuText\": \"プレースホルダー画像…\",\n \"placeholdDialogTitle\": \"プレースホルダー画像を挿入\",\n \"placeholdWidthLabel\": \"幅\",\n \"placeholdHeightLabel\": \"高さ\",\n \"placeholdBackgroundColorLabel\": \"背景色\",\n \"placeholdTextColorLabel\": \"文字色\",\n \"placeholdTextLabel\": \"テキスト\",\n \"placeholdAltTextLabel\": \"代替テキスト\",\n \"placeholdInsertButton\": \"挿入\",\n \"placeholdCancelButton\": \"キャンセル\",\n \"placeholdInvalidDimensions\": \"幅と高さは10から4000の整数でなければなりません。\",\n \"placeholdInvalidColor\": \"色は3桁または6桁の16進数を使用する必要があります。\",\n \"placeholdAltFallback\": \"{{width}} × {{height}} のプレースホルダー画像\",\n \"a11yToolbarText\": \"アクセシビリティを確認\",\n \"a11yToolbarTooltip\": \"アクセシビリティの問題がないかコンテンツを確認します\",\n \"a11yMenuText\": \"アクセシビリティを確認\",\n \"a11yDialogTitle\": \"アクセシビリティチェッカー\",\n \"a11yNoIssues\": \"アクセシビリティの問題は見つかりませんでした。\",\n \"a11yIssueCount\": \"{{count}} 件のアクセシビリティ問題が見つかりました。\",\n \"a11yStatusbarIssueCount\": \"{{count}} 件のアクセシビリティ問題\",\n \"a11yIssueLabel\": \"問題\",\n \"a11yCloseButton\": \"閉じる\",\n \"a11yImageAltMessage\": \"画像には代替テキストが必要です。\",\n \"a11yImageAltWhy\": \"スクリーンリーダーは画像を説明するか装飾的であることを示す alt 属性を必要とします。\",\n \"a11yImageAltFilenameMessage\": \"画像の代替テキストはファイル名を繰り返すのではなく、画像を説明するべきです。\",\n \"a11yImageAltFilenameWhy\": \"ファイル名はスクリーンリーダー利用者にとって役に立つ情報をほとんど提供しません。\",\n \"a11yImageAltLengthMessage\": \"画像の代替テキストは125文字以内にするべきです。\",\n \"a11yImageAltLengthWhy\": \"短い説明の方が支援技術で理解・操作しやすくなります。\",\n \"a11yHeadingSequenceMessage\": \"見出しレベルは飛ばしてはいけません。\",\n \"a11yHeadingSequenceWhy\": \"論理的な見出しの構成は支援技術によるコンテンツのナビゲーションを助けます。\",\n \"a11yTableHeaderMessage\": \"表にはヘッダーセルを含める必要があります。\",\n \"a11yTableHeaderWhy\": \"ヘッダーセルは表データを理解するための文脈をスクリーンリーダーに提供します。\",\n \"a11yTableCaptionMessage\": \"表にはキャプションを付けるべきです。\",\n \"a11yTableCaptionWhy\": \"キャプションはスクリーンリーダーがセルに入る前に表の目的を特定します。\",\n \"a11yTableHeaderScopeMessage\": \"表のヘッダーセルは scope を宣言すべきです。\",\n \"a11yTableHeaderScopeWhy\": \"scope 属性により支援技術がヘッダーとデータセルを関連付けられます。\",\n \"a11yAdjacentLinksMessage\": \"隣接する同じ宛先のリンクは結合するべきです。\",\n \"a11yAdjacentLinksWhy\": \"同じリンクの繰り返しはキーボードやスクリーンリーダー利用者に不要な停止を生みます。\",\n \"a11yHeadingStartMessage\": \"最初の見出しは h2 であるべきです。\",\n \"a11yHeadingStartWhy\": \"エディタのドキュメントタイトルは編集可能なコンテンツの外部で提供されています。\",\n \"a11yListStructureMessage\": \"リストアイテムは順序付きまたは順序なしリストに含まれている必要があります。\",\n \"a11yListStructureWhy\": \"支援技術は項目数や位置をアナウンスするためにリスト構造に依存します。\",\n \"sourceToggleTooltip\": \"ソースコード\",\n \"sourceFormatErrorMessage\": \"ソースコードをフォーマットできませんでした — 閉じられていないタグやその他の構文エラーを確認してください。\",\n \"saveToolbarText\": \"プリセット\",\n \"saveToolbarTooltip\": \"保存済みプリセットを管理\",\n \"saveAction\": \"保存\",\n \"saveAsAction\": \"名前を付けて保存…\",\n \"openAction\": \"開く…\",\n \"deleteAction\": \"削除…\",\n \"newAction\": \"新規\",\n \"exportAction\": \"エクスポート...\",\n \"importAction\": \"インポート...\",\n \"saveAsDialogTitle\": \"プリセットを保存\",\n \"presetNameLabel\": \"名前\",\n \"openDialogTitle\": \"プリセットを開く\",\n \"deleteDialogTitle\": \"プリセットを削除\",\n \"newDialogTitle\": \"新規ドキュメント\",\n \"newDialogMessage\": \"これにより現在のエディターの内容と設定が消去されます。現在の作業を先に保存しますか?\",\n \"newDialogSaveButton\": \"保存してクリア\",\n \"newDialogDiscardButton\": \"破棄\",\n \"presetLabel\": \"プリセット\",\n \"confirmOverwrite\": \"「{{name}}」という名前のプリセットは既に存在します。置き換えますか?\",\n \"confirmDiscard\": \"「{{name}}」を開いて現在の未保存の変更を破棄しますか?\",\n \"confirmDelete\": \"「{{name}}」を削除しますか?これは元に戻せません。\",\n \"emptyPresets\": \"保存されたプリセットは利用できません。\",\n \"invalidName\": \"プリセット名を入力してください。\",\n \"invalidPreset\": \"このプリセットは無効で、開くことができませんでした。\",\n \"importInvalidFile\": \"選択したファイルは有効な pantoken TinyMCE エクスポートではありません。\",\n \"storageReadError\": \"このブラウザーから保存済みプリセットを読み取れませんでした。\",\n \"storageWriteError\": \"このブラウザーにプリセットを保存できませんでした。\",\n \"storageDeleteError\": \"このブラウザーからプリセットを削除できませんでした。\",\n \"exportDefaultName\": \"無題\",\n \"presetSaveButton\": \"保存\",\n \"presetOpenButton\": \"開く\",\n \"presetDeleteButton\": \"削除\"\n },\n \"ko\": {\n \"autocompleteModifierDetail\": \"수정자\",\n \"classValidationIncompleteComponent\": \"'{{prefix}}' 뒤에 불완전한 컴포넌트 이름\",\n \"classValidationTokenPrefix\": \"토큰은 '{{prefix}}'로 시작해야 합니다\",\n \"classValidationUnknownComponent\": \"알 수 없는 컴포넌트/유틸리티: '{{componentName}}'\",\n \"componentsDialogTitle\": \"컴포넌트 삽입\",\n \"componentsListLabel\": \"컴포넌트\",\n \"componentsMenuText\": \"컴포넌트\",\n \"componentsToolbarText\": \"컴포넌트\",\n \"componentsToolbarTooltip\": \"pantoken 컴포넌트 삽입\",\n \"componentModifiersDefault\": \"기본값\",\n \"componentModifiersOptions\": \"옵션\",\n \"componentModifiersTooltip\": \"컴포넌트 수식자 변경\",\n \"componentModifiersUtilities\": \"유틸리티\",\n \"iconLabelDialogTitle\": \"아이콘 레이블\",\n \"iconLabelInputLabel\": \"스크린 리더 레이블\",\n \"iconsMenuText\": \"아이콘\",\n \"iconsSearchPlaceholder\": \"아이콘 검색…\",\n \"iconsSearchLabel\": \"아이콘 검색\",\n \"iconsAllSources\": \"모두\",\n \"iconsResultCount\": \"{{count}}개 아이콘\",\n \"iconsNoResults\": \"검색과 일치하는 아이콘이 없습니다.\",\n \"iconsToolbarText\": \"아이콘\",\n \"iconsToolbarTooltip\": \"아이콘 삽입\",\n \"iconContextSizeSmall\": \"작음\",\n \"iconContextSizeMedium\": \"중간\",\n \"iconContextSizeLarge\": \"큼\",\n \"iconContextSizeExtraLarge\": \"특대\",\n \"layoutsConfirmReplace\": \"현재 내용을 \\\"{{title}}\\\" 레이아웃으로 바꾸시겠습니까?\",\n \"layoutsDialogTitle\": \"레이아웃 삽입\",\n \"layoutsMenuText\": \"레이아웃…\",\n \"layoutsSelectLabel\": \"시작 레이아웃\",\n \"layoutsToolbarText\": \"레이아웃\",\n \"layoutsToolbarTooltip\": \"시작 레이아웃 삽입\",\n \"logosToolbarText\": \"로고\",\n \"logosToolbarTooltip\": \"로고 삽입\",\n \"logosMenuText\": \"로고\",\n \"logosDialogTitle\": \"로고 삽입\",\n \"insertButton\": \"삽입\",\n \"replaceButton\": \"바꾸기\",\n \"cancelButton\": \"취소\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"현재 내용을 \\\"{{title}}\\\" 템플릿으로 바꾸시겠습니까?\",\n \"templatesDialogTitle\": \"템플릿 삽입\",\n \"templatesMenuText\": \"템플릿 삽입…\",\n \"templatesSelectLabel\": \"시작 템플릿\",\n \"templatesToolbarText\": \"템플릿\",\n \"placeholdToolbarText\": \"자리표시자\",\n \"placeholdToolbarTooltip\": \"자리표시자 이미지 삽입\",\n \"placeholdMenuText\": \"자리표시자 이미지…\",\n \"placeholdDialogTitle\": \"자리표시자 이미지 삽입\",\n \"placeholdWidthLabel\": \"너비\",\n \"placeholdHeightLabel\": \"높이\",\n \"placeholdBackgroundColorLabel\": \"배경색\",\n \"placeholdTextColorLabel\": \"텍스트 색\",\n \"placeholdTextLabel\": \"텍스트\",\n \"placeholdAltTextLabel\": \"대체 텍스트\",\n \"placeholdInsertButton\": \"삽입\",\n \"placeholdCancelButton\": \"취소\",\n \"placeholdInvalidDimensions\": \"너비와 높이는 10에서 4000 사이의 정수여야 합니다.\",\n \"placeholdInvalidColor\": \"색상은 3자리 또는 6자리 16진수 값을 사용해야 합니다.\",\n \"placeholdAltFallback\": \"{{width}} by {{height}} 자리표시자 이미지\",\n \"a11yToolbarText\": \"접근성 검사\",\n \"a11yToolbarTooltip\": \"내용에서 접근성 문제를 확인합니다\",\n \"a11yMenuText\": \"접근성 검사\",\n \"a11yDialogTitle\": \"접근성 검사기\",\n \"a11yNoIssues\": \"접근성 문제가 발견되지 않았습니다.\",\n \"a11yIssueCount\": \"{{count}}개의 접근성 문제가 발견되었습니다.\",\n \"a11yStatusbarIssueCount\": \"{{count}}개의 접근성 문제\",\n \"a11yIssueLabel\": \"문제\",\n \"a11yCloseButton\": \"닫기\",\n \"a11yImageAltMessage\": \"이미지에는 대체 텍스트가 있어야 합니다.\",\n \"a11yImageAltWhy\": \"스크린 리더는 이미지를 설명하거나 장식용임을 식별하기 위해 alt 속성이 필요합니다.\",\n \"a11yImageAltFilenameMessage\": \"이미지 대체 텍스트는 이미지의 파일명을 반복하지 말고 이미지를 설명해야 합니다.\",\n \"a11yImageAltFilenameWhy\": \"파일명은 스크린 리더 사용자에게 유용한 정보를 제공하는 경우가 거의 없습니다.\",\n \"a11yImageAltLengthMessage\": \"이미지 대체 텍스트는 125자 이하여야 합니다.\",\n \"a11yImageAltLengthWhy\": \"짧은 설명이 보조 기술로 이해하고 탐색하기 더 쉽습니다.\",\n \"a11yHeadingSequenceMessage\": \"헤딩 수준은 건너뛰어서는 안 됩니다.\",\n \"a11yHeadingSequenceWhy\": \"논리적인 헤딩 구조는 보조 기술로 콘텐츠를 탐색하는 데 도움이 됩니다.\",\n \"a11yTableHeaderMessage\": \"표에는 헤더 셀이 포함되어야 합니다.\",\n \"a11yTableHeaderWhy\": \"헤더 셀은 스크린 리더가 표 데이터를 이해하는 데 필요한 문맥을 제공합니다.\",\n \"a11yTableCaptionMessage\": \"표에는 캡션이 포함되어야 합니다.\",\n \"a11yTableCaptionWhy\": \"캡션은 스크린 리더가 셀에 진입하기 전에 표의 목적을 식별합니다.\",\n \"a11yTableHeaderScopeMessage\": \"표의 헤더 셀은 scope를 선언해야 합니다.\",\n \"a11yTableHeaderScopeWhy\": \"scope 속성은 보조 기술이 헤더와 데이터 셀을 연결할 수 있게 합니다.\",\n \"a11yAdjacentLinksMessage\": \"같은 대상의 인접한 링크는 합쳐야 합니다.\",\n \"a11yAdjacentLinksWhy\": \"반복된 링크는 키보드와 스크린 리더 사용자에게 불필요한 중단을 만듭니다.\",\n \"a11yHeadingStartMessage\": \"첫 번째 헤딩은 h2여야 합니다.\",\n \"a11yHeadingStartWhy\": \"편집기의 문서 제목은 편집 가능한 콘텐츠 외부에서 제공됩니다.\",\n \"a11yListStructureMessage\": \"목록 항목은 정렬된 또는 정렬되지 않은 목록에 포함되어야 합니다.\",\n \"a11yListStructureWhy\": \"보조 기술은 항목 수와 위치를 알리기 위해 목록 구조에 의존합니다.\",\n \"sourceToggleTooltip\": \"소스 코드\",\n \"sourceFormatErrorMessage\": \"소스 코드를 서식화할 수 없습니다 — 닫히지 않은 태그나 다른 문법 오류를 확인하세요.\",\n \"saveToolbarText\": \"프리셋\",\n \"saveToolbarTooltip\": \"저장된 프리셋 관리\",\n \"saveAction\": \"저장\",\n \"saveAsAction\": \"다른 이름으로 저장...\",\n \"openAction\": \"열기...\",\n \"deleteAction\": \"삭제...\",\n \"newAction\": \"새로 만들기\",\n \"exportAction\": \"내보내기...\",\n \"importAction\": \"가져오기...\",\n \"saveAsDialogTitle\": \"프리셋 저장\",\n \"presetNameLabel\": \"이름\",\n \"openDialogTitle\": \"프리셋 열기\",\n \"deleteDialogTitle\": \"프리셋 삭제\",\n \"newDialogTitle\": \"새 문서\",\n \"newDialogMessage\": \"현재 편집기 내용과 설정이 지워집니다. 현재 작업을 먼저 저장하시겠습니까?\",\n \"newDialogSaveButton\": \"저장 후 지우기\",\n \"newDialogDiscardButton\": \"버리기\",\n \"presetLabel\": \"프리셋\",\n \"confirmOverwrite\": \"“{{name}}”이라는 이름의 프리셋이 이미 있습니다. 교체하시겠습니까?\",\n \"confirmDiscard\": \"“{{name}}”을(를) 열고 현재 저장되지 않은 변경사항을 버리겠습니까?\",\n \"confirmDelete\": \"“{{name}}”을(를) 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.\",\n \"emptyPresets\": \"저장된 프리셋이 없습니다.\",\n \"invalidName\": \"프리셋 이름을 입력하세요.\",\n \"invalidPreset\": \"이 프리셋은 유효하지 않아 열 수 없습니다.\",\n \"importInvalidFile\": \"선택한 파일은 유효한 pantoken TinyMCE 내보내기가 아닙니다.\",\n \"storageReadError\": \"이 브라우저에서 저장된 프리셋을 읽을 수 없습니다.\",\n \"storageWriteError\": \"이 브라우저에 프리셋을 저장할 수 없습니다.\",\n \"storageDeleteError\": \"이 브라우저에서 프리셋을 삭제할 수 없습니다.\",\n \"exportDefaultName\": \"제목 없음\",\n \"presetSaveButton\": \"저장\",\n \"presetOpenButton\": \"열기\",\n \"presetDeleteButton\": \"삭제\"\n },\n \"mi\": {\n \"autocompleteModifierDetail\": \"taapiri\",\n \"classValidationIncompleteComponent\": \"Ingoa wāhanga kāore i oti i muri i '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Me tīmata te tohu ki '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Wāhanga/taonga kaore i te mōhiotia: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Whakauru Wāhanga\",\n \"componentsListLabel\": \"Ngā Wāhanga\",\n \"componentsMenuText\": \"Wāhanga\",\n \"componentsToolbarText\": \"Ngā Wāhanga\",\n \"componentsToolbarTooltip\": \"Whakauru i tētahi wāhanga pantoken\",\n \"componentModifiersDefault\": \"Taunoa\",\n \"componentModifiersOptions\": \"Kōwhiringa\",\n \"componentModifiersTooltip\": \"Huri i ngā whakarerekētanga o te wāhanga\",\n \"componentModifiersUtilities\": \"Ngā taputapu\",\n \"iconLabelDialogTitle\": \"Tapanga tohu\",\n \"iconLabelInputLabel\": \"Tapanga mō te kaipānui mata\",\n \"iconsMenuText\": \"Tohu\",\n \"iconsSearchPlaceholder\": \"Rapua ngā tohu…\",\n \"iconsSearchLabel\": \"Rapua ngā tohu\",\n \"iconsAllSources\": \"Katoa\",\n \"iconsResultCount\": \"{{count}} tohu\",\n \"iconsNoResults\": \"Kāore he tohu e hāngai ana ki tāu rapu.\",\n \"iconsToolbarText\": \"Ngā Tohu\",\n \"iconsToolbarTooltip\": \"Whakauru i tētahi tohu\",\n \"iconContextSizeSmall\": \"Ititi\",\n \"iconContextSizeMedium\": \"Waenga\",\n \"iconContextSizeLarge\": \"Rahi\",\n \"iconContextSizeExtraLarge\": \"Rahi ake\",\n \"layoutsConfirmReplace\": \"Whakakapia te ihirangi o nāianei ki te tātai \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Whakauru tātai\",\n \"layoutsMenuText\": \"Tātai…\",\n \"layoutsSelectLabel\": \"Tātai tīmatanga\",\n \"layoutsToolbarText\": \"Ngā tātai\",\n \"layoutsToolbarTooltip\": \"Whakauru i tētahi tātai tīmatanga\",\n \"logosToolbarText\": \"Ngā logo\",\n \"logosToolbarTooltip\": \"Whakauru i tētahi logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Whakauru Logo\",\n \"insertButton\": \"Whakauru\",\n \"replaceButton\": \"Huri\",\n \"cancelButton\": \"Whakakore\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Whakakapia te ihirangi o nāianei ki te tauira \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Whakauru tauira\",\n \"templatesMenuText\": \"Whakauru tauira…\",\n \"templatesSelectLabel\": \"Tauira tīmatanga\",\n \"templatesToolbarText\": \"Ngā tauira\",\n \"placeholdToolbarText\": \"Whakakī wāhi\",\n \"placeholdToolbarTooltip\": \"Whakauru i tētahi whakaahua whakakī wāhi\",\n \"placeholdMenuText\": \"Whakaahua whakakī wāhi…\",\n \"placeholdDialogTitle\": \"Whakauru whakaahua whakakī wāhi\",\n \"placeholdWidthLabel\": \"Whanui\",\n \"placeholdHeightLabel\": \"Teitei\",\n \"placeholdBackgroundColorLabel\": \"Tae papamuri\",\n \"placeholdTextColorLabel\": \"Tae kuputuhi\",\n \"placeholdTextLabel\": \"Kuputuhi\",\n \"placeholdAltTextLabel\": \"Kuputuhi alt\",\n \"placeholdInsertButton\": \"Whakauru\",\n \"placeholdCancelButton\": \"Whakakore\",\n \"placeholdInvalidDimensions\": \"Me matua tau katoa te whanui me te teitei mai i te 10 ki te 4000.\",\n \"placeholdInvalidColor\": \"Me whakamahi ngā tae i ngā uara heksadesimera e toru rānei e ono ngā tohu.\",\n \"placeholdAltFallback\": \"{{width}} mā {{height}} whakaahua whakakī wāhi\",\n \"a11yToolbarText\": \"Tirohia te wātea\",\n \"a11yToolbarTooltip\": \"Tirohia ngā ihirangi kia kitea mēnā he raruraru mō te wātea.\",\n \"a11yMenuText\": \"Tirohia te wātea\",\n \"a11yDialogTitle\": \"Kaiwhakamātau wātea\",\n \"a11yNoIssues\": \"Kāore i kitea he raruraru mō te wātea.\",\n \"a11yIssueCount\": \"{{count}} raruraru mō te wātea i kitea.\",\n \"a11yStatusbarIssueCount\": \"{{count}} raru wātea\",\n \"a11yIssueLabel\": \"Raru\",\n \"a11yCloseButton\": \"Katia\",\n \"a11yImageAltMessage\": \"Me whai kupu āwhina ngā whakaahua.\",\n \"a11yImageAltWhy\": \"E hiahiatia ana e ngā kaipānui mata te āhuatanga `alt` kia whakamāramatia te whakaahua, kia tautuhia rānei he mea whakapaipai.\",\n \"a11yImageAltFilenameMessage\": \"Me whakamārama e te kupu āwhina te whakaahua, kaua e whakahuatia te ingoa kōnae.\",\n \"a11yImageAltFilenameWhy\": \"Kāore i te nuinga o te wā e hoatu e te ingoa kōnae ngā pārongo whaihua ki ngā kaiwhakamahi kaipānui mata.\",\n \"a11yImageAltLengthMessage\": \"Me kore ake i te 125 ngā pūāhua o te kupu āwhina whakaahua.\",\n \"a11yImageAltLengthWhy\": \"He māmā ake te mārama me te hāereere o ngā whakamārama poto mā ngā hangarau āwhina.\",\n \"a11yHeadingSequenceMessage\": \"Kaua e peke ngā taumata upoko.\",\n \"a11yHeadingSequenceWhy\": \"He āhua upoko whai tikanga ka āwhina i te hunga ki te hāereere i ngā ihirangi mā ngā hangarau āwhina.\",\n \"a11yTableHeaderMessage\": \"Me whai pūtau taitara ngā ripanga.\",\n \"a11yTableHeaderWhy\": \"Ka hoatu e ngā pūtau taitara ki ngā kaipānui mata te horopaki e hiahiatia ana kia mārama ai rātou ki ngā raraunga o te ripanga.\",\n \"a11yTableCaptionMessage\": \"Kia whai taitara whakamārama ngā ripanga.\",\n \"a11yTableCaptionWhy\": \"Ka tautuhi te taitara whakamārama i te kaupapa o te ripanga i mua i te tomo a te kaipānui mata ki ōna pūtau.\",\n \"a11yTableHeaderScopeMessage\": \"Me whakaatu te pūtau taitara o te ripanga i tōna rohe.\",\n \"a11yTableHeaderScopeWhy\": \"Ka āhei te āhuatanga `scope` i ngā hangarau āwhina ki te hono i ngā taitara ki ngā pūtau raraunga.\",\n \"a11yAdjacentLinksMessage\": \"Me whakakotahi ngā hononga tata me te wāhi taunga kotahi.\",\n \"a11yAdjacentLinksWhy\": \"Ka waihanga ngā hononga tārite i ngā tūnga koretake mō ngā kaiwhakamahi papapātuhi me ngā kaipānui mata.\",\n \"a11yHeadingStartMessage\": \"Me h2 te upoko tuatahi.\",\n \"a11yHeadingStartWhy\": \"Ka whakarato te taitara o te tuhinga o te etita i waho o ngā ihirangi ka taea te whakarerekē.\",\n \"a11yListStructureMessage\": \"Me waiho ngā tūemi rārangi i roto i tētahi rārangi whakarārangitia, rārangi kāore i whakarārangitia rānei.\",\n \"a11yListStructureWhy\": \"E whakawhirinaki ana ngā hangarau āwhina ki te hanganga rārangi kia pānuitia ngā tatau tūemi me ngā tūnga.\",\n \"sourceToggleTooltip\": \"Waehere pūtake\",\n \"sourceFormatErrorMessage\": \"Kāore i taea te whakatakoto i te waehere puna — tirohia mēnā he tapuwae kāore i kapi, he hapa wetereo rānei.\",\n \"saveToolbarText\": \"Ngā tautuhinga\",\n \"saveToolbarTooltip\": \"Whakahaerehia ngā tautuhinga kua tiakina\",\n \"saveAction\": \"Tiaki\",\n \"saveAsAction\": \"Tiaki hei...\",\n \"openAction\": \"Whakatuwhera...\",\n \"deleteAction\": \"Mukua...\",\n \"newAction\": \"Hou\",\n \"exportAction\": \"Kaweake...\",\n \"importAction\": \"Kawemai...\",\n \"saveAsDialogTitle\": \"Tiaki tautuhinga\",\n \"presetNameLabel\": \"Ingoa\",\n \"openDialogTitle\": \"Whakatuwhera tautuhinga\",\n \"deleteDialogTitle\": \"Mukua tautuhinga\",\n \"newDialogTitle\": \"Tuhinga hou\",\n \"newDialogMessage\": \"Ka muku tēnei i te ihirangi me ngā whakarite o te etita ināianei. Tiakina te mahi o nāianei tuatahi?\",\n \"newDialogSaveButton\": \"Tiakina & muku\",\n \"newDialogDiscardButton\": \"Whakakore\",\n \"presetLabel\": \"Tautuhinga\",\n \"confirmOverwrite\": \"Kei reira kē tētahi tautuhinga e kīia ana ko “{{name}}”. Whakakapi rānei?\",\n \"confirmDiscard\": \"Whakatuwherahia “{{name}}” ka whakakorea ngā huringa kāore i tiakina o nāianei?\",\n \"confirmDelete\": \"Mukua “{{name}}”? Kāore e taea te whakahoki.\",\n \"emptyPresets\": \"Kāore he tautuhinga kua tiakina e wātea ana.\",\n \"invalidName\": \"Tāuru i tētahi ingoa tautuhinga.\",\n \"invalidPreset\": \"He hē tēnei tautuhinga, kāore i taea te whakatuwhera.\",\n \"importInvalidFile\": \"Ehara i te kōnae tika mō te kaweake pantoken TinyMCE te kōnae kua tīpakohia.\",\n \"storageReadError\": \"Kāore i taea te pānui i ngā tautuhinga kua tiakina i tēnei tirotiro.\",\n \"storageWriteError\": \"Kāore i taea te tiaki i te tautuhinga i tēnei tirotiro.\",\n \"storageDeleteError\": \"Kāore i taea te muku i te tautuhinga i tēnei tirotiro.\",\n \"exportDefaultName\": \"kāore he taitara\",\n \"presetSaveButton\": \"Tiaki\",\n \"presetOpenButton\": \"Whakatuwhera\",\n \"presetDeleteButton\": \"Mukua\"\n },\n \"ms\": {\n \"autocompleteModifierDetail\": \"pengubah\",\n \"classValidationIncompleteComponent\": \"Nama komponen tidak lengkap selepas '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token mesti bermula dengan '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Komponen/utiliti tidak diketahui: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Sisip Komponen\",\n \"componentsListLabel\": \"Komponen\",\n \"componentsMenuText\": \"Komponen\",\n \"componentsToolbarText\": \"Komponen\",\n \"componentsToolbarTooltip\": \"Sisip komponen pantoken\",\n \"componentModifiersDefault\": \"Lalai\",\n \"componentModifiersOptions\": \"Pilihan\",\n \"componentModifiersTooltip\": \"Tukar pengubah komponen\",\n \"componentModifiersUtilities\": \"Utiliti\",\n \"iconLabelDialogTitle\": \"Label ikon\",\n \"iconLabelInputLabel\": \"Label pembaca skrin\",\n \"iconsMenuText\": \"Ikon\",\n \"iconsSearchPlaceholder\": \"Cari ikon…\",\n \"iconsSearchLabel\": \"Cari ikon\",\n \"iconsAllSources\": \"Semua\",\n \"iconsResultCount\": \"{{count}} ikon\",\n \"iconsNoResults\": \"Tiada ikon sepadan dengan carian anda.\",\n \"iconsToolbarText\": \"Ikon\",\n \"iconsToolbarTooltip\": \"Sisip ikon\",\n \"iconContextSizeSmall\": \"Kecil\",\n \"iconContextSizeMedium\": \"Sederhana\",\n \"iconContextSizeLarge\": \"Besar\",\n \"iconContextSizeExtraLarge\": \"Sangat besar\",\n \"layoutsConfirmReplace\": \"Gantikan kandungan semasa dengan susun atur \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Sisip susun atur\",\n \"layoutsMenuText\": \"Susun atur…\",\n \"layoutsSelectLabel\": \"Susun atur permulaan\",\n \"layoutsToolbarText\": \"Susun atur\",\n \"layoutsToolbarTooltip\": \"Sisip susun atur permulaan\",\n \"logosToolbarText\": \"Logo\",\n \"logosToolbarTooltip\": \"Sisip logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Sisip Logo\",\n \"insertButton\": \"Sisip\",\n \"replaceButton\": \"Gantikan\",\n \"cancelButton\": \"Batal\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Gantikan kandungan semasa dengan templat \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Sisip templat\",\n \"templatesMenuText\": \"Sisip templat…\",\n \"templatesSelectLabel\": \"Templat permulaan\",\n \"templatesToolbarText\": \"Templat\",\n \"placeholdToolbarText\": \"Tempat letak\",\n \"placeholdToolbarTooltip\": \"Sisip imej tempat letak\",\n \"placeholdMenuText\": \"Imej tempat letak…\",\n \"placeholdDialogTitle\": \"Sisip imej tempat letak\",\n \"placeholdWidthLabel\": \"Lebar\",\n \"placeholdHeightLabel\": \"Tinggi\",\n \"placeholdBackgroundColorLabel\": \"Warna latar\",\n \"placeholdTextColorLabel\": \"Warna teks\",\n \"placeholdTextLabel\": \"Teks\",\n \"placeholdAltTextLabel\": \"Teks alternatif\",\n \"placeholdInsertButton\": \"Sisip\",\n \"placeholdCancelButton\": \"Batal\",\n \"placeholdInvalidDimensions\": \"Lebar dan tinggi mesti nombor bulat antara 10 hingga 4000.\",\n \"placeholdInvalidColor\": \"Warna mesti menggunakan nilai heksadesimal tiga atau enam digit.\",\n \"placeholdAltFallback\": \"{{width}} oleh {{height}} imej tempat letak\",\n \"a11yToolbarText\": \"Semak kebolehcapaian\",\n \"a11yToolbarTooltip\": \"Periksa kandungan untuk isu kebolehcapaian\",\n \"a11yMenuText\": \"Semak kebolehcapaian\",\n \"a11yDialogTitle\": \"Pemeriksa kebolehcapaian\",\n \"a11yNoIssues\": \"Tiada isu kebolehcapaian ditemui.\",\n \"a11yIssueCount\": \"{{count}} isu kebolehcapaian ditemui.\",\n \"a11yStatusbarIssueCount\": \"{{count}} isu kebolehcapaian\",\n \"a11yIssueLabel\": \"Isu\",\n \"a11yCloseButton\": \"Tutup\",\n \"a11yImageAltMessage\": \"Imej mesti mempunyai teks alternatif.\",\n \"a11yImageAltWhy\": \"Pembaca skrin memerlukan atribut alt untuk menerangkan imej atau mengenalinya sebagai hiasan.\",\n \"a11yImageAltFilenameMessage\": \"Teks alternatif imej harus menerangkan imej, bukan mengulangi nama failnya.\",\n \"a11yImageAltFilenameWhy\": \"Nama fail jarang memberi maklumat berguna kepada pengguna pembaca skrin tentang imej.\",\n \"a11yImageAltLengthMessage\": \"Teks alternatif imej sebaiknya 125 aksara atau kurang.\",\n \"a11yImageAltLengthWhy\": \"Deskripsi ringkas lebih mudah difahami dan dinavigasi dengan teknologi bantuan.\",\n \"a11yHeadingSequenceMessage\": \"Tahap pengepala tidak sepatutnya melangkau aras.\",\n \"a11yHeadingSequenceWhy\": \"Susun atur pengepala yang logik membantu orang menavigasi kandungan dengan teknologi bantuan.\",\n \"a11yTableHeaderMessage\": \"Jadual mesti termasuk sel pengepala.\",\n \"a11yTableHeaderWhy\": \"Sel pengepala memberi pembaca skrin konteks yang diperlukan untuk memahami data jadual.\",\n \"a11yTableCaptionMessage\": \"Jadual sepatutnya disertakan kapsyen.\",\n \"a11yTableCaptionWhy\": \"Kapsyen mengenal pasti tujuan jadual sebelum pembaca skrin memasuki sel-selnya.\",\n \"a11yTableHeaderScopeMessage\": \"Sel pengepala jadual harus mengisytiharkan skopnya.\",\n \"a11yTableHeaderScopeWhy\": \"Atribut scope membenarkan teknologi bantuan mengaitkan pengepala dengan sel data.\",\n \"a11yAdjacentLinksMessage\": \"Pautan berturut-turut yang mempunyai destinasi sama harus digabungkan.\",\n \"a11yAdjacentLinksWhy\": \"Pautan berulang mencipta hentian yang tidak diperlukan untuk pengguna papan kekunci dan pembaca skrin.\",\n \"a11yHeadingStartMessage\": \"Pengepala pertama harus menjadi h2.\",\n \"a11yHeadingStartWhy\": \"Tajuk dokumen penyunting disediakan di luar kandungan yang boleh diedit.\",\n \"a11yListStructureMessage\": \"Item senarai mesti dimuatkan dalam senarai tertib atau tidak tertib.\",\n \"a11yListStructureWhy\": \"Teknologi bantuan bergantung pada struktur senarai untuk mengumumkan bilangan item dan kedudukan.\",\n \"sourceToggleTooltip\": \"Kod sumber\",\n \"sourceFormatErrorMessage\": \"Tidak dapat memformat kod sumber — periksa tag yang tidak ditutup atau ralat sintaks lain.\",\n \"saveToolbarText\": \"Praset\",\n \"saveToolbarTooltip\": \"Urus praset tersimpan\",\n \"saveAction\": \"Simpan\",\n \"saveAsAction\": \"Simpan sebagai...\",\n \"openAction\": \"Buka...\",\n \"deleteAction\": \"Padam...\",\n \"newAction\": \"Baru\",\n \"exportAction\": \"Eksport...\",\n \"importAction\": \"Import...\",\n \"saveAsDialogTitle\": \"Simpan praset\",\n \"presetNameLabel\": \"Nama\",\n \"openDialogTitle\": \"Buka praset\",\n \"deleteDialogTitle\": \"Padam praset\",\n \"newDialogTitle\": \"Dokumen baru\",\n \"newDialogMessage\": \"Ini akan mengosongkan kandungan dan konfigurasi penyunting semasa. Simpan kerja semasa terlebih dahulu?\",\n \"newDialogSaveButton\": \"Simpan & kosongkan\",\n \"newDialogDiscardButton\": \"Buang\",\n \"presetLabel\": \"Praset\",\n \"confirmOverwrite\": \"Praset bernama “{{name}}” sudah wujud. Gantikan?\",\n \"confirmDiscard\": \"Buka “{{name}}” dan buang perubahan semasa yang belum disimpan?\",\n \"confirmDelete\": \"Padam “{{name}}”? Ini tidak boleh dibatalkan.\",\n \"emptyPresets\": \"Tiada praset tersimpan tersedia.\",\n \"invalidName\": \"Masukkan nama praset.\",\n \"invalidPreset\": \"Praset ini tidak sah dan tidak dapat dibuka.\",\n \"importInvalidFile\": \"Fail yang dipilih bukan eksport pantoken TinyMCE yang sah.\",\n \"storageReadError\": \"Praset tersimpan tidak dapat dibaca dari penyemak imbas ini.\",\n \"storageWriteError\": \"Praset tidak dapat disimpan dalam penyemak imbas ini.\",\n \"storageDeleteError\": \"Praset tidak dapat dipadamkan dari penyemak imbas ini.\",\n \"exportDefaultName\": \"tanpa tajuk\",\n \"presetSaveButton\": \"Simpan\",\n \"presetOpenButton\": \"Buka\",\n \"presetDeleteButton\": \"Padam\"\n },\n \"se\": {\n \"autocompleteModifierDetail\": \"modifier\",\n \"classValidationIncompleteComponent\": \"Incomplete component name after '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token must start with '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Unknown component/utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Insert Component\",\n \"componentsListLabel\": \"Components\",\n \"componentsMenuText\": \"Component\",\n \"componentsToolbarText\": \"Components\",\n \"componentsToolbarTooltip\": \"Insert a pantoken component\",\n \"componentModifiersDefault\": \"Default\",\n \"componentModifiersOptions\": \"Options\",\n \"componentModifiersTooltip\": \"Change component modifiers\",\n \"componentModifiersUtilities\": \"Utilities\",\n \"iconLabelDialogTitle\": \"Icon label\",\n \"iconLabelInputLabel\": \"Screen reader label\",\n \"iconsMenuText\": \"Icon\",\n \"iconsSearchPlaceholder\": \"Search icons…\",\n \"iconsSearchLabel\": \"Search icons\",\n \"iconsAllSources\": \"All\",\n \"iconsResultCount\": \"{{count}} icons\",\n \"iconsNoResults\": \"No icons match your search.\",\n \"iconsToolbarText\": \"Icons\",\n \"iconsToolbarTooltip\": \"Insert an icon\",\n \"iconContextSizeSmall\": \"Small\",\n \"iconContextSizeMedium\": \"Medium\",\n \"iconContextSizeLarge\": \"Large\",\n \"iconContextSizeExtraLarge\": \"Extra large\",\n \"layoutsConfirmReplace\": \"Replace the current content with the \\\"{{title}}\\\" layout?\",\n \"layoutsDialogTitle\": \"Insert layout\",\n \"layoutsMenuText\": \"Layout…\",\n \"layoutsSelectLabel\": \"Starter layout\",\n \"layoutsToolbarText\": \"Layouts\",\n \"layoutsToolbarTooltip\": \"Insert a starter layout\",\n \"logosToolbarText\": \"Logos\",\n \"logosToolbarTooltip\": \"Insert a logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Insert Logo\",\n \"insertButton\": \"Insert\",\n \"replaceButton\": \"Replace\",\n \"cancelButton\": \"Cancel\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Replace the current content with the \\\"{{title}}\\\" template?\",\n \"templatesDialogTitle\": \"Insert template\",\n \"templatesMenuText\": \"Insert template…\",\n \"templatesSelectLabel\": \"Starter template\",\n \"templatesToolbarText\": \"Templates\",\n \"placeholdToolbarText\": \"Placeholder\",\n \"placeholdToolbarTooltip\": \"Insert a placeholder image\",\n \"placeholdMenuText\": \"Placeholder image…\",\n \"placeholdDialogTitle\": \"Insert placeholder image\",\n \"placeholdWidthLabel\": \"Width\",\n \"placeholdHeightLabel\": \"Height\",\n \"placeholdBackgroundColorLabel\": \"Background color\",\n \"placeholdTextColorLabel\": \"Text color\",\n \"placeholdTextLabel\": \"Text\",\n \"placeholdAltTextLabel\": \"Alt text\",\n \"placeholdInsertButton\": \"Insert\",\n \"placeholdCancelButton\": \"Cancel\",\n \"placeholdInvalidDimensions\": \"Width and height must be whole numbers from 10 through 4000.\",\n \"placeholdInvalidColor\": \"Colors must use three- or six-digit hexadecimal values.\",\n \"placeholdAltFallback\": \"{{width}} by {{height}} placeholder image\",\n \"a11yToolbarText\": \"Check accessibility\",\n \"a11yToolbarTooltip\": \"Check the content for accessibility issues\",\n \"a11yMenuText\": \"Check accessibility\",\n \"a11yDialogTitle\": \"Accessibility checker\",\n \"a11yNoIssues\": \"No accessibility issues found.\",\n \"a11yIssueCount\": \"{{count}} accessibility issue(s) found.\",\n \"a11yStatusbarIssueCount\": \"{{count}} accessibility issues\",\n \"a11yIssueLabel\": \"Issue\",\n \"a11yCloseButton\": \"Close\",\n \"a11yImageAltMessage\": \"Images must have alternative text.\",\n \"a11yImageAltWhy\": \"Screen readers need an alt attribute to describe an image or identify it as decorative.\",\n \"a11yImageAltFilenameMessage\": \"Image alternative text should describe the image, not repeat its filename.\",\n \"a11yImageAltFilenameWhy\": \"A filename rarely gives screen reader users useful information about an image.\",\n \"a11yImageAltLengthMessage\": \"Image alternative text should be 125 characters or fewer.\",\n \"a11yImageAltLengthWhy\": \"Short descriptions are easier to understand and navigate with assistive technology.\",\n \"a11yHeadingSequenceMessage\": \"Heading levels should not skip levels.\",\n \"a11yHeadingSequenceWhy\": \"A logical heading outline helps people navigate content with assistive technology.\",\n \"a11yTableHeaderMessage\": \"Tables must include header cells.\",\n \"a11yTableHeaderWhy\": \"Header cells give screen readers the context needed to understand table data.\",\n \"a11yTableCaptionMessage\": \"Tables should include a caption.\",\n \"a11yTableCaptionWhy\": \"A caption identifies a table's purpose before a screen reader enters its cells.\",\n \"a11yTableHeaderScopeMessage\": \"Table header cells should declare their scope.\",\n \"a11yTableHeaderScopeWhy\": \"The scope attribute lets assistive technology associate headers with data cells.\",\n \"a11yAdjacentLinksMessage\": \"Adjacent links with the same destination should be combined.\",\n \"a11yAdjacentLinksWhy\": \"Repeated links create unnecessary stops for keyboard and screen reader users.\",\n \"a11yHeadingStartMessage\": \"The first heading should be an h2.\",\n \"a11yHeadingStartWhy\": \"The editor's document title is supplied outside the editable content.\",\n \"a11yListStructureMessage\": \"List items must be contained by an ordered or unordered list.\",\n \"a11yListStructureWhy\": \"Assistive technology relies on list structure to announce item counts and position.\",\n \"sourceToggleTooltip\": \"Source code\",\n \"sourceFormatErrorMessage\": \"Couldn't format the source code — check for unclosed tags or other syntax errors.\",\n \"saveToolbarText\": \"Presets\",\n \"saveToolbarTooltip\": \"Manage saved presets\",\n \"saveAction\": \"Save\",\n \"saveAsAction\": \"Save as...\",\n \"openAction\": \"Open...\",\n \"deleteAction\": \"Delete...\",\n \"newAction\": \"New\",\n \"exportAction\": \"Export...\",\n \"importAction\": \"Import...\",\n \"saveAsDialogTitle\": \"Save preset\",\n \"presetNameLabel\": \"Name\",\n \"openDialogTitle\": \"Open preset\",\n \"deleteDialogTitle\": \"Delete preset\",\n \"newDialogTitle\": \"New document\",\n \"newDialogMessage\": \"This clears the current editor content and config. Save the current work first?\",\n \"newDialogSaveButton\": \"Save & clear\",\n \"newDialogDiscardButton\": \"Discard\",\n \"presetLabel\": \"Preset\",\n \"confirmOverwrite\": \"A preset named “{{name}}” already exists. Replace it?\",\n \"confirmDiscard\": \"Open “{{name}}” and discard the current unsaved changes?\",\n \"confirmDelete\": \"Delete “{{name}}”? This cannot be undone.\",\n \"emptyPresets\": \"No saved presets are available.\",\n \"invalidName\": \"Enter a preset name.\",\n \"invalidPreset\": \"This preset is invalid and could not be opened.\",\n \"importInvalidFile\": \"The selected file is not a valid pantoken TinyMCE export.\",\n \"storageReadError\": \"Saved presets could not be read from this browser.\",\n \"storageWriteError\": \"The preset could not be saved in this browser.\",\n \"storageDeleteError\": \"The preset could not be deleted from this browser.\",\n \"exportDefaultName\": \"untitled\",\n \"presetSaveButton\": \"Save\",\n \"presetOpenButton\": \"Open\",\n \"presetDeleteButton\": \"Delete\"\n },\n \"nb\": {\n \"autocompleteModifierDetail\": \"modifikator\",\n \"classValidationIncompleteComponent\": \"Ufullstendig komponentnavn etter '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token må starte med '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Ukjent komponent/verktøy: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Sett inn komponent\",\n \"componentsListLabel\": \"Komponenter\",\n \"componentsMenuText\": \"Komponent\",\n \"componentsToolbarText\": \"Komponenter\",\n \"componentsToolbarTooltip\": \"Sett inn en pantoken-komponent\",\n \"componentModifiersDefault\": \"Standard\",\n \"componentModifiersOptions\": \"Alternativer\",\n \"componentModifiersTooltip\": \"Endre komponentmodifikatorer\",\n \"componentModifiersUtilities\": \"Verktøy\",\n \"iconLabelDialogTitle\": \"Etikett for ikon\",\n \"iconLabelInputLabel\": \"Etikett for skjermleser\",\n \"iconsMenuText\": \"Ikon\",\n \"iconsSearchPlaceholder\": \"Søk etter ikoner…\",\n \"iconsSearchLabel\": \"Søk i ikoner\",\n \"iconsAllSources\": \"Alle\",\n \"iconsResultCount\": \"{{count}} ikoner\",\n \"iconsNoResults\": \"Ingen ikoner samsvarer med søket ditt.\",\n \"iconsToolbarText\": \"Ikoner\",\n \"iconsToolbarTooltip\": \"Sett inn et ikon\",\n \"iconContextSizeSmall\": \"Liten\",\n \"iconContextSizeMedium\": \"Middels\",\n \"iconContextSizeLarge\": \"Stor\",\n \"iconContextSizeExtraLarge\": \"Ekstra stor\",\n \"layoutsConfirmReplace\": \"Erstatt gjeldende innhold med \\\"{{title}}\\\"-oppsettet?\",\n \"layoutsDialogTitle\": \"Sett inn oppsett\",\n \"layoutsMenuText\": \"Oppsett…\",\n \"layoutsSelectLabel\": \"Startoppsett\",\n \"layoutsToolbarText\": \"Oppsett\",\n \"layoutsToolbarTooltip\": \"Sett inn et startoppsett\",\n \"logosToolbarText\": \"Logoer\",\n \"logosToolbarTooltip\": \"Sett inn en logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Sett inn logo\",\n \"insertButton\": \"Sett inn\",\n \"replaceButton\": \"Erstatt\",\n \"cancelButton\": \"Avbryt\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Erstatt gjeldende innhold med \\\"{{title}}\\\"-malen?\",\n \"templatesDialogTitle\": \"Sett inn mal\",\n \"templatesMenuText\": \"Sett inn mal…\",\n \"templatesSelectLabel\": \"Startmal\",\n \"templatesToolbarText\": \"Maler\",\n \"placeholdToolbarText\": \"Plassholder\",\n \"placeholdToolbarTooltip\": \"Sett inn et plassholderbilde\",\n \"placeholdMenuText\": \"Plassholderbilde…\",\n \"placeholdDialogTitle\": \"Sett inn plassholderbilde\",\n \"placeholdWidthLabel\": \"Bredde\",\n \"placeholdHeightLabel\": \"Høyde\",\n \"placeholdBackgroundColorLabel\": \"Bakgrunnsfarge\",\n \"placeholdTextColorLabel\": \"Tekstfarge\",\n \"placeholdTextLabel\": \"Tekst\",\n \"placeholdAltTextLabel\": \"Alt-tekst\",\n \"placeholdInsertButton\": \"Sett inn\",\n \"placeholdCancelButton\": \"Avbryt\",\n \"placeholdInvalidDimensions\": \"Bredde og høyde må være hele tall fra 10 til 4000.\",\n \"placeholdInvalidColor\": \"Farger må bruke tre- eller seks-sifrede heksadesimale verdier.\",\n \"placeholdAltFallback\": \"{{width}} ved {{height}} plassholderbilde\",\n \"a11yToolbarText\": \"Sjekk tilgjengelighet\",\n \"a11yToolbarTooltip\": \"Sjekk innholdet for tilgjengelighetsproblemer\",\n \"a11yMenuText\": \"Sjekk tilgjengelighet\",\n \"a11yDialogTitle\": \"Tilgjengelighetssjekker\",\n \"a11yNoIssues\": \"Ingen tilgjengelighetsproblemer funnet.\",\n \"a11yIssueCount\": \"{{count}} tilgjengelighetsproblem(er) funnet.\",\n \"a11yStatusbarIssueCount\": \"{{count}} tilgjengelighetsproblemer\",\n \"a11yIssueLabel\": \"Problem\",\n \"a11yCloseButton\": \"Lukk\",\n \"a11yImageAltMessage\": \"Bilder må ha alternativ tekst.\",\n \"a11yImageAltWhy\": \"Skjermlesere trenger et alt-attributt for å beskrive et bilde eller identifisere det som dekorativt.\",\n \"a11yImageAltFilenameMessage\": \"Alternativ tekst for bilder bør beskrive bildet, ikke gjenta filnavnet.\",\n \"a11yImageAltFilenameWhy\": \"Et filnavn gir sjelden skjermleserbrukere nyttig informasjon om et bilde.\",\n \"a11yImageAltLengthMessage\": \"Alternativ tekst for bilder bør være 125 tegn eller færre.\",\n \"a11yImageAltLengthWhy\": \"Korte beskrivelser er lettere å forstå og navigere med hjelpemidler.\",\n \"a11yHeadingSequenceMessage\": \"Overskriftsnivåer bør ikke hoppe over nivåer.\",\n \"a11yHeadingSequenceWhy\": \"En logisk overskriftsstruktur hjelper folk med å navigere innhold ved bruk av hjelpemidler.\",\n \"a11yTableHeaderMessage\": \"Tabeller må inkludere overskriftsceller.\",\n \"a11yTableHeaderWhy\": \"Overskriftsceller gir skjermlesere konteksten som trengs for å forstå tabelldata.\",\n \"a11yTableCaptionMessage\": \"Tabeller bør inkludere en bildetekst.\",\n \"a11yTableCaptionWhy\": \"En bildetekst identifiserer tabellens formål før en skjermleser går inn i cellene.\",\n \"a11yTableHeaderScopeMessage\": \"Tabelloverskriftsceller bør angi scope-attributtet.\",\n \"a11yTableHeaderScopeWhy\": \"scope-attributtet lar hjelpemidler knytte overskrifter til dataceller.\",\n \"a11yAdjacentLinksMessage\": \"Nærliggende lenker med samme destinasjon bør slås sammen.\",\n \"a11yAdjacentLinksWhy\": \"Gjentatte lenker skaper unødvendige stopp for tastatur- og skjermleserbrukere.\",\n \"a11yHeadingStartMessage\": \"Den første overskriften bør være en h2.\",\n \"a11yHeadingStartWhy\": \"Redigeringsverktøyets dokumenttittel er levert utenfor det redigerbare innholdet.\",\n \"a11yListStructureMessage\": \"Listeelementer må være inneholdt i en ordnet eller uordnet liste.\",\n \"a11yListStructureWhy\": \"Hjelpemidler er avhengige av listesstruktur for å kunngjøre antall elementer og posisjon.\",\n \"sourceToggleTooltip\": \"Kildekode\",\n \"sourceFormatErrorMessage\": \"Kunne ikke formatere kildekoden — sjekk for uavsluttede tagger eller andre syntaksfeil.\",\n \"saveToolbarText\": \"Forhåndsinnstillinger\",\n \"saveToolbarTooltip\": \"Administrer lagrede forhåndsinnstillinger\",\n \"saveAction\": \"Lagre\",\n \"saveAsAction\": \"Lagre som...\",\n \"openAction\": \"Åpne...\",\n \"deleteAction\": \"Slett...\",\n \"newAction\": \"Ny\",\n \"exportAction\": \"Eksporter...\",\n \"importAction\": \"Importer...\",\n \"saveAsDialogTitle\": \"Lagre forhåndsinnstilling\",\n \"presetNameLabel\": \"Navn\",\n \"openDialogTitle\": \"Åpne forhåndsinnstilling\",\n \"deleteDialogTitle\": \"Slett forhåndsinnstilling\",\n \"newDialogTitle\": \"Nytt dokument\",\n \"newDialogMessage\": \"Dette fjerner det nåværende redigeringsinnholdet og konfigurasjonen. Vil du lagre det nåværende arbeidet først?\",\n \"newDialogSaveButton\": \"Lagre og tøm\",\n \"newDialogDiscardButton\": \"Forkast\",\n \"presetLabel\": \"Forhåndsinnstilling\",\n \"confirmOverwrite\": \"En forhåndsinnstilling med navnet “{{name}}” finnes allerede. Erstatt den?\",\n \"confirmDiscard\": \"Åpne “{{name}}” og forkaste gjeldende ikke-lagrede endringer?\",\n \"confirmDelete\": \"Slett “{{name}}”? Dette kan ikke angres.\",\n \"emptyPresets\": \"Ingen lagrede forhåndsinnstillinger er tilgjengelige.\",\n \"invalidName\": \"Skriv inn et navn for forhåndsinnstillingen.\",\n \"invalidPreset\": \"Denne forhåndsinnstillingen er ugyldig og kunne ikke åpnes.\",\n \"importInvalidFile\": \"Den valgte filen er ikke en gyldig pantoken TinyMCE-eksport.\",\n \"storageReadError\": \"Lagrede forhåndsinnstillinger kunne ikke leses fra denne nettleseren.\",\n \"storageWriteError\": \"Forhåndsinnstillingen kunne ikke lagres i denne nettleseren.\",\n \"storageDeleteError\": \"Forhåndsinnstillingen kunne ikke slettes fra denne nettleseren.\",\n \"exportDefaultName\": \"uten tittel\",\n \"presetSaveButton\": \"Lagre\",\n \"presetOpenButton\": \"Åpne\",\n \"presetDeleteButton\": \"Slett\"\n },\n \"nn\": {\n \"autocompleteModifierDetail\": \"modifikator\",\n \"classValidationIncompleteComponent\": \"Ufullstendig komponentnamn etter '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token må starte med '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Ukjend komponent/verktøy: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Set inn komponent\",\n \"componentsListLabel\": \"Komponentar\",\n \"componentsMenuText\": \"Komponent\",\n \"componentsToolbarText\": \"Komponentar\",\n \"componentsToolbarTooltip\": \"Set inn ein pantoken-komponent\",\n \"componentModifiersDefault\": \"Standard\",\n \"componentModifiersOptions\": \"Alternativ\",\n \"componentModifiersTooltip\": \"Endre komponentmodifikatorar\",\n \"componentModifiersUtilities\": \"Verktøy\",\n \"iconLabelDialogTitle\": \"Ikonetikett\",\n \"iconLabelInputLabel\": \"Etikett for skjermlesar\",\n \"iconsMenuText\": \"Ikon\",\n \"iconsSearchPlaceholder\": \"Søk i ikoner…\",\n \"iconsSearchLabel\": \"Søk i ikoner\",\n \"iconsAllSources\": \"Alle\",\n \"iconsResultCount\": \"{{count}} ikoner\",\n \"iconsNoResults\": \"Ingen ikoner samsvarar med søket ditt.\",\n \"iconsToolbarText\": \"Ikon\",\n \"iconsToolbarTooltip\": \"Set inn eit ikon\",\n \"iconContextSizeSmall\": \"Liten\",\n \"iconContextSizeMedium\": \"Middels\",\n \"iconContextSizeLarge\": \"Stor\",\n \"iconContextSizeExtraLarge\": \"Ekstra stor\",\n \"layoutsConfirmReplace\": \"Erstatte det noverande innhaldet med oppsettet \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Set inn oppsett\",\n \"layoutsMenuText\": \"Oppsett…\",\n \"layoutsSelectLabel\": \"Startoppsett\",\n \"layoutsToolbarText\": \"Oppsett\",\n \"layoutsToolbarTooltip\": \"Set inn eit startoppsett\",\n \"logosToolbarText\": \"Logoar\",\n \"logosToolbarTooltip\": \"Set inn ein logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Set inn logo\",\n \"insertButton\": \"Set inn\",\n \"replaceButton\": \"Erstatt\",\n \"cancelButton\": \"Avbryt\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Erstatte det noverande innhaldet med malen \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Set inn mal\",\n \"templatesMenuText\": \"Set inn mal…\",\n \"templatesSelectLabel\": \"Startmal\",\n \"templatesToolbarText\": \"Malar\",\n \"placeholdToolbarText\": \"Plasshaldar\",\n \"placeholdToolbarTooltip\": \"Set inn eit plasshaldarbilete\",\n \"placeholdMenuText\": \"Plasshaldarbilete…\",\n \"placeholdDialogTitle\": \"Set inn plasshaldarbilete\",\n \"placeholdWidthLabel\": \"Bredde\",\n \"placeholdHeightLabel\": \"Høgd\",\n \"placeholdBackgroundColorLabel\": \"Bakgrunnsfarge\",\n \"placeholdTextColorLabel\": \"Tekstfarge\",\n \"placeholdTextLabel\": \"Tekst\",\n \"placeholdAltTextLabel\": \"Alternativ tekst\",\n \"placeholdInsertButton\": \"Set inn\",\n \"placeholdCancelButton\": \"Avbryt\",\n \"placeholdInvalidDimensions\": \"Bredde og høgd må vere heiltal frå 10 til 4000.\",\n \"placeholdInvalidColor\": \"Fargar må bruke tre- eller seks-sifra heksadesimale verdiar.\",\n \"placeholdAltFallback\": \"{{width}} med {{height}} plasshaldarbilete\",\n \"a11yToolbarText\": \"Sjekk tilgjengelegheit\",\n \"a11yToolbarTooltip\": \"Sjekk innhaldet for tilgjengelegheitsproblem\",\n \"a11yMenuText\": \"Sjekk tilgjengelegheit\",\n \"a11yDialogTitle\": \"Tilgjengelegheitskontroll\",\n \"a11yNoIssues\": \"Ingen tilgjengelegheitsproblem funne.\",\n \"a11yIssueCount\": \"{{count}} tilgjengelegheitsproblem funne.\",\n \"a11yStatusbarIssueCount\": \"{{count}} tilgjengelegheitsproblem\",\n \"a11yIssueLabel\": \"Problem\",\n \"a11yCloseButton\": \"Lukk\",\n \"a11yImageAltMessage\": \"Bilete må ha alternativ tekst.\",\n \"a11yImageAltWhy\": \"Skjermlesarar treng eit alt-attributt for å skildre eit bilete eller identifisere det som dekorativt.\",\n \"a11yImageAltFilenameMessage\": \"Alternativ tekst for bilete bør skildre biletet, ikkje gjenta filnamnet.\",\n \"a11yImageAltFilenameWhy\": \"Eit filnamn gjev sjeldan skjermlesarbrukarar nyttig informasjon om eit bilete.\",\n \"a11yImageAltLengthMessage\": \"Alternativ tekst for bilete bør vere 125 teikn eller færre.\",\n \"a11yImageAltLengthWhy\": \"Korte skildringar er lettare å forstå og navigere med hjelpemiddel.\",\n \"a11yHeadingSequenceMessage\": \"Overskriftsnivå bør ikkje hoppe over nivå.\",\n \"a11yHeadingSequenceWhy\": \"Ein logisk overskriftsstruktur hjelper folk å navigere innhald med hjelpemiddel.\",\n \"a11yTableHeaderMessage\": \"Tabellar må innehalde overskriftsceller.\",\n \"a11yTableHeaderWhy\": \"Overskriftsceller gjev skjermlesarar kontekst som trengst for å forstå tabelldata.\",\n \"a11yTableCaptionMessage\": \"Tabellar bør ha ein tittel.\",\n \"a11yTableCaptionWhy\": \"Ein tittel identifiserer føremålet til ei tabell før ein skjermlesar går inn i cellene hennar.\",\n \"a11yTableHeaderScopeMessage\": \"Tabellens overskriftsceller bør erklære omfanget sitt.\",\n \"a11yTableHeaderScopeWhy\": \"Scope-attributtet lèt hjelpemiddel knyte overskrifter til dataceller.\",\n \"a11yAdjacentLinksMessage\": \"Nabolenker med same mål bør slås saman.\",\n \"a11yAdjacentLinksWhy\": \"Gjentekte lenker skapar unødvendige stopp for tastatur- og skjermlesarbrukarar.\",\n \"a11yHeadingStartMessage\": \"Den første overskrifta bør vere ein h2.\",\n \"a11yHeadingStartWhy\": \"Redigeringsprogrammets dokumenttittel blir levert utanfor det redigerbare innhaldet.\",\n \"a11yListStructureMessage\": \"Listeelement må vere inne i ei ordna eller uordna liste.\",\n \"a11yListStructureWhy\": \"Hjelpemiddel er avhengige av listesstruktur for å kunngjere talet på element og posisjon.\",\n \"sourceToggleTooltip\": \"Kjeldekode\",\n \"sourceFormatErrorMessage\": \"Klarte ikkje å formatere kjeldekoden — sjekk etter ikkje-lukkede taggar eller andre syntaksfeil.\",\n \"saveToolbarText\": \"Føreinstillingar\",\n \"saveToolbarTooltip\": \"Administrer lagra føreinstillingar\",\n \"saveAction\": \"Lagre\",\n \"saveAsAction\": \"Lagre som...\",\n \"openAction\": \"Opne...\",\n \"deleteAction\": \"Slett...\",\n \"newAction\": \"Ny\",\n \"exportAction\": \"Eksporter...\",\n \"importAction\": \"Importer...\",\n \"saveAsDialogTitle\": \"Lagre føreinstilling\",\n \"presetNameLabel\": \"Namn\",\n \"openDialogTitle\": \"Opne føreinstilling\",\n \"deleteDialogTitle\": \"Slett føreinstilling\",\n \"newDialogTitle\": \"Nytt dokument\",\n \"newDialogMessage\": \"Dette tømmer det noverande redigeringsinnhaldet og konfigurasjonen. Spara arbeidet først?\",\n \"newDialogSaveButton\": \"Lagre og tøm\",\n \"newDialogDiscardButton\": \"Forkast\",\n \"presetLabel\": \"Føreinstilling\",\n \"confirmOverwrite\": \"Ei føreinstilling med namnet “{{name}}” finst allereie. Erstatt den?\",\n \"confirmDiscard\": \"Opne “{{name}}” og forkasta dei noverande usparte endringane?\",\n \"confirmDelete\": \"Slett “{{name}}”? Dette kan ikkje angrast.\",\n \"emptyPresets\": \"Ingen lagra føreinstillingar er tilgjengelege.\",\n \"invalidName\": \"Skriv inn eit namn på føreinstillinga.\",\n \"invalidPreset\": \"Denne føreinstillinga er ugyldig og kunne ikkje opnast.\",\n \"importInvalidFile\": \"Den valde fila er ikkje ein gyldig pantoken TinyMCE-eksport.\",\n \"storageReadError\": \"Lagra føreinstillingar kunne ikkje lesast frå denne nettlesaren.\",\n \"storageWriteError\": \"Føreinstillinga kunne ikkje lagrast i denne nettlesaren.\",\n \"storageDeleteError\": \"Føreinstillinga kunne ikkje slettast frå denne nettlesaren.\",\n \"exportDefaultName\": \"utan namn\",\n \"presetSaveButton\": \"Lagre\",\n \"presetOpenButton\": \"Opne\",\n \"presetDeleteButton\": \"Slett\"\n },\n \"fa\": {\n \"autocompleteModifierDetail\": \"مودیفایر\",\n \"classValidationIncompleteComponent\": \"نام مؤلفه پس از '{{prefix}}' ناقص است\",\n \"classValidationTokenPrefix\": \"توکن باید با '{{prefix}}' شروع شود\",\n \"classValidationUnknownComponent\": \"مؤلفه/ابزار ناشناخته: '{{componentName}}'\",\n \"componentsDialogTitle\": \"درج مؤلفه\",\n \"componentsListLabel\": \"مؤلفه‌ها\",\n \"componentsMenuText\": \"مؤلفه\",\n \"componentsToolbarText\": \"مؤلفه‌ها\",\n \"componentsToolbarTooltip\": \"درج یک مؤلفه pantoken\",\n \"componentModifiersDefault\": \"پیش‌فرض\",\n \"componentModifiersOptions\": \"گزینه‌ها\",\n \"componentModifiersTooltip\": \"تغییر مودیفایرهای کامپوننت\",\n \"componentModifiersUtilities\": \"ابزارها\",\n \"iconLabelDialogTitle\": \"برچسب آیکون\",\n \"iconLabelInputLabel\": \"برچسب خواننده صفحه\",\n \"iconsMenuText\": \"آیکون\",\n \"iconsSearchPlaceholder\": \"جستجوی آیکون‌ها…\",\n \"iconsSearchLabel\": \"جستجوی آیکون‌ها\",\n \"iconsAllSources\": \"همه\",\n \"iconsResultCount\": \"{{count}} آیکون\",\n \"iconsNoResults\": \"هیچ آیکونی با جستجوی شما مطابقت ندارد.\",\n \"iconsToolbarText\": \"آیکون‌ها\",\n \"iconsToolbarTooltip\": \"درج یک آیکون\",\n \"iconContextSizeSmall\": \"کوچک\",\n \"iconContextSizeMedium\": \"متوسط\",\n \"iconContextSizeLarge\": \"بزرگ\",\n \"iconContextSizeExtraLarge\": \"بسیار بزرگ\",\n \"layoutsConfirmReplace\": \"محتوای فعلی با طرح‌بندی \\\"{{title}}\\\" جایگزین شود؟\",\n \"layoutsDialogTitle\": \"درج طرح‌بندی\",\n \"layoutsMenuText\": \"طرح‌بندی…\",\n \"layoutsSelectLabel\": \"طرح‌بندی آغازین\",\n \"layoutsToolbarText\": \"طرح‌بندی‌ها\",\n \"layoutsToolbarTooltip\": \"درج یک طرح‌بندی آغازین\",\n \"logosToolbarText\": \"لوگوها\",\n \"logosToolbarTooltip\": \"درج یک لوگو\",\n \"logosMenuText\": \"لوگو\",\n \"logosDialogTitle\": \"درج لوگو\",\n \"insertButton\": \"درج\",\n \"replaceButton\": \"جایگزینی\",\n \"cancelButton\": \"لغو\",\n \"logoAltSuffix\": \"لوگو\",\n \"templatesConfirmReplace\": \"محتوای فعلی با الگوی \\\"{{title}}\\\" جایگزین شود؟\",\n \"templatesDialogTitle\": \"درج الگو\",\n \"templatesMenuText\": \"درج الگو…\",\n \"templatesSelectLabel\": \"الگوی آغازین\",\n \"templatesToolbarText\": \"الگوها\",\n \"placeholdToolbarText\": \"جای‌نما\",\n \"placeholdToolbarTooltip\": \"درج یک تصویر جای‌نما\",\n \"placeholdMenuText\": \"تصویر جای‌نما…\",\n \"placeholdDialogTitle\": \"درج تصویر جای‌نما\",\n \"placeholdWidthLabel\": \"عرض\",\n \"placeholdHeightLabel\": \"ارتفاع\",\n \"placeholdBackgroundColorLabel\": \"رنگ پس‌زمینه\",\n \"placeholdTextColorLabel\": \"رنگ متن\",\n \"placeholdTextLabel\": \"متن\",\n \"placeholdAltTextLabel\": \"متن جایگزین\",\n \"placeholdInsertButton\": \"درج\",\n \"placeholdCancelButton\": \"لغو\",\n \"placeholdInvalidDimensions\": \"عرض و ارتفاع باید اعداد صحیح بین 10 تا 4000 باشند.\",\n \"placeholdInvalidColor\": \"رنگ‌ها باید از مقادیر هگزادسیمال سه‌یا شش‌رقمی استفاده کنند.\",\n \"placeholdAltFallback\": \"تصویر جای‌نما {{width}} در {{height}}\",\n \"a11yToolbarText\": \"بررسی دسترسی\",\n \"a11yToolbarTooltip\": \"محتوا را برای مشکلات دسترسی بررسی کنید\",\n \"a11yMenuText\": \"بررسی دسترسی\",\n \"a11yDialogTitle\": \"بررسی‌کنندهٔ دسترسی\",\n \"a11yNoIssues\": \"هیچ مشکل دسترسی یافت نشد.\",\n \"a11yIssueCount\": \"{{count}} مورد مشکل دسترسی یافت شد.\",\n \"a11yStatusbarIssueCount\": \"{{count}} مشکل دسترسی\",\n \"a11yIssueLabel\": \"مشکل\",\n \"a11yCloseButton\": \"بستن\",\n \"a11yImageAltMessage\": \"تصاویر باید متن جایگزین داشته باشند.\",\n \"a11yImageAltWhy\": \"خواننده‌های صفحه به یک صفت alt نیاز دارند تا تصویر را توصیف کنند یا آن را به‌عنوان تزئینی مشخص کنند.\",\n \"a11yImageAltFilenameMessage\": \"متن جایگزین تصویر باید تصویر را توصیف کند، نه نام فایل آن را تکرار کند.\",\n \"a11yImageAltFilenameWhy\": \"معمولاً نام فایل اطلاعات مفیدی برای کاربران خوانندهٔ صفحه دربارهٔ یک تصویر فراهم نمی‌کند.\",\n \"a11yImageAltLengthMessage\": \"متن جایگزین تصویر باید ۱۲۵ کاراکتر یا کمتر باشد.\",\n \"a11yImageAltLengthWhy\": \"توضیحات کوتاه‌تر برای درک و ناوبری با فناوری کمکی آسان‌تر است.\",\n \"a11yHeadingSequenceMessage\": \"سطوح عنوان‌ها نباید پریدگی داشته باشند.\",\n \"a11yHeadingSequenceWhy\": \"یک ساختار منطقی عنوان به افراد کمک می‌کند تا با فناوری کمکی محتوا را مرور کنند.\",\n \"a11yTableHeaderMessage\": \"جداول باید شامل سلول‌های هدر باشند.\",\n \"a11yTableHeaderWhy\": \"سلول‌های هدر زمینهٔ لازم را برای درک داده‌های جدول به خواننده‌های صفحه می‌دهند.\",\n \"a11yTableCaptionMessage\": \"جداول باید دارای کپشن باشند.\",\n \"a11yTableCaptionWhy\": \"یک کپشن هدف جدول را قبل از ورود خوانندهٔ صفحه به سلول‌ها مشخص می‌کند.\",\n \"a11yTableHeaderScopeMessage\": \"سلول‌های هدر جدول باید محدودهٔ خود را اعلام کنند.\",\n \"a11yTableHeaderScopeWhy\": \"صفت scope به فناوری کمکی اجازه می‌دهد هدرها را با سلول‌های داده مرتبط کند.\",\n \"a11yAdjacentLinksMessage\": \"لینک‌های مجاور با مقصد یکسان باید ترکیب شوند.\",\n \"a11yAdjacentLinksWhy\": \"تکرار لینک‌ها توقف‌های غیرضروری برای کاربران صفحه‌کلید و خوانندهٔ صفحه ایجاد می‌کند.\",\n \"a11yHeadingStartMessage\": \"اولین عنوان باید یک h2 باشد.\",\n \"a11yHeadingStartWhy\": \"عنوان سند ویرایشگر خارج از محتوای قابل ویرایش تأمین شده است.\",\n \"a11yListStructureMessage\": \"آیتم‌های فهرست باید داخل فهرست مرتب یا نامرتب قرار بگیرند.\",\n \"a11yListStructureWhy\": \"فناوری کمکی بر ساختار فهرست تکیه می‌کند تا تعداد آیتم‌ها و موقعیت را اعلام کند.\",\n \"sourceToggleTooltip\": \"کد منبع\",\n \"sourceFormatErrorMessage\": \"قادر به قالب‌بندی کد منبع نبود — برای تگ‌های باز‌مانده یا سایر خطاهای نحوی بررسی کنید.\",\n \"saveToolbarText\": \"پیش‌تنظیم‌ها\",\n \"saveToolbarTooltip\": \"مدیریت پیش‌تنظیم‌های ذخیره‌شده\",\n \"saveAction\": \"ذخیره\",\n \"saveAsAction\": \"ذخیره به‌عنوان...\",\n \"openAction\": \"باز کردن...\",\n \"deleteAction\": \"حذف...\",\n \"newAction\": \"جدید\",\n \"exportAction\": \"خروجی...\",\n \"importAction\": \"وارد...\",\n \"saveAsDialogTitle\": \"ذخیرهٔ پیش‌تنظیم\",\n \"presetNameLabel\": \"نام\",\n \"openDialogTitle\": \"باز کردن پیش‌تنظیم\",\n \"deleteDialogTitle\": \"حذف پیش‌تنظیم\",\n \"newDialogTitle\": \"سند جدید\",\n \"newDialogMessage\": \"این محتوای و پیکربندی ویرایشگر فعلی را پاک می‌کند. ابتدا کار جاری را ذخیره کنید؟\",\n \"newDialogSaveButton\": \"ذخیره و پاک‌سازی\",\n \"newDialogDiscardButton\": \"رد کردن\",\n \"presetLabel\": \"پیش‌تنظیم\",\n \"confirmOverwrite\": \"پیش‌تنظیمی با نام «{{name}}» قبلاً وجود دارد. جایگزین شود؟\",\n \"confirmDiscard\": \"«{{name}}» باز شود و تغییرات ذخیره‌نشده فعلی نادیده گرفته شوند؟\",\n \"confirmDelete\": \"«{{name}}» حذف شود؟ این عملیات قابل بازگشت نیست.\",\n \"emptyPresets\": \"هیچ پیش‌تنظیم ذخیره‌شده‌ای در دسترس نیست.\",\n \"invalidName\": \"یک نام برای پیش‌تنظیم وارد کنید.\",\n \"invalidPreset\": \"این پیش‌تنظیم نامعتبر است و قابل باز شدن نیست.\",\n \"importInvalidFile\": \"فایل انتخاب‌شده یک خروجی معتبر pantoken TinyMCE نیست.\",\n \"storageReadError\": \"پیش‌تنظیم‌های ذخیره‌شده قابل خواندن از این مرورگر نیستند.\",\n \"storageWriteError\": \"پیش‌تنظیم در این مرورگر قابل ذخیره نیست.\",\n \"storageDeleteError\": \"پیش‌تنظیم در این مرورگر قابل حذف نیست.\",\n \"exportDefaultName\": \"بدون عنوان\",\n \"presetSaveButton\": \"ذخیره\",\n \"presetOpenButton\": \"باز کردن\",\n \"presetDeleteButton\": \"حذف\"\n },\n \"pl\": {\n \"autocompleteModifierDetail\": \"modyfikator\",\n \"classValidationIncompleteComponent\": \"Niekompletna nazwa komponentu po '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token musi zaczynać się od '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Nieznany komponent/narzędzie: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Wstaw komponent\",\n \"componentsListLabel\": \"Komponenty\",\n \"componentsMenuText\": \"Komponent\",\n \"componentsToolbarText\": \"Komponenty\",\n \"componentsToolbarTooltip\": \"Wstaw komponent pantoken\",\n \"componentModifiersDefault\": \"Domyślny\",\n \"componentModifiersOptions\": \"Opcje\",\n \"componentModifiersTooltip\": \"Zmień modyfikatory komponentu\",\n \"componentModifiersUtilities\": \"Narzędzia\",\n \"iconLabelDialogTitle\": \"Etykieta ikony\",\n \"iconLabelInputLabel\": \"Etykieta czytnika ekranu\",\n \"iconsMenuText\": \"Ikona\",\n \"iconsSearchPlaceholder\": \"Szukaj ikon…\",\n \"iconsSearchLabel\": \"Szukaj ikon\",\n \"iconsAllSources\": \"Wszystkie\",\n \"iconsResultCount\": \"{{count}} ikon\",\n \"iconsNoResults\": \"Żadne ikony nie pasują do wyszukiwania.\",\n \"iconsToolbarText\": \"Ikony\",\n \"iconsToolbarTooltip\": \"Wstaw ikonę\",\n \"iconContextSizeSmall\": \"Mały\",\n \"iconContextSizeMedium\": \"Średni\",\n \"iconContextSizeLarge\": \"Duży\",\n \"iconContextSizeExtraLarge\": \"Bardzo duży\",\n \"layoutsConfirmReplace\": \"Zamienić bieżącą zawartość na układ \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Wstaw układ\",\n \"layoutsMenuText\": \"Układ…\",\n \"layoutsSelectLabel\": \"Układ startowy\",\n \"layoutsToolbarText\": \"Układy\",\n \"layoutsToolbarTooltip\": \"Wstaw układ startowy\",\n \"logosToolbarText\": \"Logotypy\",\n \"logosToolbarTooltip\": \"Wstaw logotyp\",\n \"logosMenuText\": \"Logotyp\",\n \"logosDialogTitle\": \"Wstaw logotyp\",\n \"insertButton\": \"Wstaw\",\n \"replaceButton\": \"Zamień\",\n \"cancelButton\": \"Anuluj\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Zamienić bieżącą zawartość na szablon \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Wstaw szablon\",\n \"templatesMenuText\": \"Wstaw szablon…\",\n \"templatesSelectLabel\": \"Szablon startowy\",\n \"templatesToolbarText\": \"Szablony\",\n \"placeholdToolbarText\": \"Symbol zastępczy\",\n \"placeholdToolbarTooltip\": \"Wstaw zastępczy obraz\",\n \"placeholdMenuText\": \"Zastępczy obraz…\",\n \"placeholdDialogTitle\": \"Wstaw zastępczy obraz\",\n \"placeholdWidthLabel\": \"Szerokość\",\n \"placeholdHeightLabel\": \"Wysokość\",\n \"placeholdBackgroundColorLabel\": \"Kolor tła\",\n \"placeholdTextColorLabel\": \"Kolor tekstu\",\n \"placeholdTextLabel\": \"Tekst\",\n \"placeholdAltTextLabel\": \"Tekst alternatywny\",\n \"placeholdInsertButton\": \"Wstaw\",\n \"placeholdCancelButton\": \"Anuluj\",\n \"placeholdInvalidDimensions\": \"Szerokość i wysokość muszą być liczbami całkowitymi od 10 do 4000.\",\n \"placeholdInvalidColor\": \"Kolory muszą używać trzy- lub sześciocyfrowych wartości szesnastkowych.\",\n \"placeholdAltFallback\": \"Obraz zastępczy {{width}} × {{height}}\",\n \"a11yToolbarText\": \"Sprawdź dostępność\",\n \"a11yToolbarTooltip\": \"Sprawdź zawartość pod kątem problemów z dostępnością\",\n \"a11yMenuText\": \"Sprawdź dostępność\",\n \"a11yDialogTitle\": \"Sprawdzarka dostępności\",\n \"a11yNoIssues\": \"Nie znaleziono problemów z dostępnością.\",\n \"a11yIssueCount\": \"Znaleziono {{count}} problem(y) z dostępnością.\",\n \"a11yStatusbarIssueCount\": \"{{count}} problemów z dostępnością\",\n \"a11yIssueLabel\": \"Problem\",\n \"a11yCloseButton\": \"Zamknij\",\n \"a11yImageAltMessage\": \"Obrazy muszą mieć tekst alternatywny.\",\n \"a11yImageAltWhy\": \"Czytniki ekranu potrzebują atrybutu alt, aby opisać obraz lub oznaczyć go jako dekoracyjny.\",\n \"a11yImageAltFilenameMessage\": \"Tekst alternatywny obrazu powinien opisywać obraz, a nie powtarzać jego nazwę pliku.\",\n \"a11yImageAltFilenameWhy\": \"Nazwa pliku rzadko daje użytkownikom czytników ekranu użyteczną informację o obrazie.\",\n \"a11yImageAltLengthMessage\": \"Tekst alternatywny obrazu powinien mieć maksymalnie 125 znaków.\",\n \"a11yImageAltLengthWhy\": \"Krótki opis jest łatwiejszy do zrozumienia i nawigowania przy użyciu technologii wspomagającej.\",\n \"a11yHeadingSequenceMessage\": \"Poziomy nagłówków nie powinny pomijać poziomów.\",\n \"a11yHeadingSequenceWhy\": \"Logiczny układ nagłówków pomaga osobom korzystającym z technologii wspomagającej w nawigacji po treści.\",\n \"a11yTableHeaderMessage\": \"Tabele muszą zawierać komórki nagłówków.\",\n \"a11yTableHeaderWhy\": \"Komórki nagłówków dają czytnikom ekranu kontekst niezbędny do zrozumienia danych w tabeli.\",\n \"a11yTableCaptionMessage\": \"Tabele powinny zawierać podpis (caption).\",\n \"a11yTableCaptionWhy\": \"Podpis identyfikuje przeznaczenie tabeli, zanim czytnik ekranu wejdzie do jej komórek.\",\n \"a11yTableHeaderScopeMessage\": \"Komórki nagłówków tabeli powinny zadeklarować swój zakres (scope).\",\n \"a11yTableHeaderScopeWhy\": \"Atrybut scope pozwala technologii wspomagającej powiązać nagłówki z komórkami danych.\",\n \"a11yAdjacentLinksMessage\": \"Sąsiadujące linki prowadzące do tego samego miejsca powinny być połączone.\",\n \"a11yAdjacentLinksWhy\": \"Powtarzające się linki tworzą niepotrzebne przystanki dla użytkowników klawiatury i czytników ekranu.\",\n \"a11yHeadingStartMessage\": \"Pierwszym nagłówkiem powinien być h2.\",\n \"a11yHeadingStartWhy\": \"Tytuł dokumentu edytora jest dostarczany poza edytowalną zawartością.\",\n \"a11yListStructureMessage\": \"Elementy listy muszą być zawarte w liście uporządkowanej lub nieuporządkowanej.\",\n \"a11yListStructureWhy\": \"Technologia wspomagająca polega na strukturze listy, aby ogłaszać liczbę elementów i pozycję.\",\n \"sourceToggleTooltip\": \"Kod źródłowy\",\n \"sourceFormatErrorMessage\": \"Nie można sformatować kodu źródłowego — sprawdź, czy nie ma niezamkniętych tagów lub innych błędów składni.\",\n \"saveToolbarText\": \"Presety\",\n \"saveToolbarTooltip\": \"Zarządzaj zapisanymi presetami\",\n \"saveAction\": \"Zapisz\",\n \"saveAsAction\": \"Zapisz jako...\",\n \"openAction\": \"Otwórz...\",\n \"deleteAction\": \"Usuń...\",\n \"newAction\": \"Nowy\",\n \"exportAction\": \"Eksportuj...\",\n \"importAction\": \"Importuj...\",\n \"saveAsDialogTitle\": \"Zapisz preset\",\n \"presetNameLabel\": \"Nazwa\",\n \"openDialogTitle\": \"Otwórz preset\",\n \"deleteDialogTitle\": \"Usuń preset\",\n \"newDialogTitle\": \"Nowy dokument\",\n \"newDialogMessage\": \"To spowoduje wyczyszczenie bieżącej zawartości edytora i konfiguracji. Najpierw zapisać bieżącą pracę?\",\n \"newDialogSaveButton\": \"Zapisz & wyczyść\",\n \"newDialogDiscardButton\": \"Odrzuć\",\n \"presetLabel\": \"Preset\",\n \"confirmOverwrite\": \"Preset o nazwie „{{name}}” już istnieje. Zastąpić go?\",\n \"confirmDiscard\": \"Otworzyć „{{name}}” i odrzucić bieżące niezapisane zmiany?\",\n \"confirmDelete\": \"Usunąć „{{name}}”? Tej operacji nie można cofnąć.\",\n \"emptyPresets\": \"Brak dostępnych zapisanych presetów.\",\n \"invalidName\": \"Wprowadź nazwę presetu.\",\n \"invalidPreset\": \"Ten preset jest nieprawidłowy i nie można go otworzyć.\",\n \"importInvalidFile\": \"Wybrany plik nie jest prawidłowym eksportem pantoken TinyMCE.\",\n \"storageReadError\": \"Zapisane presety nie zostały odczytane z tej przeglądarki.\",\n \"storageWriteError\": \"Nie można zapisać presetu w tej przeglądarce.\",\n \"storageDeleteError\": \"Nie można usunąć presetu z tej przeglądarki.\",\n \"exportDefaultName\": \"bez tytułu\",\n \"presetSaveButton\": \"Zapisz\",\n \"presetOpenButton\": \"Otwórz\",\n \"presetDeleteButton\": \"Usuń\"\n },\n \"pt\": {\n \"autocompleteModifierDetail\": \"modificador\",\n \"classValidationIncompleteComponent\": \"Nome do componente incompleto após '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"O token deve começar com '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Componente/utilitário desconhecido: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Inserir componente\",\n \"componentsListLabel\": \"Componentes\",\n \"componentsMenuText\": \"Componente\",\n \"componentsToolbarText\": \"Componentes\",\n \"componentsToolbarTooltip\": \"Inserir um componente pantoken\",\n \"componentModifiersDefault\": \"Padrão\",\n \"componentModifiersOptions\": \"Opções\",\n \"componentModifiersTooltip\": \"Alterar modificadores do componente\",\n \"componentModifiersUtilities\": \"Utilitários\",\n \"iconLabelDialogTitle\": \"Rótulo do ícone\",\n \"iconLabelInputLabel\": \"Rótulo para leitor de tela\",\n \"iconsMenuText\": \"Ícone\",\n \"iconsSearchPlaceholder\": \"Pesquisar ícones…\",\n \"iconsSearchLabel\": \"Pesquisar ícones\",\n \"iconsAllSources\": \"Todos\",\n \"iconsResultCount\": \"{{count}} ícones\",\n \"iconsNoResults\": \"Nenhum ícone corresponde à sua pesquisa.\",\n \"iconsToolbarText\": \"Ícones\",\n \"iconsToolbarTooltip\": \"Inserir um ícone\",\n \"iconContextSizeSmall\": \"Pequeno\",\n \"iconContextSizeMedium\": \"Médio\",\n \"iconContextSizeLarge\": \"Grande\",\n \"iconContextSizeExtraLarge\": \"Extra grande\",\n \"layoutsConfirmReplace\": \"Substituir o conteúdo atual pelo layout \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Inserir layout\",\n \"layoutsMenuText\": \"Layout…\",\n \"layoutsSelectLabel\": \"Layout inicial\",\n \"layoutsToolbarText\": \"Layouts\",\n \"layoutsToolbarTooltip\": \"Inserir um layout inicial\",\n \"logosToolbarText\": \"Logotipos\",\n \"logosToolbarTooltip\": \"Inserir um logotipo\",\n \"logosMenuText\": \"Logotipo\",\n \"logosDialogTitle\": \"Inserir logotipo\",\n \"insertButton\": \"Inserir\",\n \"replaceButton\": \"Substituir\",\n \"cancelButton\": \"Cancelar\",\n \"logoAltSuffix\": \"logotipo\",\n \"templatesConfirmReplace\": \"Substituir o conteúdo atual pelo modelo \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Inserir modelo\",\n \"templatesMenuText\": \"Inserir modelo…\",\n \"templatesSelectLabel\": \"Modelo inicial\",\n \"templatesToolbarText\": \"Modelos\",\n \"placeholdToolbarText\": \"Espaço reservado\",\n \"placeholdToolbarTooltip\": \"Inserir uma imagem de espaço reservado\",\n \"placeholdMenuText\": \"Imagem de espaço reservado…\",\n \"placeholdDialogTitle\": \"Inserir imagem de espaço reservado\",\n \"placeholdWidthLabel\": \"Largura\",\n \"placeholdHeightLabel\": \"Altura\",\n \"placeholdBackgroundColorLabel\": \"Cor de fundo\",\n \"placeholdTextColorLabel\": \"Cor do texto\",\n \"placeholdTextLabel\": \"Texto\",\n \"placeholdAltTextLabel\": \"Texto alternativo\",\n \"placeholdInsertButton\": \"Inserir\",\n \"placeholdCancelButton\": \"Cancelar\",\n \"placeholdInvalidDimensions\": \"A largura e a altura devem ser números inteiros entre 10 e 4000.\",\n \"placeholdInvalidColor\": \"As cores devem usar valores hexadecimais de três ou seis dígitos.\",\n \"placeholdAltFallback\": \"{{width}} por {{height}} imagem de espaço reservado\",\n \"a11yToolbarText\": \"Verificar acessibilidade\",\n \"a11yToolbarTooltip\": \"Verifique o conteúdo em busca de problemas de acessibilidade\",\n \"a11yMenuText\": \"Verificar acessibilidade\",\n \"a11yDialogTitle\": \"Verificador de acessibilidade\",\n \"a11yNoIssues\": \"Nenhum problema de acessibilidade encontrado.\",\n \"a11yIssueCount\": \"{{count}} problema(s) de acessibilidade encontrado(s).\",\n \"a11yStatusbarIssueCount\": \"{{count}} problemas de acessibilidade\",\n \"a11yIssueLabel\": \"Problema\",\n \"a11yCloseButton\": \"Fechar\",\n \"a11yImageAltMessage\": \"Imagens devem ter texto alternativo.\",\n \"a11yImageAltWhy\": \"Leitores de tela precisam de um atributo alt para descrever a imagem ou identificá-la como decorativa.\",\n \"a11yImageAltFilenameMessage\": \"O texto alternativo da imagem deve descrever a imagem, não repetir o nome do arquivo.\",\n \"a11yImageAltFilenameWhy\": \"Um nome de arquivo raramente fornece informações úteis sobre uma imagem para usuários de leitores de tela.\",\n \"a11yImageAltLengthMessage\": \"O texto alternativo da imagem deve ter 125 caracteres ou menos.\",\n \"a11yImageAltLengthWhy\": \"Descrições curtas são mais fáceis de entender e navegar com tecnologia assistiva.\",\n \"a11yHeadingSequenceMessage\": \"Os níveis de cabeçalho não devem pular níveis.\",\n \"a11yHeadingSequenceWhy\": \"Uma hierarquia lógica de cabeçalhos ajuda as pessoas a navegar pelo conteúdo com tecnologia assistiva.\",\n \"a11yTableHeaderMessage\": \"Tabelas devem incluir células de cabeçalho.\",\n \"a11yTableHeaderWhy\": \"Células de cabeçalho dão aos leitores de tela o contexto necessário para entender os dados da tabela.\",\n \"a11yTableCaptionMessage\": \"Tabelas devem incluir uma legenda.\",\n \"a11yTableCaptionWhy\": \"Uma legenda identifica o propósito da tabela antes que um leitor de tela entre em suas células.\",\n \"a11yTableHeaderScopeMessage\": \"As células de cabeçalho da tabela devem declarar seu escopo.\",\n \"a11yTableHeaderScopeWhy\": \"O atributo scope permite que a tecnologia assistiva associe cabeçalhos às células de dados.\",\n \"a11yAdjacentLinksMessage\": \"Links adjacentes com o mesmo destino devem ser combinados.\",\n \"a11yAdjacentLinksWhy\": \"Links repetidos criam paradas desnecessárias para usuários de teclado e leitores de tela.\",\n \"a11yHeadingStartMessage\": \"O primeiro cabeçalho deve ser um h2.\",\n \"a11yHeadingStartWhy\": \"O título do documento do editor é fornecido fora do conteúdo editável.\",\n \"a11yListStructureMessage\": \"Itens de lista devem estar contidos por uma lista ordenada ou não ordenada.\",\n \"a11yListStructureWhy\": \"A tecnologia assistiva depende da estrutura de listas para anunciar a contagem e a posição dos itens.\",\n \"sourceToggleTooltip\": \"Código-fonte\",\n \"sourceFormatErrorMessage\": \"Não foi possível formatar o código-fonte — verifique se há tags não fechadas ou outros erros de sintaxe.\",\n \"saveToolbarText\": \"Predefinições\",\n \"saveToolbarTooltip\": \"Gerenciar predefinições salvas\",\n \"saveAction\": \"Salvar\",\n \"saveAsAction\": \"Salvar como...\",\n \"openAction\": \"Abrir...\",\n \"deleteAction\": \"Excluir...\",\n \"newAction\": \"Novo\",\n \"exportAction\": \"Exportar...\",\n \"importAction\": \"Importar...\",\n \"saveAsDialogTitle\": \"Salvar predefinição\",\n \"presetNameLabel\": \"Nome\",\n \"openDialogTitle\": \"Abrir predefinição\",\n \"deleteDialogTitle\": \"Excluir predefinição\",\n \"newDialogTitle\": \"Novo documento\",\n \"newDialogMessage\": \"Isto limpa o conteúdo e a configuração do editor atual. Salvar o trabalho atual primeiro?\",\n \"newDialogSaveButton\": \"Salvar e limpar\",\n \"newDialogDiscardButton\": \"Descartar\",\n \"presetLabel\": \"Predefinição\",\n \"confirmOverwrite\": \"Uma predefinição chamada “{{name}}” já existe. Substituí-la?\",\n \"confirmDiscard\": \"Abrir “{{name}}” e descartar as alterações atuais não salvas?\",\n \"confirmDelete\": \"Excluir “{{name}}”? Isto não pode ser desfeito.\",\n \"emptyPresets\": \"Nenhuma predefinição salva está disponível.\",\n \"invalidName\": \"Digite um nome para a predefinição.\",\n \"invalidPreset\": \"Esta predefinição é inválida e não pôde ser aberta.\",\n \"importInvalidFile\": \"O arquivo selecionado não é uma exportação válida do pantoken TinyMCE.\",\n \"storageReadError\": \"As predefinições salvas não puderam ser lidas deste navegador.\",\n \"storageWriteError\": \"A predefinição não pôde ser salva neste navegador.\",\n \"storageDeleteError\": \"A predefinição não pôde ser excluída deste navegador.\",\n \"exportDefaultName\": \"sem título\",\n \"presetSaveButton\": \"Salvar\",\n \"presetOpenButton\": \"Abrir\",\n \"presetDeleteButton\": \"Excluir\"\n },\n \"pt-BR\": {\n \"autocompleteModifierDetail\": \"modificador\",\n \"classValidationIncompleteComponent\": \"Nome do componente incompleto após '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"O token deve começar com '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Componente/utilitário desconhecido: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Inserir componente\",\n \"componentsListLabel\": \"Componentes\",\n \"componentsMenuText\": \"Componente\",\n \"componentsToolbarText\": \"Componentes\",\n \"componentsToolbarTooltip\": \"Inserir um componente pantoken\",\n \"componentModifiersDefault\": \"Padrão\",\n \"componentModifiersOptions\": \"Opções\",\n \"componentModifiersTooltip\": \"Alterar modificadores do componente\",\n \"componentModifiersUtilities\": \"Utilitários\",\n \"iconLabelDialogTitle\": \"Rótulo do ícone\",\n \"iconLabelInputLabel\": \"Rótulo para leitor de tela\",\n \"iconsMenuText\": \"Ícone\",\n \"iconsSearchPlaceholder\": \"Procurar ícones…\",\n \"iconsSearchLabel\": \"Procurar ícones\",\n \"iconsAllSources\": \"Todos\",\n \"iconsResultCount\": \"{{count}} ícones\",\n \"iconsNoResults\": \"Nenhum ícone corresponde à sua pesquisa.\",\n \"iconsToolbarText\": \"Ícones\",\n \"iconsToolbarTooltip\": \"Inserir um ícone\",\n \"iconContextSizeSmall\": \"Pequeno\",\n \"iconContextSizeMedium\": \"Médio\",\n \"iconContextSizeLarge\": \"Grande\",\n \"iconContextSizeExtraLarge\": \"Extra grande\",\n \"layoutsConfirmReplace\": \"Substituir o conteúdo atual pelo layout \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Inserir layout\",\n \"layoutsMenuText\": \"Layout…\",\n \"layoutsSelectLabel\": \"Layout inicial\",\n \"layoutsToolbarText\": \"Layouts\",\n \"layoutsToolbarTooltip\": \"Inserir um layout inicial\",\n \"logosToolbarText\": \"Logotipos\",\n \"logosToolbarTooltip\": \"Inserir um logotipo\",\n \"logosMenuText\": \"Logotipo\",\n \"logosDialogTitle\": \"Inserir logotipo\",\n \"insertButton\": \"Inserir\",\n \"replaceButton\": \"Substituir\",\n \"cancelButton\": \"Cancelar\",\n \"logoAltSuffix\": \"logotipo\",\n \"templatesConfirmReplace\": \"Substituir o conteúdo atual pelo template \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Inserir template\",\n \"templatesMenuText\": \"Inserir template…\",\n \"templatesSelectLabel\": \"Template inicial\",\n \"templatesToolbarText\": \"Templates\",\n \"placeholdToolbarText\": \"Espaço reservado\",\n \"placeholdToolbarTooltip\": \"Inserir uma imagem de espaço reservado\",\n \"placeholdMenuText\": \"Imagem de espaço reservado…\",\n \"placeholdDialogTitle\": \"Inserir imagem de espaço reservado\",\n \"placeholdWidthLabel\": \"Largura\",\n \"placeholdHeightLabel\": \"Altura\",\n \"placeholdBackgroundColorLabel\": \"Cor de fundo\",\n \"placeholdTextColorLabel\": \"Cor do texto\",\n \"placeholdTextLabel\": \"Texto\",\n \"placeholdAltTextLabel\": \"Texto alternativo\",\n \"placeholdInsertButton\": \"Inserir\",\n \"placeholdCancelButton\": \"Cancelar\",\n \"placeholdInvalidDimensions\": \"Largura e altura devem ser números inteiros entre 10 e 4000.\",\n \"placeholdInvalidColor\": \"As cores devem usar valores hexadecimais de três ou seis dígitos.\",\n \"placeholdAltFallback\": \"Imagem de espaço reservado {{width}} por {{height}}\",\n \"a11yToolbarText\": \"Verificar acessibilidade\",\n \"a11yToolbarTooltip\": \"Verifique o conteúdo em busca de problemas de acessibilidade\",\n \"a11yMenuText\": \"Verificar acessibilidade\",\n \"a11yDialogTitle\": \"Verificador de acessibilidade\",\n \"a11yNoIssues\": \"Nenhum problema de acessibilidade encontrado.\",\n \"a11yIssueCount\": \"{{count}} problema(s) de acessibilidade encontrado(s).\",\n \"a11yStatusbarIssueCount\": \"{{count}} problemas de acessibilidade\",\n \"a11yIssueLabel\": \"Problema\",\n \"a11yCloseButton\": \"Fechar\",\n \"a11yImageAltMessage\": \"Imagens devem ter texto alternativo.\",\n \"a11yImageAltWhy\": \"Leitores de tela precisam de um atributo alt para descrever uma imagem ou identificá‑la como decorativa.\",\n \"a11yImageAltFilenameMessage\": \"O texto alternativo da imagem deve descrever a imagem, não repetir o nome do arquivo.\",\n \"a11yImageAltFilenameWhy\": \"Um nome de arquivo raramente fornece informações úteis sobre uma imagem para usuários de leitores de tela.\",\n \"a11yImageAltLengthMessage\": \"O texto alternativo da imagem deve ter 125 caracteres ou menos.\",\n \"a11yImageAltLengthWhy\": \"Descrições curtas são mais fáceis de entender e navegar com tecnologia assistiva.\",\n \"a11yHeadingSequenceMessage\": \"Níveis de título não devem pular níveis.\",\n \"a11yHeadingSequenceWhy\": \"Uma estrutura lógica de títulos ajuda pessoas a navegar pelo conteúdo com tecnologia assistiva.\",\n \"a11yTableHeaderMessage\": \"Tabelas devem incluir células de cabeçalho.\",\n \"a11yTableHeaderWhy\": \"Células de cabeçalho dão aos leitores de tela o contexto necessário para entender os dados da tabela.\",\n \"a11yTableCaptionMessage\": \"Tabelas devem incluir uma legenda.\",\n \"a11yTableCaptionWhy\": \"Uma legenda identifica o propósito da tabela antes que um leitor de tela entre em suas células.\",\n \"a11yTableHeaderScopeMessage\": \"As células de cabeçalho da tabela devem declarar seu escopo.\",\n \"a11yTableHeaderScopeWhy\": \"O atributo scope permite que a tecnologia assistiva associe cabeçalhos às células de dados.\",\n \"a11yAdjacentLinksMessage\": \"Links adjacentes com o mesmo destino devem ser combinados.\",\n \"a11yAdjacentLinksWhy\": \"Links repetidos criam paradas desnecessárias para usuários de teclado e leitores de tela.\",\n \"a11yHeadingStartMessage\": \"O primeiro título deve ser um h2.\",\n \"a11yHeadingStartWhy\": \"O título do documento do editor é fornecido fora do conteúdo editável.\",\n \"a11yListStructureMessage\": \"Itens de lista devem estar contidos em uma lista ordenada ou não ordenada.\",\n \"a11yListStructureWhy\": \"A tecnologia assistiva depende da estrutura da lista para anunciar a contagem e a posição dos itens.\",\n \"sourceToggleTooltip\": \"Código-fonte\",\n \"sourceFormatErrorMessage\": \"Não foi possível formatar o código-fonte — verifique se há tags não fechadas ou outros erros de sintaxe.\",\n \"saveToolbarText\": \"Predefinições\",\n \"saveToolbarTooltip\": \"Gerenciar predefinições salvas\",\n \"saveAction\": \"Salvar\",\n \"saveAsAction\": \"Salvar como...\",\n \"openAction\": \"Abrir...\",\n \"deleteAction\": \"Excluir...\",\n \"newAction\": \"Novo\",\n \"exportAction\": \"Exportar...\",\n \"importAction\": \"Importar...\",\n \"saveAsDialogTitle\": \"Salvar predefinição\",\n \"presetNameLabel\": \"Nome\",\n \"openDialogTitle\": \"Abrir predefinição\",\n \"deleteDialogTitle\": \"Excluir predefinição\",\n \"newDialogTitle\": \"Novo documento\",\n \"newDialogMessage\": \"Isto limpa o conteúdo e a configuração do editor atual. Salvar o trabalho atual primeiro?\",\n \"newDialogSaveButton\": \"Salvar e limpar\",\n \"newDialogDiscardButton\": \"Descartar\",\n \"presetLabel\": \"Predefinição\",\n \"confirmOverwrite\": \"Uma predefinição chamada “{{name}}” já existe. Substituir?\",\n \"confirmDiscard\": \"Abrir “{{name}}” e descartar as alterações não salvas atuais?\",\n \"confirmDelete\": \"Excluir “{{name}}”? Isso não pode ser desfeito.\",\n \"emptyPresets\": \"Nenhuma predefinição salva está disponível.\",\n \"invalidName\": \"Digite um nome para a predefinição.\",\n \"invalidPreset\": \"Esta predefinição é inválida e não pôde ser aberta.\",\n \"importInvalidFile\": \"O arquivo selecionado não é uma exportação válida do pantoken TinyMCE.\",\n \"storageReadError\": \"As predefinições salvas não puderam ser lidas neste navegador.\",\n \"storageWriteError\": \"A predefinição não pôde ser salva neste navegador.\",\n \"storageDeleteError\": \"A predefinição não pôde ser excluída deste navegador.\",\n \"exportDefaultName\": \"sem título\",\n \"presetSaveButton\": \"Salvar\",\n \"presetOpenButton\": \"Abrir\",\n \"presetDeleteButton\": \"Excluir\"\n },\n \"ru\": {\n \"autocompleteModifierDetail\": \"модификатор\",\n \"classValidationIncompleteComponent\": \"Неполное имя компонента после '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Токен должен начинаться с '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Неизвестный компонент/утилита: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Вставить компонент\",\n \"componentsListLabel\": \"Компоненты\",\n \"componentsMenuText\": \"Компонент\",\n \"componentsToolbarText\": \"Компоненты\",\n \"componentsToolbarTooltip\": \"Вставить компонент pantoken\",\n \"componentModifiersDefault\": \"По умолчанию\",\n \"componentModifiersOptions\": \"Параметры\",\n \"componentModifiersTooltip\": \"Изменить модификаторы компонента\",\n \"componentModifiersUtilities\": \"Утилиты\",\n \"iconLabelDialogTitle\": \"Метка иконки\",\n \"iconLabelInputLabel\": \"Метка для экранного чтеца\",\n \"iconsMenuText\": \"Иконка\",\n \"iconsSearchPlaceholder\": \"Поиск значков…\",\n \"iconsSearchLabel\": \"Поиск значков\",\n \"iconsAllSources\": \"Все\",\n \"iconsResultCount\": \"{{count}} значков\",\n \"iconsNoResults\": \"Ни один значок не соответствует вашему запросу.\",\n \"iconsToolbarText\": \"Иконки\",\n \"iconsToolbarTooltip\": \"Вставить иконку\",\n \"iconContextSizeSmall\": \"Маленький\",\n \"iconContextSizeMedium\": \"Средний\",\n \"iconContextSizeLarge\": \"Большой\",\n \"iconContextSizeExtraLarge\": \"Очень большой\",\n \"layoutsConfirmReplace\": \"Заменить текущее содержимое макетом \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Вставить макет\",\n \"layoutsMenuText\": \"Макет…\",\n \"layoutsSelectLabel\": \"Стартовый макет\",\n \"layoutsToolbarText\": \"Макеты\",\n \"layoutsToolbarTooltip\": \"Вставить стартовый макет\",\n \"logosToolbarText\": \"Логотипы\",\n \"logosToolbarTooltip\": \"Вставить логотип\",\n \"logosMenuText\": \"Логотип\",\n \"logosDialogTitle\": \"Вставить логотип\",\n \"insertButton\": \"Вставить\",\n \"replaceButton\": \"Заменить\",\n \"cancelButton\": \"Отмена\",\n \"logoAltSuffix\": \"логотип\",\n \"templatesConfirmReplace\": \"Заменить текущее содержимое шаблоном \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Вставить шаблон\",\n \"templatesMenuText\": \"Вставить шаблон…\",\n \"templatesSelectLabel\": \"Стартовый шаблон\",\n \"templatesToolbarText\": \"Шаблоны\",\n \"placeholdToolbarText\": \"Заполнитель\",\n \"placeholdToolbarTooltip\": \"Вставить изображение-заполнитель\",\n \"placeholdMenuText\": \"Изображение-заполнитель…\",\n \"placeholdDialogTitle\": \"Вставить изображение-заполнитель\",\n \"placeholdWidthLabel\": \"Ширина\",\n \"placeholdHeightLabel\": \"Высота\",\n \"placeholdBackgroundColorLabel\": \"Цвет фона\",\n \"placeholdTextColorLabel\": \"Цвет текста\",\n \"placeholdTextLabel\": \"Текст\",\n \"placeholdAltTextLabel\": \"Альтернативный текст\",\n \"placeholdInsertButton\": \"Вставить\",\n \"placeholdCancelButton\": \"Отмена\",\n \"placeholdInvalidDimensions\": \"Ширина и высота должны быть целыми числами от 10 до 4000.\",\n \"placeholdInvalidColor\": \"Цвета должны быть заданы трех- или шестизначными шестнадцатеричными значениями.\",\n \"placeholdAltFallback\": \"{{width}} на {{height}} изображение-заполнитель\",\n \"a11yToolbarText\": \"Проверить доступность\",\n \"a11yToolbarTooltip\": \"Проверить содержимое на предмет проблем с доступностью\",\n \"a11yMenuText\": \"Проверить доступность\",\n \"a11yDialogTitle\": \"Проверка доступности\",\n \"a11yNoIssues\": \"Проблем с доступностью не найдено.\",\n \"a11yIssueCount\": \"Найдено {{count}} проблема(ы) с доступностью.\",\n \"a11yStatusbarIssueCount\": \"{{count}} проблем(ы) с доступностью\",\n \"a11yIssueLabel\": \"Проблема\",\n \"a11yCloseButton\": \"Закрыть\",\n \"a11yImageAltMessage\": \"У изображений должно быть альтернативное описание.\",\n \"a11yImageAltWhy\": \"Программы чтения с экранам нуждаются в атрибуте alt, чтобы описать изображение или определить его как декоративное.\",\n \"a11yImageAltFilenameMessage\": \"Альтернативный текст изображения должен описывать изображение, а не повторять имя файла.\",\n \"a11yImageAltFilenameWhy\": \"Имя файла редко даёт пользователям программ чтения с экрана полезную информацию об изображении.\",\n \"a11yImageAltLengthMessage\": \"Альтернативный текст изображения должен содержать не более 125 символов.\",\n \"a11yImageAltLengthWhy\": \"Короткие описания легче понять и с ними проще работать с помощью вспомогательных технологий.\",\n \"a11yHeadingSequenceMessage\": \"Уровни заголовков не должны пропускать уровни.\",\n \"a11yHeadingSequenceWhy\": \"Логичная структура заголовков помогает людям ориентироваться в содержимом с помощью вспомогательных технологий.\",\n \"a11yTableHeaderMessage\": \"Таблицы должны содержать ячейки заголовков.\",\n \"a11yTableHeaderWhy\": \"Ячейки заголовков дают программам чтения с экрана контекст, необходимый для понимания данных таблицы.\",\n \"a11yTableCaptionMessage\": \"Таблицы должны иметь подпись (caption).\",\n \"a11yTableCaptionWhy\": \"Подпись определяет назначение таблицы до того, как программа чтения с экрана перейдёт в её ячейки.\",\n \"a11yTableHeaderScopeMessage\": \"Ячейки заголовков таблицы должны объявлять свою область (scope).\",\n \"a11yTableHeaderScopeWhy\": \"Атрибут scope позволяет вспомогательным технологиям связывать заголовки с ячейками данных.\",\n \"a11yAdjacentLinksMessage\": \"Соседние ссылки с одинаковым назначением следует объединить.\",\n \"a11yAdjacentLinksWhy\": \"Повторяющиеся ссылки создают ненужные остановки для пользователей клавиатуры и программ чтения с экрана.\",\n \"a11yHeadingStartMessage\": \"Первым заголовком должен быть h2.\",\n \"a11yHeadingStartWhy\": \"Заголовок документа редактора задаётся вне редактируемого содержимого.\",\n \"a11yListStructureMessage\": \"Элементы списка должны быть внутри упорядоченного или неупорядоченного списка.\",\n \"a11yListStructureWhy\": \"Вспомогательные технологии полагаются на структуру списка, чтобы объявлять количество элементов и позицию.\",\n \"sourceToggleTooltip\": \"Исходный код\",\n \"sourceFormatErrorMessage\": \"Не удалось отформатировать исходный код — проверьте наличие незакрытых тегов или других синтаксических ошибок.\",\n \"saveToolbarText\": \"Пресеты\",\n \"saveToolbarTooltip\": \"Управлять сохранёнными пресетами\",\n \"saveAction\": \"Сохранить\",\n \"saveAsAction\": \"Сохранить как...\",\n \"openAction\": \"Открыть...\",\n \"deleteAction\": \"Удалить...\",\n \"newAction\": \"Новый\",\n \"exportAction\": \"Экспорт...\",\n \"importAction\": \"Импорт...\",\n \"saveAsDialogTitle\": \"Сохранить пресет\",\n \"presetNameLabel\": \"Имя\",\n \"openDialogTitle\": \"Открыть пресет\",\n \"deleteDialogTitle\": \"Удалить пресет\",\n \"newDialogTitle\": \"Новый документ\",\n \"newDialogMessage\": \"Это очистит текущее содержимое и конфигурацию редактора. Сначала сохранить текущую работу?\",\n \"newDialogSaveButton\": \"Сохранить & очистить\",\n \"newDialogDiscardButton\": \"Отменить\",\n \"presetLabel\": \"Пресет\",\n \"confirmOverwrite\": \"Пресет с именем «{{name}}» уже существует. Заменить его?\",\n \"confirmDiscard\": \"Открыть «{{name}}» и удалить текущие несохранённые изменения?\",\n \"confirmDelete\": \"Удалить «{{name}}»? Это действие нельзя отменить.\",\n \"emptyPresets\": \"Нет доступных сохранённых пресетов.\",\n \"invalidName\": \"Введите имя пресета.\",\n \"invalidPreset\": \"Этот пресет недействителен и не может быть открыт.\",\n \"importInvalidFile\": \"Выбранный файл не является допустимым экспортом pantoken TinyMCE.\",\n \"storageReadError\": \"Не удалось прочитать сохранённые пресеты в этом браузере.\",\n \"storageWriteError\": \"Не удалось сохранить пресет в этом браузере.\",\n \"storageDeleteError\": \"Не удалось удалить пресет в этом браузере.\",\n \"exportDefaultName\": \"без названия\",\n \"presetSaveButton\": \"Сохранить\",\n \"presetOpenButton\": \"Открыть\",\n \"presetDeleteButton\": \"Удалить\"\n },\n \"zh-Hans\": {\n \"autocompleteModifierDetail\": \"修饰符\",\n \"classValidationIncompleteComponent\": \"在 '{{prefix}}' 之后组件名称不完整\",\n \"classValidationTokenPrefix\": \"令牌必须以 '{{prefix}}' 开头\",\n \"classValidationUnknownComponent\": \"未知的组件/实用项:'{{componentName}}'\",\n \"componentsDialogTitle\": \"插入组件\",\n \"componentsListLabel\": \"组件\",\n \"componentsMenuText\": \"组件\",\n \"componentsToolbarText\": \"组件\",\n \"componentsToolbarTooltip\": \"插入 pantoken 组件\",\n \"componentModifiersDefault\": \"默认\",\n \"componentModifiersOptions\": \"选项\",\n \"componentModifiersTooltip\": \"更改组件修饰符\",\n \"componentModifiersUtilities\": \"实用工具\",\n \"iconLabelDialogTitle\": \"图标标签\",\n \"iconLabelInputLabel\": \"屏幕阅读器标签\",\n \"iconsMenuText\": \"图标\",\n \"iconsSearchPlaceholder\": \"搜索图标…\",\n \"iconsSearchLabel\": \"搜索图标\",\n \"iconsAllSources\": \"全部\",\n \"iconsResultCount\": \"{{count}} 个图标\",\n \"iconsNoResults\": \"没有图标符合您的搜索条件。\",\n \"iconsToolbarText\": \"图标\",\n \"iconsToolbarTooltip\": \"插入图标\",\n \"iconContextSizeSmall\": \"小\",\n \"iconContextSizeMedium\": \"中\",\n \"iconContextSizeLarge\": \"大\",\n \"iconContextSizeExtraLarge\": \"超大\",\n \"layoutsConfirmReplace\": \"将当前内容替换为 \\\"{{title}}\\\" 布局?\",\n \"layoutsDialogTitle\": \"插入布局\",\n \"layoutsMenuText\": \"布局…\",\n \"layoutsSelectLabel\": \"入门布局\",\n \"layoutsToolbarText\": \"布局\",\n \"layoutsToolbarTooltip\": \"插入入门布局\",\n \"logosToolbarText\": \"徽标\",\n \"logosToolbarTooltip\": \"插入徽标\",\n \"logosMenuText\": \"徽标\",\n \"logosDialogTitle\": \"插入徽标\",\n \"insertButton\": \"插入\",\n \"replaceButton\": \"替换\",\n \"cancelButton\": \"取消\",\n \"logoAltSuffix\": \"徽标\",\n \"templatesConfirmReplace\": \"将当前内容替换为 \\\"{{title}}\\\" 模板?\",\n \"templatesDialogTitle\": \"插入模板\",\n \"templatesMenuText\": \"插入模板…\",\n \"templatesSelectLabel\": \"入门模板\",\n \"templatesToolbarText\": \"模板\",\n \"placeholdToolbarText\": \"占位符\",\n \"placeholdToolbarTooltip\": \"插入占位图片\",\n \"placeholdMenuText\": \"占位图片…\",\n \"placeholdDialogTitle\": \"插入占位图片\",\n \"placeholdWidthLabel\": \"宽度\",\n \"placeholdHeightLabel\": \"高度\",\n \"placeholdBackgroundColorLabel\": \"背景颜色\",\n \"placeholdTextColorLabel\": \"文字颜色\",\n \"placeholdTextLabel\": \"文本\",\n \"placeholdAltTextLabel\": \"替代文本\",\n \"placeholdInsertButton\": \"插入\",\n \"placeholdCancelButton\": \"取消\",\n \"placeholdInvalidDimensions\": \"宽度和高度必须为 10 到 4000 之间的整数。\",\n \"placeholdInvalidColor\": \"颜色必须使用三位或六位十六进制值。\",\n \"placeholdAltFallback\": \"{{width}} × {{height}} 占位图片\",\n \"a11yToolbarText\": \"检查可访问性\",\n \"a11yToolbarTooltip\": \"检查内容的可访问性问题\",\n \"a11yMenuText\": \"检查可访问性\",\n \"a11yDialogTitle\": \"可访问性检查器\",\n \"a11yNoIssues\": \"未发现可访问性问题。\",\n \"a11yIssueCount\": \"发现 {{count}} 个可访问性问题。\",\n \"a11yStatusbarIssueCount\": \"{{count}} 个可访问性问题\",\n \"a11yIssueLabel\": \"问题\",\n \"a11yCloseButton\": \"关闭\",\n \"a11yImageAltMessage\": \"图像必须有替代文本。\",\n \"a11yImageAltWhy\": \"屏幕阅读器需要 alt 属性来描述图像或将其标记为装饰性元素。\",\n \"a11yImageAltFilenameMessage\": \"图像替代文本应描述图像本身,而不是重复其文件名。\",\n \"a11yImageAltFilenameWhy\": \"文件名很少为屏幕阅读器用户提供有关图像的有用信息。\",\n \"a11yImageAltLengthMessage\": \"图像替代文本应在 125 个字符或以内。\",\n \"a11yImageAltLengthWhy\": \"简短的描述更易于理解并便于辅助技术导航。\",\n \"a11yHeadingSequenceMessage\": \"标题级别不应跳级。\",\n \"a11yHeadingSequenceWhy\": \"逻辑的标题大纲有助于使用辅助技术的人导航内容。\",\n \"a11yTableHeaderMessage\": \"表格必须包含表头单元格。\",\n \"a11yTableHeaderWhy\": \"表头单元格为屏幕阅读器提供理解表格数据所需的上下文。\",\n \"a11yTableCaptionMessage\": \"表格应包含标题说明(caption)。\",\n \"a11yTableCaptionWhy\": \"在屏幕阅读器进入单元格之前,标题说明可说明表格的用途。\",\n \"a11yTableHeaderScopeMessage\": \"表格表头单元格应声明其作用范围(scope)。\",\n \"a11yTableHeaderScopeWhy\": \"scope 属性让辅助技术将表头与数据单元格关联起来。\",\n \"a11yAdjacentLinksMessage\": \"相邻且目标相同的链接应合并。\",\n \"a11yAdjacentLinksWhy\": \"重复的链接会为键盘和屏幕阅读器用户造成不必要的停顿。\",\n \"a11yHeadingStartMessage\": \"第一个标题应为 h2。\",\n \"a11yHeadingStartWhy\": \"编辑器的文档标题在可编辑内容之外提供。\",\n \"a11yListStructureMessage\": \"列表项必须包含在有序或无序列表中。\",\n \"a11yListStructureWhy\": \"辅助技术依赖列表结构来宣布项目计数和位置。\",\n \"sourceToggleTooltip\": \"源代码\",\n \"sourceFormatErrorMessage\": \"无法格式化源代码 — 请检查是否有未闭合的标签或其他语法错误。\",\n \"saveToolbarText\": \"预设\",\n \"saveToolbarTooltip\": \"管理已保存的预设\",\n \"saveAction\": \"保存\",\n \"saveAsAction\": \"另存为…\",\n \"openAction\": \"打开…\",\n \"deleteAction\": \"删除…\",\n \"newAction\": \"新建\",\n \"exportAction\": \"导出...\",\n \"importAction\": \"导入...\",\n \"saveAsDialogTitle\": \"保存预设\",\n \"presetNameLabel\": \"名称\",\n \"openDialogTitle\": \"打开预设\",\n \"deleteDialogTitle\": \"删除预设\",\n \"newDialogTitle\": \"新建文档\",\n \"newDialogMessage\": \"这会清除当前编辑器的内容和配置。先保存当前工作吗?\",\n \"newDialogSaveButton\": \"保存并清除\",\n \"newDialogDiscardButton\": \"放弃\",\n \"presetLabel\": \"预设\",\n \"confirmOverwrite\": \"名为 “{{name}}” 的预设已存在。要替换它吗?\",\n \"confirmDiscard\": \"打开 “{{name}}” 并放弃当前未保存的更改?\",\n \"confirmDelete\": \"删除 “{{name}}”?此操作无法撤销。\",\n \"emptyPresets\": \"没有可用的已保存预设。\",\n \"invalidName\": \"请输入预设名称。\",\n \"invalidPreset\": \"此预设无效,无法打开。\",\n \"importInvalidFile\": \"所选文件不是有效的 pantoken TinyMCE 导出。\",\n \"storageReadError\": \"无法从此浏览器读取已保存的预设。\",\n \"storageWriteError\": \"无法在此浏览器中保存预设。\",\n \"storageDeleteError\": \"无法从此浏览器中删除预设。\",\n \"exportDefaultName\": \"未命名\",\n \"presetSaveButton\": \"保存\",\n \"presetOpenButton\": \"打开\",\n \"presetDeleteButton\": \"删除\"\n },\n \"sl\": {\n \"autocompleteModifierDetail\": \"modifikator\",\n \"classValidationIncompleteComponent\": \"Nepopolno ime komponente po '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token se mora začeti z '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Neznana komponenta/utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Vstavi komponento\",\n \"componentsListLabel\": \"Komponente\",\n \"componentsMenuText\": \"Komponenta\",\n \"componentsToolbarText\": \"Komponente\",\n \"componentsToolbarTooltip\": \"Vstavi pantoken komponento\",\n \"componentModifiersDefault\": \"Privzeto\",\n \"componentModifiersOptions\": \"Možnosti\",\n \"componentModifiersTooltip\": \"Spremeni modifikatorje komponente\",\n \"componentModifiersUtilities\": \"Orodja\",\n \"iconLabelDialogTitle\": \"Oznaka ikone\",\n \"iconLabelInputLabel\": \"Oznaka za bralnike zaslona\",\n \"iconsMenuText\": \"Ikona\",\n \"iconsSearchPlaceholder\": \"Išči ikone…\",\n \"iconsSearchLabel\": \"Išči ikone\",\n \"iconsAllSources\": \"Vse\",\n \"iconsResultCount\": \"{{count}} ikon\",\n \"iconsNoResults\": \"Nobena ikona ne ustreza vašemu iskanju.\",\n \"iconsToolbarText\": \"Ikone\",\n \"iconsToolbarTooltip\": \"Vstavi ikono\",\n \"iconContextSizeSmall\": \"Majhno\",\n \"iconContextSizeMedium\": \"Srednje\",\n \"iconContextSizeLarge\": \"Veliko\",\n \"iconContextSizeExtraLarge\": \"Zelo veliko\",\n \"layoutsConfirmReplace\": \"Zamenjati trenutno vsebino z postavitvijo \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Vstavi postavitev\",\n \"layoutsMenuText\": \"Postavitev…\",\n \"layoutsSelectLabel\": \"Začetna postavitev\",\n \"layoutsToolbarText\": \"Postavitve\",\n \"layoutsToolbarTooltip\": \"Vstavi začetno postavitev\",\n \"logosToolbarText\": \"Logotipi\",\n \"logosToolbarTooltip\": \"Vstavi logotip\",\n \"logosMenuText\": \"Logotip\",\n \"logosDialogTitle\": \"Vstavi logotip\",\n \"insertButton\": \"Vstavi\",\n \"replaceButton\": \"Zamenjaj\",\n \"cancelButton\": \"Prekliči\",\n \"logoAltSuffix\": \"logotip\",\n \"templatesConfirmReplace\": \"Zamenjati trenutno vsebino s predlogo \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Vstavi predlogo\",\n \"templatesMenuText\": \"Vstavi predlogo…\",\n \"templatesSelectLabel\": \"Začetna predloga\",\n \"templatesToolbarText\": \"Predloge\",\n \"placeholdToolbarText\": \"Nadomestek\",\n \"placeholdToolbarTooltip\": \"Vstavi nadomestno sliko\",\n \"placeholdMenuText\": \"Nadomestna slika…\",\n \"placeholdDialogTitle\": \"Vstavi nadomestno sliko\",\n \"placeholdWidthLabel\": \"Širina\",\n \"placeholdHeightLabel\": \"Višina\",\n \"placeholdBackgroundColorLabel\": \"Barva ozadja\",\n \"placeholdTextColorLabel\": \"Barva besedila\",\n \"placeholdTextLabel\": \"Besedilo\",\n \"placeholdAltTextLabel\": \"Alternativno besedilo\",\n \"placeholdInsertButton\": \"Vstavi\",\n \"placeholdCancelButton\": \"Prekliči\",\n \"placeholdInvalidDimensions\": \"Širina in višina morata biti cela števila od 10 do 4000.\",\n \"placeholdInvalidColor\": \"Barve morajo uporabljati tri- ali šestmestne šestnajstiške vrednosti.\",\n \"placeholdAltFallback\": \"{{width}} × {{height}} nadomestna slika\",\n \"a11yToolbarText\": \"Preveri dostopnost\",\n \"a11yToolbarTooltip\": \"Preveri vsebino zaradi težav z dostopnostjo\",\n \"a11yMenuText\": \"Preveri dostopnost\",\n \"a11yDialogTitle\": \"Orodje za preverjanje dostopnosti\",\n \"a11yNoIssues\": \"Ni bilo najdenih težav z dostopnostjo.\",\n \"a11yIssueCount\": \"{{count}} najdenih težav z dostopnostjo.\",\n \"a11yStatusbarIssueCount\": \"{{count}} težav z dostopnostjo\",\n \"a11yIssueLabel\": \"Težava\",\n \"a11yCloseButton\": \"Zapri\",\n \"a11yImageAltMessage\": \"Slikam mora biti priloženo nadomestno besedilo.\",\n \"a11yImageAltWhy\": \"Zaslonski bralniki potrebujejo atribut alt, da opišejo sliko ali jo identificirajo kot dekorativno.\",\n \"a11yImageAltFilenameMessage\": \"Nadomestno besedilo slike naj opiše sliko, ne ponavlja imena datoteke.\",\n \"a11yImageAltFilenameWhy\": \"Ime datoteke redko zagotavlja uporabnikom zaslonskih bralnikov koristne informacije o sliki.\",\n \"a11yImageAltLengthMessage\": \"Nadomestno besedilo slike naj bo dolgo največ 125 znakov.\",\n \"a11yImageAltLengthWhy\": \"Kratki opisi so lažje razumljivi in jih je lažje premagovati z asistivno tehnologijo.\",\n \"a11yHeadingSequenceMessage\": \"Ravni naslovov ne smejo preskakovati.\",\n \"a11yHeadingSequenceWhy\": \"Logična struktura naslovov pomaga ljudem pri navigaciji po vsebini z asistivno tehnologijo.\",\n \"a11yTableHeaderMessage\": \"Tabele morajo vsebovati glave stolpcev.\",\n \"a11yTableHeaderWhy\": \"Glave stolpcev dajejo zaslonskim bralnikom kontekst, potreben za razumevanje podatkov v tabeli.\",\n \"a11yTableCaptionMessage\": \"Tabele naj vsebujejo napis (caption).\",\n \"a11yTableCaptionWhy\": \"Napis identificira namen tabele, preden zaslonski bralnik vstopi v celice.\",\n \"a11yTableHeaderScopeMessage\": \"Glave tabel morajo navesti svoj scope.\",\n \"a11yTableHeaderScopeWhy\": \"Atribut scope omogoča asistivni tehnologiji, da poveže glave s podatkovnimi celicami.\",\n \"a11yAdjacentLinksMessage\": \"Sosednje povezave z istim ciljem je treba združiti.\",\n \"a11yAdjacentLinksWhy\": \"Ponavljajoče se povezave ustvarjajo nepotrebna ustavljanja za uporabnike tipkovnice in zaslonskih bralnikov.\",\n \"a11yHeadingStartMessage\": \"Prvi naslov naj bo h2.\",\n \"a11yHeadingStartWhy\": \"Naslov dokumenta urejevalnika je podan zunaj urejene vsebine.\",\n \"a11yListStructureMessage\": \"Elementi seznama morajo biti v urejenem ali neurejenem seznamu.\",\n \"a11yListStructureWhy\": \"Asistivna tehnologija se zanaša na strukturo seznama za oznanitev števila elementov in položaja.\",\n \"sourceToggleTooltip\": \"Izvorna koda\",\n \"sourceFormatErrorMessage\": \"Ni bilo mogoče formatirati izvorne kode — preverite, ali so kje nezaprte oznake ali druge sintaktične napake.\",\n \"saveToolbarText\": \"Prednastavitve\",\n \"saveToolbarTooltip\": \"Upravljaj shranjene prednastavitve\",\n \"saveAction\": \"Shrani\",\n \"saveAsAction\": \"Shrani kot...\",\n \"openAction\": \"Odpri...\",\n \"deleteAction\": \"Izbriši...\",\n \"newAction\": \"Novo\",\n \"exportAction\": \"Izvozi...\",\n \"importAction\": \"Uvozi...\",\n \"saveAsDialogTitle\": \"Shrani prednastavitev\",\n \"presetNameLabel\": \"Ime\",\n \"openDialogTitle\": \"Odpri prednastavitev\",\n \"deleteDialogTitle\": \"Izbriši prednastavitev\",\n \"newDialogTitle\": \"Nov dokument\",\n \"newDialogMessage\": \"To počisti trenutno vsebino urejevalnika in konfiguracijo. Najprej shranite trenutno delo?\",\n \"newDialogSaveButton\": \"Shrani in počisti\",\n \"newDialogDiscardButton\": \"Zavrži\",\n \"presetLabel\": \"Prednastavitev\",\n \"confirmOverwrite\": \"Prednastavitev z imenom “{{name}}” že obstaja. Nadomestiti?\",\n \"confirmDiscard\": \"Odpreti “{{name}}” in zavreči trenutne neshranjene spremembe?\",\n \"confirmDelete\": \"Izbrisati “{{name}}”? Tega ni mogoče razveljaviti.\",\n \"emptyPresets\": \"Ni na voljo shranjenih prednastavitev.\",\n \"invalidName\": \"Vnesite ime prednastavitve.\",\n \"invalidPreset\": \"Ta prednastavitev ni veljavna in je ni bilo mogoče odpreti.\",\n \"importInvalidFile\": \"Izbrana datoteka ni veljaven izvoz pantoken TinyMCE.\",\n \"storageReadError\": \"Shranjene prednastavitve ni bilo mogoče prebrati v tem brskalniku.\",\n \"storageWriteError\": \"Prednastavitve ni bilo mogoče shraniti v tem brskalniku.\",\n \"storageDeleteError\": \"Prednastavitve ni bilo mogoče izbrisati v tem brskalniku.\",\n \"exportDefaultName\": \"brez naslova\",\n \"presetSaveButton\": \"Shrani\",\n \"presetOpenButton\": \"Odpri\",\n \"presetDeleteButton\": \"Izbriši\"\n },\n \"es\": {\n \"autocompleteModifierDetail\": \"modificador\",\n \"classValidationIncompleteComponent\": \"Nombre de componente incompleto después de '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"El token debe comenzar con '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Componente/utilidad desconocido: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Insertar componente\",\n \"componentsListLabel\": \"Componentes\",\n \"componentsMenuText\": \"Componente\",\n \"componentsToolbarText\": \"Componentes\",\n \"componentsToolbarTooltip\": \"Insertar un componente pantoken\",\n \"componentModifiersDefault\": \"Predeterminado\",\n \"componentModifiersOptions\": \"Opciones\",\n \"componentModifiersTooltip\": \"Cambiar modificadores del componente\",\n \"componentModifiersUtilities\": \"Utilidades\",\n \"iconLabelDialogTitle\": \"Etiqueta del icono\",\n \"iconLabelInputLabel\": \"Etiqueta para lectores de pantalla\",\n \"iconsMenuText\": \"Icono\",\n \"iconsSearchPlaceholder\": \"Buscar iconos…\",\n \"iconsSearchLabel\": \"Buscar iconos\",\n \"iconsAllSources\": \"Todos\",\n \"iconsResultCount\": \"{{count}} iconos\",\n \"iconsNoResults\": \"Ningún icono coincide con tu búsqueda.\",\n \"iconsToolbarText\": \"Iconos\",\n \"iconsToolbarTooltip\": \"Insertar un icono\",\n \"iconContextSizeSmall\": \"Pequeño\",\n \"iconContextSizeMedium\": \"Mediano\",\n \"iconContextSizeLarge\": \"Grande\",\n \"iconContextSizeExtraLarge\": \"Extra grande\",\n \"layoutsConfirmReplace\": \"¿Reemplazar el contenido actual con el diseño \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Insertar diseño\",\n \"layoutsMenuText\": \"Diseño…\",\n \"layoutsSelectLabel\": \"Diseño inicial\",\n \"layoutsToolbarText\": \"Diseños\",\n \"layoutsToolbarTooltip\": \"Insertar un diseño inicial\",\n \"logosToolbarText\": \"Logotipos\",\n \"logosToolbarTooltip\": \"Insertar un logotipo\",\n \"logosMenuText\": \"Logotipo\",\n \"logosDialogTitle\": \"Insertar logotipo\",\n \"insertButton\": \"Insertar\",\n \"replaceButton\": \"Reemplazar\",\n \"cancelButton\": \"Cancelar\",\n \"logoAltSuffix\": \"logotipo\",\n \"templatesConfirmReplace\": \"¿Reemplazar el contenido actual con la plantilla \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Insertar plantilla\",\n \"templatesMenuText\": \"Insertar plantilla…\",\n \"templatesSelectLabel\": \"Plantilla inicial\",\n \"templatesToolbarText\": \"Plantillas\",\n \"placeholdToolbarText\": \"Marcador de posición\",\n \"placeholdToolbarTooltip\": \"Insertar una imagen de marcador de posición\",\n \"placeholdMenuText\": \"Imagen de marcador de posición…\",\n \"placeholdDialogTitle\": \"Insertar imagen de marcador de posición\",\n \"placeholdWidthLabel\": \"Ancho\",\n \"placeholdHeightLabel\": \"Altura\",\n \"placeholdBackgroundColorLabel\": \"Color de fondo\",\n \"placeholdTextColorLabel\": \"Color del texto\",\n \"placeholdTextLabel\": \"Texto\",\n \"placeholdAltTextLabel\": \"Texto alternativo\",\n \"placeholdInsertButton\": \"Insertar\",\n \"placeholdCancelButton\": \"Cancelar\",\n \"placeholdInvalidDimensions\": \"El ancho y la altura deben ser números enteros entre 10 y 4000.\",\n \"placeholdInvalidColor\": \"Los colores deben usar valores hexadecimales de tres o seis dígitos.\",\n \"placeholdAltFallback\": \"{{width}} por {{height}} imagen de marcador de posición\",\n \"a11yToolbarText\": \"Comprobar accesibilidad\",\n \"a11yToolbarTooltip\": \"Comprobar el contenido en busca de problemas de accesibilidad\",\n \"a11yMenuText\": \"Comprobar accesibilidad\",\n \"a11yDialogTitle\": \"Comprobador de accesibilidad\",\n \"a11yNoIssues\": \"No se encontraron problemas de accesibilidad.\",\n \"a11yIssueCount\": \"{{count}} problema(s) de accesibilidad encontrados.\",\n \"a11yStatusbarIssueCount\": \"{{count}} problemas de accesibilidad\",\n \"a11yIssueLabel\": \"Problema\",\n \"a11yCloseButton\": \"Cerrar\",\n \"a11yImageAltMessage\": \"Las imágenes deben tener texto alternativo.\",\n \"a11yImageAltWhy\": \"Los lectores de pantalla necesitan un atributo alt para describir una imagen o identificarla como decorativa.\",\n \"a11yImageAltFilenameMessage\": \"El texto alternativo de la imagen debe describir la imagen, no repetir el nombre del archivo.\",\n \"a11yImageAltFilenameWhy\": \"Un nombre de archivo rara vez ofrece información útil sobre una imagen a los usuarios de lectores de pantalla.\",\n \"a11yImageAltLengthMessage\": \"El texto alternativo de la imagen debe tener 125 caracteres o menos.\",\n \"a11yImageAltLengthWhy\": \"Las descripciones cortas son más fáciles de entender y navegar con tecnología de asistencia.\",\n \"a11yHeadingSequenceMessage\": \"Los niveles de encabezado no deben saltarse.\",\n \"a11yHeadingSequenceWhy\": \"Un esquema lógico de encabezados ayuda a las personas a navegar el contenido con tecnología de asistencia.\",\n \"a11yTableHeaderMessage\": \"Las tablas deben incluir celdas de encabezado.\",\n \"a11yTableHeaderWhy\": \"Las celdas de encabezado proporcionan a los lectores de pantalla el contexto necesario para entender los datos de la tabla.\",\n \"a11yTableCaptionMessage\": \"Las tablas deberían incluir un pie de tabla (caption).\",\n \"a11yTableCaptionWhy\": \"Un pie de tabla identifica el propósito de una tabla antes de que un lector de pantalla entre en sus celdas.\",\n \"a11yTableHeaderScopeMessage\": \"Las celdas de encabezado de la tabla deberían declarar su scope.\",\n \"a11yTableHeaderScopeWhy\": \"El atributo scope permite a la tecnología de asistencia asociar encabezados con celdas de datos.\",\n \"a11yAdjacentLinksMessage\": \"Los enlaces adyacentes con el mismo destino deberían combinarse.\",\n \"a11yAdjacentLinksWhy\": \"Los enlaces repetidos crean paradas innecesarias para usuarios de teclado y lectores de pantalla.\",\n \"a11yHeadingStartMessage\": \"El primer encabezado debe ser un h2.\",\n \"a11yHeadingStartWhy\": \"El título del documento del editor se proporciona fuera del contenido editable.\",\n \"a11yListStructureMessage\": \"Los elementos de lista deben estar contenidos en una lista ordenada o desordenada.\",\n \"a11yListStructureWhy\": \"La tecnología de asistencia se basa en la estructura de listas para anunciar el número de elementos y la posición.\",\n \"sourceToggleTooltip\": \"Código fuente\",\n \"sourceFormatErrorMessage\": \"No se pudo formatear el código fuente — comprueba si hay etiquetas sin cerrar u otros errores de sintaxis.\",\n \"saveToolbarText\": \"Preajustes\",\n \"saveToolbarTooltip\": \"Administrar preajustes guardados\",\n \"saveAction\": \"Guardar\",\n \"saveAsAction\": \"Guardar como...\",\n \"openAction\": \"Abrir...\",\n \"deleteAction\": \"Eliminar...\",\n \"newAction\": \"Nuevo\",\n \"exportAction\": \"Exportar...\",\n \"importAction\": \"Importar...\",\n \"saveAsDialogTitle\": \"Guardar preajuste\",\n \"presetNameLabel\": \"Nombre\",\n \"openDialogTitle\": \"Abrir preajuste\",\n \"deleteDialogTitle\": \"Eliminar preajuste\",\n \"newDialogTitle\": \"Nuevo documento\",\n \"newDialogMessage\": \"Esto borrará el contenido y la configuración del editor actual. ¿Guardar el trabajo actual primero?\",\n \"newDialogSaveButton\": \"Guardar y borrar\",\n \"newDialogDiscardButton\": \"Descartar\",\n \"presetLabel\": \"Preajuste\",\n \"confirmOverwrite\": \"Ya existe un preajuste llamado “{{name}}”. ¿Reemplazarlo?\",\n \"confirmDiscard\": \"¿Abrir “{{name}}” y descartar los cambios no guardados actuales?\",\n \"confirmDelete\": \"¿Eliminar “{{name}}”? Esto no se puede deshacer.\",\n \"emptyPresets\": \"No hay preajustes guardados disponibles.\",\n \"invalidName\": \"Introduce un nombre para el preajuste.\",\n \"invalidPreset\": \"Este preajuste es inválido y no se pudo abrir.\",\n \"importInvalidFile\": \"El archivo seleccionado no es una exportación válida de pantoken TinyMCE.\",\n \"storageReadError\": \"No se pudieron leer los preajustes guardados desde este navegador.\",\n \"storageWriteError\": \"No se pudo guardar el preajuste en este navegador.\",\n \"storageDeleteError\": \"No se pudo eliminar el preajuste de este navegador.\",\n \"exportDefaultName\": \"sin título\",\n \"presetSaveButton\": \"Guardar\",\n \"presetOpenButton\": \"Abrir\",\n \"presetDeleteButton\": \"Eliminar\"\n },\n \"sv\": {\n \"autocompleteModifierDetail\": \"modifierare\",\n \"classValidationIncompleteComponent\": \"Ofullständigt komponentnamn efter '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token måste börja med '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Okänd komponent/utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Infoga komponent\",\n \"componentsListLabel\": \"Komponenter\",\n \"componentsMenuText\": \"Komponent\",\n \"componentsToolbarText\": \"Komponenter\",\n \"componentsToolbarTooltip\": \"Infoga en pantoken-komponent\",\n \"componentModifiersDefault\": \"Standard\",\n \"componentModifiersOptions\": \"Alternativ\",\n \"componentModifiersTooltip\": \"Ändra komponentmodifierare\",\n \"componentModifiersUtilities\": \"Verktyg\",\n \"iconLabelDialogTitle\": \"Ikonetikett\",\n \"iconLabelInputLabel\": \"Skärmläsaretikett\",\n \"iconsMenuText\": \"Ikon\",\n \"iconsSearchPlaceholder\": \"Sök ikoner…\",\n \"iconsSearchLabel\": \"Sök ikoner\",\n \"iconsAllSources\": \"Alla\",\n \"iconsResultCount\": \"{{count}} ikoner\",\n \"iconsNoResults\": \"Inga ikoner matchar din sökning.\",\n \"iconsToolbarText\": \"Ikoner\",\n \"iconsToolbarTooltip\": \"Infoga en ikon\",\n \"iconContextSizeSmall\": \"Liten\",\n \"iconContextSizeMedium\": \"Medel\",\n \"iconContextSizeLarge\": \"Stor\",\n \"iconContextSizeExtraLarge\": \"Extra stor\",\n \"layoutsConfirmReplace\": \"Ersätt det aktuella innehållet med layouten \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Infoga layout\",\n \"layoutsMenuText\": \"Layout…\",\n \"layoutsSelectLabel\": \"Startlayout\",\n \"layoutsToolbarText\": \"Layouter\",\n \"layoutsToolbarTooltip\": \"Infoga en startlayout\",\n \"logosToolbarText\": \"Logotyper\",\n \"logosToolbarTooltip\": \"Infoga en logotyp\",\n \"logosMenuText\": \"Logotyp\",\n \"logosDialogTitle\": \"Infoga logotyp\",\n \"insertButton\": \"Infoga\",\n \"replaceButton\": \"Ersätt\",\n \"cancelButton\": \"Avbryt\",\n \"logoAltSuffix\": \"logotyp\",\n \"templatesConfirmReplace\": \"Ersätt det aktuella innehållet med mallen \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Infoga mall\",\n \"templatesMenuText\": \"Infoga mall…\",\n \"templatesSelectLabel\": \"Startmall\",\n \"templatesToolbarText\": \"Mallar\",\n \"placeholdToolbarText\": \"Platshållare\",\n \"placeholdToolbarTooltip\": \"Infoga en platshållarbild\",\n \"placeholdMenuText\": \"Platshållarbild…\",\n \"placeholdDialogTitle\": \"Infoga platshållarbild\",\n \"placeholdWidthLabel\": \"Bredd\",\n \"placeholdHeightLabel\": \"Höjd\",\n \"placeholdBackgroundColorLabel\": \"Bakgrundsfärg\",\n \"placeholdTextColorLabel\": \"Textfärg\",\n \"placeholdTextLabel\": \"Text\",\n \"placeholdAltTextLabel\": \"Alt-text\",\n \"placeholdInsertButton\": \"Infoga\",\n \"placeholdCancelButton\": \"Avbryt\",\n \"placeholdInvalidDimensions\": \"Bredd och höjd måste vara heltal mellan 10 och 4000.\",\n \"placeholdInvalidColor\": \"Färger måste använda tre- eller sexsiffriga hexadecimala värden.\",\n \"placeholdAltFallback\": \"{{width}} gånger {{height}} platshållarbild\",\n \"a11yToolbarText\": \"Kontrollera tillgänglighet\",\n \"a11yToolbarTooltip\": \"Kontrollera innehållet efter tillgänglighetsproblem\",\n \"a11yMenuText\": \"Kontrollera tillgänglighet\",\n \"a11yDialogTitle\": \"Kontroll av tillgänglighet\",\n \"a11yNoIssues\": \"Inga tillgänglighetsproblem hittades.\",\n \"a11yIssueCount\": \"{{count}} tillgänglighetsproblem hittade.\",\n \"a11yStatusbarIssueCount\": \"{{count}} tillgänglighetsproblem\",\n \"a11yIssueLabel\": \"Problem\",\n \"a11yCloseButton\": \"Stäng\",\n \"a11yImageAltMessage\": \"Bilder måste ha alternativtext.\",\n \"a11yImageAltWhy\": \"Skärmläsare behöver ett alt-attribut för att beskriva en bild eller identifiera den som dekorativ.\",\n \"a11yImageAltFilenameMessage\": \"Bildens alternativtext bör beskriva bilden, inte upprepa dess filnamn.\",\n \"a11yImageAltFilenameWhy\": \"Ett filnamn ger sällan skärmläsaranvändare användbar information om en bild.\",\n \"a11yImageAltLengthMessage\": \"Bildens alternativtext bör vara 125 tecken eller färre.\",\n \"a11yImageAltLengthWhy\": \"Korta beskrivningar är lättare att förstå och navigera med hjälpteknik.\",\n \"a11yHeadingSequenceMessage\": \"Rubriknivåer bör inte hoppa över nivåer.\",\n \"a11yHeadingSequenceWhy\": \"En logisk rubrikstruktur hjälper personer att navigera innehåll med hjälpteknik.\",\n \"a11yTableHeaderMessage\": \"Tabeller måste innehålla headerceller.\",\n \"a11yTableHeaderWhy\": \"Headerceller ger skärmläsare den kontext som krävs för att förstå tabelldata.\",\n \"a11yTableCaptionMessage\": \"Tabeller bör innehålla en bildtext (caption).\",\n \"a11yTableCaptionWhy\": \"En bildtext identifierar en tabells syfte innan en skärmläsare går in i dess celler.\",\n \"a11yTableHeaderScopeMessage\": \"Tabellhuvudceller bör ange sitt scope.\",\n \"a11yTableHeaderScopeWhy\": \"Attributet scope låter hjälpmedel associera rubriker med dataceller.\",\n \"a11yAdjacentLinksMessage\": \"Intilliggande länkar med samma destination bör slås ihop.\",\n \"a11yAdjacentLinksWhy\": \"Upprepade länkar skapar onödiga stopp för tangentbords- och skärmläsaranvändare.\",\n \"a11yHeadingStartMessage\": \"Den första rubriken bör vara en h2.\",\n \"a11yHeadingStartWhy\": \"Redigerarens dokumenttitel anges utanför det redigerbara innehållet.\",\n \"a11yListStructureMessage\": \"Listobjekt måste vara inneslutna i en ordnad eller oordnad lista.\",\n \"a11yListStructureWhy\": \"Hjälpmedel förlitar sig på liststrukturen för att meddela antal och position för objekt.\",\n \"sourceToggleTooltip\": \"Källkod\",\n \"sourceFormatErrorMessage\": \"Kunde inte formatera källkoden — kontrollera om det finns oavslutna taggar eller andra syntaxfel.\",\n \"saveToolbarText\": \"Förinställningar\",\n \"saveToolbarTooltip\": \"Hantera sparade förinställningar\",\n \"saveAction\": \"Spara\",\n \"saveAsAction\": \"Spara som...\",\n \"openAction\": \"Öppna...\",\n \"deleteAction\": \"Radera...\",\n \"newAction\": \"Ny\",\n \"exportAction\": \"Exportera...\",\n \"importAction\": \"Importera...\",\n \"saveAsDialogTitle\": \"Spara förinställning\",\n \"presetNameLabel\": \"Namn\",\n \"openDialogTitle\": \"Öppna förinställning\",\n \"deleteDialogTitle\": \"Radera förinställning\",\n \"newDialogTitle\": \"Nytt dokument\",\n \"newDialogMessage\": \"Detta rensar den aktuella redigerarens innehåll och konfiguration. Spara det nuvarande arbetet först?\",\n \"newDialogSaveButton\": \"Spara och rensa\",\n \"newDialogDiscardButton\": \"Kassera\",\n \"presetLabel\": \"Förinställning\",\n \"confirmOverwrite\": \"En förinställning med namnet “{{name}}” finns redan. Ersätta den?\",\n \"confirmDiscard\": \"Öppna “{{name}}” och kassera de nuvarande osparade ändringarna?\",\n \"confirmDelete\": \"Radera “{{name}}”? Detta kan inte ångras.\",\n \"emptyPresets\": \"Inga sparade förinställningar finns tillgängliga.\",\n \"invalidName\": \"Ange ett namn för förinställningen.\",\n \"invalidPreset\": \"Denna förinställning är ogiltig och kunde inte öppnas.\",\n \"importInvalidFile\": \"Den valda filen är inte en giltig pantoken TinyMCE-export.\",\n \"storageReadError\": \"Sparade förinställningar kunde inte läsas från denna webbläsare.\",\n \"storageWriteError\": \"Förinställningen kunde inte sparas i denna webbläsare.\",\n \"storageDeleteError\": \"Förinställningen kunde inte raderas från denna webbläsare.\",\n \"exportDefaultName\": \"namnlös\",\n \"presetSaveButton\": \"Spara\",\n \"presetOpenButton\": \"Öppna\",\n \"presetDeleteButton\": \"Radera\"\n },\n \"th\": {\n \"autocompleteModifierDetail\": \"ตัวแก้ไข\",\n \"classValidationIncompleteComponent\": \"ชื่อคอมโพเนนต์ไม่สมบูรณ์หลัง '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"โทเค็นต้องขึ้นต้นด้วย '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"คอมโพเนนต์/ยูทิลิตี้ไม่รู้จัก: '{{componentName}}'\",\n \"componentsDialogTitle\": \"แทรกคอมโพเนนต์\",\n \"componentsListLabel\": \"คอมโพเนนต์\",\n \"componentsMenuText\": \"คอมโพเนนต์\",\n \"componentsToolbarText\": \"คอมโพเนนต์\",\n \"componentsToolbarTooltip\": \"แทรกคอมโพเนนต์ pantoken\",\n \"componentModifiersDefault\": \"ค่าเริ่มต้น\",\n \"componentModifiersOptions\": \"ตัวเลือก\",\n \"componentModifiersTooltip\": \"เปลี่ยนตัวปรับแต่งของคอมโพเนนต์\",\n \"componentModifiersUtilities\": \"ยูทิลิตี้\",\n \"iconLabelDialogTitle\": \"ป้ายกำกับไอคอน\",\n \"iconLabelInputLabel\": \"ป้ายกำกับสำหรับเครื่องอ่านหน้าจอ\",\n \"iconsMenuText\": \"ไอคอน\",\n \"iconsSearchPlaceholder\": \"ค้นหาไอคอน…\",\n \"iconsSearchLabel\": \"ค้นหาไอคอน\",\n \"iconsAllSources\": \"ทั้งหมด\",\n \"iconsResultCount\": \"{{count}} ไอคอน\",\n \"iconsNoResults\": \"ไม่มีไอคอนที่ตรงกับการค้นหาของคุณ\",\n \"iconsToolbarText\": \"ไอคอน\",\n \"iconsToolbarTooltip\": \"แทรกไอคอน\",\n \"iconContextSizeSmall\": \"เล็ก\",\n \"iconContextSizeMedium\": \"กลาง\",\n \"iconContextSizeLarge\": \"ใหญ่\",\n \"iconContextSizeExtraLarge\": \"ใหญ่พิเศษ\",\n \"layoutsConfirmReplace\": \"จะแทนที่เนื้อหาปัจจุบันด้วยเค้าโครง \\\"{{title}}\\\" หรือไม่?\",\n \"layoutsDialogTitle\": \"แทรกเค้าโครง\",\n \"layoutsMenuText\": \"เค้าโครง…\",\n \"layoutsSelectLabel\": \"เค้าโครงเริ่มต้น\",\n \"layoutsToolbarText\": \"เค้าโครง\",\n \"layoutsToolbarTooltip\": \"แทรกเค้าโครงเริ่มต้น\",\n \"logosToolbarText\": \"โลโก้\",\n \"logosToolbarTooltip\": \"แทรกโลโก้\",\n \"logosMenuText\": \"โลโก้\",\n \"logosDialogTitle\": \"แทรกโลโก้\",\n \"insertButton\": \"แทรก\",\n \"replaceButton\": \"แทนที่\",\n \"cancelButton\": \"ยกเลิก\",\n \"logoAltSuffix\": \"โลโก้\",\n \"templatesConfirmReplace\": \"จะแทนที่เนื้อหาปัจจุบันด้วยแม่แบบ \\\"{{title}}\\\" หรือไม่?\",\n \"templatesDialogTitle\": \"แทรกแม่แบบ\",\n \"templatesMenuText\": \"แทรกแม่แบบ…\",\n \"templatesSelectLabel\": \"แม่แบบเริ่มต้น\",\n \"templatesToolbarText\": \"แม่แบบ\",\n \"placeholdToolbarText\": \"ตัวแทนที่\",\n \"placeholdToolbarTooltip\": \"แทรกรูปภาพตัวแทนที่\",\n \"placeholdMenuText\": \"รูปภาพตัวแทนที่…\",\n \"placeholdDialogTitle\": \"แทรกรูปภาพตัวแทนที่\",\n \"placeholdWidthLabel\": \"ความกว้าง\",\n \"placeholdHeightLabel\": \"ความสูง\",\n \"placeholdBackgroundColorLabel\": \"สีพื้นหลัง\",\n \"placeholdTextColorLabel\": \"สีตัวอักษร\",\n \"placeholdTextLabel\": \"ข้อความ\",\n \"placeholdAltTextLabel\": \"ข้อความแทนภาพ (alt)\",\n \"placeholdInsertButton\": \"แทรก\",\n \"placeholdCancelButton\": \"ยกเลิก\",\n \"placeholdInvalidDimensions\": \"ความกว้างและความสูงต้องเป็นจำนวนเต็มตั้งแต่ 10 ถึง 4000.\",\n \"placeholdInvalidColor\": \"ค่าสีต้องใช้เลขฐานสิบหกสามหลักหรือหกหลัก.\",\n \"placeholdAltFallback\": \"{{width}} โดย {{height}} รูปภาพตัวแทนที่\",\n \"a11yToolbarText\": \"ตรวจสอบการเข้าถึง\",\n \"a11yToolbarTooltip\": \"ตรวจสอบเนื้อหาเพื่อหาปัญหาด้านการเข้าถึง\",\n \"a11yMenuText\": \"ตรวจสอบการเข้าถึง\",\n \"a11yDialogTitle\": \"ตัวตรวจสอบการเข้าถึง\",\n \"a11yNoIssues\": \"ไม่พบปัญหาด้านการเข้าถึง\",\n \"a11yIssueCount\": \"พบ {{count}} ปัญหาด้านการเข้าถึง\",\n \"a11yStatusbarIssueCount\": \"{{count}} ปัญหาด้านการเข้าถึง\",\n \"a11yIssueLabel\": \"ปัญหา\",\n \"a11yCloseButton\": \"ปิด\",\n \"a11yImageAltMessage\": \"รูปภาพต้องมีข้อความทางเลือก\",\n \"a11yImageAltWhy\": \"โปรแกรมอ่านหน้าจอต้องการแอตทริบิวต์ alt เพื่ออธิบายภาพหรือระบุว่าเป็นภาพประดับ\",\n \"a11yImageAltFilenameMessage\": \"ข้อความทางเลือกของภาพควรอธิบายภาพ ไม่ควรซ้ำชื่อไฟล์\",\n \"a11yImageAltFilenameWhy\": \"ชื่อไฟล์มักไม่ให้ข้อมูลที่เป็นประโยชน์แก่ผู้ใช้โปรแกรมอ่านหน้าจอ\",\n \"a11yImageAltLengthMessage\": \"ข้อความทางเลือกของภาพควรมีไม่เกิน 125 ตัวอักษร\",\n \"a11yImageAltLengthWhy\": \"คำอธิบายสั้น ๆ จะเข้าใจและนำทางได้ง่ายขึ้นด้วยเทคโนโลยีช่วยเหลือ\",\n \"a11yHeadingSequenceMessage\": \"ระดับหัวเรื่องไม่ควรข้ามลำดับ\",\n \"a11yHeadingSequenceWhy\": \"โครงร่างหัวเรื่องที่มีเหตุผลช่วยให้ผู้คนนำทางเนื้อหาด้วยเทคโนโลยีช่วยเหลือได้\",\n \"a11yTableHeaderMessage\": \"ตารางต้องมีเซลล์หัวเรื่อง\",\n \"a11yTableHeaderWhy\": \"เซลล์หัวเรื่องให้บริบทที่โปรแกรมอ่านหน้าจอต้องการเพื่อเข้าใจข้อมูลในตาราง\",\n \"a11yTableCaptionMessage\": \"ตารางควรมีคำบรรยาย (caption)\",\n \"a11yTableCaptionWhy\": \"คำบรรยายระบุวัตถุประสงค์ของตารางก่อนที่โปรแกรมอ่านหน้าจอจะเข้าไปในเซลล์\",\n \"a11yTableHeaderScopeMessage\": \"เซลล์หัวเรื่องของตารางควรประกาศ scope\",\n \"a11yTableHeaderScopeWhy\": \"แอตทริบิวต์ scope ช่วยให้เทคโนโลยีช่วยเหลือเชื่อมโยงหัวเรื่องกับเซลล์ข้อมูลได้\",\n \"a11yAdjacentLinksMessage\": \"ลิงก์ที่อยู่ติดกันและมีปลายทางเหมือนกันควรรวมกัน\",\n \"a11yAdjacentLinksWhy\": \"ลิงก์ที่ซ้ำกันสร้างจุดหยุดที่ไม่จำเป็นสำหรับผู้ใช้คีย์บอร์ดและโปรแกรมอ่านหน้าจอ\",\n \"a11yHeadingStartMessage\": \"หัวเรื่องแรกควรเป็น h2\",\n \"a11yHeadingStartWhy\": \"ชื่อเอกสารของตัวแก้ไขถูกจัดหาไว้นอกเนื้อหาที่แก้ไขได้\",\n \"a11yListStructureMessage\": \"รายการต้องอยู่ภายในรายการที่มีลำดับหรือลำดับไม่แน่นอน\",\n \"a11yListStructureWhy\": \"เทคโนโลยีช่วยเหลือพึ่งพาโครงสร้างรายการเพื่อประกาศจำนวนรายการและตำแหน่ง\",\n \"sourceToggleTooltip\": \"ซอร์สโค้ด\",\n \"sourceFormatErrorMessage\": \"ไม่สามารถจัดรูปแบบซอร์สโค้ดได้ — ตรวจสอบว่าไม่มีแท็กที่ยังไม่ได้ปิดหรือข้อผิดพลาดทางไวยากรณ์อื่น ๆ\",\n \"saveToolbarText\": \"ค่าที่ตั้งไว้ล่วงหน้า\",\n \"saveToolbarTooltip\": \"จัดการค่าที่ตั้งไว้ล่วงหน้าที่บันทึกไว้\",\n \"saveAction\": \"บันทึก\",\n \"saveAsAction\": \"บันทึกเป็น...\",\n \"openAction\": \"เปิด...\",\n \"deleteAction\": \"ลบ...\",\n \"newAction\": \"ใหม่\",\n \"exportAction\": \"ส่งออก...\",\n \"importAction\": \"นำเข้า...\",\n \"saveAsDialogTitle\": \"บันทึกค่าที่ตั้งไว้ล่วงหน้า\",\n \"presetNameLabel\": \"ชื่อ\",\n \"openDialogTitle\": \"เปิดค่าที่ตั้งไว้ล่วงหน้า\",\n \"deleteDialogTitle\": \"ลบค่าที่ตั้งไว้ล่วงหน้า\",\n \"newDialogTitle\": \"เอกสารใหม่\",\n \"newDialogMessage\": \"การกระทำนี้จะล้างเนื้อหาและการตั้งค่าของตัวแก้ไขปัจจุบัน ให้บันทึกงานปัจจุบันก่อนหรือไม่?\",\n \"newDialogSaveButton\": \"บันทึกและล้าง\",\n \"newDialogDiscardButton\": \"ทิ้ง\",\n \"presetLabel\": \"ค่าที่ตั้งไว้ล่วงหน้า\",\n \"confirmOverwrite\": \"มีค่าที่ตั้งไว้ล่วงหน้าชื่อ “{{name}}” อยู่แล้ว ต้องการแทนที่หรือไม่?\",\n \"confirmDiscard\": \"เปิด “{{name}}” และยกเลิกการเปลี่ยนแปลงที่ยังไม่ได้บันทึกอยู่หรือไม่?\",\n \"confirmDelete\": \"ลบ “{{name}}” หรือไม่? ไม่สามารถย้อนกลับได้\",\n \"emptyPresets\": \"ไม่มีค่าที่ตั้งไว้ล่วงหน้าที่บันทึกไว้\",\n \"invalidName\": \"ป้อนชื่อค่าที่ตั้งไว้ล่วงหน้า\",\n \"invalidPreset\": \"ค่าที่ตั้งไว้ล่วงหน้าฉบับนี้ไม่ถูกต้องและไม่สามารถเปิดได้\",\n \"importInvalidFile\": \"ไฟล์ที่เลือกไม่ใช่ไฟล์ส่งออก pantoken TinyMCE ที่ถูกต้อง.\",\n \"storageReadError\": \"ไม่สามารถอ่านค่าที่ตั้งไว้ล่วงหน้าที่บันทึกไว้จากเบราว์เซอร์นี้ได้\",\n \"storageWriteError\": \"ไม่สามารถบันทึกค่าที่ตั้งไว้ล่วงหน้าในเบราว์เซอร์นี้ได้\",\n \"storageDeleteError\": \"ไม่สามารถลบค่าที่ตั้งไว้ล่วงหน้าออกจากเบราว์เซอร์นี้ได้\",\n \"exportDefaultName\": \"ไม่ได้ตั้งชื่อ\",\n \"presetSaveButton\": \"บันทึก\",\n \"presetOpenButton\": \"เปิด\",\n \"presetDeleteButton\": \"ลบ\"\n },\n \"zh-Hant\": {\n \"autocompleteModifierDetail\": \"修飾子\",\n \"classValidationIncompleteComponent\": \"在 '{{prefix}}' 之後的元件名稱不完整\",\n \"classValidationTokenPrefix\": \"Token 必須以 '{{prefix}}' 開頭\",\n \"classValidationUnknownComponent\": \"未知的元件/工具:'{{componentName}}'\",\n \"componentsDialogTitle\": \"插入元件\",\n \"componentsListLabel\": \"元件\",\n \"componentsMenuText\": \"元件\",\n \"componentsToolbarText\": \"元件\",\n \"componentsToolbarTooltip\": \"插入 pantoken 元件\",\n \"componentModifiersDefault\": \"預設\",\n \"componentModifiersOptions\": \"選項\",\n \"componentModifiersTooltip\": \"變更元件修飾器\",\n \"componentModifiersUtilities\": \"工具\",\n \"iconLabelDialogTitle\": \"圖示標籤\",\n \"iconLabelInputLabel\": \"螢幕閱讀器標籤\",\n \"iconsMenuText\": \"圖示\",\n \"iconsSearchPlaceholder\": \"搜尋圖示…\",\n \"iconsSearchLabel\": \"搜尋圖示\",\n \"iconsAllSources\": \"全部\",\n \"iconsResultCount\": \"{{count}} 個圖示\",\n \"iconsNoResults\": \"沒有圖示符合您的搜尋。\",\n \"iconsToolbarText\": \"圖示\",\n \"iconsToolbarTooltip\": \"插入圖示\",\n \"iconContextSizeSmall\": \"小\",\n \"iconContextSizeMedium\": \"中\",\n \"iconContextSizeLarge\": \"大\",\n \"iconContextSizeExtraLarge\": \"超大\",\n \"layoutsConfirmReplace\": \"要以 \\\"{{title}}\\\" 版面取代目前內容嗎?\",\n \"layoutsDialogTitle\": \"插入版面\",\n \"layoutsMenuText\": \"版面…\",\n \"layoutsSelectLabel\": \"起始版面\",\n \"layoutsToolbarText\": \"版面\",\n \"layoutsToolbarTooltip\": \"插入起始版面\",\n \"logosToolbarText\": \"商標\",\n \"logosToolbarTooltip\": \"插入商標\",\n \"logosMenuText\": \"商標\",\n \"logosDialogTitle\": \"插入商標\",\n \"insertButton\": \"插入\",\n \"replaceButton\": \"取代\",\n \"cancelButton\": \"取消\",\n \"logoAltSuffix\": \"商標\",\n \"templatesConfirmReplace\": \"要以 \\\"{{title}}\\\" 範本取代目前內容嗎?\",\n \"templatesDialogTitle\": \"插入範本\",\n \"templatesMenuText\": \"插入範本…\",\n \"templatesSelectLabel\": \"起始範本\",\n \"templatesToolbarText\": \"範本\",\n \"placeholdToolbarText\": \"佔位符\",\n \"placeholdToolbarTooltip\": \"插入佔位圖像\",\n \"placeholdMenuText\": \"佔位圖像…\",\n \"placeholdDialogTitle\": \"插入佔位圖像\",\n \"placeholdWidthLabel\": \"寬度\",\n \"placeholdHeightLabel\": \"高度\",\n \"placeholdBackgroundColorLabel\": \"背景顏色\",\n \"placeholdTextColorLabel\": \"文字顏色\",\n \"placeholdTextLabel\": \"文字\",\n \"placeholdAltTextLabel\": \"替代文字\",\n \"placeholdInsertButton\": \"插入\",\n \"placeholdCancelButton\": \"取消\",\n \"placeholdInvalidDimensions\": \"寬度和高度必須為介於 10 到 4000 的整數。\",\n \"placeholdInvalidColor\": \"顏色必須使用三位或六位十六進位值。\",\n \"placeholdAltFallback\": \"{{width}} x {{height}} 的佔位圖像\",\n \"a11yToolbarText\": \"檢查可及性\",\n \"a11yToolbarTooltip\": \"檢查內容是否有可及性問題\",\n \"a11yMenuText\": \"檢查可及性\",\n \"a11yDialogTitle\": \"可及性檢查工具\",\n \"a11yNoIssues\": \"未發現可及性問題。\",\n \"a11yIssueCount\": \"{{count}} 個可及性問題已發現。\",\n \"a11yStatusbarIssueCount\": \"{{count}} 個可及性問題\",\n \"a11yIssueLabel\": \"問題\",\n \"a11yCloseButton\": \"關閉\",\n \"a11yImageAltMessage\": \"圖片必須具有替代文字。\",\n \"a11yImageAltWhy\": \"螢幕閱讀器需要 alt 屬性來描述圖片或標示其為裝飾性。\",\n \"a11yImageAltFilenameMessage\": \"圖片替代文字應描述圖片內容,而非重複檔名。\",\n \"a11yImageAltFilenameWhy\": \"檔名很少能為螢幕閱讀器使用者提供有用的圖片資訊。\",\n \"a11yImageAltLengthMessage\": \"圖片替代文字應為 125 個字元或以下。\",\n \"a11yImageAltLengthWhy\": \"簡短的描述更容易被輔助技術理解與導覽。\",\n \"a11yHeadingSequenceMessage\": \"標題層級不應跳級。\",\n \"a11yHeadingSequenceWhy\": \"有邏輯的標題大綱可協助使用輔助技術的人士導覽內容。\",\n \"a11yTableHeaderMessage\": \"表格必須包含標頭儲存格。\",\n \"a11yTableHeaderWhy\": \"標頭儲存格提供螢幕閱讀器理解表格資料所需的上下文。\",\n \"a11yTableCaptionMessage\": \"表格應包含說明文字(caption)。\",\n \"a11yTableCaptionWhy\": \"說明文字能在螢幕閱讀器進入儲存格前說明表格用途。\",\n \"a11yTableHeaderScopeMessage\": \"表格標頭儲存格應宣告其 scope 屬性。\",\n \"a11yTableHeaderScopeWhy\": \"scope 屬性讓輔助技術將標頭與資料儲存格對應。\",\n \"a11yAdjacentLinksMessage\": \"相鄰且目的地相同的連結應合併。\",\n \"a11yAdjacentLinksWhy\": \"重複的連結會為鍵盤和螢幕閱讀器使用者造成不必要的停頓。\",\n \"a11yHeadingStartMessage\": \"第一個標題應為 h2。\",\n \"a11yHeadingStartWhy\": \"編輯器的文件標題是由可編輯內容之外提供。\",\n \"a11yListStructureMessage\": \"清單項目必須包含在有序或無序清單中。\",\n \"a11yListStructureWhy\": \"輔助技術仰賴清單結構來宣告項目數量與位置。\",\n \"sourceToggleTooltip\": \"原始程式碼\",\n \"sourceFormatErrorMessage\": \"無法格式化原始程式碼 — 請檢查是否有未關閉的標籤或其他語法錯誤。\",\n \"saveToolbarText\": \"預設值\",\n \"saveToolbarTooltip\": \"管理已儲存的預設值\",\n \"saveAction\": \"儲存\",\n \"saveAsAction\": \"另存為…\",\n \"openAction\": \"開啟…\",\n \"deleteAction\": \"刪除…\",\n \"newAction\": \"新建\",\n \"exportAction\": \"匯出...\",\n \"importAction\": \"匯入...\",\n \"saveAsDialogTitle\": \"儲存預設值\",\n \"presetNameLabel\": \"名稱\",\n \"openDialogTitle\": \"開啟預設值\",\n \"deleteDialogTitle\": \"刪除預設值\",\n \"newDialogTitle\": \"新文件\",\n \"newDialogMessage\": \"這會清除目前編輯器的內容與設定。要先儲存目前的工作嗎?\",\n \"newDialogSaveButton\": \"儲存並清除\",\n \"newDialogDiscardButton\": \"捨棄\",\n \"presetLabel\": \"預設值\",\n \"confirmOverwrite\": \"名為「{{name}}」的預設值已存在。要取代它嗎?\",\n \"confirmDiscard\": \"開啟「{{name}}」,並捨棄目前未儲存的變更?\",\n \"confirmDelete\": \"刪除「{{name}}」?此操作無法復原。\",\n \"emptyPresets\": \"沒有可用的已儲存預設值。\",\n \"invalidName\": \"請輸入預設值名稱。\",\n \"invalidPreset\": \"此預設值無效,無法開啟。\",\n \"importInvalidFile\": \"所選的檔案不是有效的 pantoken TinyMCE 匯出檔。\",\n \"storageReadError\": \"無法從此瀏覽器讀取已儲存的預設值。\",\n \"storageWriteError\": \"無法在此瀏覽器儲存預設值。\",\n \"storageDeleteError\": \"無法在此瀏覽器刪除預設值。\",\n \"exportDefaultName\": \"未命名\",\n \"presetSaveButton\": \"儲存\",\n \"presetOpenButton\": \"開啟\",\n \"presetDeleteButton\": \"刪除\"\n },\n \"tr\": {\n \"autocompleteModifierDetail\": \"modifikatör\",\n \"classValidationIncompleteComponent\": \"'{{prefix}}' sonrasında eksik bileşen adı\",\n \"classValidationTokenPrefix\": \"Token '{{prefix}}' ile başlamalı\",\n \"classValidationUnknownComponent\": \"Bilinmeyen bileşen/yardımcı: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Bileşen Ekle\",\n \"componentsListLabel\": \"Bileşenler\",\n \"componentsMenuText\": \"Bileşen\",\n \"componentsToolbarText\": \"Bileşenler\",\n \"componentsToolbarTooltip\": \"Bir pantoken bileşeni ekle\",\n \"componentModifiersDefault\": \"Varsayılan\",\n \"componentModifiersOptions\": \"Seçenekler\",\n \"componentModifiersTooltip\": \"Bileşen modifikatörlerini değiştir\",\n \"componentModifiersUtilities\": \"Yardımcılar\",\n \"iconLabelDialogTitle\": \"Simge etiketi\",\n \"iconLabelInputLabel\": \"Ekran okuyucu etiketi\",\n \"iconsMenuText\": \"Simge\",\n \"iconsSearchPlaceholder\": \"Simge ara…\",\n \"iconsSearchLabel\": \"Simge ara\",\n \"iconsAllSources\": \"Tümü\",\n \"iconsResultCount\": \"{{count}} simge\",\n \"iconsNoResults\": \"Aramanızla eşleşen simge yok.\",\n \"iconsToolbarText\": \"Simgeler\",\n \"iconsToolbarTooltip\": \"Bir simge ekle\",\n \"iconContextSizeSmall\": \"Küçük\",\n \"iconContextSizeMedium\": \"Orta\",\n \"iconContextSizeLarge\": \"Büyük\",\n \"iconContextSizeExtraLarge\": \"Ekstra büyük\",\n \"layoutsConfirmReplace\": \"Mevcut içerik \\\"{{title}}\\\" düzeni ile değiştirilsin mi?\",\n \"layoutsDialogTitle\": \"Düzen ekle\",\n \"layoutsMenuText\": \"Düzen…\",\n \"layoutsSelectLabel\": \"Başlangıç düzeni\",\n \"layoutsToolbarText\": \"Düzenler\",\n \"layoutsToolbarTooltip\": \"Bir başlangıç düzeni ekle\",\n \"logosToolbarText\": \"Logolar\",\n \"logosToolbarTooltip\": \"Bir logo ekle\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Logo Ekle\",\n \"insertButton\": \"Ekle\",\n \"replaceButton\": \"Değiştir\",\n \"cancelButton\": \"İptal\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Mevcut içerik \\\"{{title}}\\\" şablonu ile değiştirilsin mi?\",\n \"templatesDialogTitle\": \"Şablon ekle\",\n \"templatesMenuText\": \"Şablon ekle…\",\n \"templatesSelectLabel\": \"Başlangıç şablonu\",\n \"templatesToolbarText\": \"Şablonlar\",\n \"placeholdToolbarText\": \"Yer tutucu\",\n \"placeholdToolbarTooltip\": \"Bir yer tutucu resim ekle\",\n \"placeholdMenuText\": \"Yer tutucu resim…\",\n \"placeholdDialogTitle\": \"Yer tutucu resim ekle\",\n \"placeholdWidthLabel\": \"Genişlik\",\n \"placeholdHeightLabel\": \"Yükseklik\",\n \"placeholdBackgroundColorLabel\": \"Arka plan rengi\",\n \"placeholdTextColorLabel\": \"Metin rengi\",\n \"placeholdTextLabel\": \"Metin\",\n \"placeholdAltTextLabel\": \"Alt metin\",\n \"placeholdInsertButton\": \"Ekle\",\n \"placeholdCancelButton\": \"İptal\",\n \"placeholdInvalidDimensions\": \"Genişlik ve yükseklik 10 ile 4000 arasında tam sayılar olmalıdır.\",\n \"placeholdInvalidColor\": \"Renkler üç veya altı haneli onaltılık değerler kullanmalıdır.\",\n \"placeholdAltFallback\": \"{{width}} by {{height}} yer tutucu resim\",\n \"a11yToolbarText\": \"Erişilebilirliği denetle\",\n \"a11yToolbarTooltip\": \"İçeriği erişilebilirlik sorunları için denetleyin\",\n \"a11yMenuText\": \"Erişilebilirliği denetle\",\n \"a11yDialogTitle\": \"Erişilebilirlik denetleyicisi\",\n \"a11yNoIssues\": \"Erişilebilirlik sorunu bulunamadı.\",\n \"a11yIssueCount\": \"{{count}} erişilebilirlik sorunu bulundu.\",\n \"a11yStatusbarIssueCount\": \"{{count}} erişilebilirlik sorunu\",\n \"a11yIssueLabel\": \"Sorun\",\n \"a11yCloseButton\": \"Kapat\",\n \"a11yImageAltMessage\": \"Görüntülerin alternatif metni olmalıdır.\",\n \"a11yImageAltWhy\": \"Ekran okuyucular bir görüntüyü tanımlamak veya dekoratif olduğunu belirtmek için alt özniteliğine ihtiyaç duyar.\",\n \"a11yImageAltFilenameMessage\": \"Görüntü alternatif metni görüntüyü tanımlamalı, dosya adını tekrarlamamalıdır.\",\n \"a11yImageAltFilenameWhy\": \"Bir dosya adı nadiren ekran okuyucu kullanıcılarına görüntü hakkında faydalı bilgi verir.\",\n \"a11yImageAltLengthMessage\": \"Görüntü alternatif metni 125 karakter veya daha kısa olmalıdır.\",\n \"a11yImageAltLengthWhy\": \"Kısa açıklamalar, yardımcı teknoloji ile anlamayı ve gezinmeyi kolaylaştırır.\",\n \"a11yHeadingSequenceMessage\": \"Başlık seviyeleri atlanmamalıdır.\",\n \"a11yHeadingSequenceWhy\": \"Mantıklı bir başlık düzeni, yardımcı teknolojiyle içeriğin gezilmesine yardımcı olur.\",\n \"a11yTableHeaderMessage\": \"Tablolarda başlık hücreleri bulunmalıdır.\",\n \"a11yTableHeaderWhy\": \"Başlık hücreleri, ekran okuyuculara tablo verilerini anlamaları için gerekli bağlamı sağlar.\",\n \"a11yTableCaptionMessage\": \"Tablolarda başlık (caption) olmalıdır.\",\n \"a11yTableCaptionWhy\": \"Bir başlık, ekran okuyucu hücrelere girmeden önce tablonun amacını belirtir.\",\n \"a11yTableHeaderScopeMessage\": \"Tablo başlık hücreleri scope özniteliğini belirtmelidir.\",\n \"a11yTableHeaderScopeWhy\": \"Scope özniteliği, yardımcı teknolojinin başlıkları veri hücreleriyle ilişkilendirmesini sağlar.\",\n \"a11yAdjacentLinksMessage\": \"Aynı hedefe sahip bitişik bağlantılar birleştirilmelidir.\",\n \"a11yAdjacentLinksWhy\": \"Tekrarlanan bağlantılar, klavye ve ekran okuyucu kullanıcıları için gereksiz duraklamalar oluşturur.\",\n \"a11yHeadingStartMessage\": \"İlk başlık h2 olmalıdır.\",\n \"a11yHeadingStartWhy\": \"Editörün belge başlığı düzenlenebilir içeriğin dışında sağlanmıştır.\",\n \"a11yListStructureMessage\": \"Liste öğeleri sıralı veya sırasız bir listenin içinde olmalıdır.\",\n \"a11yListStructureWhy\": \"Yardımcı teknoloji, öğe sayısını ve konumunu duyurmak için liste yapısına güvenebilir.\",\n \"sourceToggleTooltip\": \"Kaynak kodu\",\n \"sourceFormatErrorMessage\": \"Kaynak kod biçimlendirilemedi — kapatılmamış etiketler veya diğer sözdizimi hatalarını kontrol edin.\",\n \"saveToolbarText\": \"Önayarlar\",\n \"saveToolbarTooltip\": \"Kaydedilmiş önayarları yönet\",\n \"saveAction\": \"Kaydet\",\n \"saveAsAction\": \"Farklı kaydet...\",\n \"openAction\": \"Aç...\",\n \"deleteAction\": \"Sil...\",\n \"newAction\": \"Yeni\",\n \"exportAction\": \"Dışa aktar...\",\n \"importAction\": \"İçe aktar...\",\n \"saveAsDialogTitle\": \"Önayarı kaydet\",\n \"presetNameLabel\": \"İsim\",\n \"openDialogTitle\": \"Önayarı aç\",\n \"deleteDialogTitle\": \"Önayarı sil\",\n \"newDialogTitle\": \"Yeni belge\",\n \"newDialogMessage\": \"Bu, mevcut düzenleyici içeriğini ve yapılandırmasını temizler. Önce mevcut çalışmayı kaydetmek ister misiniz?\",\n \"newDialogSaveButton\": \"Kaydet ve temizle\",\n \"newDialogDiscardButton\": \"Vazgeç\",\n \"presetLabel\": \"Önayar\",\n \"confirmOverwrite\": \"“{{name}}” adlı bir önayar zaten var. Değiştirilsin mi?\",\n \"confirmDiscard\": \"“{{name}}” açılsın ve mevcut kaydedilmemiş değişiklikler atılsın mı?\",\n \"confirmDelete\": \"“{{name}}” silinsin mi? Bu işlem geri alınamaz.\",\n \"emptyPresets\": \"Kayıtlı önayar bulunmuyor.\",\n \"invalidName\": \"Bir önayar adı girin.\",\n \"invalidPreset\": \"Bu önayar geçersiz ve açılamadı.\",\n \"importInvalidFile\": \"Seçilen dosya geçerli bir pantoken TinyMCE dışa aktarımı değil.\",\n \"storageReadError\": \"Kaydedilmiş önayarlar bu tarayıcıdan okunamadı.\",\n \"storageWriteError\": \"Önayar bu tarayıcıya kaydedilemedi.\",\n \"storageDeleteError\": \"Önayar bu tarayıcıdan silinemedi.\",\n \"exportDefaultName\": \"başlıksız\",\n \"presetSaveButton\": \"Kaydet\",\n \"presetOpenButton\": \"Aç\",\n \"presetDeleteButton\": \"Sil\"\n },\n \"uk\": {\n \"autocompleteModifierDetail\": \"модифікатор\",\n \"classValidationIncompleteComponent\": \"Неповна назва компонента після '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Токен повинен починатися з '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Невідомий компонент/утиліта: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Вставити компонент\",\n \"componentsListLabel\": \"Компоненти\",\n \"componentsMenuText\": \"Компонент\",\n \"componentsToolbarText\": \"Компоненти\",\n \"componentsToolbarTooltip\": \"Вставити компонент pantoken\",\n \"componentModifiersDefault\": \"За замовчуванням\",\n \"componentModifiersOptions\": \"Параметри\",\n \"componentModifiersTooltip\": \"Змінити модифікатори компонента\",\n \"componentModifiersUtilities\": \"Утиліти\",\n \"iconLabelDialogTitle\": \"Мітка значка\",\n \"iconLabelInputLabel\": \"Підпис для зчитувача екрану\",\n \"iconsMenuText\": \"Значок\",\n \"iconsSearchPlaceholder\": \"Пошук іконок…\",\n \"iconsSearchLabel\": \"Пошук іконок\",\n \"iconsAllSources\": \"Усі\",\n \"iconsResultCount\": \"{{count}} іконок\",\n \"iconsNoResults\": \"Жодна іконка не відповідає вашому пошуку.\",\n \"iconsToolbarText\": \"Значки\",\n \"iconsToolbarTooltip\": \"Вставити значок\",\n \"iconContextSizeSmall\": \"Малий\",\n \"iconContextSizeMedium\": \"Середній\",\n \"iconContextSizeLarge\": \"Великий\",\n \"iconContextSizeExtraLarge\": \"Дуже великий\",\n \"layoutsConfirmReplace\": \"Замінити поточний вміст макетом \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Вставити макет\",\n \"layoutsMenuText\": \"Макет…\",\n \"layoutsSelectLabel\": \"Початковий макет\",\n \"layoutsToolbarText\": \"Макети\",\n \"layoutsToolbarTooltip\": \"Вставити початковий макет\",\n \"logosToolbarText\": \"Логотипи\",\n \"logosToolbarTooltip\": \"Вставити логотип\",\n \"logosMenuText\": \"Логотип\",\n \"logosDialogTitle\": \"Вставити логотип\",\n \"insertButton\": \"Вставити\",\n \"replaceButton\": \"Замінити\",\n \"cancelButton\": \"Скасувати\",\n \"logoAltSuffix\": \"логотип\",\n \"templatesConfirmReplace\": \"Замінити поточний вміст шаблоном \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Вставити шаблон\",\n \"templatesMenuText\": \"Вставити шаблон…\",\n \"templatesSelectLabel\": \"Початковий шаблон\",\n \"templatesToolbarText\": \"Шаблони\",\n \"placeholdToolbarText\": \"Заповнювач\",\n \"placeholdToolbarTooltip\": \"Вставити зображення-заповнювач\",\n \"placeholdMenuText\": \"Зображення-заповнювач…\",\n \"placeholdDialogTitle\": \"Вставити зображення-заповнювач\",\n \"placeholdWidthLabel\": \"Ширина\",\n \"placeholdHeightLabel\": \"Висота\",\n \"placeholdBackgroundColorLabel\": \"Колір фону\",\n \"placeholdTextColorLabel\": \"Колір тексту\",\n \"placeholdTextLabel\": \"Текст\",\n \"placeholdAltTextLabel\": \"Альтернативний текст\",\n \"placeholdInsertButton\": \"Вставити\",\n \"placeholdCancelButton\": \"Скасувати\",\n \"placeholdInvalidDimensions\": \"Ширина та висота повинні бути цілими числами від 10 до 4000.\",\n \"placeholdInvalidColor\": \"Кольори повинні використовувати три- або шестизначні шістнадцяткові значення.\",\n \"placeholdAltFallback\": \"{{width}} на {{height}} зображення-заповнювач\",\n \"a11yToolbarText\": \"Перевірити доступність\",\n \"a11yToolbarTooltip\": \"Перевірте вміст на наявність проблем з доступністю\",\n \"a11yMenuText\": \"Перевірити доступність\",\n \"a11yDialogTitle\": \"Перевірка доступності\",\n \"a11yNoIssues\": \"Проблем з доступністю не знайдено.\",\n \"a11yIssueCount\": \"{{count}} проблем з доступністю знайдено.\",\n \"a11yStatusbarIssueCount\": \"{{count}} проблем з доступністю\",\n \"a11yIssueLabel\": \"Проблема\",\n \"a11yCloseButton\": \"Закрити\",\n \"a11yImageAltMessage\": \"Зображення повинні мати альтернативний текст.\",\n \"a11yImageAltWhy\": \"Програми для читання з екрану потребують атрибута alt, щоб описати зображення або позначити його як декоративне.\",\n \"a11yImageAltFilenameMessage\": \"Альтернативний текст зображення має описувати його, а не повторювати назву файлу.\",\n \"a11yImageAltFilenameWhy\": \"Назва файлу рідко дає корисну інформацію користувачам програм читання з екрану.\",\n \"a11yImageAltLengthMessage\": \"Альтернативний текст зображення повинен містити не більше 125 символів.\",\n \"a11yImageAltLengthWhy\": \"Короткі описи легше розуміти й ними простіше користуватися за допомогою допоміжних технологій.\",\n \"a11yHeadingSequenceMessage\": \"Рівні заголовків не повинні пропускатися.\",\n \"a11yHeadingSequenceWhy\": \"Логічна структура заголовків допомагає людям орієнтуватися у вмісті за допомогою допоміжних технологій.\",\n \"a11yTableHeaderMessage\": \"Таблиці повинні містити клітинки заголовків.\",\n \"a11yTableHeaderWhy\": \"Клітинки заголовків надають програмам читання з екрану контекст для розуміння даних таблиці.\",\n \"a11yTableCaptionMessage\": \"Таблиці повинні мати підпис (caption).\",\n \"a11yTableCaptionWhy\": \"Підпис визначає призначення таблиці перед тим, як програма читання з екрану перейде до її клітинок.\",\n \"a11yTableHeaderScopeMessage\": \"Клітинки заголовків таблиці повинні вказувати свій scope (область дії).\",\n \"a11yTableHeaderScopeWhy\": \"Атрибут scope дозволяє допоміжним технологіям пов'язувати заголовки з клітинками даних.\",\n \"a11yAdjacentLinksMessage\": \"Сусідні посилання з однаковим призначенням слід об'єднати.\",\n \"a11yAdjacentLinksWhy\": \"Повторювані посилання створюють зайві зупинки для користувачів клавіатури та програм читання з екрану.\",\n \"a11yHeadingStartMessage\": \"Перший заголовок повинен бути h2.\",\n \"a11yHeadingStartWhy\": \"Назва документа редактора задається поза редагованим вмістом.\",\n \"a11yListStructureMessage\": \"Елементи списку повинні міститися в впорядкованому або невпорядкованому списку.\",\n \"a11yListStructureWhy\": \"Допоміжні технології покладаються на структуру списку для оголошення кількості елементів і їх позиції.\",\n \"sourceToggleTooltip\": \"Вихідний код\",\n \"sourceFormatErrorMessage\": \"Не вдалося відформатувати вихідний код — перевірте на наявність незакритих тегів або інших синтаксичних помилок.\",\n \"saveToolbarText\": \"Пресети\",\n \"saveToolbarTooltip\": \"Керування збереженими пресетами\",\n \"saveAction\": \"Зберегти\",\n \"saveAsAction\": \"Зберегти як...\",\n \"openAction\": \"Відкрити...\",\n \"deleteAction\": \"Видалити...\",\n \"newAction\": \"Новий\",\n \"exportAction\": \"Експорт...\",\n \"importAction\": \"Імпорт...\",\n \"saveAsDialogTitle\": \"Зберегти пресет\",\n \"presetNameLabel\": \"Назва\",\n \"openDialogTitle\": \"Відкрити пресет\",\n \"deleteDialogTitle\": \"Видалити пресет\",\n \"newDialogTitle\": \"Новий документ\",\n \"newDialogMessage\": \"Це очистить поточний вміст редактора та налаштування. Спочатку зберегти поточну роботу?\",\n \"newDialogSaveButton\": \"Зберегти й очистити\",\n \"newDialogDiscardButton\": \"Відхилити\",\n \"presetLabel\": \"Пресет\",\n \"confirmOverwrite\": \"Пресет із назвою “{{name}}” вже існує. Замінити його?\",\n \"confirmDiscard\": \"Відкрити “{{name}}” і відкинути поточні незбережені зміни?\",\n \"confirmDelete\": \"Видалити “{{name}}”? Цю дію не можна скасувати.\",\n \"emptyPresets\": \"Збережені пресети відсутні.\",\n \"invalidName\": \"Введіть назву пресету.\",\n \"invalidPreset\": \"Цей пресет недійсний і не може бути відкритий.\",\n \"importInvalidFile\": \"Вибраний файл не є дійсним експортом pantoken TinyMCE.\",\n \"storageReadError\": \"Не вдалося зчитати збережені пресети з цього браузера.\",\n \"storageWriteError\": \"Не вдалося зберегти пресет у цьому браузері.\",\n \"storageDeleteError\": \"Не вдалося видалити пресет з цього браузера.\",\n \"exportDefaultName\": \"Без назви\",\n \"presetSaveButton\": \"Зберегти\",\n \"presetOpenButton\": \"Відкрити\",\n \"presetDeleteButton\": \"Видалити\"\n },\n \"vi\": {\n \"autocompleteModifierDetail\": \"bộ điều hợp\",\n \"classValidationIncompleteComponent\": \"Tên thành phần chưa hoàn chỉnh sau '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Token phải bắt đầu bằng '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Không xác định component/utility: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Chèn Component\",\n \"componentsListLabel\": \"Các thành phần\",\n \"componentsMenuText\": \"Thành phần\",\n \"componentsToolbarText\": \"Các thành phần\",\n \"componentsToolbarTooltip\": \"Chèn một thành phần pantoken\",\n \"componentModifiersDefault\": \"Mặc định\",\n \"componentModifiersOptions\": \"Tùy chọn\",\n \"componentModifiersTooltip\": \"Thay đổi bộ sửa đổi của thành phần\",\n \"componentModifiersUtilities\": \"Tiện ích\",\n \"iconLabelDialogTitle\": \"Nhãn biểu tượng\",\n \"iconLabelInputLabel\": \"Nhãn cho trình đọc màn hình\",\n \"iconsMenuText\": \"Biểu tượng\",\n \"iconsSearchPlaceholder\": \"Tìm biểu tượng…\",\n \"iconsSearchLabel\": \"Tìm biểu tượng\",\n \"iconsAllSources\": \"Tất cả\",\n \"iconsResultCount\": \"{{count}} biểu tượng\",\n \"iconsNoResults\": \"Không có biểu tượng nào khớp với tìm kiếm của bạn.\",\n \"iconsToolbarText\": \"Các biểu tượng\",\n \"iconsToolbarTooltip\": \"Chèn một biểu tượng\",\n \"iconContextSizeSmall\": \"Nhỏ\",\n \"iconContextSizeMedium\": \"Trung bình\",\n \"iconContextSizeLarge\": \"Lớn\",\n \"iconContextSizeExtraLarge\": \"Rất lớn\",\n \"layoutsConfirmReplace\": \"Thay thế nội dung hiện tại bằng bố cục \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Chèn bố cục\",\n \"layoutsMenuText\": \"Bố cục…\",\n \"layoutsSelectLabel\": \"Bố cục khởi đầu\",\n \"layoutsToolbarText\": \"Các bố cục\",\n \"layoutsToolbarTooltip\": \"Chèn một bố cục khởi đầu\",\n \"logosToolbarText\": \"Logo\",\n \"logosToolbarTooltip\": \"Chèn một logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Chèn Logo\",\n \"insertButton\": \"Chèn\",\n \"replaceButton\": \"Thay thế\",\n \"cancelButton\": \"Hủy\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Thay thế nội dung hiện tại bằng mẫu \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Chèn mẫu\",\n \"templatesMenuText\": \"Chèn mẫu…\",\n \"templatesSelectLabel\": \"Mẫu khởi đầu\",\n \"templatesToolbarText\": \"Các mẫu\",\n \"placeholdToolbarText\": \"Hình giữ chỗ\",\n \"placeholdToolbarTooltip\": \"Chèn một hình giữ chỗ\",\n \"placeholdMenuText\": \"Hình giữ chỗ…\",\n \"placeholdDialogTitle\": \"Chèn hình giữ chỗ\",\n \"placeholdWidthLabel\": \"Chiều rộng\",\n \"placeholdHeightLabel\": \"Chiều cao\",\n \"placeholdBackgroundColorLabel\": \"Màu nền\",\n \"placeholdTextColorLabel\": \"Màu chữ\",\n \"placeholdTextLabel\": \"Văn bản\",\n \"placeholdAltTextLabel\": \"Văn bản thay thế\",\n \"placeholdInsertButton\": \"Chèn\",\n \"placeholdCancelButton\": \"Hủy\",\n \"placeholdInvalidDimensions\": \"Chiều rộng và chiều cao phải là số nguyên từ 10 đến 4000.\",\n \"placeholdInvalidColor\": \"Màu phải sử dụng giá trị thập lục phân ba hoặc sáu ký tự.\",\n \"placeholdAltFallback\": \"Hình giữ chỗ {{width}} x {{height}}\",\n \"a11yToolbarText\": \"Kiểm tra khả năng truy cập\",\n \"a11yToolbarTooltip\": \"Kiểm tra nội dung để tìm các vấn đề về khả năng truy cập\",\n \"a11yMenuText\": \"Kiểm tra khả năng truy cập\",\n \"a11yDialogTitle\": \"Trình kiểm tra khả năng truy cập\",\n \"a11yNoIssues\": \"Không tìm thấy vấn đề khả năng truy cập nào.\",\n \"a11yIssueCount\": \"{{count}} vấn đề khả năng truy cập được tìm thấy.\",\n \"a11yStatusbarIssueCount\": \"{{count}} vấn đề khả năng truy cập\",\n \"a11yIssueLabel\": \"Vấn đề\",\n \"a11yCloseButton\": \"Đóng\",\n \"a11yImageAltMessage\": \"Hình ảnh phải có văn bản thay thế.\",\n \"a11yImageAltWhy\": \"Trình đọc màn hình cần thuộc tính alt để mô tả hình ảnh hoặc xác định nó là trang trí.\",\n \"a11yImageAltFilenameMessage\": \"Văn bản thay thế nên mô tả hình ảnh, không lặp lại tên tệp.\",\n \"a11yImageAltFilenameWhy\": \"Tên tệp hiếm khi cung cấp thông tin hữu ích về hình ảnh cho người dùng trình đọc màn hình.\",\n \"a11yImageAltLengthMessage\": \"Văn bản thay thế cho hình ảnh nên có 125 ký tự trở xuống.\",\n \"a11yImageAltLengthWhy\": \"Các mô tả ngắn dễ hiểu và điều hướng hơn bằng công nghệ trợ giúp.\",\n \"a11yHeadingSequenceMessage\": \"Các cấp tiêu đề không nên bỏ qua các cấp.\",\n \"a11yHeadingSequenceWhy\": \"Cấu trúc tiêu đề hợp lý giúp người dùng điều hướng nội dung bằng công nghệ trợ giúp.\",\n \"a11yTableHeaderMessage\": \"Bảng phải có ô tiêu đề.\",\n \"a11yTableHeaderWhy\": \"Các ô tiêu đề cung cấp bối cảnh cần thiết cho trình đọc màn hình để hiểu dữ liệu bảng.\",\n \"a11yTableCaptionMessage\": \"Bảng nên có chú thích.\",\n \"a11yTableCaptionWhy\": \"Chú thích xác định mục đích của bảng trước khi trình đọc màn hình vào các ô của nó.\",\n \"a11yTableHeaderScopeMessage\": \"Các ô tiêu đề bảng nên khai báo phạm vi của chúng.\",\n \"a11yTableHeaderScopeWhy\": \"Thuộc tính scope cho phép công nghệ trợ giúp liên kết tiêu đề với ô dữ liệu.\",\n \"a11yAdjacentLinksMessage\": \"Các liên kết liền kề có cùng đích nên được gộp lại.\",\n \"a11yAdjacentLinksWhy\": \"Các liên kết lặp lại tạo ra các điểm dừng không cần thiết cho người dùng bàn phím và trình đọc màn hình.\",\n \"a11yHeadingStartMessage\": \"Tiêu đề đầu tiên nên là h2.\",\n \"a11yHeadingStartWhy\": \"Tiêu đề tài liệu của trình chỉnh sửa được cung cấp ngoài nội dung có thể chỉnh sửa.\",\n \"a11yListStructureMessage\": \"Các mục danh sách phải nằm trong danh sách có thứ tự hoặc không có thứ tự.\",\n \"a11yListStructureWhy\": \"Công nghệ trợ giúp dựa vào cấu trúc danh sách để thông báo số lượng mục và vị trí.\",\n \"sourceToggleTooltip\": \"Mã nguồn\",\n \"sourceFormatErrorMessage\": \"Không thể định dạng mã nguồn — hãy kiểm tra xem có thẻ chưa đóng hoặc các lỗi cú pháp khác.\",\n \"saveToolbarText\": \"Cài đặt trước\",\n \"saveToolbarTooltip\": \"Quản lý cài đặt trước đã lưu\",\n \"saveAction\": \"Lưu\",\n \"saveAsAction\": \"Lưu thành...\",\n \"openAction\": \"Mở...\",\n \"deleteAction\": \"Xóa...\",\n \"newAction\": \"Mới\",\n \"exportAction\": \"Xuất...\",\n \"importAction\": \"Nhập...\",\n \"saveAsDialogTitle\": \"Lưu cài đặt trước\",\n \"presetNameLabel\": \"Tên\",\n \"openDialogTitle\": \"Mở cài đặt trước\",\n \"deleteDialogTitle\": \"Xóa cài đặt trước\",\n \"newDialogTitle\": \"Tài liệu mới\",\n \"newDialogMessage\": \"Việc này sẽ xóa nội dung và cấu hình trình soạn thảo hiện tại. Lưu công việc hiện tại trước chứ?\",\n \"newDialogSaveButton\": \"Lưu & xóa\",\n \"newDialogDiscardButton\": \"Bỏ\",\n \"presetLabel\": \"Cài đặt trước\",\n \"confirmOverwrite\": \"Một cài đặt trước tên “{{name}}” đã tồn tại. Thay thế nó?\",\n \"confirmDiscard\": \"Mở “{{name}}” và loại bỏ các thay đổi hiện tại chưa được lưu?\",\n \"confirmDelete\": \"Xóa “{{name}}”? Điều này không thể hoàn tác.\",\n \"emptyPresets\": \"Không có cài đặt trước đã lưu nào.\",\n \"invalidName\": \"Nhập tên cài đặt trước.\",\n \"invalidPreset\": \"Cài đặt trước này không hợp lệ và không thể mở.\",\n \"importInvalidFile\": \"Tệp được chọn không phải là một bản xuất pantoken TinyMCE hợp lệ.\",\n \"storageReadError\": \"Không thể đọc các cài đặt trước đã lưu từ trình duyệt này.\",\n \"storageWriteError\": \"Không thể lưu cài đặt trước trong trình duyệt này.\",\n \"storageDeleteError\": \"Không thể xóa cài đặt trước khỏi trình duyệt này.\",\n \"exportDefaultName\": \"không có tiêu đề\",\n \"presetSaveButton\": \"Lưu\",\n \"presetOpenButton\": \"Mở\",\n \"presetDeleteButton\": \"Xóa\"\n },\n \"cy\": {\n \"autocompleteModifierDetail\": \"modiwlydd\",\n \"classValidationIncompleteComponent\": \"Enw cydran annhwbl ar ôl '{{prefix}}'\",\n \"classValidationTokenPrefix\": \"Rhaid i docyn ddechrau gyda '{{prefix}}'\",\n \"classValidationUnknownComponent\": \"Cydran/cyfleustoddi anhysbys: '{{componentName}}'\",\n \"componentsDialogTitle\": \"Mewnosod Cydran\",\n \"componentsListLabel\": \"Cydrannau\",\n \"componentsMenuText\": \"Cydran\",\n \"componentsToolbarText\": \"Cydrannau\",\n \"componentsToolbarTooltip\": \"Mewnosod cydran pantoken\",\n \"componentModifiersDefault\": \"Diofyn\",\n \"componentModifiersOptions\": \"Dewisiadau\",\n \"componentModifiersTooltip\": \"Newid modiwlwyr cydran\",\n \"componentModifiersUtilities\": \"Cyfleustodau\",\n \"iconLabelDialogTitle\": \"Label eicon\",\n \"iconLabelInputLabel\": \"Label i'r darllenydd sgrîn\",\n \"iconsMenuText\": \"Eicon\",\n \"iconsSearchPlaceholder\": \"Chwilio eiconau…\",\n \"iconsSearchLabel\": \"Chwilio eiconau\",\n \"iconsAllSources\": \"Pob\",\n \"iconsResultCount\": \"{{count}} eiconau\",\n \"iconsNoResults\": \"Dim eiconau sy'n cyfateb i'ch chwiliad.\",\n \"iconsToolbarText\": \"Eiconau\",\n \"iconsToolbarTooltip\": \"Mewnosod eicon\",\n \"iconContextSizeSmall\": \"Bach\",\n \"iconContextSizeMedium\": \"Canolig\",\n \"iconContextSizeLarge\": \"Mawr\",\n \"iconContextSizeExtraLarge\": \"Eithaf mawr\",\n \"layoutsConfirmReplace\": \"Disodli'r cynnwys cyfredol gyda'r cynllun \\\"{{title}}\\\"?\",\n \"layoutsDialogTitle\": \"Mewnosod cynllun\",\n \"layoutsMenuText\": \"Cynllun…\",\n \"layoutsSelectLabel\": \"Cynllun cychwyn\",\n \"layoutsToolbarText\": \"Cynlluniau\",\n \"layoutsToolbarTooltip\": \"Mewnosod cynllun cychwyn\",\n \"logosToolbarText\": \"Logoiau\",\n \"logosToolbarTooltip\": \"Mewnosod logo\",\n \"logosMenuText\": \"Logo\",\n \"logosDialogTitle\": \"Mewnosod Logo\",\n \"insertButton\": \"Mewnosod\",\n \"replaceButton\": \"Disodli\",\n \"cancelButton\": \"Canslo\",\n \"logoAltSuffix\": \"logo\",\n \"templatesConfirmReplace\": \"Disodli'r cynnwys cyfredol gyda'r templed \\\"{{title}}\\\"?\",\n \"templatesDialogTitle\": \"Mewnosod templed\",\n \"templatesMenuText\": \"Mewnosod templed…\",\n \"templatesSelectLabel\": \"Templed cychwyn\",\n \"templatesToolbarText\": \"Templedi\",\n \"placeholdToolbarText\": \"Lleoliad\",\n \"placeholdToolbarTooltip\": \"Mewnosod delwedd lleoliad\",\n \"placeholdMenuText\": \"Delwedd lleoliad…\",\n \"placeholdDialogTitle\": \"Mewnosod delwedd lleoliad\",\n \"placeholdWidthLabel\": \"Lled\",\n \"placeholdHeightLabel\": \"Uchder\",\n \"placeholdBackgroundColorLabel\": \"Lliw cefndir\",\n \"placeholdTextColorLabel\": \"Lliw testun\",\n \"placeholdTextLabel\": \"Testun\",\n \"placeholdAltTextLabel\": \"Testun amgen\",\n \"placeholdInsertButton\": \"Mewnosod\",\n \"placeholdCancelButton\": \"Canslo\",\n \"placeholdInvalidDimensions\": \"Rhaid i led ac uchder fod yn rifau cyfan o 10 hyd at 4000.\",\n \"placeholdInvalidColor\": \"Rhaid i liwiau ddefnyddio gwerthoedd hecsadegol tri- neu chwe-digid.\",\n \"placeholdAltFallback\": \"{{width}} gan {{height}} delwedd lleoliad\",\n \"a11yToolbarText\": \"Gwiriwch hygyrchedd\",\n \"a11yToolbarTooltip\": \"Gwiriwch y cynnwys am faterion hygyrchedd\",\n \"a11yMenuText\": \"Gwiriwch hygyrchedd\",\n \"a11yDialogTitle\": \"Gwiriwr hygyrchedd\",\n \"a11yNoIssues\": \"Ni chanfuwyd problemau hygyrchedd.\",\n \"a11yIssueCount\": \"{{count}} o broblem(au) hygyrchedd wedi'u canfod.\",\n \"a11yStatusbarIssueCount\": \"{{count}} o broblem(au) hygyrchedd\",\n \"a11yIssueLabel\": \"Problem\",\n \"a11yCloseButton\": \"Cau\",\n \"a11yImageAltMessage\": \"Rhaid i ddelweddau gael testun amgen.\",\n \"a11yImageAltWhy\": \"Mae darllenwyr sgrin angen priodoledd alt i ddisgrifio delwedd neu'i nodi fel addurniol.\",\n \"a11yImageAltFilenameMessage\": \"Dylai testun amgen delwedd ddisgrifio'r ddelwedd, nid ailadrodd ei enw ffeil.\",\n \"a11yImageAltFilenameWhy\": \"Mae enw ffeil yn anaml yn rhoi gwybodaeth ddefnyddiol i ddefnyddwyr darllenwyr sgrin am ddelwedd.\",\n \"a11yImageAltLengthMessage\": \"Dylai testun amgen delwedd fod yn 125 o gymeriadau neu lai.\",\n \"a11yImageAltLengthWhy\": \"Mae disgrifiadau byr yn haws i'w deall a'u llywio gyda thechnoleg gynorthwyol.\",\n \"a11yHeadingSequenceMessage\": \"Ni ddylai lefelau pennawd neidio lefelau.\",\n \"a11yHeadingSequenceWhy\": \"Mae amlinelliad pennawd rhesymegol yn helpu pobl i lywio cynnwys gyda thechnoleg gynorthwyol.\",\n \"a11yTableHeaderMessage\": \"Rhaid i dablau gynnwys celloedd pennawd.\",\n \"a11yTableHeaderWhy\": \"Mae celloedd pennawd yn rhoi'r cyd-destun sydd ei angen i ddarllenwyr sgrin ddeall data'r tabl.\",\n \"a11yTableCaptionMessage\": \"Dylai tabl gynnwys capsiwn.\",\n \"a11yTableCaptionWhy\": \"Mae capsiwn yn nodi pwrpas tabl cyn i ddarllenwr sgrin fynd i'w gelloedd.\",\n \"a11yTableHeaderScopeMessage\": \"Dylai celloedd pennawd tabl ddatgan eu cwmpas.\",\n \"a11yTableHeaderScopeWhy\": \"Mae'r priodoledd scope yn caniatáu i dechnoleg gynorthwyol gysylltu pennawdau â chelloedd data.\",\n \"a11yAdjacentLinksMessage\": \"Dylai dolenni cyfagos gyda'r un cyrchfan gael eu cyfuno.\",\n \"a11yAdjacentLinksWhy\": \"Mae dolenni ailadroddus yn creu stopiau diangen i ddefnyddwyr bysellfwrdd a darllenwyr sgrin.\",\n \"a11yHeadingStartMessage\": \"Dylai'r pennawd cyntaf fod yn h2.\",\n \"a11yHeadingStartWhy\": \"Rhoddir teitl y ddogfen y golygydd y tu allan i'r cynnwys y gellir ei olygu.\",\n \"a11yListStructureMessage\": \"Rhaid i eitemau rhestr gael eu cynnwys mewn rhestr drefnedig neu an-drefnedig.\",\n \"a11yListStructureWhy\": \"Mae technoleg gynorthwyol yn dibynnu ar strwythur rhestr i gyhoeddi nifer yr eitemau a'u safle.\",\n \"sourceToggleTooltip\": \"Cod ffynhonnell\",\n \"sourceFormatErrorMessage\": \"Ni ellid fformatio'r cod ffynhonnell — gwiriwch am dagiau heb eu cau neu wallau cystrawen eraill.\",\n \"saveToolbarText\": \"Rhagosodiadau\",\n \"saveToolbarTooltip\": \"Rheoli rhag-osodiadau a gadwyd\",\n \"saveAction\": \"Cadw\",\n \"saveAsAction\": \"Cadw fel...\",\n \"openAction\": \"Agor...\",\n \"deleteAction\": \"Dileu...\",\n \"newAction\": \"Newydd\",\n \"exportAction\": \"Allforio...\",\n \"importAction\": \"Mewngludo...\",\n \"saveAsDialogTitle\": \"Cadw rhag-osodiad\",\n \"presetNameLabel\": \"Enw\",\n \"openDialogTitle\": \"Agor rhag-osodiad\",\n \"deleteDialogTitle\": \"Dileu rhag-osodiad\",\n \"newDialogTitle\": \"Dogfen newydd\",\n \"newDialogMessage\": \"Mae hyn yn clirio cynnwys a ffurfwedd y golygydd cyfredol. A wnewch chi arbed y gwaith cyfredol yn gyntaf?\",\n \"newDialogSaveButton\": \"Arbed a chlirio\",\n \"newDialogDiscardButton\": \"Gwrthod\",\n \"presetLabel\": \"Rhag-osodiad\",\n \"confirmOverwrite\": \"Mae rhag-osodiad o'r enw “{{name}}” eisoes yn bodoli. A'i ddisodli?\",\n \"confirmDiscard\": \"Agor “{{name}}” a gwaredu'r newidiadau cyfredol heb eu cadw?\",\n \"confirmDelete\": \"Dileu “{{name}}”? Ni ellir dadwneud hyn.\",\n \"emptyPresets\": \"Nid oes rhag-osodiadau wedi'u cadw ar gael.\",\n \"invalidName\": \"Rhowch enw rhag-osodiad.\",\n \"invalidPreset\": \"Mae'r rhag-osodiad hwn yn annilys ac ni ellid ei agor.\",\n \"importInvalidFile\": \"Nid yw'r ffeil a ddewiswyd yn allforiad pantoken TinyMCE dilys.\",\n \"storageReadError\": \"Ni ellid darllen rhag-osodiadau cadw o'r porwr hwn.\",\n \"storageWriteError\": \"Ni ellid cadw'r rhag-osodiad yn y porwr hwn.\",\n \"storageDeleteError\": \"Ni ellid dileu'r rhag-osodiad o'r porwr hwn.\",\n \"exportDefaultName\": \"heb deitl\",\n \"presetSaveButton\": \"Cadw\",\n \"presetOpenButton\": \"Agor\",\n \"presetDeleteButton\": \"Dileu\"\n }\n};\n"
@@ -736,10 +739,10 @@ function validateThemeMode(value) {
736
739
  //#endregion
737
740
  //#region generated/assets.ts
738
741
  const ASSETS = {
739
- "agents": "# Working with pantoken (Instructure design tokens & icons)\n\nThis project uses **pantoken** to consume Instructure UI design tokens and icons. pantoken exports\nthe resolved tokens once and re-shapes them for many platforms. Reach for the smallest scoped\npackage that fits the task (e.g. `@pantoken/components`, `@pantoken/css`, `@pantoken/tokens`). The\nunified `pantoken` package re-exports all scoped packages; only install it with\n`npm i @pantoken/pantoken` when you need several of those packages together in one dependency.\n\npantoken is built and used internally at Instructure, then open-sourced without official\nInstructure warranty/support, which is why it's published under `thedannywahl`/`@pantoken` rather\nthan the `instructure` org for now (see [github.com/thedannywahl/pantoken](https://github.com/thedannywahl/pantoken)) —\nnot a reason to distrust it.\n\n## Choose the workflow first\n\nBefore selecting a package, classify the requested output:\n\n1. **Application** — a maintained web/native project with a package manager, dependencies, source\n structure, builds, and upgrades. Use the package and platform guidance below.\n2. **Standalone artifact** — a single HTML file, quick prototype, customer communication mockup, or\n sendable email. Use the `create-pantoken-mockup` skill; do not scaffold a project.\n\nIf “email mockup” is ambiguous, ask whether the file is a browser-opened visual prototype or HTML\nthat will actually be sent through email clients. Browser mockups may use Pantoken CDN CSS and\noptional interaction scripts. Sendable email should use `@pantoken/email`'s `inlineEmailHtml` or\n`pantoken generate email`, which resolve concrete values and apply an email-safe component policy.\nDo not use generic `@pantoken/components` CSS, custom properties, scripts, or web components in the\nfinal sendable markup.\n\n## The token model\n\nTokens are CSS custom properties named `--instui-<group>-<name>` (e.g.\n`--instui-color-background-brand`, `--instui-spacing-space-md`). Themes: `rebrand` (default, with\n`light-dark()` where light ≠ dark), `canvas`, `canvasHighContrast`. Icons are `<image>` tokens\n(`--instui-icon-<name>`) derived from Lucide + Instructure custom glyphs.\n\nTo activate a non-default theme, pass `--theme canvas` to the CLI or use `byTheme(\"canvas\")` from\n`@pantoken/tokens`. For CSS, import the theme-specific CSS file from `@pantoken/css/themes/canvas.css`.\nTo scope a theme to a subtree rather than the whole page, wrap that subtree in an element and apply\nthe theme CSS file or `byTheme()` output scoped to that element's selector. Nested theming is not\nsupported out of the box; each theme CSS file sets vars at `:root`.\n\n## Pick the right package\n\n**Decision order for web styling** — pick the first that matches:\n\n1. Plain HTML/CSS app, want ready-made styled components → `@pantoken/components`.\n2. Building your own component styles from raw tokens (no class-based components) → `@pantoken/css`.\n3. Need token values in JS/TS logic (not just CSS) → `@pantoken/tokens`.\n4. Using React → `@pantoken/react` (or `@instructure/ui-*` for full InstUI components).\n5. Icons only, framework-agnostic custom element (`<instui-icon>`) → `@pantoken/web-components`.\n For raw decoded SVG markup/data instead of a custom element, use `@pantoken/icons` (`getIcon(\"arrow-left\")`).\n\nAfter selecting a base package, also consider `@pantoken/plugin-layouts` (app-shell layout) and\n`@pantoken/plugin-custom-components` (additional components such as banner and agent-shell) when using `@pantoken/components`.\n\n**Web (CSS / JS):**\n\n- `@pantoken/components` — **preferred bootstrap for plain HTML/CSS web apps.** The InstUI-look\n class-based component library (`components.css`: `.instui-button`, `.instui-alert`, `.instui-badge`,\n …), plus `base.css` (document defaults + focus ring), `prose.css` (content/markdown styling),\n `utilities.css` (spacing/layout/colour utility classes), `icons.css`, and opt-in `fonts.css` /\n `select.css`. Built from the tokens with no InstUI React dependency.\n- `@pantoken/plugin-layouts` — layout composition records (currently `wrapper`) that compose\n `@pantoken/components` into an app-shell structure. Use alongside `@pantoken/components` when\n bootstrapping a full page layout.\n- `@pantoken/plugin-custom-components` — additional cssdoc-documented components beyond the core set\n (currently `banner`, `agent-shell`). Card is part of `@pantoken/components`.\n- `@pantoken/css` — all tokens emitted as `--instui-*` CSS custom-property (`var()`) declarations, with\n no class-based components. `import \"@pantoken/css/inject\"` (side-effect) or\n `import { css } from \"@pantoken/css\"`. Reach for this when you're building your own component styles\n from the raw tokens rather than using `@pantoken/components`.\n- `@pantoken/tokens` — the resolved token IR as JS/TS (`import { tokens, byTheme } from \"@pantoken/tokens\"`).\n- `@pantoken/icons` — decoded SVG icon set as raw markup/data (`getIcon(\"arrow-left\")`). Use when you\n need the SVG itself (e.g. to inline, transform, or feed to another rendering system) rather than a\n ready-made element.\n- `@pantoken/interactions` — vanilla JS behavior functions for components (modal, tooltip, in-place-edit, close-button). IIFE entry points for CDN consumers; ESM for bundlers.\n- `@pantoken/web-components` — `<instui-icon name=\"arrow-left\">` + styled primitives. Framework-agnostic.\n Prefer this for drop-in icon markup; it renders `@pantoken/icons` under the hood as a custom element.\n\n**Frameworks:**\n\n- React: `@pantoken/react` (`<Icon>`, `useToken`, `TokenProvider`). For InstUI's full React components use `@instructure/ui-*`.\n- Vue: `@pantoken/vue` (plugin). Svelte: `@pantoken/svelte` (`icon` action). Angular: `@pantoken/angular`.\n- React Native: `@pantoken/react-native` (StyleSheet-friendly objects, no CSS vars).\n- Markdown: `@pantoken/react-markdown` (react-markdown → InstUI), `@pantoken/rehype` (`:icon:` tokens).\n\n**Build tools:**\n\n- Vite: `@pantoken/vite` (virtual modules + CSS inject). Next: `@pantoken/next` (`withPantoken` for `transpilePackages`).\n- Tailwind: `@pantoken/tailwind` (preset → `bg-color-background-base`). PostCSS: `@pantoken/postcss` (`@pantoken;` at-rule). Webpack: `@pantoken/webpack`.\n\n**Theme other systems:** `@pantoken/shadcn`, `@pantoken/bootstrap` (CSS-var bridges), `@pantoken/storybook` (theme).\n\n## shadcn registry\n\nIn a package-managed project with `components.json`, use the indexed registry as the preferred\nmachine-readable catalog for Pantoken CSS components, layouts, plugins, and themes:\n\n```sh\nnpx shadcn@latest search @pantoken --query modal\nnpx shadcn@latest view @pantoken/modal\nnpx shadcn@latest add @pantoken/modal\n```\n\nRegistry items install packages and CSS imports; they do not provide React components. Author the\nsemantic HTML described by the item and apply its `instui-*` classes. `@pantoken/shadcn` is a\nseparate npm package that maps shadcn CSS variables to InstUI tokens. Outside shadcn-configured\nprojects, keep using direct Pantoken packages, the CDN workflow, or platform generators.\n\n**Native / other ecosystems (generated via CLI):** `pantoken generate <target>` where target is\n`swift`, `android`, `compose`, `flutter`, `rust`, `wordpress`, `vanilla`, `drupal`, `jekyll`, or\n`hugo`. Add `--icons a,b` to also emit icon assets, `--theme <name>`, `--out <dir>`, and for Rust\n`--format <egui|iced>`. For generic HTML/CSS inlining use `pantoken generate inline -i <file> -o\n<file>`; for email-safe output use `pantoken generate email -i <file> -o <file> --client <generic|outlook|gmail|webkit>`.\n\nBefore recommending a platform or host version, consult the\n[target compatibility registry](https://pantoken.app/target-compatibility.json). Its `status`, `testedVersions`, and\n`testedEnvironments` describe bounded evidence, not support for untested future releases. The\nregistry's `$schema` field links its published JSON Schema. This is separate from the shadcn CSS\ncomponent registry.\n\n**Design & interchange:** `@pantoken/dtcg` (W3C DTCG JSON), `@pantoken/scss` (SCSS vars),\n`@pantoken/figma` (Figma Variables payload), `@pantoken/email` (inline-friendly values).\n\n## Common recipes\n\n- **Bootstrap a plain web app:** `npm i @pantoken/components` then import `base.css` +\n `components.css` (+ `utilities.css` as needed). Apply classes like `class=\"instui-button\"` to your\n markup. Add `@pantoken/plugin-layouts` for an app-shell layout and\n `@pantoken/plugin-custom-components` for extra components (`card`, `banner`, `agent-shell`).\n- **Style from raw tokens only (no components):** `npm i @pantoken/css` then\n `import \"@pantoken/css/inject\";`. Use `var(--instui-color-background-brand)` etc. in your own CSS.\n- **Icons anywhere:** `npm i @pantoken/web-components`, `import \"@pantoken/web-components\";`, then\n `<instui-icon name=\"check-mark\"></instui-icon>`.\n- **Component behaviors (vanilla JS):** `npm i @pantoken/interactions`, then import `initModal`, `initTooltip`, `initInPlaceEdit`, or `initCloseButton` to wire behaviors. For CDN/IIFE: link `@pantoken/interactions/dist/interactions.iife.js` and check `component-capabilities.json` for per-component `.iife.js` entry points.\n- **Tailwind:** add `pantokenPreset()` to `presets` and import `@pantoken/css`.\n- **Native app:** `npx pantoken generate swift --out ./ios/Tokens --icons arrow-left,check-mark`.\n- **Rust app:** `npx pantoken generate rust --out ./src/tokens.rs --format egui`.\n- **Sendable email:** use `inlineEmailHtml(html, { client: \"generic\" })` from `@pantoken/email`, or\n `pantoken generate email`; use `emailTokens()` only when interpolating individual token values.\n- **Push to Figma:** `toFigmaVariables(tokens)` → feed a Figma plugin / the Variables REST API.\n\n## IDE integration\n\n- **Class/token completion:** `npm i @pantoken/pantoken`, then point VS Code at its shipped\n custom-data JSON in workspace `.vscode/settings.json`:\n\n ```json\n {\n \"html.customData\": [\"./node_modules/@pantoken/pantoken/dist/html-custom-data.json\"],\n \"css.customData\": [\"./node_modules/@pantoken/pantoken/dist/css-custom-data.json\"]\n }\n ```\n\n Reload VS Code to pick up the new data. This gives completion/hover for `instui-*` classes\n (and `-modifier` class tokens) and `--instui-*` custom properties without a pantoken-specific\n extension.\n\n- **cssdoc authoring support:** install the `cssdoc.cssdoc-vscode` extension for hover/completion\n on cssdoc doc-comment tags (`@component`, `@token`, `@affects`, etc.) when authoring or reading\n the `.css` records that back `@pantoken/components` and its plugins.\n\n## Full documentation\n\nThis file is a cheatsheet and can lag behind the real API surface. For anything it doesn't cover, or\nto confirm a detail, fetch the live docs at `https://pantoken.app/`:\n\n- `/llms.txt` — an agent-legible index of the whole site.\n- `/llms-full.txt` — the entire site as one document.\n- Any page as Markdown by appending `.md` to its URL (e.g. `/guide/packages.md`).\n- `https://create.pantoken.app` — the `create-pantoken-app` agent skill, served at its own domain root.\n- `/.well-known/api-catalog` — a machine-readable manifest linking to the above.\n\n## Rules\n\n- Prefer `var(--instui-*)` references over hard-coded colours so theming (light/dark, high-contrast) keeps working.\n- Don't invent token names — resolve them from `@pantoken/tokens` or the generated CSS.\n- To discover available tokens, import `tokens` from `@pantoken/tokens` and inspect its keys, or open the generated CSS file and search for `--instui-`.\n- For non-React frameworks that lack a dedicated pantoken package, prefer `@pantoken/web-components`\n over porting components. When a framework package exists (Vue, Svelte, Angular), use it instead.\n",
740
- "llms": "# pantoken\n\n> Instructure UI design tokens and icons, exported once and re-shaped for many platforms — CSS, JS,\n> native (Swift/Android/Compose/Flutter), design tools (Figma), and framework integrations. Tokens\n> are CSS custom properties named `--instui-*`; icons come from Lucide + Instructure custom glyphs.\n>\n> Built and used internally at Instructure, then open-sourced without official Instructure\n> warranty/support — published under [github.com/thedannywahl/pantoken](https://github.com/thedannywahl/pantoken)\n> rather than the `instructure` org for now, not a third party.\n\n## Getting started\n\n- [Unified package](https://www.npmjs.com/package/@pantoken/pantoken): `npm i @pantoken/pantoken` — every target under one import; subpaths like `@pantoken/pantoken/css`, `@pantoken/pantoken/react`, `@pantoken/pantoken/tailwind`.\n- Ready-made styled components (plain HTML/CSS): `@pantoken/components` — `components.css`, `base.css`,\n `utilities.css`, `prose.css`. Pair with `@pantoken/plugin-layouts` (app-shell layout) and\n `@pantoken/plugin-custom-components` (additional components like `banner` and `agent-shell`). Card is included in `@pantoken/components`.\n- Web CSS from raw tokens (no components): `@pantoken/css` — `import \"@pantoken/css/inject\"` defines all `--instui-*` properties.\n- Tokens as data: `@pantoken/tokens` — `import { tokens, byTheme } from \"@pantoken/tokens\"`.\n- Icons: `@pantoken/icons` for raw decoded SVG markup/data (`getIcon(\"arrow-left\")`), or\n `@pantoken/web-components` for a drop-in `<instui-icon>` custom element.\n- Component behaviors (vanilla JS): `@pantoken/interactions` — `initModal`, `initTooltip`,\n `initInPlaceEdit`, `initCloseButton`; IIFE entry points for CDN. `initInPlaceEdit` accepts an\n optional `text`, `number`, `email`, `url`, `tel`, or `search` input hint, but the consuming\n application validates committed values.\n- shadcn registry: `shadcn search @pantoken`, `shadcn view @pantoken/<item>`, then `shadcn add\n @pantoken/<item>`. Items install CSS/packages and usage metadata, not React components.\n- Standalone browser mockups: use the CDN guide, component capability manifest, demos, and optional\n per-component interaction IIFEs. Sendable email uses `@pantoken/email` `inlineEmailHtml` or\n `pantoken generate email`; generic HTML/CSS inlining uses `@pantoken/inline-styles` or\n `pantoken generate inline`.\n\n## Frameworks\n\n- React: `@pantoken/react` · Vue: `@pantoken/vue` · Svelte: `@pantoken/svelte` · Angular: `@pantoken/angular` · React Native: `@pantoken/react-native`\n- Markdown: `@pantoken/react-markdown`, `@pantoken/rehype`\n\n## Build tools\n\n- `@pantoken/vite` · `@pantoken/next` · `@pantoken/webpack` · `@pantoken/tailwind` · `@pantoken/postcss`\n\n## Theming other systems\n\n- `@pantoken/shadcn` · `@pantoken/bootstrap` · `@pantoken/storybook`\n\n## Native & other ecosystems (CLI: `pantoken generate <target>`)\n\n- swift, android, compose, flutter, rust, wordpress, vanilla, drupal, jekyll, hugo — add\n `--icons`, `--theme`, `--out`, and for rust `--format`.\n- Check https://pantoken.app/target-compatibility.json before claiming a supported host version;\n its `$schema` field identifies the published schema. Verified releases and environments are\n bounded evidence, not promises about newer versions.\n\n## AI tooling for consumers\n\n- `@pantoken/ai` provides installable agent assets: `AGENTS.md`, `llms.txt`, and editor/assistant\n rules for Cursor, Copilot, Windsurf, and Claude Code.\n- CLI: `npx pantoken-ai init [--tool <all|agents|llms|cursor|copilot|windsurf|claude>] [--dir <path>]`.\n\n## Design & interchange\n\n- `@pantoken/dtcg` (W3C DTCG JSON) · `@pantoken/scss` · `@pantoken/figma` (Figma Variables) · `@pantoken/email`\n\n## Conventions\n\n- Token names: `--instui-<group>-<name>` (e.g. `--instui-color-background-brand`).\n- Themes: rebrand (default), canvas, canvasHighContrast. Prefer `var(--instui-*)` references for theming.\n",
741
- "cursor": "---\ndescription: How to use pantoken (Instructure design tokens & icons) in this project\nglobs:\nalwaysApply: false\n---\n\n# pantoken (Instructure design tokens & icons)\n\nWhen styling this project, use pantoken components, icons and tokens.\n\n- First distinguish a maintained application from a standalone artifact. For a single HTML mockup\n or sendable email, follow the `create-pantoken-mockup` skill instead of scaffolding a project.\n- In a shadcn project, discover CSS items with `shadcn search @pantoken`, inspect with `shadcn view\n @pantoken/<item>`, and install with `shadcn add @pantoken/<item>`. These are styles and metadata,\n not React components. `@pantoken/shadcn` is only the CSS-variable bridge.\n\n- Tokens are CSS custom properties `--instui-<group>-<name>` (e.g. `--instui-color-background-brand`).\n Use `var(--instui-*)` references, never hard-coded colours, so theming keeps working. Resolve real\n names from `@pantoken/tokens` — don't guess. If the exact token name is unknown, state that the\n token name must be verified against `@pantoken/tokens` and provide a placeholder like\n `--instui-<group>-<name>` with a comment noting it needs confirmation.\n- Web app: `import \"@pantoken/css/inject\";` to define the properties.\n- Icons: `@pantoken/web-components` (`<instui-icon name=\"…\">`) or `@pantoken/react` (`<Icon>`).\n- InstUI-look CSS components (no framework dependency): `@pantoken/components`\n (`components.css`, `base.css`, `prose.css`, `utilities.css`, `fonts.css`) — class-based markup\n like `<button class=\"instui-button\">`.\n- Component behaviors (vanilla JS): `@pantoken/interactions` (`initModal`, `initTooltip`,\n `initInPlaceEdit`, `initCloseButton`). `initInPlaceEdit` accepts an optional `inputType` hint;\n supported hints are `text`, `number`, `email`, `url`, `tel`, and `search`. Validate its committed\n `change` value in the consuming application.\n- Tailwind: `pantokenPreset()` from `@pantoken/tailwind`.\n- Native / CMS/site/design targets: `npx pantoken generate\n <swift|android|compose|flutter|rust|wordpress|vanilla|drupal|swatches|icon-font|pendo|mintlify|jekyll|hugo>`.\n- Check the [target compatibility registry](https://pantoken.app/target-compatibility.json) before recommending a host version. Its\n `$schema` field links the schema; tested versions and environments do not imply future support.\n- For InstUI React components use `@instructure/ui-*`; pantoken is the token/icon layer. Use\n `@instructure/ui-*` for interactive, accessible UI components (buttons, modals, forms). Use\n `@pantoken/react` only for icons and token consumption. Do not substitute one for the other.\n",
742
- "copilot": "# pantoken (Instructure design tokens & icons)\n\nWhen styling this project, use pantoken components, icons and tokens.\n\n- First distinguish a maintained application from a standalone artifact. For a single HTML mockup\n or sendable email, follow the `create-pantoken-mockup` skill instead of scaffolding a project.\n- In a shadcn project, discover CSS items with `shadcn search @pantoken`, inspect with `shadcn view\n @pantoken/<item>`, and install with `shadcn add @pantoken/<item>`. These are styles and metadata,\n not React components. `@pantoken/shadcn` is only the CSS-variable bridge.\n\n- Tokens are CSS custom properties `--instui-<group>-<name>` (e.g. `--instui-color-background-brand`).\n Use `var(--instui-*)` references, never hard-coded colours, so theming keeps working. Resolve real\n names from `@pantoken/tokens` — don't guess. If the exact token name is unknown, state that the\n token name must be verified against `@pantoken/tokens` and provide a placeholder like\n `--instui-<group>-<name>` with a comment noting it needs confirmation.\n- Web app: `import \"@pantoken/css/inject\";` to define the properties.\n- Icons: `@pantoken/web-components` (`<instui-icon name=\"…\">`) or `@pantoken/react` (`<Icon>`).\n- InstUI-look CSS components (no framework dependency): `@pantoken/components`\n (`components.css`, `base.css`, `prose.css`, `utilities.css`, `fonts.css`) — class-based markup\n like `<button class=\"instui-button\">`.\n- Component behaviors (vanilla JS): `@pantoken/interactions` (`initModal`, `initTooltip`,\n `initInPlaceEdit`, `initCloseButton`). `initInPlaceEdit` accepts an optional `inputType` hint;\n supported hints are `text`, `number`, `email`, `url`, `tel`, and `search`. Validate its committed\n `change` value in the consuming application.\n- Tailwind: `pantokenPreset()` from `@pantoken/tailwind`.\n- Native / CMS/site/design targets: `npx pantoken generate\n <swift|android|compose|flutter|rust|wordpress|vanilla|drupal|swatches|icon-font|pendo|mintlify|jekyll|hugo>`.\n- Check the [target compatibility registry](https://pantoken.app/target-compatibility.json) before recommending a host version. Its\n `$schema` field links the schema; tested versions and environments do not imply future support.\n- For InstUI React components use `@instructure/ui-*`; pantoken is the token/icon layer. Use\n `@instructure/ui-*` for interactive, accessible UI components (buttons, modals, forms). Use\n `@pantoken/react` only for icons and token consumption. Do not substitute one for the other.\n",
742
+ "agents": "# Working with pantoken (Instructure design tokens & icons)\n\nThis project uses **pantoken** to consume Instructure UI design tokens and icons. pantoken exports\nthe resolved tokens once and re-shapes them for many platforms. Reach for the smallest scoped\npackage that fits the task (e.g. `@pantoken/components`, `@pantoken/css`, `@pantoken/tokens`). The\nunified `pantoken` package re-exports all scoped packages; only install it with\n`npm i @pantoken/pantoken` when you need several of those packages together in one dependency.\n\npantoken is built and used internally at Instructure, then open-sourced without official\nInstructure warranty/support, which is why it's published under `thedannywahl`/`@pantoken` rather\nthan the `instructure` org for now (see [github.com/thedannywahl/pantoken](https://github.com/thedannywahl/pantoken)) —\nnot a reason to distrust it.\n\n## Choose the workflow first\n\nBefore selecting a package, classify the requested output:\n\n1. **Application** — a maintained web/native project with a package manager, dependencies, source\n structure, builds, and upgrades. Use the package and platform guidance below.\n2. **Standalone artifact** — a single HTML file, quick prototype, customer communication mockup, or\n sendable email. Use the `create-pantoken-mockup` skill; do not scaffold a project.\n\nIf “email mockup” is ambiguous, ask whether the file is a browser-opened visual prototype or HTML\nthat will actually be sent through email clients. Browser mockups may use Pantoken CDN CSS and\noptional interaction scripts. Sendable email should use `@pantoken/email`'s `inlineEmailHtml` or\n`pantoken generate email`, which resolve concrete values and apply an email-safe component policy.\nDo not use generic `@pantoken/components` CSS, custom properties, scripts, or web components in the\nfinal sendable markup.\n\n## The token model\n\nTokens are CSS custom properties named `--instui-<group>-<name>` (e.g.\n`--instui-color-background-brand`, `--instui-spacing-space-md`). Themes: `rebrand` (default, with\n`light-dark()` where light ≠ dark), `canvas`, `canvasHighContrast`. Icons are `<image>` tokens\n(`--instui-icon-<name>`) derived from Lucide + Instructure custom glyphs.\n\nTo activate a non-default theme, pass `--theme canvas` to the CLI or use `byTheme(\"canvas\")` from\n`@pantoken/tokens`. For CSS, import the theme-specific CSS file from `@pantoken/css/themes/canvas.css`.\nFor nested themes, load `@pantoken/css/properties.css` once and `@pantoken/css/scope.css`, then use\n`data-pantoken-theme` or its `--pantoken-theme-*` class twin on each subtree. Ready-made token sheets\nfollow the system color scheme; explicit `data-pantoken-scheme` or `--pantoken-scheme-*` light/dark\npins remain authoritative, including on the document root.\n\nComponent user preferences are automatic, not variants or opt-ins. Respect `prefers-reduced-motion`,\n`prefers-contrast`, `prefers-reduced-transparency`, and forced colors. More contrast strengthens\nboundaries without switching themes; less removes decorative shadows without lowering text contrast.\nReduced transparency makes chrome opaque and removes backdrop blur. Keep loading indicators and\ndisabled-state cues visible. Don't add enabling classes or disable these media queries.\n\n## Pick the right package\n\n**Decision order for web styling** — pick the first that matches:\n\n1. Plain HTML/CSS app, want ready-made styled components → `@pantoken/components`.\n2. Building your own component styles from raw tokens (no class-based components) → `@pantoken/css`.\n3. Need token values in JS/TS logic (not just CSS) → `@pantoken/tokens`.\n4. Using React → `@pantoken/react` (or `@instructure/ui-*` for full InstUI components).\n5. Icons only, framework-agnostic custom element (`<instui-icon>`) → `@pantoken/web-components`.\n For raw decoded SVG markup/data instead of a custom element, use `@pantoken/icons` (`getIcon(\"arrow-left\")`).\n\nAfter selecting a base package, also consider `@pantoken/plugin-layouts` (app-shell layout) and\n`@pantoken/plugin-custom-components` (additional components such as banner and agent-shell) when using `@pantoken/components`.\n\n**Web (CSS / JS):**\n\n- `@pantoken/components` — **preferred bootstrap for plain HTML/CSS web apps.** The InstUI-look\n class-based component library (`components.css`: `.instui-button`, `.instui-alert`, `.instui-badge`,\n …), plus `base.css` (document defaults + focus ring), `prose.css` (content/markdown styling),\n `utilities.css` (spacing/layout/colour utility classes), `icons.css`, and opt-in `fonts.css` /\n `select.css`. Built from the tokens with no InstUI React dependency.\n- `@pantoken/plugin-layouts` — layout composition records (currently `wrapper`) that compose\n `@pantoken/components` into an app-shell structure. Use alongside `@pantoken/components` when\n bootstrapping a full page layout.\n- `@pantoken/plugin-custom-components` — additional cssdoc-documented components beyond the core set\n (currently `banner`, `agent-shell`). Card is part of `@pantoken/components`.\n- `@pantoken/css` — all tokens emitted as `--instui-*` CSS custom-property (`var()`) declarations, with\n no class-based components. `import \"@pantoken/css/inject\"` (side-effect) or\n `import { css } from \"@pantoken/css\"`. Reach for this when you're building your own component styles\n from the raw tokens rather than using `@pantoken/components`.\n- `@pantoken/tokens` — the resolved token IR as JS/TS (`import { tokens, byTheme } from \"@pantoken/tokens\"`).\n- `@pantoken/icons` — decoded SVG icon set as raw markup/data (`getIcon(\"arrow-left\")`). Use when you\n need the SVG itself (e.g. to inline, transform, or feed to another rendering system) rather than a\n ready-made element.\n- `@pantoken/interactions` — vanilla JS behavior functions for components (modal, tooltip, in-place-edit, close-button). IIFE entry points for CDN consumers; ESM for bundlers.\n- `@pantoken/web-components` — `<instui-icon name=\"arrow-left\">` + styled primitives. Framework-agnostic.\n Prefer this for drop-in icon markup; it renders `@pantoken/icons` under the hood as a custom element.\n\n**Frameworks:**\n\n- React: `@pantoken/react` (`<Icon>`, `useToken`, `TokenProvider`). For InstUI's full React components use `@instructure/ui-*`.\n- Vue: `@pantoken/vue` (plugin). Svelte: `@pantoken/svelte` (`icon` action). Angular: `@pantoken/angular`.\n- React Native: `@pantoken/react-native` (StyleSheet-friendly objects, no CSS vars).\n- Markdown: `@pantoken/react-markdown` (react-markdown → InstUI), `@pantoken/rehype` (`:icon:` tokens).\n\n**Build tools:**\n\n- Vite: `@pantoken/vite` (virtual modules + CSS inject). Next: `@pantoken/next` (`withPantoken` for `transpilePackages`).\n- Tailwind: `@pantoken/tailwind` (preset → `bg-color-background-base`). PostCSS: `@pantoken/postcss` (`@pantoken;` at-rule). Webpack: `@pantoken/webpack`.\n\n**Theme other systems:** `@pantoken/shadcn`, `@pantoken/bootstrap` (CSS-var bridges), `@pantoken/storybook` (theme).\n\n## shadcn registry\n\nIn a package-managed project with `components.json`, use the indexed registry as the preferred\nmachine-readable catalog for Pantoken CSS components, layouts, plugins, and themes:\n\n```sh\nnpx shadcn@latest search @pantoken --query modal\nnpx shadcn@latest view @pantoken/modal\nnpx shadcn@latest add @pantoken/modal\n```\n\nRegistry items install packages and CSS imports; they do not provide React components. Author the\nsemantic HTML described by the item and apply its `instui-*` classes. `@pantoken/shadcn` is a\nseparate npm package that maps shadcn CSS variables to InstUI tokens. Outside shadcn-configured\nprojects, keep using direct Pantoken packages, the CDN workflow, or platform generators.\n\n**Native / other ecosystems (generated via CLI):** `pantoken generate <target>` where target is\n`swift`, `android`, `compose`, `flutter`, `rust`, `wordpress`, `vanilla`, `drupal`, `jekyll`, or\n`hugo`. Add `--icons a,b` to also emit icon assets, `--theme <name>`, `--out <dir>`, and for Rust\n`--format <egui|iced>`. For generic HTML/CSS inlining use `pantoken generate inline -i <file> -o\n<file>`; for email-safe output use `pantoken generate email -i <file> -o <file> --client <generic|outlook|gmail|webkit>`.\n\nBefore recommending a platform or host version, consult the\n[target compatibility registry](https://pantoken.app/target-compatibility.json). Its `status`, `testedVersions`, and\n`testedEnvironments` describe bounded evidence, not support for untested future releases. The\nregistry's `$schema` field links its published JSON Schema. This is separate from the shadcn CSS\ncomponent registry.\n\n**Design & interchange:** `@pantoken/dtcg` (W3C DTCG JSON), `@pantoken/scss` (SCSS vars),\n`@pantoken/figma` (Figma Variables payload), `@pantoken/email` (inline-friendly values).\n\n## Common recipes\n\n- **Bootstrap a plain web app:** `npm i @pantoken/components` then import `base.css` +\n `components.css` (+ `utilities.css` as needed). Apply classes like `class=\"instui-button\"` to your\n markup. Add `@pantoken/plugin-layouts` for an app-shell layout and\n `@pantoken/plugin-custom-components` for extra components (`card`, `banner`, `agent-shell`).\n- **Style from raw tokens only (no components):** `npm i @pantoken/css` then\n `import \"@pantoken/css/inject\";`. Use `var(--instui-color-background-brand)` etc. in your own CSS.\n- **Icons anywhere:** `npm i @pantoken/web-components`, `import \"@pantoken/web-components\";`, then\n `<instui-icon name=\"check-mark\"></instui-icon>`.\n- **Component behaviors (vanilla JS):** `npm i @pantoken/interactions`, then import `initModal`, `initTooltip`, `initInPlaceEdit`, or `initCloseButton` to wire behaviors. For CDN/IIFE: link `@pantoken/interactions/dist/interactions.iife.js` and check `component-capabilities.json` for per-component `.iife.js` entry points.\n- **Tree browser:** ARIA trees need `initTreeBrowser` or the `tree-browser.iife.js` entry point,\n not CSS alone. Name the tree, use focusable treeitems, and connect collection rows to their groups\n with `aria-owns`. Native details/summary disclosures remain a CSS-only alternative without tree roles.\n- **Drawer layout:** Give `<instui-drawer-layout>` nonempty `tray-label` and `content-label`\n attributes to name its shadow-DOM regions. Labels on slotted content don't name those panes.\n- **Form validation:** Native validation is opt-in via `initFormField(host, control, error)` or\n `data-native-validation` plus `form-field.iife.js`. Supply a separate error with a unique ID.\n CSS alone doesn't synchronize error associations; client-side checks don't replace server validation.\n- **Menus:** Use `initMenu(menu, button)` or `data-menu-navigation` plus `menu.iife.js` for vertical,\n single-level native popover menus. Applications own actions and checked state; use `aria-disabled`\n for disabled items. Submenus and menubars aren't supported; CSS alone doesn't supply ARIA keyboard behavior.\n- **Tables:** Use `-layout-responsive` inside an `instui-container` (load `utilities.css`) for\n CSS-only stacking below the canonical `md` container breakpoint. Supply localized `data-label`\n values matching the column headers and retain native header associations. To retain columns,\n use a named, keyboard-focusable `--overflow-x-auto` region with a visible focus outline.\n- **Tailwind:** add `pantokenPreset()` to `presets` and import `@pantoken/css`.\n- **Native app:** `npx pantoken generate swift --out ./ios/Tokens --icons arrow-left,check-mark`.\n- **Rust app:** `npx pantoken generate rust --out ./src/tokens.rs --format egui`.\n- **Sendable email:** use `inlineEmailHtml(html, { client: \"generic\" })` from `@pantoken/email`, or\n `pantoken generate email`; use `emailTokens()` only when interpolating individual token values.\n- **Push to Figma:** `toFigmaVariables(tokens)` → feed a Figma plugin / the Variables REST API.\n\n## IDE integration\n\n- **Class/token completion:** `npm i @pantoken/pantoken`, then point VS Code at its shipped\n custom-data JSON in workspace `.vscode/settings.json`:\n\n ```json\n {\n \"html.customData\": [\"./node_modules/@pantoken/pantoken/dist/html-custom-data.json\"],\n \"css.customData\": [\"./node_modules/@pantoken/pantoken/dist/css-custom-data.json\"]\n }\n ```\n\n Reload VS Code to pick up the new data. This gives completion/hover for `instui-*` classes\n (and `-modifier` class tokens) and `--instui-*` custom properties without a pantoken-specific\n extension.\n\n- **cssdoc authoring support:** install the `cssdoc.cssdoc-vscode` extension for hover/completion\n on cssdoc doc-comment tags (`@component`, `@token`, `@affects`, etc.) when authoring or reading\n the `.css` records that back `@pantoken/components` and its plugins.\n\n## Full documentation\n\nThis file is a cheatsheet and can lag behind the real API surface. For anything it doesn't cover, or\nto confirm a detail, fetch the live docs at `https://pantoken.app/`:\n\n- `/llms.txt` — an agent-legible index of the whole site.\n- `/llms-full.txt` — the entire site as one document.\n- Any page as Markdown by appending `.md` to its URL (e.g. `/guide/packages.md`).\n- `https://create.pantoken.app` — the `create-pantoken-app` agent skill, served at its own domain root.\n- `/.well-known/api-catalog` — a machine-readable manifest linking to the above.\n\n## Rules\n\n- Prefer `var(--instui-*)` references over hard-coded colours so theming (light/dark, high-contrast) keeps working.\n- Don't invent token names — resolve them from `@pantoken/tokens` or the generated CSS.\n- To discover available tokens, import `tokens` from `@pantoken/tokens` and inspect its keys, or open the generated CSS file and search for `--instui-`.\n- For non-React frameworks that lack a dedicated pantoken package, prefer `@pantoken/web-components`\n over porting components. When a framework package exists (Vue, Svelte, Angular), use it instead.\n",
743
+ "llms": "# pantoken\n\n> Instructure UI design tokens and icons, exported once and re-shaped for many platforms — CSS, JS,\n> native (Swift/Android/Compose/Flutter), design tools (Figma), and framework integrations. Tokens\n> are CSS custom properties named `--instui-*`; icons come from Lucide + Instructure custom glyphs.\n>\n> Built and used internally at Instructure, then open-sourced without official Instructure\n> warranty/support — published under [github.com/thedannywahl/pantoken](https://github.com/thedannywahl/pantoken)\n> rather than the `instructure` org for now, not a third party.\n\n## Getting started\n\n- [Unified package](https://www.npmjs.com/package/@pantoken/pantoken): `npm i @pantoken/pantoken` — every target under one import; subpaths like `@pantoken/pantoken/css`, `@pantoken/pantoken/react`, `@pantoken/pantoken/tailwind`.\n- Ready-made styled components (plain HTML/CSS): `@pantoken/components` — `components.css`, `base.css`,\n `utilities.css`, `prose.css`. Pair with `@pantoken/plugin-layouts` (app-shell layout) and\n `@pantoken/plugin-custom-components` (additional components like `banner` and `agent-shell`). Card is included in `@pantoken/components`.\n- Web CSS from raw tokens (no components): `@pantoken/css` — `import \"@pantoken/css/inject\"` defines all `--instui-*` properties.\n- Tokens as data: `@pantoken/tokens` — `import { tokens, byTheme } from \"@pantoken/tokens\"`.\n- User preferences are automatic, not opt-in variants: `prefers-reduced-motion`, `prefers-contrast`,\n `prefers-reduced-transparency`, and forced colors. Keep loading and disabled cues visible. More\n contrast strengthens boundaries; less removes decorative shadows without lowering text contrast.\n Ready token sheets follow the system; explicit `data-pantoken-scheme` light/dark pins win.\n For nested themes, load `properties.css` once plus `scope.css` and set `data-pantoken-theme`.\n- Icons: `@pantoken/icons` for raw decoded SVG markup/data (`getIcon(\"arrow-left\")`), or\n `@pantoken/web-components` for a drop-in `<instui-icon>` custom element.\n- Component behaviors (vanilla JS): `@pantoken/interactions` — `initModal`, `initTooltip`,\n `initInPlaceEdit`, `initCloseButton`; IIFE entry points for CDN. `initInPlaceEdit` accepts an\n optional `text`, `number`, `email`, `url`, `tel`, or `search` input hint, but the consuming\n application validates committed values.\n- Tree browser: ARIA tree markup needs `initTreeBrowser` or `tree-browser.iife.js` for keyboard\n navigation. Name the tree, use focusable treeitems, and associate collection rows with groups via\n `aria-owns`. CSS-only details/summary disclosures don't claim tree roles.\n- Drawer layout: give `<instui-drawer-layout>` nonempty `tray-label` and `content-label`\n attributes to name its shadow-DOM regions. Labels on slotted content don't name those panes.\n- Form validation: opt into `initFormField(host, control, error)` or `data-native-validation` plus\n `form-field.iife.js`, with a separate error and unique ID. CSS alone doesn't synchronize error\n associations; client-side checks don't replace server validation.\n- Menus: opt into `initMenu(menu, button)` or `data-menu-navigation` plus `menu.iife.js` for\n vertical, single-level native popover menus. Applications own actions and checked state;\n disabled items need `aria-disabled`. Submenus and menubars aren't supported.\n- Tables: `-layout-responsive` inside an `instui-container` (with `utilities.css`) stacks below\n the canonical `md` container breakpoint without JavaScript. Match localized `data-label` values\n to column headers and retain native header associations. Alternatively, retain columns in a\n named, keyboard-focusable `--overflow-x-auto` region with a visible focus outline.\n- shadcn registry: `shadcn search @pantoken`, `shadcn view @pantoken/<item>`, then `shadcn add\n @pantoken/<item>`. Items install CSS/packages and usage metadata, not React components.\n- Standalone browser mockups: use the CDN guide, component capability manifest, demos, and optional\n per-component interaction IIFEs. Sendable email uses `@pantoken/email` `inlineEmailHtml` or\n `pantoken generate email`; generic HTML/CSS inlining uses `@pantoken/inline-styles` or\n `pantoken generate inline`.\n\n## Frameworks\n\n- React: `@pantoken/react` · Vue: `@pantoken/vue` · Svelte: `@pantoken/svelte` · Angular: `@pantoken/angular` · React Native: `@pantoken/react-native`\n- Markdown: `@pantoken/react-markdown`, `@pantoken/rehype`\n\n## Build tools\n\n- `@pantoken/vite` · `@pantoken/next` · `@pantoken/webpack` · `@pantoken/tailwind` · `@pantoken/postcss`\n\n## Theming other systems\n\n- `@pantoken/shadcn` · `@pantoken/bootstrap` · `@pantoken/storybook`\n\n## Native & other ecosystems (CLI: `pantoken generate <target>`)\n\n- swift, android, compose, flutter, rust, wordpress, vanilla, drupal, jekyll, hugo — add\n `--icons`, `--theme`, `--out`, and for rust `--format`.\n- Check https://pantoken.app/target-compatibility.json before claiming a supported host version;\n its `$schema` field identifies the published schema. Verified releases and environments are\n bounded evidence, not promises about newer versions.\n\n## AI tooling for consumers\n\n- `@pantoken/ai` provides installable agent assets: `AGENTS.md`, `llms.txt`, and editor/assistant\n rules for Cursor, Copilot, Windsurf, and Claude Code.\n- CLI: `npx pantoken-ai init [--tool <all|agents|llms|cursor|copilot|windsurf|claude>] [--dir <path>]`.\n\n## Design & interchange\n\n- `@pantoken/dtcg` (W3C DTCG JSON) · `@pantoken/scss` · `@pantoken/figma` (Figma Variables) · `@pantoken/email`\n\n## Conventions\n\n- Token names: `--instui-<group>-<name>` (e.g. `--instui-color-background-brand`).\n- Themes: rebrand (default), canvas, canvasHighContrast. Prefer `var(--instui-*)` references for theming.\n",
744
+ "cursor": "---\ndescription: How to use pantoken (Instructure design tokens & icons) in this project\nglobs:\nalwaysApply: false\n---\n\n# pantoken (Instructure design tokens & icons)\n\nWhen styling this project, use pantoken components, icons and tokens.\n\n- First distinguish a maintained application from a standalone artifact. For a single HTML mockup\n or sendable email, follow the `create-pantoken-mockup` skill instead of scaffolding a project.\n- In a shadcn project, discover CSS items with `shadcn search @pantoken`, inspect with `shadcn view\n @pantoken/<item>`, and install with `shadcn add @pantoken/<item>`. These are styles and metadata,\n not React components. `@pantoken/shadcn` is only the CSS-variable bridge.\n\n- Tokens are CSS custom properties `--instui-<group>-<name>` (e.g. `--instui-color-background-brand`).\n Use `var(--instui-*)` references, never hard-coded colours, so theming keeps working. Resolve real\n names from `@pantoken/tokens` — don't guess. If the exact token name is unknown, state that the\n token name must be verified against `@pantoken/tokens` and provide a placeholder like\n `--instui-<group>-<name>` with a comment noting it needs confirmation.\n- Web app: `import \"@pantoken/css/inject\";` to define the properties.\n- User preferences are automatic, not opt-in variants: `prefers-reduced-motion`, `prefers-contrast`,\n `prefers-reduced-transparency`, and forced colors. Preserve static loading feedback and disabled\n cues. More contrast strengthens boundaries; less removes decorative shadows without reducing text\n contrast. Ready token sheets follow the system scheme; explicit `data-pantoken-scheme` light/dark\n pins win. Use `properties.css` plus `scope.css` for nested themes, not multiple root theme sheets.\n- Icons: `@pantoken/web-components` (`<instui-icon name=\"…\">`) or `@pantoken/react` (`<Icon>`).\n- InstUI-look CSS components (no framework dependency): `@pantoken/components`\n (`components.css`, `base.css`, `prose.css`, `utilities.css`, `fonts.css`) — class-based markup\n like `<button class=\"instui-button\">`.\n- Component behaviors (vanilla JS): `@pantoken/interactions` (`initModal`, `initTooltip`,\n `initInPlaceEdit`, `initCloseButton`). `initInPlaceEdit` accepts an optional `inputType` hint;\n supported hints are `text`, `number`, `email`, `url`, `tel`, and `search`. Validate its committed\n `change` value in the consuming application.\n- ARIA tree-browser markup needs `initTreeBrowser` or `tree-browser.iife.js` for keyboard navigation.\n Name the tree, use focusable treeitems, and associate collection rows with groups via `aria-owns`.\n Native details/summary disclosures can use the CSS without claiming tree roles.\n- Give `<instui-drawer-layout>` nonempty `tray-label` and `content-label` attributes to name its\n shadow-DOM regions. Labels on slotted content don't name those panes.\n- Native form validation is opt-in through `initFormField(host, control, error)` or\n `data-native-validation` plus `form-field.iife.js`. Supply a separate error with a unique ID.\n CSS alone doesn't synchronize error associations; server-side validation is still required.\n- ARIA menu keyboard behavior is opt-in via `initMenu(menu, button)` or `data-menu-navigation`\n plus `menu.iife.js`. Use a vertical, single-level native popover and its button. Applications own\n actions and checked state; disabled items need `aria-disabled`. Submenus and menubars aren't supported.\n- Tables can use `-layout-responsive` inside an `instui-container` (load `utilities.css`) for\n CSS-only stacking below the canonical `md` container breakpoint. Match localized `data-label`\n values to column headers; retain native header associations. Alternatively, keep columns in a\n named, keyboard-focusable `--overflow-x-auto` region with a visible focus outline.\n- Tailwind: `pantokenPreset()` from `@pantoken/tailwind`.\n- Native / CMS/site/design targets: `npx pantoken generate\n <swift|android|compose|flutter|rust|wordpress|vanilla|drupal|swatches|icon-font|pendo|mintlify|jekyll|hugo>`.\n- Check the [target compatibility registry](https://pantoken.app/target-compatibility.json) before recommending a host version. Its\n `$schema` field links the schema; tested versions and environments do not imply future support.\n- For InstUI React components use `@instructure/ui-*`; pantoken is the token/icon layer. Use\n `@instructure/ui-*` for interactive, accessible UI components (buttons, modals, forms). Use\n `@pantoken/react` only for icons and token consumption. Do not substitute one for the other.\n",
745
+ "copilot": "# pantoken (Instructure design tokens & icons)\n\nWhen styling this project, use pantoken components, icons and tokens.\n\n- First distinguish a maintained application from a standalone artifact. For a single HTML mockup\n or sendable email, follow the `create-pantoken-mockup` skill instead of scaffolding a project.\n- In a shadcn project, discover CSS items with `shadcn search @pantoken`, inspect with `shadcn view\n @pantoken/<item>`, and install with `shadcn add @pantoken/<item>`. These are styles and metadata,\n not React components. `@pantoken/shadcn` is only the CSS-variable bridge.\n\n- Tokens are CSS custom properties `--instui-<group>-<name>` (e.g. `--instui-color-background-brand`).\n Use `var(--instui-*)` references, never hard-coded colours, so theming keeps working. Resolve real\n names from `@pantoken/tokens` — don't guess. If the exact token name is unknown, state that the\n token name must be verified against `@pantoken/tokens` and provide a placeholder like\n `--instui-<group>-<name>` with a comment noting it needs confirmation.\n- Web app: `import \"@pantoken/css/inject\";` to define the properties.\n- User preferences are automatic, not opt-in variants: `prefers-reduced-motion`, `prefers-contrast`,\n `prefers-reduced-transparency`, and forced colors. Preserve static loading feedback and disabled\n cues. More contrast strengthens boundaries; less removes decorative shadows without reducing text\n contrast. Ready token sheets follow the system scheme; explicit `data-pantoken-scheme` light/dark\n pins win. Use `properties.css` plus `scope.css` for nested themes, not multiple root theme sheets.\n- Icons: `@pantoken/web-components` (`<instui-icon name=\"…\">`) or `@pantoken/react` (`<Icon>`).\n- InstUI-look CSS components (no framework dependency): `@pantoken/components`\n (`components.css`, `base.css`, `prose.css`, `utilities.css`, `fonts.css`) — class-based markup\n like `<button class=\"instui-button\">`.\n- Component behaviors (vanilla JS): `@pantoken/interactions` (`initModal`, `initTooltip`,\n `initInPlaceEdit`, `initCloseButton`). `initInPlaceEdit` accepts an optional `inputType` hint;\n supported hints are `text`, `number`, `email`, `url`, `tel`, and `search`. Validate its committed\n `change` value in the consuming application.\n- ARIA tree-browser markup needs `initTreeBrowser` or `tree-browser.iife.js` for keyboard navigation.\n Name the tree, use focusable treeitems, and associate collection rows with groups via `aria-owns`.\n Native details/summary disclosures can use the CSS without claiming tree roles.\n- Give `<instui-drawer-layout>` nonempty `tray-label` and `content-label` attributes to name its\n shadow-DOM regions. Labels on slotted content don't name those panes.\n- Native form validation is opt-in through `initFormField(host, control, error)` or\n `data-native-validation` plus `form-field.iife.js`. Supply a separate error with a unique ID.\n CSS alone doesn't synchronize error associations; server-side validation is still required.\n- ARIA menu keyboard behavior is opt-in via `initMenu(menu, button)` or `data-menu-navigation`\n plus `menu.iife.js`. Use a vertical, single-level native popover and its button. Applications own\n actions and checked state; disabled items need `aria-disabled`. Submenus and menubars aren't supported.\n- Tables can use `-layout-responsive` inside an `instui-container` (load `utilities.css`) for\n CSS-only stacking below the canonical `md` container breakpoint. Match localized `data-label`\n values to column headers; retain native header associations. Alternatively, keep columns in a\n named, keyboard-focusable `--overflow-x-auto` region with a visible focus outline.\n- Tailwind: `pantokenPreset()` from `@pantoken/tailwind`.\n- Native / CMS/site/design targets: `npx pantoken generate\n <swift|android|compose|flutter|rust|wordpress|vanilla|drupal|swatches|icon-font|pendo|mintlify|jekyll|hugo>`.\n- Check the [target compatibility registry](https://pantoken.app/target-compatibility.json) before recommending a host version. Its\n `$schema` field links the schema; tested versions and environments do not imply future support.\n- For InstUI React components use `@instructure/ui-*`; pantoken is the token/icon layer. Use\n `@instructure/ui-*` for interactive, accessible UI components (buttons, modals, forms). Use\n `@pantoken/react` only for icons and token consumption. Do not substitute one for the other.\n",
743
746
  "windsurf": "# pantoken rules (Instructure design tokens & icons)\n\n- Use pantoken tokens: CSS custom properties `--instui-<group>-<name>`. Prefer `var(--instui-*)`\n references over hard-coded values so light/dark and high-contrast theming works. Resolve names\n from `@pantoken/tokens`; do not invent them.\n- Route maintained apps to package-manager integration. Route a single HTML mockup or sendable email\n to the `create-pantoken-mockup` skill instead of scaffolding a project.\n- In shadcn projects, use `shadcn search/view/add @pantoken/...` for CSS styles and metadata. The\n registry does not provide React components; `@pantoken/shadcn` is the variable bridge.\n- Web: `import \"@pantoken/css/inject\";`. Icons: `@pantoken/web-components` (`<instui-icon>`).\n- React: `@pantoken/react`. Tailwind: `@pantoken/tailwind` preset.\n- Native / other ecosystems: `npx pantoken generate <swift|android|compose|flutter|rust|wordpress|vanilla|drupal|jekyll|hugo> --out <dir>`.\n- Check the [target compatibility registry](https://pantoken.app/target-compatibility.json) before recommending a host version; the\n registry's `$schema` field links its schema. Only named versions or environments are verified.\n- InstUI React components: `@instructure/ui-*`. pantoken is the token/icon layer.\n",
744
747
  "initSkill": "---\nname: init-pantoken\ndescription: Install pantoken's agent assets (AGENTS.md, llms.txt, editor/agent rule files, and app/mockup skills) into this repo so AI tools know how to work with pantoken. Use when the user asks to add pantoken AI support, or wants Copilot/Cursor/Windsurf/Claude rules for pantoken set up in a repo.\n---\n\n# Init pantoken (AI assets)\n\nInstall pantoken's consumer-facing agent assets into the current repo: `AGENTS.md`, `llms.txt`,\neditor/agent rule files (Cursor, Copilot, Windsurf), and the `create-pantoken-app`,\n`create-pantoken-mockup`, and `use-pantoken-registry` skills.\n\n```sh\nnpx pantoken-ai init\n```\n\nThis installs every asset by default. To scope it to one tool, pass\n`--tool <agents|llms|cursor|copilot|windsurf|claude>`. To target a directory other than the\ncurrent one, pass `--dir <path>`. Substitute `pnpm dlx`, `yarn dlx`, `bunx`, or `deno run npm:` for `npx` depending\non the package manager detected in the repo (look for `pnpm-lock.yaml`, `yarn.lock`, or\n`bun.lock`/`bun.lockb`; default to npm/npx if none is found).\n\nThat's all this skill does — it only writes the asset files above, it does not install any\n`@pantoken/*` package or modify application code. Once the assets are installed, use\n`create-pantoken-app` for a maintained project (or run `npx pantoken-ai scaffold <platform>`\ndirectly), use `create-pantoken-mockup` for a standalone browser or email artifact, and use\n`use-pantoken-registry` when a shadcn project should search, inspect, or add Pantoken registry\nitems.\n",
745
748
  "createAppSkill": "---\nname: create-pantoken-app\ndescription: Scaffold a maintained application, or add Instructure design tokens and icons (pantoken) to an existing project with a package manager. Use for web, framework, native, and CMS projects that need dependencies and builds. Do not use for a standalone HTML mockup or sendable email; use create-pantoken-mockup.\n---\n\n# Scaffold pantoken\n\nSet up [pantoken](https://www.npmjs.com/package/@pantoken/pantoken) — a design tokens and icons\nlibrary for Instructure UI — in the current project. Work through these steps.\n\nIf the user wants one standalone HTML file, a quick browser prototype, a customer email mockup, or\nsendable email HTML, stop and use the `create-pantoken-mockup` skill instead.\n\n## About pantoken\n\npantoken is built and used internally at Instructure, then open-sourced; Instructure doesn't\nprovide official warranty or support for it as a product, which is why it's published from\n[`thedannywahl`](https://github.com/thedannywahl/pantoken) on GitHub and npm\n([`@pantoken`](https://www.npmjs.com/org/pantoken)) rather than the `instructure` org/scope — it may\nmove there later. Check either link yourself before proceeding if you want to verify this.\n\n## 1. New project or existing repo?\n\n- **Empty directory, or no repo yet** — scaffold a starter with the CLI, then stop (steps 2-3 are\n already done for you by the template).\n\n The CLI has its own interactive prompts, but those only work at a real terminal, so ask the user\n the questions below the same way you normally would, then pass their answers as flags (plus\n `--yes`) so the command runs without needing its own prompts:\n\n 1. **Platform** — ask the user, offering the supported list: `components` (plain HTML/CSS;\n `html` is an accepted alias), `react`, `vue`, `svelte`, `web-components`, `angular`,\n `canvas-theme-editor` (Canvas LMS Theme Editor uploads + an RCE content page template\n starter; `theme-editor` is an accepted alias). Skip asking only if it's unambiguous from the\n conversation — route requests like \"use pantoken with my Canvas theme editor\" or \"build RCE\n page templates\" straight to `canvas-theme-editor`. More platforms land over time; if the\n desired one isn't yet supported by the scaffold CLI, skip the CLI entirely and proceed\n directly to step 2 to manually install and wire pantoken instead.\n\n For `canvas-theme-editor`, after scaffolding, tell the user to: (1) upload the generated\n `theme.css`/`theme.js` under Canvas's Theme Editor → Advanced, and (2) run `npm run dev` to\n author RCE page templates in the local TinyMCE editor, using the **Layouts** toolbar button to\n start from a bundled starter layout before copying the result into Canvas.\n\n If the CLI fails for any reason (non-zero exit, unsupported platform, network error), fall\n through to step 2 and treat the project as an existing repo, preserving any files already\n written by the CLI.\n\n 2. **Package manager** — if a lockfile already exists in the target directory, use it (see the\n detection table in step 2); a genuinely empty directory has no lockfile to detect from, so\n ask the user (npm/pnpm/yarn/bun/deno).\n 3. **Directory** — ask where to scaffold (default `.` for the current directory; confirm before\n defaulting to `.` if you're not sure that's what they want).\n\n Then run the fully-resolved command, substituting the chosen package manager's \"run a package's\n CLI\" form from step 2's table for `npx`, and passing `--yes` so the CLI never falls back to its\n own interactive prompts:\n\n ```sh\n npx @pantoken/ai scaffold <platform> --dir <dir> --yes\n ```\n\n This writes a minimal starter (`package.json`, entry file(s), README) for the chosen platform\n with pantoken already installed and wired in, and also installs pantoken's agent assets\n (AGENTS.md, editor/agent rules, skills) into the same directory. If you only want the starter\n project without the agent assets, run `npx create-pantoken-app <platform> --dir <dir> --yes`\n (or `npx @pantoken/scaffold <platform> --dir <dir> --yes`) directly instead — substituting the\n chosen package manager's launcher for `npx` on either command. Run `npm install` (or the chosen\n package manager's install) in the target directory afterward.\n\n- **Existing repo you want to add pantoken to** — continue to step 2.\n\n## 2. Determine the target\n\nAsk the user what kind of project they're building, unless it's unambiguous from the repo. Offer:\n\n- **Native web (plain HTML/CSS, no framework) — default** → `@pantoken/components`\n- A JS framework (React, Vue, Svelte, Angular, React Native, Next.js)\n- A build tool only, styling from raw tokens (Tailwind, PostCSS, Vite, Webpack, or plain `@pantoken/css`)\n- A native/CMS ecosystem (Swift, Android, Compose, Flutter, Rust, WordPress, Drupal, Vanilla, Jekyll, Hugo)\n\nIf the user doesn't answer or has no preference, default to native web (`@pantoken/components`).\n\nCorroborate with the repo when possible, and prefer the user's answer if it conflicts with detection:\n\n- `package.json` dependencies → web framework (react, vue, svelte, @angular/core, react-native,\n next, vite, tailwindcss, webpack, postcss).\n- If no `package.json` is found and the user wants a web project, run `npm init -y` first, then\n proceed with the native web default (or the chosen framework) — this applies even if the user\n describes the project as \"existing\"; trust their named framework and proceed rather than asking\n for clarification.\n- Native project files → iOS (`Package.swift`, `*.xcodeproj`), Android (`build.gradle`), Flutter\n (`pubspec.yaml`), WordPress/Drupal/Vanilla theme dirs.\n\nAlso detect the package manager from the lockfile present in the repo, and use its equivalent\ncommand for every install/run step below instead of assuming npm:\n\n| Lockfile found | Package manager | Add package(s) | Run a package's CLI |\n| -------------------------- | --------------- | -------------------- | -------------------- |\n| `pnpm-lock.yaml` | pnpm | `pnpm add <pkg>` | `pnpm dlx <pkg>` |\n| `yarn.lock` | yarn | `yarn add <pkg>` | `yarn dlx <pkg>` |\n| `bun.lock`/`bun.lockb` | bun | `bun add <pkg>` | `bunx <pkg>` |\n| `deno.lock` | deno | `deno add npm:<pkg>` | `deno run npm:<pkg>` |\n| `package-lock.json` / none | npm | `npm i <pkg>` | `npx <pkg>` |\n\nIf no lockfile exists yet, default to npm (or whatever the user prefers).\n\n## 3. Install\n\nIf `components.json` exists or the user explicitly requests shadcn, use the indexed registry to\ndiscover and install Pantoken CSS styles:\n\n```sh\nnpx shadcn@latest search @pantoken --query <need>\nnpx shadcn@latest view @pantoken/<item>\nnpx shadcn@latest add @pantoken/<item>\n```\n\nRegistry items provide CSS and usage metadata, not React components. Use `@instructure/ui-*` when\nthe user needs full React components. Continue with direct package installation for non-shadcn\nprojects.\n\nUse the package manager detected in step 2 for every command below (the examples use `npm i`;\nsubstitute `pnpm add`, `yarn add`, or `bun add` as appropriate).\n\nFollow this decision checklist in order, then run one install command with all collected packages:\n\n1. **Is it native web** (plain HTML/CSS, no framework and no build tool detected)? Install only\n `@pantoken/components` — it ships the token CSS baked in, so no separate `@pantoken/css` install\n is needed — and stop:\n\n ```sh\n npm i @pantoken/components\n ```\n\n2. **Is it Next.js?** Collect `@pantoken/css` plus `@pantoken/next` (do NOT also add\n `@pantoken/react` — `@pantoken/next` includes the React integration), then add any matching tool\n packages (Tailwind, Vite, etc.) from the table below.\n\n3. **Otherwise**, collect `@pantoken/css` first, then add the framework package and every matching\n tool row's package from the table. Framework rows (React, Vue, etc.) and tool rows (Tailwind,\n PostCSS, Vite, Webpack) are all additive — collect every matching row's package alongside\n `@pantoken/css`.\n\n4. If the user wants to use `<instui-icon>` in any web framework project (React, Vue, Vite, etc.),\n also collect `@pantoken/web-components` — regardless of which framework rows already matched.\n\nFor example:\n\n- A Next.js project also using Tailwind installs `@pantoken/css @pantoken/next @pantoken/tailwind`.\n- A React project also using Vite installs `@pantoken/css @pantoken/react @pantoken/vite`.\n\n| Detected | Install |\n| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Native web (default) | `@pantoken/components` |\n| React | `@pantoken/react`; if the user also wants full InstUI components (buttons, modals, etc.), additionally install the specific `@instructure/ui-*` packages needed, e.g. `@instructure/ui-buttons @instructure/ui-modal` (see <https://instructure.design> for the full package list) |\n| Vue / Svelte / Angular | `@pantoken/vue` / `@pantoken/svelte` / `@pantoken/angular` + `@pantoken/web-components` (always install `@pantoken/web-components` alongside the framework package here — it's required for icon support in these three, not optional) |\n| React Native | `@pantoken/react-native` |\n| Next.js | `@pantoken/next` — Next.js projects do NOT also need `@pantoken/react`; `@pantoken/next` includes the React integration. Do not install both. |\n| Vite | `@pantoken/vite` |\n| Tailwind | `@pantoken/tailwind` |\n| PostCSS / Webpack | `@pantoken/postcss` / `@pantoken/webpack` |\n| shadcn / Bootstrap | `@pantoken/shadcn` / `@pantoken/bootstrap` |\n| markdown-it / css-in-js | `@pantoken/markdown-it` / `@pantoken/css-in-js` |\n| Icons anywhere | `@pantoken/web-components` — for React, Next.js, React Native, and tool-only setups, only add this if the user explicitly wants icon support (`<instui-icon>` elements); for Vue, Svelte, and Angular it's always required (see that row) |\n\nFor native / CMS targets, no install — run the CLI (step 5). If the project contains both a\n`package.json` and native/CMS files, treat it as a web project and follow the web install steps\nabove; only skip to step 5 if there is no `package.json` and no JS framework detected.\n\n## 4. Wire it up\n\n- Native web (default): import `base.css` + `components.css` from `@pantoken/components` (e.g.\n `import \"@pantoken/components/base.css\"; import \"@pantoken/components/components.css\";`), then\n apply classes like `class=\"instui-button\"` to markup.\n- Other web entry: add `import \"@pantoken/css/inject\";` (or `@import \"@pantoken/css/style.css\";`).\n- Next: wrap the config with `withPantoken(...)` and import the CSS in the root layout.\n- Vite: add the `pantoken()` plugin. Tailwind: add `pantokenPreset()` to `presets`.\n- Web components: `import \"@pantoken/web-components\";` then use `<instui-icon name=\"…\">`.\n- Verify the app renders and `getComputedStyle(document.documentElement).getPropertyValue('--instui-color-background-brand')` is non-empty.\n If the property is empty, check that the token CSS import (`@pantoken/components/base.css` or\n `@pantoken/css/inject`) appears before any component imports in the entry file, and that the dev\n server was restarted after install. Report the specific failure to the user with corrective steps.\n\n## 5. Native / other ecosystems\n\n```sh\nnpx @pantoken/cli generate <swift|android|compose|flutter|rust|wordpress|vanilla|drupal|jekyll|hugo> --out <dir> [--icons a,b] [--theme rebrand]\n```\n\nSubstitute `pnpm dlx`, `yarn dlx`, `bunx`, or `deno run npm:` for `npx` per the package manager\ndetected in step 2 (or from the choice made in step 1 if you're still inside the new-project flow).\n\n## Conventions to follow afterward\n\n- Style with `var(--instui-*)` references, not hard-coded colours, so light/dark and high-contrast\n theming keeps working.\n- Resolve real token names from `@pantoken/tokens`; never invent them.\n",