@pantoken/scaffold 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,17 +19,22 @@ 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 syntax-highlighted,\n hand-editable copies of `theme.css`/`theme.js` that feed the live preview), and the **?** button\n for full instructions. Use the **Layouts** toolbar button to start from one of pantoken's bundled\n starter page layouts (hero, callout, two-column, 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 (TinyMCE, matching the version/config\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) itself uses — see below).\n Use the **Layouts** button to load one of the bundled starter layouts (this replaces the whole\n document, after a confirm, rather than inserting at the cursor), and the **Source code** toggle\n to hand-edit the raw HTML in a syntax-highlighted (CodeMirror) view alongside the editor, with\n the preview pane updating live as you type — unlike TinyMCE's stock `code` plugin, which edits in\n a one-shot modal dialog with no live preview.\n- A **preview** pane showing the editor's content with the current CSS/JS tab's stylesheet/script\n applied (not just the resolved CDN URLs), wrapped to match Canvas's own content-area background\n and max width — a faithful \"what this will look like once uploaded to Canvas\" check, updated\n live as you type or edit the theme.\n- The editor and preview panes sit in a split view you can resize by dragging the divider, stack\n vertically instead of side by side, and swap the order of (drag a pane's toolbar onto the other,\n or use the **Swap panes** button). Each pane has its own fullscreen button.\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 are editable copies\n of the generated files — hand-edit them and the preview picks up your changes directly. Changing\n a Config select re-generates the CSS/JS tabs unless you've already edited them, in which case a\n **Regenerate from config** button appears instead of silently overwriting your edit.\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.\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). Canvas sanitizes pasted HTML server-side — this scaffold doesn't attempt to\n replicate that, so always verify the pasted result in Canvas (see \"Notes on Canvas's RCE\"\n below).\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",
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 <title>{{projectName}} — RCE template authoring</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/plugin-layouts\": \"latest\",\n \"@pantoken/tinymce\": \"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 \"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",
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",
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/plugin-custom-icons\": \"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 \"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
- "src/app.css": "/* Layout for this scaffold's own authoring UI (not part of any Canvas-pasted RCE content). */\n\n.instui-tray .list {\n display: flex;\n gap: 0.5rem;\n}\n\n.instui-tray .panel[hidden] {\n display: none;\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.split-pane {\n display: flex;\n flex-direction: row;\n gap: 0;\n min-height: 30rem;\n}\n\n.split-pane.-orientation-column {\n flex-direction: column;\n}\n\n.pane {\n flex: 1 1 50%;\n min-width: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n\n.pane:fullscreen {\n padding: 1rem;\n background: var(--instui-background-color-page, #fff);\n}\n\n.pane-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n /* Also the drag handle for reordering panes (not resizing — see .split-handle for that). */\n cursor: grab;\n}\n\n.pane-toolbar.-dragging {\n cursor: grabbing;\n opacity: 0.6;\n}\n\n.pane.-drop-target {\n outline: 2px dashed var(--instui-color-stroke-brand, #0374b5);\n}\n\n#editor,\n#css-editor,\n#js-editor,\n#preview {\n flex: 1 1 auto;\n min-height: 0;\n width: 100%;\n}\n\n#preview {\n border: 1px solid #ccc;\n}\n\n.split-handle {\n flex: 0 0 0.375rem;\n cursor: col-resize;\n background: var(--instui-color-stroke-base, #d3d3d3);\n}\n\n.split-pane.-orientation-column > .split-handle {\n cursor: row-resize;\n}\n\n.split-handle:hover,\n.split-handle.-dragging {\n background: var(--instui-color-stroke-brand, #0374b5);\n}\n",
29
- "src/app.html": "<div class=\"container\">\n <div class=\"header\">\n <div class=\"info\">\n <div class=\"title\">{{pageTitle}}</div>\n <div class=\"description\">{{pageDescription}}</div>\n </div>\n <div class=\"actions\">\n <button class=\"instui-button\" type=\"button\" popovertarget=\"theme-tray\">\n {{editThemeLabel}}\n </button>\n <button\n class=\"instui-button -color-secondary\"\n type=\"button\"\n command=\"show-modal\"\n commandfor=\"help-modal\"\n aria-label=\"{{helpAriaLabel}}\"\n >\n ?\n </button>\n </div>\n </div>\n <div class=\"content\">\n <slot name=\"content\" class=\"main\">\n <p>\n <button type=\"button\" id=\"copy-html\">{{copyHtmlLabel}}</button>\n <span id=\"copy-status\" role=\"status\"></span>\n </p>\n <div class=\"split-pane\" id=\"split-pane\">\n <div class=\"pane editor-pane\" id=\"editor-pane\">\n <div class=\"pane-toolbar\" data-pane-handle=\"editor-pane\">\n <span>{{editorPaneLabel}}</span>\n <button\n type=\"button\"\n class=\"pane-fullscreen\"\n data-pane=\"editor-pane\"\n aria-label=\"{{fullscreenEditorAriaLabel}}\"\n >\n ⤢\n </button>\n </div>\n <textarea id=\"editor\"></textarea>\n </div>\n <div\n class=\"split-handle\"\n id=\"split-handle\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"{{resizePanesAriaLabel}}\"\n tabindex=\"0\"\n ></div>\n <div class=\"pane preview-pane\" id=\"preview-pane\">\n <div class=\"pane-toolbar\" data-pane-handle=\"preview-pane\">\n <span>{{previewPaneLabel}}</span>\n <button\n type=\"button\"\n class=\"pane-fullscreen\"\n data-pane=\"preview-pane\"\n aria-label=\"{{fullscreenPreviewAriaLabel}}\"\n >\n ⤢\n </button>\n </div>\n <iframe id=\"preview\" title=\"{{previewFrameTitle}}\"></iframe>\n </div>\n </div>\n <p class=\"split-controls\">\n <button type=\"button\" id=\"toggle-orientation\">{{stackVerticallyLabel}}</button>\n <button type=\"button\" id=\"swap-panes\">{{swapPanesLabel}}</button>\n </p>\n </slot>\n </div>\n</div>\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 <div class=\"panel\" role=\"tabpanel\" id=\"panel-config\" aria-labelledby=\"tab-config\">\n <label>\n {{cdnProviderLabel}}\n <select id=\"cdn-provider\"></select>\n </label>\n <label>\n {{themeLabel}}\n <select id=\"theme-variant\">\n <option value=\"rebrand\">rebrand</option>\n <option value=\"canvas\">canvas</option>\n <option value=\"canvasHighContrast\">canvasHighContrast</option>\n </select>\n </label>\n <label>\n {{modeLabel}}\n <select id=\"theme-mode\">\n <option value=\"light\">light</option>\n <option value=\"adaptive\">adaptive</option>\n </select>\n </label>\n <p>\n <a id=\"download-theme-css\" download=\"theme.css\">{{downloadCssLabel}}</a>\n <a id=\"download-theme-js\" download=\"theme.js\">{{downloadJsLabel}}</a>\n </p>\n </div>\n <div class=\"panel\" role=\"tabpanel\" id=\"panel-css\" hidden aria-labelledby=\"tab-css\">\n <p><button type=\"button\" id=\"regenerate-css\" hidden>{{regenerateLabel}}</button></p>\n <div id=\"css-editor\" class=\"code-editor\"></div>\n </div>\n <div class=\"panel\" role=\"tabpanel\" id=\"panel-js\" hidden aria-labelledby=\"tab-js\">\n <p><button type=\"button\" id=\"regenerate-js\" hidden>{{regenerateLabel}}</button></p>\n <div id=\"js-editor\" class=\"code-editor\"></div>\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/main.ts": "/**\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/css/style.rebrand.light.lean.css\"; // this app's own chrome always uses this theme, independent of the preview's chosen theme\nimport \"@pantoken/components/base.css\";\nimport \"@pantoken/components/components.css\";\nimport \"@pantoken/plugin-layouts/layouts.css\";\nimport \"./app.css\";\nimport appHtml from \"./app.html?raw\";\nimport { STRINGS } from \"./strings.ts\";\nimport tinymce from \"tinymce\";\nimport \"tinymce/themes/silver/theme\";\nimport \"tinymce/icons/default\";\n// canvas-lms injects its skin CSS as a raw string via a custom mechanism (RCEWrapper.tsx's\n// injectTinySkin()) — out of scope here; plain side-effect imports achieve the same look.\nimport \"tinymce/skins/ui/oxide/skin.css\";\nimport \"tinymce/skins/ui/oxide/content.css\";\nimport \"tinymce/skins/content/default/content.css\";\nimport {\n buildTheme,\n buildThemeCss,\n buildThemeJs,\n CDN_PROVIDERS,\n DEFAULT_CDN_PROVIDER_ID,\n type ThemeMode,\n type ThemeVariant,\n} from \"@pantoken/canvas-theme-editor\";\nimport type { Editor, Ui } 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 type { CdnFile } from \"@pantoken/cdn\";\nimport {\n createLayoutsPlugin,\n createComponentsPlugin,\n createIconsPlugin,\n createLogosPlugin,\n listComponents,\n listUtilities,\n loadAllIcons,\n logos,\n products,\n pantokenHtmlLinter,\n pantokenHtmlCompletion,\n} from \"@pantoken/tinymce\";\n\n// Shared with the toolbar's source-view editor so both stay the same size.\nconst EDITOR_HEIGHT_PX = 400;\n// Canvas's content area caps out at this width — the preview mirrors that constraint.\nconst CANVAS_CONTENT_MAX_WIDTH = \"59.25rem\";\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\ndocument.querySelector<HTMLDivElement>(\"#app\")!.innerHTML = render(appHtml, STRINGS);\n\n// Tabs (Config | CSS | JS) — the .instui-tabs record is CSS-only; wiring selection is the\n// consumer's job, same as the component's own documented @example.\nconst tabButtons = document.querySelectorAll<HTMLButtonElement>('.instui-tabs [role=\"tab\"]');\nfor (const tab of tabButtons) {\n tab.addEventListener(\"click\", (): void => {\n for (const other of tabButtons) {\n const selected = other === tab;\n other.classList.toggle(\"-selected\", selected);\n other.setAttribute(\"aria-selected\", String(selected));\n const panel = document.getElementById(other.getAttribute(\"aria-controls\")!);\n if (panel) panel.hidden = !selected;\n }\n });\n}\n\n// Shared CSS assets array — tracks stylesheet URLs for dynamic injection into WYSIWYG editor.\n// Each picker plugin calls onMissingAsset to add new assets, and they're injected when an item is inserted.\nconst currentAssets: CdnFile[] = [];\nconst onMissingAsset = (asset: CdnFile) => {\n currentAssets.push(asset);\n // In a real app, you'd also trigger a download/export of the aggregated theme.css here.\n};\n\n// Register the Layouts plugin (replaces whole document on layout selection), sourced from\n// pantoken's own bundled starter page layouts (@pantoken/plugin-layouts).\nconst layoutsPlugin = createLayoutsPlugin();\ntinymce.PluginManager.add(\"pantoken_layouts\", function (editor: Editor) {\n layoutsPlugin(editor);\n // Wire the layout selection to also update the source view and refresh preview.\n const originalInsertContent = editor.insertContent;\n editor.insertContent = function (value: string) {\n originalInsertContent.call(this, value);\n replaceSourceDoc(editor.getContent());\n refreshAll();\n };\n return {};\n});\n\n/** Creates a CodeMirror editor for the given language, wired to call `onChange` on 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/** Replaces an editor's full document contents. */\nfunction replaceEditorDoc(view: EditorView, content: string): void {\n view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: content } });\n}\n\n/** Lazily creates the CodeMirror instance (HTML syntax highlighting) alongside the hidden iframe. */\nfunction ensureSourceView(editor: Editor): EditorView {\n if (sourceView) return sourceView;\n const container = document.createElement(\"div\");\n container.style.cssText = `display: none; width: 100%; height: ${EDITOR_HEIGHT_PX}px; box-sizing: border-box; overflow: auto; border: 1px solid #ccc; font-size: 13px;`;\n editor.contentAreaContainer.insertAdjacentElement(\"afterend\", container);\n sourceContainer = container;\n sourceView = createEditor(container, \"html\", \"\", debouncedUpdatePreview);\n return sourceView;\n}\n\n/** Replaces the CodeMirror document's full contents, if the source view has been created. */\nfunction replaceSourceDoc(content: string): void {\n if (!sourceView) return;\n replaceEditorDoc(sourceView, content);\n}\n\n// Register the three pantoken pickers (components, icons, logos) as TinyMCE plugins.\n// Each picker has its own toolbar button and manages CSS asset tracking. tinymce.init() below\n// awaits this promise first — plugin names must be registered before init() resolves them.\nconst registerPickerPlugins = (async () => {\n const componentModel = [...listComponents(), ...listUtilities()];\n const allIcons = await loadAllIcons();\n \n const componentsPlugin = createComponentsPlugin({\n model: componentModel as any,\n currentAssets,\n onMissingAsset,\n });\n tinymce.PluginManager.add(\"pantoken_components\", componentsPlugin);\n \n const iconsPlugin = createIconsPlugin({\n icons: allIcons,\n currentAssets,\n onMissingAsset,\n });\n tinymce.PluginManager.add(\"pantoken_icons\", iconsPlugin);\n \n const logosPlugin = createLogosPlugin({\n logos,\n products,\n currentAssets,\n onMissingAsset,\n });\n tinymce.PluginManager.add(\"pantoken_logos\", logosPlugin);\n})();\n\n// Toggles between TinyMCE's WYSIWYG view and a syntax-highlighted CodeMirror source view.\n// The source view also includes pantoken linter (validation) and autocomplete (IntelliSense).\ntinymce.PluginManager.add(\"pantoken_source_toggle\", function (editor: Editor) {\n const toggle = (api: Ui.Toolbar.ToolbarToggleButtonInstanceApi) => {\n sourceMode = !sourceMode;\n api.setActive(sourceMode);\n const view = ensureSourceView(editor);\n const contentArea = editor.contentAreaContainer;\n if (sourceMode) {\n replaceSourceDoc(editor.getContent());\n contentArea.style.display = \"none\";\n sourceContainer!.style.display = \"block\";\n view.focus();\n } else {\n contentArea.style.display = \"\";\n sourceContainer!.style.display = \"none\";\n editor.setContent(view.state.doc.toString());\n }\n refreshAll();\n };\n\n editor.ui.registry.addToggleButton(\"sourcecode\", {\n icon: \"sourcecode\",\n tooltip: \"Source code\",\n onAction: toggle,\n });\n\n return {};\n});\n\nconst providerSelect = document.querySelector<HTMLSelectElement>(\"#cdn-provider\")!;\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 = DEFAULT_CDN_PROVIDER_ID;\n\nconst themeSelect = document.querySelector<HTMLSelectElement>(\"#theme-variant\")!;\nconst modeSelect = document.querySelector<HTMLSelectElement>(\"#theme-mode\")!;\nconst previewFrame = document.querySelector<HTMLIFrameElement>(\"#preview\")!;\nconst downloadCss = document.querySelector<HTMLAnchorElement>(\"#download-theme-css\")!;\nconst downloadJs = document.querySelector<HTMLAnchorElement>(\"#download-theme-js\")!;\nconst copyButton = document.querySelector<HTMLButtonElement>(\"#copy-html\")!;\nconst copyStatus = document.querySelector<HTMLElement>(\"#copy-status\")!;\nconst regenerateCssButton = document.querySelector<HTMLButtonElement>(\"#regenerate-css\")!;\nconst regenerateJsButton = document.querySelector<HTMLButtonElement>(\"#regenerate-js\")!;\n\nlet activeEditor: Editor | undefined;\nlet cssObjectUrl: string | undefined;\nlet jsObjectUrl: string | undefined;\nlet sourceView: EditorView | undefined;\nlet sourceContainer: HTMLDivElement | undefined;\nlet sourceMode = false;\n// Once the author hand-edits the CSS/JS tab, config-select changes no longer overwrite it —\n// they only re-enable \"Regenerate from config\" so the edit isn't silently discarded.\nlet cssDirty = false;\nlet jsDirty = false;\n\n/** Reads the author's current HTML from whichever view (WYSIWYG or raw source) is active. */\nfunction getEditorHtml(): string {\n if (sourceMode && sourceView) return sourceView.state.doc.toString();\n return activeEditor?.getContent() ?? \"\";\n}\n\nfunction currentSelection(): { provider: string; theme: ThemeVariant; mode: ThemeMode } {\n return {\n provider: providerSelect.value,\n theme: themeSelect.value as ThemeVariant,\n mode: modeSelect.value as ThemeMode,\n };\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 */\nfunction updatePreview(): void {\n if (!activeEditor) return;\n const themeCss = cssEditorView.state.doc.toString();\n const themeJs = jsEditorView.state.doc.toString();\n previewFrame.srcdoc = `<!doctype html><html><head><style>${themeCss}</style></head><body>\n <div class=\"instui-view -background-primary\" style=\"max-width: ${CANVAS_CONTENT_MAX_WIDTH}; margin-inline: auto;\">\n ${getEditorHtml()}\n </div>\n <script>${themeJs}<\/script>\n </body></html>`;\n}\nconst debouncedUpdatePreview = debounce(updatePreview, 300);\n\n/** Regenerates the downloadable theme.css/theme.js blobs for the chosen provider/theme/mode. */\nfunction updateDownloads(): void {\n const { provider, theme, mode } = currentSelection();\n const { css: generatedCss, js: generatedJs } = buildTheme({ provider, theme, mode });\n if (cssObjectUrl) URL.revokeObjectURL(cssObjectUrl);\n if (jsObjectUrl) URL.revokeObjectURL(jsObjectUrl);\n cssObjectUrl = URL.createObjectURL(new Blob([generatedCss], { type: \"text/css\" }));\n jsObjectUrl = URL.createObjectURL(new Blob([generatedJs], { type: \"text/javascript\" }));\n downloadCss.href = cssObjectUrl;\n downloadJs.href = jsObjectUrl;\n}\n\n/** Re-seeds the CSS/JS editors from the current config, unless the author has hand-edited them. */\nfunction updateThemeEditors(): void {\n const { provider, theme, mode } = currentSelection();\n if (!cssDirty) replaceEditorDoc(cssEditorView, buildThemeCss({ provider, theme, mode }));\n if (!jsDirty) replaceEditorDoc(jsEditorView, buildThemeJs({ provider, theme, mode }));\n}\n\nfunction refreshAll(): void {\n updateThemeEditors();\n updatePreview();\n updateDownloads();\n}\n\n// CSS/JS editors, seeded from the initial config selection.\nconst cssEditorView = createEditor(\n document.querySelector<HTMLElement>(\"#css-editor\")!,\n \"css\",\n buildThemeCss(currentSelection()),\n () => {\n cssDirty = true;\n regenerateCssButton.hidden = false;\n debouncedUpdatePreview();\n },\n);\nconst jsEditorView = createEditor(\n document.querySelector<HTMLElement>(\"#js-editor\")!,\n \"javascript\",\n buildThemeJs(currentSelection()),\n () => {\n jsDirty = true;\n regenerateJsButton.hidden = false;\n debouncedUpdatePreview();\n },\n);\n\nregenerateCssButton.addEventListener(\"click\", () => {\n replaceEditorDoc(cssEditorView, buildThemeCss(currentSelection()));\n cssDirty = false;\n regenerateCssButton.hidden = true;\n debouncedUpdatePreview();\n});\nregenerateJsButton.addEventListener(\"click\", () => {\n replaceEditorDoc(jsEditorView, buildThemeJs(currentSelection()));\n jsDirty = false;\n regenerateJsButton.hidden = true;\n debouncedUpdatePreview();\n});\n\nproviderSelect.addEventListener(\"change\", refreshAll);\nthemeSelect.addEventListener(\"change\", refreshAll);\nmodeSelect.addEventListener(\"change\", refreshAll);\n\ncopyButton.addEventListener(\"click\", () => {\n void navigator.clipboard.writeText(getEditorHtml()).then(() => {\n copyStatus.textContent = \"Copied. Paste into the Canvas Rich Content Editor HTML view.\";\n });\n});\n\n// --- Editor/preview split-pane: orientation toggle, drag-resize, drag-to-swap, fullscreen. ---\nconst splitPane = document.querySelector<HTMLElement>(\"#split-pane\")!;\nconst splitHandle = document.querySelector<HTMLElement>(\"#split-handle\")!;\nconst editorPane = document.querySelector<HTMLElement>(\"#editor-pane\")!;\nconst previewPane = document.querySelector<HTMLElement>(\"#preview-pane\")!;\nconst orientationButton = document.querySelector<HTMLButtonElement>(\"#toggle-orientation\")!;\nconst swapButton = document.querySelector<HTMLButtonElement>(\"#swap-panes\")!;\n\nlet orientation: \"row\" | \"column\" = \"row\";\n\nfunction setPaneFlexBasis(fraction: number): void {\n const clamped = Math.min(0.85, Math.max(0.15, fraction));\n editorPane.style.flexBasis = `${clamped * 100}%`;\n previewPane.style.flexBasis = `${(1 - clamped) * 100}%`;\n}\n\norientationButton.addEventListener(\"click\", () => {\n orientation = orientation === \"row\" ? \"column\" : \"row\";\n splitPane.classList.toggle(\"-orientation-column\", orientation === \"column\");\n splitHandle.setAttribute(\"aria-orientation\", orientation === \"row\" ? \"vertical\" : \"horizontal\");\n orientationButton.textContent =\n orientation === \"row\" ? STRINGS.stackVerticallyLabel : STRINGS.stackSideBySideLabel;\n setPaneFlexBasis(0.5);\n});\n\n/** Reorders the editor/preview panes (used by both the drag gesture and the fallback button). */\nfunction swapPanes(): void {\n const parent = editorPane.parentElement!;\n const firstIsEditor = parent.firstElementChild === editorPane;\n if (firstIsEditor) parent.insertBefore(previewPane, editorPane);\n else parent.insertBefore(editorPane, previewPane);\n}\nswapButton.addEventListener(\"click\", swapPanes);\n\n// Drag-resize the split via the handle.\nsplitHandle.addEventListener(\"pointerdown\", (event) => {\n splitHandle.classList.add(\"-dragging\");\n splitHandle.setPointerCapture(event.pointerId);\n const onMove = (moveEvent: PointerEvent): void => {\n const rect = splitPane.getBoundingClientRect();\n const fraction =\n orientation === \"row\"\n ? (moveEvent.clientX - rect.left) / rect.width\n : (moveEvent.clientY - rect.top) / rect.height;\n setPaneFlexBasis(fraction);\n };\n const onUp = (): void => {\n splitHandle.classList.remove(\"-dragging\");\n splitHandle.removeEventListener(\"pointermove\", onMove);\n splitHandle.removeEventListener(\"pointerup\", onUp);\n };\n splitHandle.addEventListener(\"pointermove\", onMove);\n splitHandle.addEventListener(\"pointerup\", onUp);\n});\n\n// Drag a pane's toolbar onto the other pane to swap their order (a pointer-based reorder gesture;\n// `swapButton` above is the keyboard-accessible equivalent for anyone who can't drag).\nfor (const handle of document.querySelectorAll<HTMLElement>(\"[data-pane-handle]\")) {\n const paneId = handle.dataset.paneHandle!;\n const pane = document.getElementById(paneId)!;\n const otherPane = pane === editorPane ? previewPane : editorPane;\n\n handle.addEventListener(\"pointerdown\", (event: PointerEvent): void => {\n handle.classList.add(\"-dragging\");\n handle.setPointerCapture(event.pointerId);\n const onMove = (moveEvent: PointerEvent): void => {\n const rect = otherPane.getBoundingClientRect();\n const over =\n moveEvent.clientX >= rect.left &&\n moveEvent.clientX <= rect.right &&\n moveEvent.clientY >= rect.top &&\n moveEvent.clientY <= rect.bottom;\n otherPane.classList.toggle(\"-drop-target\", over);\n };\n const onUp = (upEvent: PointerEvent): void => {\n handle.classList.remove(\"-dragging\");\n const droppedOnOther = otherPane.classList.contains(\"-drop-target\");\n otherPane.classList.remove(\"-drop-target\");\n if (droppedOnOther) swapPanes();\n handle.removeEventListener(\"pointermove\", onMove);\n handle.removeEventListener(\"pointerup\", onUp);\n void upEvent;\n };\n handle.addEventListener(\"pointermove\", onMove);\n handle.addEventListener(\"pointerup\", onUp);\n });\n}\n\n// Per-pane fullscreen toggle.\nfor (const button of document.querySelectorAll<HTMLButtonElement>(\".pane-fullscreen\")) {\n const pane = document.getElementById(button.dataset.pane!)!;\n button.addEventListener(\"click\", (): void => {\n if (document.fullscreenElement === pane) void document.exitFullscreen();\n else void pane.requestFullscreen();\n });\n}\n\nvoid registerPickerPlugins.then(() =>\n tinymce\n .init({\n selector: \"#editor\",\n // Load all five plugin modules: layouts, source-toggle (custom), and three pickers (from @pantoken/tinymce).\n plugins: \"pantoken_layouts pantoken_source_toggle pantoken_components pantoken_icons pantoken_logos\",\n // Toolbar includes the layouts button, source-view toggle, and the three picker buttons.\n toolbar: \"pantokenLayouts sourcecode | pantokenComponents pantokenIcons pantokenLogos\",\n menubar: false,\n theme: \"silver\",\n branding: false,\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 setup(editor: Editor): void {\n editor.on(\"input change Undo Redo SetContent\", () => debouncedUpdatePreview());\n },\n })\n .then((editors: Editor[]) => {\n activeEditor = editors[0];\n refreshAll();\n }),\n);\n",
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
+ "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. */\nbody.canvas-rce-shell-enabled {\n display: flex;\n flex-direction: column;\n padding: 0;\n}\n\n#app {\n margin: 0 auto;\n width: 100%;\n}\n\nbody.canvas-rce-shell-enabled #app {\n padding: 1rem 3rem;\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(\n in srgb,\n light-dark(var(--instui-color-background-container), var(--instui-color-background-page)) 92%,\n transparent\n );\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/* instui-button -color-primary owns the fill/glyph contrast (including its dark-mode swap) —\n this only pins the icon-only link's size so it doesn't stretch inside the brand row. */\n.canvas-rce-shell__brand-mark {\n flex-shrink: 0;\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.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 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: 0.5rem;\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\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: 2px solid var(--instui-color-stroke-base);\n border-radius: 10px;\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-self: flex-start;\n gap: 0.125rem;\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: 1px solid #ccc;\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: 1px solid #ccc;\n width: 100%;\n padding: 0.5rem 1rem;\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\">\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 </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",
32
+ "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 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 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 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 header (its\n// color menu swatches) back to true colors, immune to whatever color the chrome currently has\n// active — see plugins/pantoken/custom-theme-colors.\nconst CUSTOM_THEME_COLORS_CSS = customThemeColorsCss(undefined, {\n selector: \"\",\n resetSelector: \"#theme-tray, #canvas-rce-shell\",\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 CUSTOM_THEME_COLORS_CSS,\n fontsCss,\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 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\";\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.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\";\n themeLabel.textContent = 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\";\n\n/** Reads the persisted locale choice, tolerating missing/corrupt/blocked storage. */\nfunction loadLocale(): string {\n try {\n return localStorage.getItem(LOCALE_STORAGE_KEY) || \"en\";\n } catch {\n return \"en\";\n }\n}\n\nconst activeLocale = loadLocale();\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` (a real dependency for any scaffolded project) and the icon packages\n// `build-canvas-rce.ts` vendors into `node_modules` purely so this docs-hosted preview's \"None\n// (inline)\" provider doesn't have to hit a CDN for `::name` autocomplete/picker glyphs.\nconst localAssetUrls = import.meta.glob<string>(\n \"/node_modules/@pantoken/plugin-{logos,simple-icons,lucide-lab,custom-icons}/dist/**/*.css\",\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 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 logos,\n products,\n currentAssets,\n onMissingAsset,\n buildAssetUrl: buildSelectedAssetUrl,\n },\n layouts: {\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({ onInsert: () => void refreshAll() }),\n);\ntinymce.PluginManager.add(CONTENT_CLASSES_PLUGIN_NAME, createContentClassesPlugin());\ntinymce.PluginManager.add(\n A11Y_PLUGIN_NAME,\n createA11yPlugin({ 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 height: EDITOR_HEIGHT_PX,\n display: \"footer\",\n extensions: [\n pantokenHtmlLinter({ model: [...listComponents(), ...listUtilities()] as any }),\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 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 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(buildFileUrl(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 }\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 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.\nconst PREVIEW_WIDTHS: Record<string, string> = {\n medium: \"var(--instui-breakpoints-md)\",\n small: \"var(--instui-breakpoints-sm)\",\n};\n\nlet selectedPreviewWidth = \"large\";\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 return;\n }\n if (fullscreen) {\n previewFrame.style.maxWidth = PREVIEW_WIDTHS[selectedPreviewWidth];\n } else {\n previewPane.style.flex = \"0 0 auto\";\n previewPane.style.width = PREVIEW_WIDTHS[selectedPreviewWidth];\n }\n}\n\npreviewWidthButtons.forEach((button) => {\n button.addEventListener(\"click\", () => {\n selectToggleButton(previewWidthButtons, button);\n selectedPreviewWidth = button.dataset.previewWidth!;\n applyPreviewWidth();\n persistPreferences();\n });\n});\nif (\n preferences.previewWidth &&\n [\"large\", \"medium\", \"small\"].includes(preferences.previewWidth) &&\n preferences.previewWidth !== \"large\"\n) {\n const savedWidthButton = [...previewWidthButtons].find(\n (button) => button.dataset.previewWidth === preferences.previewWidth,\n );\n if (savedWidthButton) {\n selectToggleButton(previewWidthButtons, savedWidthButton);\n selectedPreviewWidth = preferences.previewWidth;\n applyPreviewWidth();\n }\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 as \"large\" | \"medium\" | \"small\",\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 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\nvoid registerPantokenPlugin.then(() =>\n tinymce\n .init({\n selector: \"#editor\",\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 syncThemeColorFromEditor();\n syncIconAssetsFromEditor();\n document.documentElement.dataset.pantokenScheme = includeDarkModeCheckbox.checked\n ? \"dark\"\n : \"light\";\n applyEditorTheme(activeEditor);\n void refreshAll();\n }),\n);\n",
33
+ "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\";\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",
31
34
  "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}",
32
- "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 \"helpAriaLabel\": \"Help\",\n \"copyHtmlLabel\": \"Copy HTML\",\n \"editorPaneLabel\": \"Editor\",\n \"previewPaneLabel\": \"Preview\",\n \"previewFrameTitle\": \"Styled preview\",\n \"fullscreenEditorAriaLabel\": \"Fullscreen editor\",\n \"fullscreenPreviewAriaLabel\": \"Fullscreen preview\",\n \"resizePanesAriaLabel\": \"Resize editor and preview\",\n \"stackVerticallyLabel\": \"Stack vertically\",\n \"stackSideBySideLabel\": \"Stack side by side\",\n \"swapPanesLabel\": \"Swap panes\",\n \"themeTrayAriaLabel\": \"Theme settings\",\n \"tabConfigLabel\": \"Config\",\n \"tabCssLabel\": \"CSS\",\n \"tabJsLabel\": \"JS\",\n \"cdnProviderLabel\": \"CDN provider\",\n \"themeLabel\": \"Theme\",\n \"modeLabel\": \"Mode\",\n \"downloadCssLabel\": \"Download theme.css\",\n \"downloadJsLabel\": \"Download theme.js\",\n \"regenerateLabel\": \"Regenerate from config\",\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"
35
+ "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 \"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",
36
+ "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",
37
+ "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"
33
38
  },
34
39
  "components": {
35
40
  ".gitignore": "node_modules\ndist\n",
@@ -121,7 +126,6 @@ const SCAFFOLDS = {
121
126
  const SCAFFOLD_OVERLAYS = {
122
127
  "ar": {
123
128
  "angular": { "README.md": "```markdown\n# {{projectName}}\n\nتطبيق Angular مستقل (عبر Vite + `@analogjs/vite-plugin-angular`، بدون Angular CLI) مصمم باستخدام\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) و\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (عناصر pantoken مخصصة\nلـ Angular).\n\n## تطوير\n\n```sh\nnpm install\nnpm run dev\n```\n\n## ما هو موجود هنا\n\n- `src/main.ts` يستدعي `registerPantokenElements()` (من `@pantoken/angular`) مرة واحدة عند\n بدء التطبيق بحيث تعمل عناصر مثل `<instui-icon>` في القوالب، ويستورد رمز/مكون CSS بالإضافة إلى\n `@pantoken/interactions` (يهيئ النافذة المنبثقة والتلميح والسلوكيات الأخرى للمكون بشكل مباشر).\n- `src/app.component.ts` هو مكون مستقل (`CUSTOM_ELEMENTS_SCHEMA` يسمح لمجمع\n القوالب بقبول علامات العناصر المخصصة من pantoken) التي يتم تصميم نموذجها باستخدام `instui-*`\n الفئات؛ نقاط الإدراج الاختيارية (الرأس، المرشحات، المحتوى، المتابع) تم تحديدها بـ\n `<div data-slot=\"...\">`.\n- طبق فئات مثل `class=\"instui-button\"` على العلامات؛ انظر\n [مرجع المكون](https://pantoken.app/api/css) للحصول على قائمة الفئات الكاملة.\n\n## تعرف على المزيد\n\nانظر [دليل البدء السريع](https://pantoken.app/guide/getting-started) لمعرفة المزيد.\n```\n" },
124
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nموارد جاهزة للتحميل لـ **محرر المظهر** الخاص بـ Canvas LMS، بالإضافة إلى معاينة محلية لإنشاء قوالب صفحات **محرر المحتوى الغني** (RCE) مصممة باستخدام\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## ما الموجود هنا\n\n- `theme.css` / `theme.js` — قم بتحميل هذين الملفين ضمن **Theme Editor → Advanced** في Canvas.\n تم بناؤهما للموفر/المظهر/الوضع الذي اخترته عند الإنشاء الأولي (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light بشكل افتراضي) ويتضمنان محملاً لـ\n `@pantoken/interactions` (يوصل سلوكيات المكونات مثل modal و tooltip و drilldown).\n- `index.html` / `src/main.ts` — محرر محلي قائم على TinyMCE (`npm run dev`) يعكس RCE الخاص بـ Canvas\n بحيث يمكنك إنشاء قوالب الصفحات ضد فئات pantoken قبل نسخها إلى Canvas.\n يتم بناء الصفحة نفسها باستخدام تخطيط `wrapper` من pantoken: انقر على **Edit theme** لفتح درج جانبي\n يحتوي على علامات **Config** / **CSS** / **JS** (محددات موفر CDN/المظهر/الوضع، وملفات نسخ يمكن تحريرها بصرياً\n من `theme.css`/`theme.js` التي توفر المعاينة المباشرة)، والزر **?**\n للتعليمات الكاملة. استخدم زر شريط الأدوات **Layouts** للبدء من أحد قوالب صفحات البداية المجمعة في pantoken (hero و callout و two-column و rubric note و testimonial)، المأخوذة من\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## التطوير\n\n```sh\nnpm install\nnpm run dev\n```\n\nيفتح هذا خادم تطوير Vite يتضمن:\n\n- جزء **محرر** (TinyMCE، يطابق الإصدار/الإعدادات\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) التي يستخدمها بنفسه — انظر أدناه).\n استخدم زر **Layouts** لتحميل أحد التخطيطات المجمعة (هذا يستبدل المستند بالكامل، بعد تأكيد، بدلاً من الإدراج عند المؤشر)، و\n تبديل **Source code** لتحرير كود HTML الخام في عرض مضاء بصرياً (CodeMirror) بجانب المحرر، مع\n تحديث جزء المعاينة بشكل حي أثناء الكتابة — بخلاف ملحق `code` المدمج في TinyMCE، الذي يحرر في\n نافذة حوار حجم واحد بدون معاينة حية.\n- جزء **معاينة** يعرض محتوى المحرر مع تطبيق ورقة الأنماط/السكريبت الحالي من علامة CSS/JS (وليس فقط\n عناوين URL المحل المستخلصة)، مغلفة لمطابقة الخلفية ومنطقة المحتوى الحد الأقصى للعرض الخاص بـ Canvas — فحص \"كيف سيبدو هذا بمجرد تحميله إلى Canvas\" دقيق، محدث\n بشكل حي أثناء الكتابة أو تحرير المظهر.\n- يجلس المحرر وأجزاء المعاينة في عرض مقسوم يمكنك تغيير حجمه بسحب الفاصل، وتكديسه\n عمودياً بدلاً من جنباً إلى جنب، وتبديل الترتيب (اسحب شريط أدوات جزء على الآخر،\n أو استخدم زر **Swap panes**). لكل جزء زر ملء الشاشة الخاص به.\n- يحتوي درج **Edit theme** الجانبي على محددات موفر/مظهر/وضع CDN و\n روابط **Download theme.css** / **Download theme.js** في علامة **Config**؛ علاماتها **CSS**/**JS** عبارة عن نسخ قابلة للتحرير\n من الملفات المُنتجة — قم بتحريرها يدويًا وستلتقط المعاينة تغييراتك مباشرة. تغيير اختيار Config يعيد تصميم\n علامات CSS/JS ما لم تكن قد حررتها بالفعل، وفي هذه الحالة يظهر زر **Regenerate from config** بدلاً من\n الكتابة فوق تحريرك بصمت.\n\n## سير العمل\n\n1. قم بتحميل `theme.css` و `theme.js` إلى محرر المظهر في Canvas (**Advanced → CSS / JavaScript**) بحيث\n تكون فئات pantoken متاحة في كل صفحة.\n2. قم بتشغيل `npm run dev`، استخدم **Layouts** للبدء من قالب بداية مجمع، وحرره كما\n تفعل في RCE الخاص بـ Canvas نفسه.\n3. انقر على **Copy HTML** والصق النتيجة في RCE لصفحة Canvas (بدّل إلى عرض محرر HTML\n أولاً). يقوم Canvas بتطهير HTML المُلصق من جانب الخادم — لا يحاول هذا الإنشاء الأولي تكرار ذلك، لذا تحقق دائماً من النتيجة المُلصقة في Canvas (انظر \"ملاحظات حول RCE الخاص بـ Canvas\"\n أدناه).\n\n## ملاحظات حول RCE الخاص بـ Canvas\n\nيقوم محرر Canvas للمحتوى الغني بتشغيل TinyMCE وتطهير HTML المُرسل من جانب الخادم مقابل قائمة بيضاء (`gems/canvas_sanitize` في canvas-lms، تُبقى متزامنة مع\n`valid_elements`/`extended_valid_elements` الخاصة بـ TinyMCE نفسه). ما تعنيه تلك القائمة البيضاء للقوالب المبنية هنا:\n\n- `class`، `id`، `style`، `title`، `role`، و `aria-*` مسموحة على كل عنصر —\n خطافات التصميم `class=\"instui-*\"` الخاصة بـ pantoken (و `style` المدمج، مثل موضع CSS anchor)\n **تبقى** محفوظة عند اللصق والحفظ، خلافاً للإرشادات الأقدم في هذا الملف. يتم دائماً حذف علامات `<script>`.\n- **مكونات pantoken الآمنة لـ RCE**: المكونات الثابتة/العرض — alert و view و heading و text و table و\n زر-كـ-`<a>` (وليس `<button>` حقيقي)، blockquote. التزم بـ HTML الدلالي الذي يدعمه pantoken بالفعل\n (`div`، `p`، `span`، `a`، `img`، العناوين، القوائم، الجداول).\n- **RCE-غير آمن**: أي شيء من مجموعة السلوك `@pantoken/interactions` — modal و tooltip و\n drilldown و close-button أو أي مكون آخر يتم تشغيله بواسطة السمات الأصلية `popover`/`popovertarget`/\n `command`/`commandfor`. تلك السمات ليست في قائمة Canvas البيضاء المسموح بها، لذلك\n يبقى الوسم ولكن السلوك التفاعلي ينكسر بصمت في المرة الأولى التي يتم فيها حفظ الصفحة في Canvas، حتى مع وجود محمل `theme.js` `@pantoken/interactions`. يتم حذف عناصر النموذج الحقيقية (`input`، `form`، `button`، `select`، `textarea`، `label`) و `<svg>` المدمج بالكامل — لا يستخدم أي من قوالب البداية المجمعة لهما.\n\nيحمل `theme.js` `@pantoken/interactions` من CDN، الذي يعمل في نطاق صفحة Canvas العام —\nمفيد للتفاعلات على الصفحات التي تبنيها مباشرة في RCE الخاص بـ Canvas مع تحريرات HTML الخام، لكن (كما هو موضح أعلاه) أي وسم يتم تشغيله بواسطة سمة `popover`/`command` المُلصق من معاينة RCE هنا لن يبقى تفاعليًا بمجرد حفظه.\n" },
125
129
  "components": { "README.md": "# {{projectName}}\n\nتطبيق TypeScript عادي (عبر Vite) مصمم باستخدام\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)، رموز وأيقونات Instructure.\n\n## تطوير\n\n```sh\nnpm install\nnpm run dev\n```\n\n## ما الموجود هنا\n\n- [`index.html`] يحتوي على علامات الصفحة الفعلية — غلاف تخطيط [`wrapper`] من\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). عرض المصدر\n وعدّله مباشرة؛ لا يتم حقن أي شيء بواسطة JavaScript.\n- [`src/main.ts`] يستورد [`@pantoken/css`] (يحدد كل خاصية [`--instui-*`] المخصصة)،\n [`@pantoken/components/base.css`] (قيم المستند الافتراضية + حلقة التركيز)، [`components.css`]\n (فئات [`.instui-*`])، [`@pantoken/interactions`] (ينظم النافذة المنبثقة والتلميح وسلوكيات المكونات الأخرى\n الجاهزة للاستخدام)، والخاص بك [`src/style.css`] — أضف السلوك التفاعلي هنا.\n- نقاط الإدراج الاختيارية (الرأس، والمرشحات، والمحتوى، واللاحقة) يتم تحديدها باستخدام\n [`<div data-slot=\"...\">`] في [`index.html`] — استبدل محتوياتها بوسمك الخاص.\n- طبّق الفئات مثل [`class=\"instui-button\"`] على الوسوم؛ انظر إلى\n [مرجع المكون](https://pantoken.app/api/css) للحصول على قائمة الفئات الكاملة.\n\n## تعرف على المزيد\n\nراجع [دليل HTML](https://pantoken.app/guide/components) لتعرف على المزيد.\n" },
126
130
  "next": { "README.md": "# {{projectName}}\n\nتطبيق Next.js (App Router) مصمم بـ [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next)،\nرموز التصميم والأيقونات من Instructure.\n\n## تطوير\n\n```sh\nnpm install\nnpm run dev\n```\n\n## ما هو موجود هنا\n\n- يغلف `next.config.mjs` الإعدادات مع `withPantoken(...)` (يضيف pantoken إلى `transpilePackages`).\n- يستورد `app/layout.tsx` `@pantoken/css`، الذي يحدد كل خاصية مخصصة `--instui-*`، في الجذر بحيث تكون متاحة على كل صفحة، بالإضافة إلى فئة الجذر لتخطيط `wrapper` على `<body>` و `PantokenInteractions` (مكون عميل يحمل `@pantoken/interactions` — ينظم سلوكيات النوافذ المنبثقة والتلميحات والمكونات الأخرى جاهزة للاستخدام).\n- يعرض `app/page.tsx` ترميزًا منسقًا بفئات `instui-*`؛ تُحدد نقاط الإدراج الاختيارية (الرأس والمرشحات والمحتوى والنهاية) بـ `<div data-slot=\"...\">`.\n\n## معرفة المزيد\n\nراجع [دليل البدء](https://pantoken.app/guide/getting-started) لمعرفة المزيد.\n" },
127
131
  "react": { "README.md": "# {{projectName}}\n\nتطبيق Vite + React مُصمّم باستخدام [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react) و[`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css)، رموز التصميم والأيقونات من Instructure.\n\n## تطوير\n\n```sh\nnpm install\nnpm run dev\n```\n\n## ما يوجد هنا\n\n- يستورد `src/main.tsx` من `@pantoken/css` (التي تحدد كل خاصية `--instui-*` مخصصة) و`@pantoken/interactions` (التي تُفعّل سلوكيات الحوار والتلميح والمكونات الأخرى جاهزة للاستخدام).\n- يعرّض `src/App.tsx` ترميز HTML مصمّم باستخدام فئات `instui-*`؛ نقاط الإدراج الاختيارية (رأس، مرشحات، محتوى، متأخرة) مشار إليها بـ `<div data-slot=\"...\">`.\n- لمكتبة InstUI الكاملة لمكونات React (أزرار، حوارات، إلخ. — بما في ذلك `@pantoken/react`'s `<Icon>`)، أضف حزم `@instructure/ui-*` المحددة التي تحتاجها — انظر <https://instructure.design>.\n\n## تعرف على المزيد\n\nراجع [دليل البدء](https://pantoken.app/guide/getting-started) لمعرفة المزيد.\n" },
@@ -131,7 +135,6 @@ const SCAFFOLD_OVERLAYS = {
131
135
  },
132
136
  "hy": {
133
137
  "angular": { "README.md": "# {{projectName}}\n\nԻնքնուրույն Angular հավելված (Vite + `@analogjs/vite-plugin-angular`-ի միջոցով, առանց Angular CLI-ի) ոճավորված\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) և\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) հետ (pantoken հատուկ տարրեր\nAngular-ի համար):\n\n## Մշակել\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Ինչ կա այստեղ\n\n- `src/main.ts`-ը կանչում է `registerPantokenElements()`-ը (`@pantoken/angular`-ից) մեկ անգամ բեռնման ժամանակ, որպեսզի `<instui-icon>`-ի նման տարրերը աշխատեն հավելվածներում, և ներմուծում է տոկեն/բաղադրիչ CSS-ը և `@pantoken/interactions`-ը (միացնում է մոդալ, հուշում և այլ բաղադրիչ վարքագիծ անմիջապես):\n- `src/app.component.ts`-ը ինքնուրույն բաղադրիչ է (`CUSTOM_ELEMENTS_SCHEMA`-ը թույլ է տալիս հավելվածների կազմապատկերին ընդունել pantoken-ի հատուկ տարր պիտակներ), որի հավելվածը ոճավորված է `instui-*` դասերով; ընտրովի ներմուծման կետերը (գլխավոր, ֆիլտրեր, բովանդակություն, վերջավոր) նշված են `<div data-slot=\"...\">`-ով:\n- Կիրառել դասեր `class=\"instui-button\"`-ի նման նշումներին; տե՛ս [բաղադրիչի հղում](https://pantoken.app/api/css) ամբողջ դասի ցանկի համար:\n\n## Իմացեք ավելի շատ\n\nՏե՛ս [Սկսելու համար ուղեցույց](https://pantoken.app/guide/getting-started) ավելի շատ իմանալու համար:\n" },
134
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nCanvas LMS-ի **Theme Editor**-ի համար պատրաստ ներբեռնման ակտիվներ, ինչպես նաև Rich Content Editor (RCE) էջերի շաբլոնները ստեղծելու համար տեղական նախադիտում [`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)-ով:\n\n## Ինչ կա այստեղ\n\n- `theme.css` / `theme.js` — այս երկու ֆայլերը վերբեռնեք Canvas-ի **Theme Editor → Advanced** բաժնում:\n Դրանք կառուցված են այն CDN մատակարարի/թեմայի/ռեժիմի համար, որը դուք ընտրել եք գոյացման ժամանակ (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light լռելյայն հաստատված), և ներառում են `@pantoken/interactions`-ի բեռնիչ (միացնում է բաղադրիչների վարքը, ինչպես modal, tooltip և drilldown):\n- `index.html` / `src/main.ts` — տեղական, TinyMCE-ի վրա հիմնված խմբագիր (`npm run dev`), որը արտացոլում է Canvas-ի\n RCE-ն, այնպես որ դուք կարող եք ստեղծել էջերի շաբլոնները pantoken-ի դասերի հետ՝ այդ դրանք Canvas-ում մեջտեղ պատճենելուց առաջ:\n Էջն ինքն կառուցված է pantoken-ի `wrapper` դասավորությամբ՝ սեղմեք **Edit theme** թեմայի խմբագրումը բացելու համար\n **Config** / **CSS** / **JS** ներդիրներով (CDN մատակարար/թեմա/ռեժիմ ընտրելու համար, և շարահյուսական ընդգծվածով,\n `theme.css`/`theme.js`-ի ձեռքով խմբագրելի պատճենները, որոնք կերակուր տալիս են ինտերակտիվ նախադիտումին), և **?** կոճակը\n ամբողջական հրահանգների համար: Օգտագործեք **Layouts** գործիքագոտի կոճակը՝ pantoken-ի կապակցված մեկնարկային էջերի դասավորություններից մեկից մեկնարկելու համար (hero, callout, երկու սյունակ, rubric note, testimonial), որոնցից կազմված են\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts):\n\n## Զարգացում\n\n```sh\nnpm install\nnpm run dev\n```\n\nՍա բացում է Vite development սերվերը՝\n\n- **Editor** շրջան (TinyMCE, համապատասխան տարբերակ/կամ\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) ինքն օգտագործում է — տես ստորև):\n Օգտագործեք **Layouts** կոճակը՝ կապակցված մեկնարկային դասավորություններից մեկ բեռնելու համար (սա ամբողջ\n փաստաթուղթն փոխարինում է հաստատման մեջ, այլ ոչ թե կուրսորում ներբեռնելը), և **Source code** միացմամբ\n ամբողջ HTML-ն ձեռքով խմբագրել շարահյուսական ընդգծվածով (CodeMirror) տեսարանում խմբագրի կողքին, նախադիտման շրջանը թարմացվում է\n ցածր, ինչ դուք մուտքագրում եք — ի տարբերություն TinyMCE-ի բաժնային `code` պլագինի, որը խմբագրում է մեկանգամյա modal երկխոսակում՝\n առանց ինտերակտիվ նախադիտման:\n- A **նախադիտում** շրջան, որը ցույց տալիս է խմբագրի բովանդակությունը ընթացիկ CSS/JS ներդիրի ոճի թերթ/սկրիպտով\n կիրառված (ոչ միայն լուծված CDN URL-ներ), Canvas-ի սեփական բովանդակ-տարածքի ֆոնի և առավելագույն լայնության հետ համընդհանուր — հավատարիմ \"ինչ կլինի այն Canvas-ում վերբեռնվելուց հետո\" ստուգում, թարմացվում է\n ցածր, ինչ դուք մուտքագրում կամ թեմա խմբագրում եք:\n- Խմբագիր և նախադիտման շրջաններ տեղադրված են բաժանված դեսքում, որը կարող եք չափափոխել բաժանիչը տանելով, բաղկացել\n ուղղահայաց փոխարենը կողքի կողքի, և փոխել (տանել շրջանի գործիքագոտին մյուսի վրա,\n կամ օգտագործել **Swap panes** կոճակը): Յուրաքանչյուր շրջան ունի իր սեփական ամբողջ էկրան կոճակ:\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 are editable copies\n of the generated files — hand-edit them and the preview picks up your changes directly. Changing\n a Config select re-generates the CSS/JS tabs unless you've already edited them, in which case a\n **Regenerate from config** button appears instead of silently overwriting your edit.\n\nԹեմայի խմբագրման դիտասինակի **Config** ներդիրը պահում է CDN մատակարար/թեմա/ռեժիմ ընտրելու համար և\n**Download theme.css** / **Download theme.js** հղումներ; դրա **CSS**/**JS** ներդիրները խմբագրվող պատճեններ են\nցուցադրվածի ֆայլերի — ձեռքով խմբագրել դրանք և նախադիտումը ուղղակիորեն ընկալում է ձեր փոփոխությունները: Փոխելով\nConfig ընտրել վերաստեղծել CSS/JS ներդիրները, եթե դուք դեռ չեք խմբագրել դրանք, որի դեպքում\n**Regenerate from config** կոճակ հայտնվում է, այլ չինքը լռուն վերաշարադրել ձեր խմբագրումը:\n\n## Workflow\n\n1. Վերբեռնեք `theme.css` և `theme.js` Canvas-ի Theme Editor (**Advanced → CSS / JavaScript**) այնպես որ\n pantoken-ի դասերը հասանելի են յուրաքանչյուր էջում:\n2. Գործարկեք `npm run dev`, օգտագործեք **Layouts** մեկնարկային մեկը մեկնարկելու համար, և խմբագրել այն, ինչպես դուք\n կային Canvas-ի սեփական RCE-ում:\n3. Սեղմեք **Copy HTML** և մեջտեղ ստացված արդյունքը Canvas էջի RCE-ում (փոխել HTML խմբագիր\n տեսարան առաջինը): Canvas ընտրահատ HTML սխալ-կողմի վրա — այս մակարդակը ոչ մի դեպքում չի փորձել\n կրկնօրինակել, այնպես որ միշտ գուշակել ստացված արդյունքը Canvas-ում (տես \"Canvas-ի RCE-ի վերաբերյալ նշումներ\"\n ստորև):\n\n## Canvas-ի RCE-ի վերաբերյալ նշումներ\n\nCanvas Rich Content Editor-ն գործարկում է TinyMCE և պահում ներկայացվածի HTML-ը սերվերի վրա\nթույլ ցուցակի դեմ (`gems/canvas_sanitize` canvas-lms-ում, պահ-ից պահ TinyMCE-ի սեփական\n`valid_elements`/`extended_valid_elements`): Ինչ այդ թույլ ցուցակը նշանակում է այստեղ կառուցված շաբլոնների համար.\n\n- `class`, `id`, `style`, `title`, `role`, և `aria-*` հատկանիշներ թույլ տրվածե յուրաքանչյուր տարրի վրա —\n pantoken-ի `class=\"instui-*\"` ստեղծման կեռներ (և ամբողջ միջուկային `style`, օրինակ CSS anchor դիրքավորման համար)\n **կատարել են** պահում թարկել խմբազերծել, հակառակ հին ղեկավարության այս ֆայլում: `<script>` ներդիրներ\n միշտ վերջ հատվածահատ:\n- **RCE-անվտանգ pantoken բաղադրիչներ**: ստատիկ/դիտել բաղադրիչներ — alert, view, heading, text, table,\n ա button-as-`<a>` (ոչ այն `<button>`), blockquote: Մնալ վերլուծական HTML pantoken-ի\n հավաքածու (`div`, `p`, `span`, `a`, `img`, վերնագրեր, ցանկերը, սեղաններ):\n- **RCE-ապահովել**: մի որ որ `@pantoken/interactions`-ի վարքի հավաքածուից — modal, tooltip,\n drilldown, close-button, կամ որ այլ բաղադրիչ խմբավար տեղային `popover`/`popovertarget`/\n `command`/`commandfor` հատկանիշներ: Այդ հատկանիշները չեն Canvas-ի պահ-մկ թույլ ցուցակում, այնպես որ\n մարկապ ապահովել, բայց ինտերակտիվ վարքը լռուն խախտել առաջինը, որ էջը\n պահ-ը Canvas-ում, նույնիսկ `theme.js`-ի `@pantoken/interactions` բեռնիչով: Իրական form\n տարրեր (`input`, `form`, `button`, `select`, `textarea`, `label`) և ամբողջ միջուկային `<svg>` են\n վերջ հատվածահատ — բաղկացավածի մեկնարկային շաբլոնները խմբավար չեն:\n\n`theme.js` բեռ `@pantoken/interactions` CDN-ից, որը գործարկում է Canvas-ի գլոբալ էջ տեղ —\nօգտակար ինտերակցիայի համար էջերի վրա, որը դուք գծել եք ուղղակիորեն Canvas-ի RCE-ում raw HTML խմբագրմամբ, բայց (վերը\nներկայացված) որ որ `popover`/`command`-attribute-խմբավար մարկապ թարկել RCE նախադիտումից այստեղ չի մնալ\nինտերակտիվ, մեկ պահ:\n" },
135
138
  "components": { "README.md": "# {{projectName}}\n\nՊարզ TypeScript հավելված (Vite-ի միջոցով) որ ստեղծվել է\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructure-ի\nդիզայն տոկենների և պատկերակներով:\n\n## Զարգացում\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Ինչ կա այստեղ\n\n- `index.html` պահում է իրական էջի մեջբերումը — `wrapper`-դասավորման թաղ\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts): Դիտեք աղբյուրը\n և խմբագրեք այն անմիջապես. JavaScript-ը ոչինչ չի ներարկվում:\n- `src/main.ts` ներմուծում է `@pantoken/css` (սահմանում է յուրաքանչյուր `--instui-*` սովորական հատկություն),\n `@pantoken/components/base.css` (փաստաթղթի կանխադրված + ֆոկուս օղակ), `components.css`\n (`.instui-*` դասեր), `@pantoken/interactions` (միացնում է մոդալ, հուշում և այլ բաղադրիչ վարքագծեր հաստիք),\n և ձեր սեփական `src/style.css` — ավելացրեք ինտերակտիվ վարքագիծ այստեղ:\n- Ընտրովի ներդրման կետերը (վերնագիր, ֆիլտրեր, բովանդակություն, հետևել) նշվում են\n `<div data-slot=\"...\">` `index.html`-ում — փոխարինել նրանց բովանդակությունը ձեր սեփական մեջբերմամբ:\n- Կիրառել դասեր, ինչպես `class=\"instui-button\"` մեջբերմամբ. տես\n [բաղադրիչի հղում](https://pantoken.app/api/css) ամբողջ դասերի ցանկի համար:\n\n## Իմացեք ավելի շատ\n\nՏեսեք [HTML ուղեցույց](https://pantoken.app/guide/components) ավելի շատ իմանալու համար:\n" },
136
139
  "next": { "README.md": "# {{projectName}}\n\nNext.js (App Router) հավելված՝ ստեղծված [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next)ով, Instructure-ի դիզայն տոկենները և պատկերակները:\n\n## Մշակում\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Ինչ կա այստեղ\n\n- `next.config.mjs` փաղաղել է կազմաձևումը `withPantoken(...)`ով (ավելացնում է pantoken-ը `transpilePackages`-ում):\n- `app/layout.tsx` ներածում է `@pantoken/css`, որը սահմանում է `--instui-*` բոլոր հատուկ հատկությունները արմատում՝ որպեսզի դրանք հասանելի լինեն բոլոր էջերում, ինչպես նաև `wrapper` դասավորության արմատային դասը `<body>` և `PantokenInteractions`-ի վրա (հաճախորդի բաղադրիչ, որը բեռնում է `@pantoken/interactions` — կազմավորում է մոդալ, ցուցակ և այլ բաղադրիչների վարքագիծ ուղղակիորեն):\n- `app/page.tsx` ներկայացնում է նշանակում, որը ստեղծված է `instui-*` դասերով; ընտրովի տեղադրման կետերը (վերնագիր, ֆիլտրեր, բովանդակություն, հետևում) նշված են `<div data-slot=\"...\">`-ով:\n\n## Իմացեք ավելին\n\nՏե՛ս [սկսելու ուղեցույցը](https://pantoken.app/guide/getting-started) ավելին իմանալու համար:\n" },
137
140
  "react": { "README.md": "# {{projectName}}\n\nVite + React հավելված՝ ձևավորված [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react) և [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css) միջոցով, Instructure-ի դիզայն տոկեններ և պատկերակներ:\n\n## Մշակում\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Ինչ կա այստեղ\n\n- `src/main.tsx`-ը ներմուծում է `@pantoken/css` (սահմանում է յուրաքանչյուր `--instui-*` հատուկ հատկություն) և `@pantoken/interactions` (միացնում է մոդալ, ծանուցում և այլ բաղադրիչ վարքագիծ հստակ):\n- `src/App.tsx`-ը ցուցադրում է մարկածը ձևավորված `instui-*` դասերով; տարբերակային հատում կետերը (վերնագիր, ֆիլտրեր, բովանդակություն, վերջավորություն) նշված են `<div data-slot=\"...\">`-ով:\n- InstUI-ի լրիվ React բաղադրիչ գրադարանի համար (կոճակներ, մոդալներ և այլն — ներառյալ `@pantoken/react`-ի `<Icon>`), ավելացրեք ձեզ անհրաժեշտ տեղանշված `@instructure/ui-*` փաթեթները — տես <https://instructure.design>:\n\n## Իմացեք ավելին\n\nՏե՛ս [ծանուցում սկսելու ուղեցույցը](https://pantoken.app/guide/getting-started) ավելին իմանալու համար:\n" },
@@ -141,7 +144,6 @@ const SCAFFOLD_OVERLAYS = {
141
144
  },
142
145
  "ca": {
143
146
  "angular": { "README.md": "# {{projectName}}\n\nUna aplicació Angular autònoma (via Vite + `@analogjs/vite-plugin-angular`, sense Angular CLI) estilitzada amb\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) i\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (elements personalitzats de pantoken\nper a Angular).\n\n## Desenvolupar\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Què hi ha aquí\n\n- `src/main.ts` crida `registerPantokenElements()` (des de `@pantoken/angular`) una vegada durant l'arrencada perquè elements com `<instui-icon>` funcionin en plantilles, i importa el CSS token/component més\n`@pantoken/interactions` (connecta comportaments de modal, tooltip i altres components de forma predeterminada).\n- `src/app.component.ts` és un component autònom (`CUSTOM_ELEMENTS_SCHEMA` permet al compilador de plantilles acceptar etiquetes d'elements personalitzats de pantoken) la plantilla del qual està estilitzada amb classes `instui-*`; els punts d'inserció opcionals (capçalera, filtres, contingut, final) es marquen amb\n`<div data-slot=\"...\">`.\n- Aplica classes com `class=\"instui-button\"` al codi; consulta la\n[referència de components](https://pantoken.app/api/css) per a la llista completa de classes.\n\n## Més informació\n\nConsulta la [guia de primeres pasos](https://pantoken.app/guide/getting-started) per a més informació.\n" },
144
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nActius llestos per pujar al **Theme Editor** de Canvas LMS, més una vista previa local per crear plantilles de pàgines del Rich Content Editor (RCE) estilitzades amb\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Què hi ha aquí\n\n- `theme.css` / `theme.js` — puja aquests dos fitxers en **Theme Editor → Advanced** a Canvas.\n Estan construïts per al proveïdor CDN/tema/mode que vas triar en fer l'andamiatge (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light per defecte) i inclouen un carregador per a\n `@pantoken/interactions` (connecta comportaments de components com modal, tooltip i drilldown).\n- `index.html` / `src/main.ts` — un editor local basat en TinyMCE (`npm run dev`) que reflecteix l'RCE de Canvas perquè puguis crear plantilles de pàgines contra les classes de pantoken abans de copiar-les a Canvas.\n La pàgina es construeix amb el disseny `wrapper` de pantoken: fes clic a **Edit theme** per obrir una safata amb pestanyes **Config** / **CSS** / **JS** (seleccions de proveïdor CDN/tema/mode, i còpies destacades sintàcticament i editables a mà de `theme.css`/`theme.js` que alimenten la vista previa en directe), i el botó **?** per a instruccions completes. Utilitza el botó de barra d'eines **Layouts** per començar des d'un dels dissenys de pàgina inicial inclosos de pantoken (heroi, trucada, dos columnes, nota de rúbrica, testimoni), obtinguts de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Desenvolupar\n\n```sh\nnpm install\nnpm run dev\n```\n\nAixò obri un servidor de desenvolupament de Vite amb:\n\n- Un panell **editor** (TinyMCE, que coincideix amb la versió/configuració que\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) utilitza — mira més avall).\n Utilitza el botó **Layouts** per carregar un dels dissenys d'iniciació inclosos (això reemplaça tot el document, després de confirmar, en lloc d'inserir al cursor), i el botó de commutació **Source code** per editar manualment l'HTML sense format en una vista destacada sintàcticament (CodeMirror) al costat de l'editor, amb el panell de vista previa actualitzant-se en directe mentre escrius — a diferència del connector `code` estàndard de TinyMCE, que edita en un diàleg modal d'una sola vegada sense vista previa en directe.\n- Un panell de **vista previa** que mostra el contingut de l'editor amb la fulla d'estil/script de la pestanya CSS/JS actual aplicada (no només les URL del CDN resoltes), envoltada per coincidir amb el fons de l'àrea de contingut de Canvas i l'amplada màxima — una comprovació fidel de \"com es veurà aquest element una vegada es pugi a Canvas\", actualitzada en directe mentre escrius o edites el tema.\n- Els panells de l'editor i la vista previa es troben en una vista dividida que pots redimensionar arrossegant el divisor, apilar verticalment en lloc de costat a costat, i intercanviar l'ordre (arrossega la barra d'eines d'un panell al d'altri, o utilitza el botó **Swap panes**). Cada panell té el seu propi botó de pantalla completa.\n- La pestanya **Config** de la safata **Edit theme** conté les seleccions del proveïdor CDN/tema/mode i els enllaços **Download theme.css** / **Download theme.js**; les seves pestanyes **CSS**/**JS** són còpies editables dels fitxers generats — edita'ls manualment i la vista previa recull els teus canvis directament. Canviar una selecció de Config regenera les pestanyes CSS/JS tret que ja les hagis editat, en aquest cas apareix un botó **Regenerate from config** en lloc de sobreescriure silenciosament la teva edició.\n\n## Flux de treball\n\n1. Puja `theme.css` i `theme.js` al Theme Editor de Canvas (**Advanced → CSS / JavaScript**) perquè les classes de pantoken estiguin disponibles a cada pàgina.\n2. Executa `npm run dev`, utilitza **Layouts** per començar des d'un inici inclòs, i edita-ho com ho farías en l'RCE propi de Canvas.\n3. Fes clic a **Copy HTML** i enganxa el resultat en l'RCE d'una pàgina de Canvas (passa a la vista de l'editor HTML primer). Canvas higienitza l'HTML pegat al costat del servidor — aquest andamiatge no intenta replicar-ho, així que sempre verifica el resultat pegat a Canvas (veure \"Notes sobre l'RCE de Canvas\" més avall).\n\n## Notes sobre l'RCE de Canvas\n\nL'editor de contingut ric de Canvas executa TinyMCE i higienitza l'HTML enviat al servidor contra una llista de permesos (`gems/canvas_sanitize` a canvas-lms, mantinguda sincronitzada amb la seva pròpia `valid_elements`/`extended_valid_elements` de TinyMCE). Què significa aquesta llista de permesos per a les plantilles construïdes aquí:\n\n- Els atributs `class`, `id`, `style`, `title`, `role`, i `aria-*` estan permesos en cada element —\n els ganxos de disseny `class=\"instui-*\"` de pantoken (i inline `style`, per exemple, per al posicionament d'ancla CSS)\n **sí que sobreviuen** ser pegats i desats, contràriament a les guies més antigues en aquest fitxer. Els atributs `<script>` sempre s'eliminen.\n- **Components de pantoken segurs per a RCE**: components estàtics/de visualització — alerta, vista, encapçalament, text, taula,\n un botó-com-`<a>` (no és un verdader `<button>`), cita de bloc. Manté-t amb HTML semàntic que pantoken ja suporta (`div`, `p`, `span`, `a`, `img`, encapçalaments, llistes, taules).\n- **No segur per a RCE**: qualsevol cosa del conjunt de comportaments de `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, o qualsevol altre component conduït pels atributs natiu `popover`/`popovertarget`/\n `command`/`commandfor`. Aquests atributs no es troben a la llista de permesos de l'higienitzador de Canvas, així que el marcat sobreviu però el comportament interactiu es trenca silenciosament la primera vegada que es guarda la pàgina a Canvas, fins i tot amb el carregador `@pantoken/interactions` de `theme.js` present. Els elements de formulari reals (`input`, `form`, `button`, `select`, `textarea`, `label`) i inline `<svg>` s'eliminen totalment — cap dels andamiatges inicials inclosos els utilitzen.\n\n`theme.js` carrega `@pantoken/interactions` des del CDN, que s'executa en l'abast de la pàgina global de Canvas —\nútil per a interaccions en pàgines que construeixes directament en l'RCE de Canvas amb edicions HTML sense format, però (com es va dir anteriorment) qualsevol marcat conduït per atributs `popover`/`command` pegat des de la vista previa de RCE aquí no romandrà interactiu una vegada desat.\n" },
145
147
  "components": { "README.md": "# {{projectName}}\n\nUna aplicació TypeScript simple (via Vite) estilitzada amb\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), els tokens de disseny i icones\nd'Instructure.\n\n## Desenvolupar\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Què hi ha aquí\n\n- `index.html` conté el marcat de pàgina real — un shell de disseny `wrapper` de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Visualitza el codi font\n i edita-ho directament; res no s'injecta per JavaScript.\n- `src/main.ts` importa `@pantoken/css` (defineix cada propietat personalitzada `--instui-*`),\n `@pantoken/components/base.css` (paràmetres per defecte del document + anell de focus), `components.css`\n (classes `.instui-*`), `@pantoken/interactions` (connecta modal, tooltip i altres comportaments de component fora de la caixa), i el teu propi `src/style.css` — afegeix comportament interactiu aquí.\n- Els punts d'inserció opcionals (capçalera, filtres, contingut, pista) es marquen amb\n `<div data-slot=\"...\">` en `index.html` — reemplaça els seus continguts amb el teu marcat.\n- Aplica classes com `class=\"instui-button\"` al marcat; consulteu la\n [referència de components](https://pantoken.app/api/css) per a la llista completa de classes.\n\n## Més informació\n\nConsulteu la [guia HTML](https://pantoken.app/guide/components) per aprendre més.\n" },
146
148
  "next": { "README.md": "# {{projectName}}\n\nUna aplicació Next.js (App Router) estilitzada amb [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next), els tokens de disseny i les icones d'Instructure.\n\n## Desenvolupar\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Què hi ha aquí\n\n- `next.config.mjs` embolica la configuració amb `withPantoken(...)` (afegeix pantoken a `transpilePackages`).\n- `app/layout.tsx` importa `@pantoken/css`, que defineix cada propietat personalitzada `--instui-*`, a l'arrel de manera que estigui disponible a cada pàgina, més la classe arrel del layout `wrapper` a `<body>` i `PantokenInteractions` (un component client que carrega `@pantoken/interactions` — connecta comportaments de modal, tooltip i altres components automàticament).\n- `app/page.tsx` renderitza marcat estilitzat amb classes `instui-*`; els punts d'inserció opcionals (header, filters, content, trailing) estan marcats amb `<div data-slot=\"...\">`.\n\n## Saber més\n\nConsulta la [guia de primeres passes](https://pantoken.app/guide/getting-started) per saber més.\n" },
147
149
  "react": { "README.md": "# {{projectName}}\n\nUna aplicació Vite + React estilitzada amb [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react) i [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), tokens de disseny i icones d'Instructure.\n\n## Desenvolupar\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Què hi ha aquí\n\n- `src/main.tsx` importa `@pantoken/css` (defineix cada propietat personalitzada `--instui-*`) i `@pantoken/interactions` (connecta comportaments de modal, tooltip i altres components de sèrie).\n- `src/App.tsx` renderitza marques estilitzades amb classes `instui-*`; els punts d'inserció opcionals (capçalera, filtres, contingut, final) estan marcats amb `<div data-slot=\"...\">`.\n- Per a la biblioteca completa de components React d'InstUI (botons, modals, etc. — incloent `@pantoken/react`'s `<Icon>`), afegiu els paquets específics `@instructure/ui-*` que necessiteu — veure <https://instructure.design>.\n\n## Saber més\n\nVeure la [guia de primers passos](https://pantoken.app/guide/getting-started) per obtenir més informació.\n" },
@@ -151,7 +153,6 @@ const SCAFFOLD_OVERLAYS = {
151
153
  },
152
154
  "da": {
153
155
  "angular": { "README.md": "# {{projectName}}\n\nEn standalone Angular-app (via Vite + `@analogjs/vite-plugin-angular`, ingen Angular CLI) stiliseret med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) og\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken custom elements\ntil Angular).\n\n## Udvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hvad er her\n\n- `src/main.ts` kalder `registerPantokenElements()` (fra `@pantoken/angular`) én gang ved opstart, så\n elementer som `<instui-icon>` virker i skabeloner, og importerer token/komponent-CSS plus\n `@pantoken/interactions` (forbinder modal-, tooltip- og andre komponentadfærder ud af\n boksen).\n- `src/app.component.ts` er en standalone-komponent (`CUSTOM_ELEMENTS_SCHEMA` lader skabelon-compileren\n acceptere pantoken's custom element-tags) hvis skabelon er stiliseret med `instui-*`\n klasser; valgfri indsætningspunkter (header, filters, content, trailing) er markeret med\n `<div data-slot=\"...\">`.\n- Anvend klasser som `class=\"instui-button\"` på markup; se\n [komponentreference](https://pantoken.app/api/css) for den komplette klasselist.\n\n## Læs mere\n\nSe [startguiden](https://pantoken.app/guide/getting-started) for at lære mere.\n" },
154
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nUploadklar aktiver til Canvas LMS's **Theme Editor**, plus en lokal eksempel til forfatning af Rich Content Editor (RCE)-sideskabeloner designet med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Hvad der er her\n\n- `theme.css` / `theme.js` — upload disse to filer under **Theme Editor → Advanced** i Canvas.\n De er bygget til CDN-provideren/tema/tilstand du valgte ved opskaffering (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light som standard) og inkluderer en loader til\n `@pantoken/interactions` (forbinder komponentadfærd som modal, tooltip og drilldown).\n- `index.html` / `src/main.ts` — en lokal, TinyMCE-baseret editor (`npm run dev`) der afspejler Canvas's\n RCE, så du kan forfatte sideskabeloner mod pantoken's klasser før du kopierer dem til Canvas.\n Siden selv er bygget med pantoken's `wrapper` layout: klik **Edit theme** for at åbne en bakke\n med **Config** / **CSS** / **JS** faneblade (CDN-provider/tema/tilstand-vælgere, og syntaksmarkeret,\n håndedigerbar kopi af `theme.css`/`theme.js` der indfaster den direkte forhåndsvisning), og **?**-knappen\n til fulde instruktioner. Brug **Layouts** værktøjslinjeknappen til at starte fra en af pantoken's bundlede\n startsidesidelayouts (hero, callout, to-kolonne, rubric note, testimonial), hentet fra\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Udvikl\n\n```sh\nnpm install\nnpm run dev\n```\n\nDette åbner en Vite dev-server med:\n\n- En **editor**-rude (TinyMCE, matchende version/config som\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) selv bruger — se nedenfor).\n Brug **Layouts**-knappen til at indlæse en af de bundlede starterlayouts (dette erstatter hele\n dokumentet efter en bekræftelse, snarere end at indsætte ved markøren), og **Source code**-skifte\n til at håndedigere det rå HTML i en syntaksmarkeret (CodeMirror) visning ved siden af editoren, med\n forhåndsvisningsruden der opdateres direkte mens du skriver — i modsætning til TinyMCE's standard `code` plugin, som redigerer i\n en engangsboksdialog uden direkte forhåndsvisning.\n- En **preview**-rude som viser editorens indhold med det aktuelle CSS/JS-faneblds stylesheet/script\n anvendt (ikke bare de løste CDN-URL'er), pakket for at matche Canvas's eget indholds-områdes baggrund\n og max-bredde — et troværdigt \"hvordan dette vil se ud når det er uploadet til Canvas\" tjek, opdateret\n direkte mens du skriver eller redigerer temaet.\n- Editor- og forhåndsvisningsruderne sidder i en delt visning du kan ændre størrelse på ved at trække skillelinjen,\n stable vertikalt i stedet for side om side, og bytte rækkefølgen af (træk en rudes værktøjslinje til den anden,\n eller brug **Swap panes**-knappen). Hver rude har sin egen fuldskerm-knap.\n- **Edit theme**-bakken's **Config**-faneblad indeholder CDN-provider/tema/tilstand-vælgere og\n **Download theme.css** / **Download theme.js** links; dets **CSS**/**JS**-faneblade er redigerbar kopi\n af de genererede filer — håndedigér dem og forhåndsvisningen henter dine ændringer direkte. Ændring af\n en Config-vælger regenererer CSS/JS-fanebladene medmindre du allerede har redigeret dem, i hvilket tilfælde en\n **Regenerate from config**-knap dukker op i stedet for at stille overskrive din redigering.\n\n## Workflow\n\n1. Upload `theme.css` og `theme.js` til Canvas's Theme Editor (**Advanced → CSS / JavaScript**) så\n pantoken's klasser er tilgængelige på hver side.\n2. Kør `npm run dev`, brug **Layouts** til at starte fra en bundlet starter, og rediger det som du\n ville i Canvas's egen RCE.\n3. Klik **Copy HTML** og indsæt resultatet i en Canvas-sides RCE (skift til HTML-editoren\n visning først). Canvas saniterer indsatte HTML server-side — dette stilladser forsøger ikke at\n kopiere det, så verificer altid det indsatte resultat i Canvas (se \"Noter om Canvas's RCE\"\n nedenfor).\n\n## Noter om Canvas's RCE\n\nCanvas Rich Content Editor kører TinyMCE og saniterer indsendt HTML på serveren mod en\ntilladelsesliste (`gems/canvas_sanitize` i canvas-lms, holdt i synkronisering med TinyMCE's egen\n`valid_elements`/`extended_valid_elements`). Hvad denne tilladelsesliste betyder for skabeloner bygget her:\n\n- `class`, `id`, `style`, `title`, `role` og `aria-*` attributter er tilladt på hvert element —\n pantoken's `class=\"instui-*\"` styling hooks (og inline `style`, f.eks. til CSS anker-positionering)\n **gør** overleve at blive indsatte og gemt, i modsætning til ældre vejledning i denne fil. `<script>` tags\n fjernes altid.\n- **RCE-sikre pantoken-komponenter**: statiske/display-komponenter — alert, view, heading, text, table,\n en knap-som-`<a>` (ikke en rigtig `<button>`), blockquote. Hold dig til semantisk HTML pantoken allerede\n understøtter (`div`, `p`, `span`, `a`, `img`, overskrifter, lister, tabeller).\n- **RCE-usikker**: noget fra `@pantoken/interactions`'s adfærdssæt — modal, tooltip,\n drilldown, close-button, eller enhver anden komponent drevet af det native `popover`/`popovertarget`/\n `command`/`commandfor` attributter. Disse attributter er ikke i Canvas's sanitizer tilladelsesliste, så\n markeringen overlever men den interaktive adfærd bryder stumme første gang siden\n gemmes i Canvas, selv med `theme.js`'s `@pantoken/interactions` loader til stede. Rigtige form\n elementer (`input`, `form`, `button`, `select`, `textarea`, `label`) og inline `<svg>` er\n fjernet helt — ingen af de bundlede starter-skabeloner bruger dem.\n\n`theme.js` indlæser `@pantoken/interactions` fra CDN'en, som køres i Canvas's globale sidescope —\nnyttigt til interaktioner på sider du bygger direkte i Canvas's RCE med rå HTML-redigeringer, men (pr.\novenstående) enhver `popover`/`command`-attribut-drevet markup indsatte fra RCE-forhåndsvisningen her forbliver ikke\ninteraktiv når den gemmes.\n" },
155
156
  "components": { "README.md": "# {{projectName}}\n\nEn simpel TypeScript-app (via Vite) stilet med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructures\ndesign tokens og ikoner.\n\n## Udvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hvad er her\n\n- `index.html` indeholder det faktiske sidemarkup — en `wrapper`-layout skal fra\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Se kildekoden\n og rediger den direkte; intet indsprøjtes af JavaScript.\n- `src/main.ts` importerer `@pantoken/css` (definerer hver `--instui-*` brugerdefineret egenskab),\n `@pantoken/components/base.css` (dokumentstandards + fokusring), `components.css`\n (`.instui-*` klasser), `@pantoken/interactions` (aktiverer modal, tooltip og andre komponentadfærd som standard), og din egen `src/style.css` — tilføj interaktiv adfærd her.\n- Valgfrie indsætningspunkter (overskrift, filtre, indhold, slutning) er markeret med\n `<div data-slot=\"...\">` i `index.html` — erstat deres indhold med dit eget markup.\n- Anvend klasser som `class=\"instui-button\"` på markup; se\n [komponentreference](https://pantoken.app/api/css) for den komplette klasselist.\n\n## Læs mere\n\nSe [HTML-vejledningen](https://pantoken.app/guide/components) for at lære mere.\n" },
156
157
  "next": { "README.md": "# {{projectName}}\n\nEn Next.js (App Router)-app udformet med [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nInstructures designtokens og ikoner.\n\n## Udvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hvad finder du her\n\n- `next.config.mjs` omslutter konfigurationen med `withPantoken(...)` (tilføjer pantoken til\n `transpilePackages`).\n- `app/layout.tsx` importerer `@pantoken/css`, som definerer hver `--instui-*` brugerdefineret\n egenskab, ved roden, så den er tilgængelig på hver side, samt `wrapper` layoutets rodklasse på\n `<body>` og `PantokenInteractions` (en klientkomponent, der indlæser `@pantoken/interactions` —\n forbinder modal, tooltip og anden komponentadfærd direkte).\n- `app/page.tsx` gengiver markup, der er formateret med `instui-*` klasser; valgfri indsætningspunkter (header,\n filters, content, trailing) markeres med `<div data-slot=\"...\">`.\n\n## Få mere at vide\n\nSe [introduktionsvejledningen](https://pantoken.app/guide/getting-started) for at få mere at vide.\n" },
157
158
  "react": { "README.md": "# {{projectName}}\n\nEn Vite + React-app udformet med [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nog [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructures designtokens og\nikoner.\n\n## Udvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hvad er her\n\n- `src/main.tsx` importerer `@pantoken/css` (definerer hver `--instui-*` custom property) og\n `@pantoken/interactions` (sætter modal-, tooltip- og anden komponentadfærd op fra starten).\n- `src/App.tsx` gengiver markup udformet med `instui-*` classes; valgfri indsætningspunkter (header,\n filters, content, trailing) er markeret med `<div data-slot=\"...\">`.\n- For InstUI's komplette React-komponentbibliotek (buttons, modals, osv. — inklusive `@pantoken/react`'s\n `<Icon>`), tilføj de specifikke `@instructure/ui-*` pakker du har brug for — se <https://instructure.design>.\n\n## Lær mere\n\nSe [startguiden](https://pantoken.app/guide/getting-started) for at lære mere.\n" },
@@ -161,7 +162,6 @@ const SCAFFOLD_OVERLAYS = {
161
162
  },
162
163
  "nl": {
163
164
  "angular": { "README.md": "# {{projectName}}\n\nEen standalone Angular-app (via Vite + `@analogjs/vite-plugin-angular`, geen Angular CLI) gestyled met\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) en\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken custom elements\nvoor Angular).\n\n## Ontwikkelen\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Wat is hier\n\n- `src/main.ts` roept `registerPantokenElements()` aan (van `@pantoken/angular`) eenmaal bij bootstrap zodat elementen zoals `<instui-icon>` in templates werken, en importeert de token/component CSS plus\n`@pantoken/interactions` (verbindt modal, tooltip, en ander componentgedrag direct).\n- `src/app.component.ts` is een standalone component (`CUSTOM_ELEMENTS_SCHEMA` laat de template compiler pantoken's custom element tags accepteren) waarvan de template gestyled is met `instui-*`\nclasses; optionele insertie punten (header, filters, content, trailing) zijn gemarkeerd met\n`<div data-slot=\"...\">`.\n- Pas classes zoals `class=\"instui-button\"` toe op markup; zie de\n[componentreferentie](https://pantoken.app/api/css) voor de volledige klassenlijst.\n\n## Meer informatie\n\nZie de [startgids](https://pantoken.app/guide/getting-started) voor meer informatie.\n" },
164
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nUpload-klare assets voor Canvas LMS's **Theme Editor**, plus een lokale preview voor het schrijven van Rich Content Editor (RCE) paginasjablonen opgesteld met\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Wat hier staat\n\n- `theme.css` / `theme.js` — upload deze twee bestanden onder **Theme Editor → Advanced** in Canvas.\n Ze zijn gemaakt voor de CDN-provider/thema/modus die u hebt gekozen bij het scaffolding (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light standaard) en bevatten een loader voor\n `@pantoken/interactions` (schakelt componentgedragingen in zoals modal, tooltip en drilldown).\n- `index.html` / `src/main.ts` — een lokale, TinyMCE-gebaseerde editor (`npm run dev`) die Canvas's\n RCE weerspiegelt, zodat u paginasjablonen tegen pantoken's classes kunt schrijven voordat u deze in Canvas kopieert.\n De pagina zelf is gemaakt met pantoken's `wrapper` layout: klik op **Edit theme** om een tray\n met **Config** / **CSS** / **JS** tabbladen te openen (CDN-provider/thema/modus selecties en syntaxgemarkeerde,\n handmatig bewerkbare kopieën van `theme.css`/`theme.js` die de live preview voeden), en de **?** knop\n voor volledige instructies. Gebruik de **Layouts** werkbalkknop om te starten met een van pantoken's gebundelde\n starterlayouts (hero, callout, twee kolommen, rubric opmerking, getuigenis), afkomstig van\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Ontwikkelen\n\n```sh\nnpm install\nnpm run dev\n```\n\nDit opent een Vite dev server met:\n\n- Een **editor** deelvenster (TinyMCE, overeenkomstig de versie/configuratie die\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) zelf gebruikt — zie hieronder).\n Gebruik de **Layouts** knop om een van de gebundelde starterlayouts te laden (dit vervangt het hele\n document, na een bevestiging, in plaats van in te voegen bij de cursor), en de **Source code** toggle\n om de ruwe HTML in een syntaxgemarkeerde (CodeMirror) weergave naast de editor handmatig te bewerken, met\n het voorbeelddeelvenster live bijgewerkt terwijl u typt — anders dan TinyMCE's standaard `code` plugin, dat in\n een eenmalig modaal dialoogvenster bewerkt zonder live preview.\n- Een **preview** deelvenster met de inhoud van de editor met de huidige CSS/JS tab's stylesheet/script\n toegepast (niet alleen de opgeloste CDN-URL's), ingepakt om overeen te komen met Canvas's eigen content-area achtergrond\n en maximale breedte — een betrouwbare \"hoe dit er uitziet zodra het naar Canvas is geüpload\" controle, live bijgewerkt\n terwijl u typt of het thema bewerkt.\n- De editor en preview deelvensters bevinden zich in een gesplitste weergave die u kunt vergroten/verkleinen door de scheidingslijn te slepen, stapelen\n verticaal in plaats van naast elkaar, en de volgorde van verwisselen (sleep een deelvenster's werkbalk naar het andere,\n of gebruik de **Swap panes** knop). Elk deelvenster heeft zijn eigen fullscreen knop.\n- De **Edit theme** tray's **Config** tab bevat de CDN-provider/thema/modus selecties en\n **Download theme.css** / **Download theme.js** koppelingen; zijn **CSS**/**JS** tabbladen zijn bewerkbare kopieën\n van de gegenereerde bestanden — bewerk ze handmatig en de preview haalt uw wijzigingen direct op. Het wijzigen van\n een Config-selectie genereert de CSS/JS-tabbladen opnieuw, tenzij u deze al hebt bewerkt, in welk geval een\n **Regenerate from config** knop verschijnt in plaats van uw bewerking stilzwijgend te overschrijven.\n\n## Workflow\n\n1. Upload `theme.css` en `theme.js` naar Canvas's Theme Editor (**Advanced → CSS / JavaScript**) zodat\n pantoken's classes op elke pagina beschikbaar zijn.\n2. Voer `npm run dev` uit, gebruik **Layouts** om te starten met een gebundelde starter, en bewerk dit zoals u\n zou doen in Canvas's eigen RCE.\n3. Klik op **Copy HTML** en plak het resultaat in een Canvas pagina's RCE (schakel eerst naar de HTML editor\n weergave). Canvas desinfecteert geplakte HTML server-zijdig — deze scaffold probeert dat niet te\n repliceren, dus controleer altijd het geplakte resultaat in Canvas (zie \"Opmerkingen over Canvas's RCE\"\n hieronder).\n\n## Opmerkingen over Canvas's RCE\n\nDe Canvas Rich Content Editor voert TinyMCE uit en desinfecteert ingediende HTML op de server tegen een\nallowlist (`gems/canvas_sanitize` in canvas-lms, gesynchroniseerd met TinyMCE's eigen\n`valid_elements`/`extended_valid_elements`). Wat die allowlist voor sjablonen die hier zijn gebouwd betekent:\n\n- `class`, `id`, `style`, `title`, `role` en `aria-*` attributen zijn toegestaan op elk element —\n pantoken's `class=\"instui-*\"` styling hooks (en inline `style`, bv. voor CSS anchor positioning)\n **doen** blijven behouden wanneer geplakt en opgeslagen, in tegenstelling tot oudere richtlijnen in dit bestand. `<script>` tags\n worden altijd verwijderd.\n- **RCE-veilige pantoken-componenten**: statische/weergave-componenten — alert, view, heading, text, table,\n een knop-als-`<a>` (geen echte `<button>`), blockquote. Houd je aan semantische HTML die pantoken al\n ondersteunt (`div`, `p`, `span`, `a`, `img`, koppen, lijsten, tabellen).\n- **RCE-onveilig**: alles uit `@pantoken/interactions`'s gedragsset — modal, tooltip,\n drilldown, close-button, of enig ander onderdeel aangestuurd door de systeemeigen `popover`/`popovertarget`/\n `command`/`commandfor` attributen. Die attributen bevinden zich niet in Canvas's sanitizer allowlist, dus\n de opmaak blijft behouden maar het interactieve gedrag breekt stil de eerste keer dat de pagina in Canvas wordt\n opgeslagen, zelfs met `theme.js`'s `@pantoken/interactions` loader aanwezig. Echte formulierelementen (`input`, `form`, `button`, `select`, `textarea`, `label`) en inline `<svg>` zijn\n geheel verwijderd — geen van de gebundelde starterlayouts gebruiken deze.\n\n`theme.js` laadt `@pantoken/interactions` van de CDN, die in Canvas's globale paginabereik wordt uitgevoerd —\nnuttig voor interacties op pagina's die u rechtstreeks in Canvas's RCE bouwt met ruwe HTML-bewerkingen, maar (zie\nhierboven) enige `popover`/`command`-kenmerk-aangestuurde opmaak geplakt vanuit de RCE preview hier zal niet\ninteractief blijven zodra deze is opgeslagen.\n" },
165
165
  "components": { "README.md": "# {{projectName}}\n\nEen gewone TypeScript-app (via Vite) opgesteld met\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), de ontwerp tokens en pictogrammen van Instructure.\n\n## Ontwikkelen\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Wat is hier\n\n- `index.html` bevat de werkelijke pagina-opmaak — een `wrapper`-layout shell van\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Bekijk de bron\n en bewerk het direct; niets wordt door JavaScript ingespoten.\n- `src/main.ts` importeert `@pantoken/css` (definieert elke `--instui-*` aangepaste eigenschap),\n `@pantoken/components/base.css` (documentstandaarden + focusring), `components.css`\n (`.instui-*` klassen), `@pantoken/interactions` (verbindt modal-, tooltip- en andere componentgedragingen meteen), en uw eigen `src/style.css` — voeg hier interactief gedrag toe.\n- Optionele invoegpunten (koptekst, filters, inhoud, navolgende) zijn gemarkeerd met\n `<div data-slot=\"...\">` in `index.html` — vervang hun inhoud door uw eigen opmaak.\n- Pas klassen toe zoals `class=\"instui-button\"` naar opmaak; zie de\n [componentreferentie](https://pantoken.app/api/css) voor de volledige klassenlijst.\n\n## Meer informatie\n\nRaadpleeg de [HTML-gids](https://pantoken.app/guide/components) voor meer informatie.\n" },
166
166
  "next": { "README.md": "# {{projectName}}\n\nEen Next.js (App Router)-app gestileerd met [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nInstructure's designtokens en pictogrammen.\n\n## Ontwikkelen\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Wat staat hier\n\n- `next.config.mjs` verpakt de config met `withPantoken(...)` (voegt pantoken toe aan\n `transpilePackages`).\n- `app/layout.tsx` importeert `@pantoken/css`, die elke `--instui-*` aangepaste\n eigenschap definieert, op het rootniveau zodat deze op elke pagina beschikbaar is, plus de rootklasse van de `wrapper` lay-out op\n `<body>` en `PantokenInteractions` (een clientcomponent die `@pantoken/interactions` laadt —\n verbindt modal-, tooltip- en ander componentgedrag standaard).\n- `app/page.tsx` geeft opmaak weer met `instui-*` klassen; optionele invoegpunten (koptekst,\n filters, inhoud, volgende) zijn gemarkeerd met `<div data-slot=\"...\">`.\n\n## Meer informatie\n\nRaadpleeg de [gids aan de slag](https://pantoken.app/guide/getting-started) voor meer informatie.\n" },
167
167
  "react": { "README.md": "# {{projectName}}\n\nEen Vite + React-app gestileerd met [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nen [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructure's design tokens en\niconen.\n\n## Ontwikkelen\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Wat is hier\n\n- `src/main.tsx` importeert `@pantoken/css` (definieert elke `--instui-*` aangepaste eigenschap) en\n `@pantoken/interactions` (koppelt modal, tooltip en ander componentgedrag direct\n in).\n- `src/App.tsx` rendert opmaak gestileerd met `instui-*` klassen; optionele invoegpunten (header,\n filters, content, trailing) zijn gemarkeerd met `<div data-slot=\"...\">`.\n- Voor InstUI's volledige React-componentenbibliotheek (knoppen, modalen, enz. — inclusief `@pantoken/react`'s\n `<Icon>`), voeg de specifieke `@instructure/ui-*` pakketten toe die u nodig hebt — zie <https://instructure.design>.\n\n## Meer informatie\n\nZie de [gids Aan de slag](https://pantoken.app/guide/getting-started) voor meer informatie.\n" },
@@ -171,7 +171,6 @@ const SCAFFOLD_OVERLAYS = {
171
171
  },
172
172
  "en-AU": {
173
173
  "angular": { "README.md": "# {{projectName}}\n\nA standalone Angular app (via Vite + `@analogjs/vite-plugin-angular`, no Angular CLI) styled with\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) and\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken custom elements\nfor Angular).\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.ts` calls `registerPantokenElements()` (from `@pantoken/angular`) once at bootstrap so\n elements like `<instui-icon>` work in templates, and imports the token/component CSS plus\n `@pantoken/interactions` (wires up modal, tooltip, and other component behaviours out of the\n box).\n- `src/app.component.ts` is a standalone component (`CUSTOM_ELEMENTS_SCHEMA` lets the template\n compiler accept pantoken's custom element tags) whose template is styled with `instui-*`\n classes; optional insertion points (header, filters, content, trailing) are marked with\n `<div data-slot=\"...\">`.\n- Apply classes like `class=\"instui-button\"` to markup; see the\n [component reference](https://pantoken.app/api/css) for the full class list.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
174
- "canvas-theme-editor": { "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 behaviours 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 syntax-highlighted,\n hand-editable copies of `theme.css`/`theme.js` that feed the live preview), and the **?** button\n for full instructions. Use the **Layouts** toolbar button to start from one of pantoken's bundled\n starter page layouts (hero, callout, two-column, 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 (TinyMCE, matching the version/config\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) itself uses — see below).\n Use the **Layouts** button to load one of the bundled starter layouts (this replaces the whole\n document, after a confirm, rather than inserting at the cursor), and the **Source code** toggle\n to hand-edit the raw HTML in a syntax-highlighted (CodeMirror) view alongside the editor, with\n the preview pane updating live as you type — unlike TinyMCE's stock `code` plugin, which edits in\n a one-shot modal dialog with no live preview.\n- A **preview** pane showing the editor's content with the current CSS/JS tab's stylesheet/script\n applied (not just the resolved CDN URLs), wrapped to match Canvas's own content-area background\n and max width — a faithful \"what this will look like once uploaded to Canvas\" check, updated\n live as you type or edit the theme.\n- The editor and preview panes sit in a split view you can resize by dragging the divider, stack\n vertically instead of side by side, and swap the order of (drag a pane's toolbar onto the other,\n or use the **Swap panes** button). Each pane has its own fullscreen button.\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 are editable copies\n of the generated files — hand-edit them and the preview picks up your changes directly. Changing\n a Config select re-generates the CSS/JS tabs unless you've already edited them, in which case a\n **Regenerate from config** button appears instead of silently overwriting your edit.\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.\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). Canvas sanitises pasted HTML server-side — this scaffold doesn't attempt to\n replicate that, so always verify the pasted result in Canvas (see \"Notes on Canvas's RCE\"\n below).\n\n## Notes on Canvas's RCE\n\nThe Canvas Rich Content Editor runs TinyMCE and sanitises 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 behaviour 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 sanitiser allowlist, so\n the markup survives but the interactive behaviour 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" },
175
174
  "components": { "README.md": "# {{projectName}}\n\nA plain TypeScript app (via Vite) styled with\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructure's\ndesign tokens and icons.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `index.html` holds the actual page markup — a `wrapper`-layout shell from\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). View source\n and edit it directly; nothing is injected by JavaScript.\n- `src/main.ts` imports `@pantoken/css` (defines every `--instui-*` custom property),\n `@pantoken/components/base.css` (document defaults + focus ring), `components.css`\n (`.instui-*` classes), `@pantoken/interactions` (wires up modal, tooltip, and other component\n behaviours out of the box), and your own `src/style.css` — add interactive behaviour here.\n- Optional insertion points (header, filters, content, trailing) are marked with\n `<div data-slot=\"...\">` in `index.html` — replace their contents with your own markup.\n- Apply classes like `class=\"instui-button\"` to markup; see the\n [component reference](https://pantoken.app/api/css) for the full class list.\n\n## Learn more\n\nSee the [HTML guide](https://pantoken.app/guide/components) to learn more.\n" },
176
175
  "next": { "README.md": "# {{projectName}}\n\nA Next.js (App Router) app styled with [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nInstructure's design tokens and icons.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `next.config.mjs` wraps the config with `withPantoken(...)` (adds pantoken to\n `transpilePackages`).\n- `app/layout.tsx` imports `@pantoken/css`, which defines every `--instui-*` custom\n property, at the root so it's available on every page, plus the `wrapper` layout's root class on\n `<body>` and `PantokenInteractions` (a client component that loads `@pantoken/interactions` —\n wires up modal, tooltip, and other component behaviours out of the box).\n- `app/page.tsx` renders markup styled with `instui-*` classes; optional insertion points (header,\n filters, content, trailing) are marked with `<div data-slot=\"...\">`.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
177
176
  "react": { "README.md": "# {{projectName}}\n\nA Vite + React app styled with [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nand [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructure's design tokens and\nicons.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.tsx` imports `@pantoken/css` (defines every `--instui-*` custom property) and\n `@pantoken/interactions` (wires up modal, tooltip, and other component behaviours out of the\n box).\n- `src/App.tsx` renders markup styled with `instui-*` classes; optional insertion points (header,\n filters, content, trailing) are marked with `<div data-slot=\"...\">`.\n- For InstUI's full React component library (buttons, modals, etc. — including `@pantoken/react`'s\n `<Icon>`), add the specific __PTK_PACKAGE_#__ packages you need — see <https://instructure.design>.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
@@ -181,7 +180,6 @@ const SCAFFOLD_OVERLAYS = {
181
180
  },
182
181
  "en-CA": {
183
182
  "angular": { "README.md": "# {{projectName}}\n\nA standalone Angular app (via Vite + `@analogjs/vite-plugin-angular`, no Angular CLI) styled with\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) and\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken custom elements\nfor Angular).\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.ts` calls `registerPantokenElements()` (from `@pantoken/angular`) once at bootstrap so\n elements like `<instui-icon>` work in templates, and imports the token/component CSS plus\n `@pantoken/interactions` (wires up modal, tooltip, and other component behaviours out of the\n box).\n- `src/app.component.ts` is a standalone component (`CUSTOM_ELEMENTS_SCHEMA` lets the template\n compiler accept pantoken's custom element tags) whose template is styled with `instui-*`\n classes; optional insertion points (header, filters, content, trailing) are marked with\n `<div data-slot=\"...\">`.\n- Apply classes like `class=\"instui-button\"` to markup; see the\n [component reference](https://pantoken.app/api/css) for the full class list.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
184
- "canvas-theme-editor": { "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 behaviours 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 syntax-highlighted,\n hand-editable copies of `theme.css`/`theme.js` that feed the live preview), and the **?** button\n for full instructions. Use the **Layouts** toolbar button to start from one of pantoken's bundled\n starter page layouts (hero, callout, two-column, 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 (TinyMCE, matching the version/config\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) itself uses — see below).\n Use the **Layouts** button to load one of the bundled starter layouts (this replaces the whole\n document, after a confirm, rather than inserting at the cursor), and the **Source code** toggle\n to hand-edit the raw HTML in a syntax-highlighted (CodeMirror) view alongside the editor, with\n the preview pane updating live as you type — unlike TinyMCE's stock `code` plugin, which edits in\n a one-shot modal dialog with no live preview.\n- A **preview** pane showing the editor's content with the current CSS/JS tab's stylesheet/script\n applied (not just the resolved CDN URLs), wrapped to match Canvas's own content-area background\n and max width — a faithful \"what this will look like once uploaded to Canvas\" check, updated\n live as you type or edit the theme.\n- The editor and preview panes sit in a split view you can resize by dragging the divider, stack\n vertically instead of side by side, and swap the order of (drag a pane's toolbar onto the other,\n or use the **Swap panes** button). Each pane has its own fullscreen button.\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 are editable copies\n of the generated files — hand-edit them and the preview picks up your changes directly. Changing\n a Config select re-generates the CSS/JS tabs unless you've already edited them, in which case a\n **Regenerate from config** button appears instead of silently overwriting your edit.\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.\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). Canvas sanitises pasted HTML server-side — this scaffold doesn't attempt to\n replicate that, so always verify the pasted result in Canvas (see \"Notes on Canvas's RCE\"\n below).\n\n## Notes on Canvas's RCE\n\nThe Canvas Rich Content Editor runs TinyMCE and sanitises 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 behaviour 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 sanitiser allowlist, so\n the markup survives but the interactive behaviour 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" },
185
183
  "next": { "README.md": "```markdown\n# {{projectName}}\n\nA Next.js (App Router) app styled with [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nInstructure's design tokens and icons.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `next.config.mjs` wraps the config with `withPantoken(...)` (adds pantoken to\n `transpilePackages`).\n- `app/layout.tsx` imports `@pantoken/css`, which defines every `--instui-*` custom\n property, at the root so it's available on every page, plus the `wrapper` layout's root class on\n `<body>` and `PantokenInteractions` (a client component that loads `@pantoken/interactions` —\n wires up modal, tooltip, and other component behaviours out of the box).\n- `app/page.tsx` renders markup styled with `instui-*` classes; optional insertion points (header,\n filters, content, trailing) are marked with `<div data-slot=\"...\">`.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n```\n" },
186
184
  "react": { "README.md": "# {{projectName}}\n\nA Vite + React app styled with [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nand [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructure's design tokens and\nicons.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.tsx` imports `@pantoken/css` (defines every `--instui-*` custom property) and\n `@pantoken/interactions` (wires up modal, tooltip, and other component behaviours out of the\n box).\n- `src/App.tsx` renders markup styled with `instui-*` classes; optional insertion points (header,\n filters, content, trailing) are marked with `<div data-slot=\"...\">`.\n- For InstUI's full React component library (buttons, modals, etc. — including `@pantoken/react`'s\n `<Icon>`), add the specific `@instructure/ui-*` packages you need — see <https://instructure.design>.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
187
185
  "vue": { "README.md": "# {{projectName}}\n\nA Vite + Vue 3 app styled with [`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)\nand [`@pantoken/vue`](https://www.npmjs.com/package/@pantoken/vue) (the pantoken Vue plugin).\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.ts` calls `app.use(PantokenVue)` (from `@pantoken/vue`) so elements like\n `<instui-icon>` work in templates, and imports the token CSS plus `@pantoken/interactions`\n (wires up modal, tooltip, and other component behaviours out of the box).\n- `src/App.vue`'s template is styled with `instui-*` classes; optional insertion points (header,\n filters, content, trailing) are marked with `<div data-slot=\"...\">`.\n- Apply classes like `class=\"instui-button\"` to markup; see the\n [component reference](https://pantoken.app/api/css) for the full class list.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
@@ -189,7 +187,6 @@ const SCAFFOLD_OVERLAYS = {
189
187
  },
190
188
  "en-GB": {
191
189
  "angular": { "README.md": "# {{projectName}}\n\nA standalone Angular app (via Vite + `@analogjs/vite-plugin-angular`, no Angular CLI) styled with\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) and\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken custom elements\nfor Angular).\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.ts` calls `registerPantokenElements()` (from `@pantoken/angular`) once at bootstrap so\n elements like `<instui-icon>` work in templates, and imports the token/component CSS plus\n `@pantoken/interactions` (wires up modal, tooltip, and other component behaviours out of the\n box).\n- `src/app.component.ts` is a standalone component (`CUSTOM_ELEMENTS_SCHEMA` lets the template\n compiler accept pantoken's custom element tags) whose template is styled with `instui-*`\n classes; optional insertion points (header, filters, content, trailing) are marked with\n `<div data-slot=\"...\">`.\n- Apply classes like `class=\"instui-button\"` to markup; see the\n [component reference](https://pantoken.app/api/css) for the full class list.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
192
- "canvas-theme-editor": { "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 behaviours 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 syntax-highlighted,\n hand-editable copies of `theme.css`/`theme.js` that feed the live preview), and the **?** button\n for full instructions. Use the **Layouts** toolbar button to start from one of pantoken's bundled\n starter page layouts (hero, callout, two-column, 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 (TinyMCE, matching the version/config\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) itself uses — see below).\n Use the **Layouts** button to load one of the bundled starter layouts (this replaces the whole\n document, after a confirm, rather than inserting at the cursor), and the **Source code** toggle\n to hand-edit the raw HTML in a syntax-highlighted (CodeMirror) view alongside the editor, with\n the preview pane updating live as you type — unlike TinyMCE's stock `code` plugin, which edits in\n a one-shot modal dialogue with no live preview.\n- A **preview** pane showing the editor's content with the current CSS/JS tab's stylesheet/script\n applied (not just the resolved CDN URLs), wrapped to match Canvas's own content-area background\n and max width — a faithful \"what this will look like once uploaded to Canvas\" check, updated\n live as you type or edit the theme.\n- The editor and preview panes sit in a split view you can resize by dragging the divider, stack\n vertically instead of side by side, and swap the order of (drag a pane's toolbar onto the other,\n or use the **Swap panes** button). Each pane has its own full-screen button.\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 are editable copies\n of the generated files — hand-edit them and the preview picks up your changes directly. Changing\n a Config select re-generates the CSS/JS tabs unless you've already edited them, in which case a\n **Regenerate from config** button appears instead of silently overwriting your edit.\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.\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). Canvas sanitises pasted HTML server-side — this scaffold doesn't attempt to\n replicate that, so always verify the pasted result in Canvas (see \"Notes on Canvas's RCE\"\n below).\n\n## Notes on Canvas's RCE\n\nThe Canvas Rich Content Editor runs TinyMCE and sanitises 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 behaviour 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 sanitiser allowlist, so\n the markup survives but the interactive behaviour 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" },
193
190
  "components": { "README.md": "# {{projectName}}\n\nA plain TypeScript app (via Vite) styled with\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructure's\ndesign tokens and icons.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `index.html` holds the actual page markup — a `wrapper`-layout shell from\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). View source\n and edit it directly; nothing is injected by JavaScript.\n- `src/main.ts` imports `@pantoken/css` (defines every `--instui-*` custom property),\n `@pantoken/components/base.css` (document defaults + focus ring), `components.css`\n (`.instui-*` classes), `@pantoken/interactions` (wires up modal, tooltip, and other component\n behaviours out of the box), and your own `src/style.css` — add interactive behaviour here.\n- Optional insertion points (header, filters, content, trailing) are marked with\n `<div data-slot=\"...\">` in `index.html` — replace their contents with your own markup.\n- Apply classes like `class=\"instui-button\"` to markup; see the\n [component reference](https://pantoken.app/api/css) for the full class list.\n\n## Learn more\n\nSee the [HTML guide](https://pantoken.app/guide/components) to learn more.\n" },
194
191
  "next": { "README.md": "# {{projectName}}\n\nA Next.js (App Router) app styled with [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nInstructure's design tokens and icons.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `next.config.mjs` wraps the config with `withPantoken(...)` (adds pantoken to\n `transpilePackages`).\n- `app/layout.tsx` imports `@pantoken/css`, which defines every `--instui-*` custom\n property, at the root so it's available on every page, plus the `wrapper` layout's root class on\n `<body>` and `PantokenInteractions` (a client component that loads `@pantoken/interactions` —\n wires up modal, tooltip, and other component behaviours out of the box).\n- `app/page.tsx` renders markup styled with `instui-*` classes; optional insertion points (header,\n filters, content, trailing) are marked with `<div data-slot=\"...\">`.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
195
192
  "react": { "README.md": "# {{projectName}}\n\nA Vite + React app styled with [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nand [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructure's design tokens and\nicons.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.tsx` imports `@pantoken/css` (defines every `--instui-*` custom property) and\n `@pantoken/interactions` (wires up modal, tooltip, and other component behaviours out of the\n box).\n- `src/App.tsx` renders markup styled with `instui-*` classes; optional insertion points (header,\n filters, content, trailing) are marked with `<div data-slot=\"...\">`.\n- For InstUI's full React component library (buttons, modals, etc. — including `@pantoken/react`'s\n `<Icon>`), add the specific `@instructure/ui-*` packages you need — see <https://instructure.design>.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
@@ -199,7 +196,6 @@ const SCAFFOLD_OVERLAYS = {
199
196
  },
200
197
  "en": {
201
198
  "angular": { "README.md": "# {{projectName}}\n\nA standalone Angular application built with Vite + `@analogjs/vite-plugin-angular` (no Angular CLI), styled using\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) and\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken custom elements\nfor Angular).\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.ts` invokes `registerPantokenElements()` (from `@pantoken/angular`) once at bootstrap so\n elements like `<instui-icon>` render in templates, and it imports the token/component CSS plus\n `@pantoken/interactions` (enables modal, tooltip, and other component behaviors).\n- `src/app.component.ts` is a self-contained component (`CUSTOM_ELEMENTS_SCHEMA` allows the template\n compiler to accept pantoken's custom element tags) whose template uses `instui-*`\n classes; optional insertion slots (header, filters, content, trailing) are marked with\n `<div data-slot=\"...\">`.\n- Add classes such as `class=\"instui-button\"` to your markup; see the\n [component reference](https://pantoken.app/api/css) for the full class list.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
202
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nReady-to-upload assets for Canvas LMS's Theme Editor, plus a local preview for creating Rich Content Editor (RCE) page templates styled with\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## What’s included\n\n- `theme.css` / `theme.js` — upload these two files under Theme Editor → Advanced in Canvas.\n They are built for the CDN provider / theme / mode chosen when scaffolding (`--cdn`/`--theme`/`--theme-mode`; jsDelivr/rebrand/light by default) and include a loader for\n `@pantoken/interactions` (connects component behaviors like modal, tooltip, and drilldown).\n- `index.html` / `src/main.ts` — a local TinyMCE-based editor (`npm run dev`) that mimics Canvas’s RCE so you can author page templates using pantoken’s classes before pasting them into Canvas.\n The page uses pantoken’s `wrapper` layout: click Edit theme to open a tray with Config / CSS / JS tabs (CDN provider / theme / mode selectors and editable, syntax-highlighted copies of `theme.css`/`theme.js` that feed the live preview), plus a ? button with full instructions. Use the Layouts toolbar button to start from one of pantoken’s bundled starter page layouts (hero, callout, two-column, rubric note, testimonial) sourced from\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Development\n\n```sh\nnpm install\nnpm run dev\n```\n\nThis starts a Vite development server with:\n\n- An editor pane (TinyMCE, matching the version/config used by [instructure/canvas-lms](https://github.com/instructure/canvas-lms)). Use the Layouts button to load a bundled starter layout (this replaces the entire document after confirmation, rather than inserting at the cursor), and use the Source code toggle to edit the raw HTML in a syntax-highlighted CodeMirror view alongside the editor. The preview updates live as you type — unlike TinyMCE’s built-in `code` plugin, which opens a one-off modal with no live preview.\n- A preview pane that renders the editor’s content with the current CSS/JS tabs’ stylesheet/script applied (not just the CDN URLs), wrapped to match Canvas’s content-area background and max width — a faithful live preview of how it will look once uploaded to Canvas.\n- Resizable split view for editor and preview panes (drag the divider), with options to stack vertically, swap the panes’ order (drag a pane’s toolbar onto the other or use the Swap panes button), and each pane has a fullscreen button.\n- The Edit theme tray’s Config tab holds the CDN provider / theme / mode selectors and Download theme.css / Download theme.js links; the CSS and JS tabs are editable copies of the generated files — edit them and the preview updates immediately. Changing a Config selector re-generates the CSS/JS tabs unless you’ve already modified them, in which case a Regenerate from config button appears instead of overwriting your edits.\n\n## Workflow\n\n1. Upload `theme.css` and `theme.js` to Canvas’s Theme Editor (Advanced → CSS / JavaScript) so pantoken’s classes are available sitewide.\n2. Run `npm run dev`, use Layouts to start from a bundled starter, and edit as you would inside Canvas’s RCE.\n3. Click Copy HTML and paste the result into a Canvas page’s RCE (switch to the HTML editor view first). Canvas sanitizes pasted HTML server-side — this scaffold does not replicate that sanitization, so always verify the pasted result inside Canvas (see “Notes on Canvas’s RCE” below).\n\n## Notes on Canvas’s RCE\n\nCanvas’s Rich Content Editor runs TinyMCE and sanitizes submitted HTML on the server using an allowlist (`gems/canvas_sanitize` in canvas-lms, kept aligned with TinyMCE’s `valid_elements`/`extended_valid_elements`). Practical implications for templates created here:\n\n- `class`, `id`, `style`, `title`, `role`, and `aria-*` attributes are permitted on all elements — pantoken’s `class=\"instui-*\"` styling hooks (and inline `style`, e.g., for CSS anchor positioning) do survive paste-and-save, contrary to older notes in this file. `<script>` tags are always removed.\n- RCE-safe pantoken components: static/display elements such as alert, view, heading, text, table, a button implemented as `<a>` (not a real `<button>`), and blockquote. Prefer semantic HTML that pantoken supports (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- RCE-unsafe: any component relying on `@pantoken/interactions`’s behavior attributes — modal, tooltip, drilldown, close-button, or components driven by native `popover`/`popovertarget`/`command`/`commandfor` attributes. Those attributes aren’t in Canvas’s sanitizer allowlist, so while the markup may remain, the interactive behavior will break the first time the page is saved in Canvas, even if `theme.js`’s `@pantoken/interactions` loader is present. Real form elements (`input`, `form`, `button`, `select`, `textarea`, `label`) and inline `<svg>` are stripped entirely — none of the bundled starter templates use them.\n\n`theme.js` loads `@pantoken/interactions` from the CDN into Canvas’s global page scope — useful for interactions on pages authored directly in Canvas with raw HTML edits, but as noted above any attribute-driven interactive markup copied from the local RCE preview won’t remain interactive once saved in Canvas.\n" },
203
199
  "components": { "README.md": "# {{projectName}}\n\nA plain TypeScript application (built with Vite) styled with\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), using Instructure’s\ndesign tokens and icons.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What’s included\n\n- `index.html` contains the actual page markup — a `wrapper`-layout shell from\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Open the source\n and edit it directly; JavaScript does not inject any markup.\n- `src/main.ts` imports `@pantoken/css` (which defines every `--instui-*` custom property),\n `@pantoken/components/base.css` (document defaults and focus ring), `components.css`\n (`.instui-*` classes), `@pantoken/interactions` (which wires up modal, tooltip, and other component\n behaviors out of the box), and your own `src/style.css` — add interactive behavior there.\n- Optional insertion points (header, filters, content, trailing) are marked with\n `<div data-slot=\"...\">` inside `index.html` — replace those placeholders with your own markup.\n- Add classes such as `class=\"instui-button\"` to your markup; see the\n [component reference](https://pantoken.app/api/css) for the complete class list.\n\n## Learn more\n\nSee the [HTML guide](https://pantoken.app/guide/components) for more information.\n" },
204
200
  "next": { "README.md": "# {{projectName}}\n\nA Next.js (App Router) application styled with [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nInstructure design tokens and icons.\n\n## Development\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Contents\n\n- `next.config.mjs` wraps the configuration with `withPantoken(...)` (adds pantoken to\n `transpilePackages`).\n- `app/layout.tsx` imports `@pantoken/css`, which defines every `--instui-*` custom\n property at the root so they’re available on every page, and applies the `wrapper` layout’s root class to\n `<body>` and `PantokenInteractions` (a client component that loads `@pantoken/interactions` —\n enabling modal, tooltip, and other component behaviors out of the box).\n- `app/page.tsx` outputs markup styled with `instui-*` classes; optional insertion points (header,\n filters, content, trailing) are exposed via `<div data-slot=\"...\">`.\n\n## More information\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) for details.\n" },
205
201
  "react": { "README.md": "# {{projectName}}\n\nA Vite + React application styled with [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nand [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), using Instructure’s design tokens and\nicons.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.tsx` imports `@pantoken/css` (which defines every `--instui-*` custom property) and\n `@pantoken/interactions` (which enables modal, tooltip, and other component behaviors out of the\n box).\n- `src/App.tsx` renders markup styled with `instui-*` classes; optional insertion points (header,\n filters, content, trailing) are marked with `<div data-slot=\"...\">`.\n- For InstUI's full React component library (buttons, modals, etc. — including `@pantoken/react`'s\n `<Icon>`), add the specific `@instructure/ui-*` packages you need — see <https://instructure.design>.\n\n## Learn more\n\nSee the [getting started guide](https://pantoken.app/guide/getting-started) to learn more.\n" },
@@ -209,7 +205,6 @@ const SCAFFOLD_OVERLAYS = {
209
205
  },
210
206
  "fi": {
211
207
  "angular": { "README.md": "# {{projectName}}\n\nItsenäinen Angular-sovellus (Viten + `@analogjs/vite-plugin-angular` avulla, ilman Angular CLI:tä) tyylitetty\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) ja\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) avulla (pantoken-mukautettuja\nelementtejä Angularille).\n\n## Kehitä\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mitä täällä on\n\n- `src/main.ts` kutsuu `registerPantokenElements()`:ää (lähteestä `@pantoken/angular`) kerran\n käynnistyksen yhteydessä, jotta elementit kuten `<instui-icon>` toimivat malleissa, ja tuo\n token/komponentti-CSS:ään sekä `@pantoken/interactions`:ään (määrittää modaalin, työkaluvihjeen ja\n muiden komponenttikäyttäytymisten toimintamme valmiiksi).\n- `src/app.component.ts` on itsenäinen komponentti (`CUSTOM_ELEMENTS_SCHEMA` sallii mallikääntäjän\n hyväksyä pantoken-mukautettuja elementtitunnisteitä), jonka mallia tyylitetään\n `instui-*`-luokilla; valinnaiset lisäyspaikat (otsikko, suodattimet, sisältö, jäljellä)\n merkitään `<div data-slot=\"...\">`:llä.\n- Käytä luokkia kuten `class=\"instui-button\"` merkintään; katso\n [komponenttireferenssi](https://pantoken.app/api/css) täydellisen luokkaloettelon suhteen.\n\n## Lisätietoja\n\nKatso [aloitusopas](https://pantoken.app/guide/getting-started) saadaksesi lisätietoja.\n" },
212
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nLatausvalmiit varat Canvas LMS:n **Theme Editorille**, sekä paikallinen esikatselu Rich Content Editorin (RCE) sivumallineiden kirjoittamiseen, jotka on tyylitetty käyttäen\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Mitä tässä on\n\n- `theme.css` / `theme.js` — lataa nämä kaksi tiedostoa **Theme Editor → Advanced** -kohtaan Canvasissa.\n Ne on rakennettu CDN-palveluntarjoajalle/teemalle/tilalle, jonka valitsit generoidessasi (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light oletuksena) ja ne sisältävät latausohjelman\n `@pantoken/interactions` -kohteelle (käynnistää komponenttien käyttäytymisen, kuten modaali, vihje ja porautuminen).\n- `index.html` / `src/main.ts` — paikallinen TinyMCE-pohjainen editori (`npm run dev`), joka heijastaa Canvasin\n RCE:tä, joten voit kirjoittaa sivumalleja pantokenin luokkia vastaan ennen kuin kopioit ne Canvasiin.\n Sivu itse on rakennettu pantokenin `wrapper` -asettelulla: napsauta **Edit theme** -painiketta avataksesi laatikon,\n jossa on **Config** / **CSS** / **JS** -välilehdet (CDN-palveluntarjoaja/teema/tilavalitsimet ja syntaksiin korostettavat,\n käsin muokattavat kopiot `theme.css`/`theme.js` -kohdista, jotka syöttävät live-esikatseluun), ja **?** -painike\n täysille ohjeille. Käytä **Layouts**-työkalupainikeita aloittaaksesi yhdestä pantokenin niputetuista aloitussivuasetteluista (hero, callout, two-column, rubric note, testimonial), jotka saadaan\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts) -kohdasta.\n\n## Kehitys\n\n```sh\nnpm install\nnpm run dev\n```\n\nTämä avaa Vite-kehityspalvelimen, jossa on:\n\n- **Editori**-pane (TinyMCE, vastaava versio/konfiguraatio\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) käyttää — katso alla).\n Käytä **Layouts**-painiketta lataaaksesi yhden niputetuista aloitusasetteluista (tämä korvaa koko\n asiakirjan vahvistuksen jälkeen sen sijaan, että insertoisi kursorin), ja **Source code** -vaihtoa\n muokataksesi raakaa HTML:ää syntaksiin korostetussa (CodeMirror) näkymässä editorin vieressä, esikatselupane\n päivittyy live-tilassa kirjoitettaessa — toisin kuin TinyMCE:n oletusarvoinen `code` -laajennos, joka muokkaa\n yhden kerran modaali-ikkunassa ilman live-esikatselua.\n- **Esikatselu**-pane, joka näyttää editorin sisällön nykyisen CSS/JS-välilehden tyylisarjalla/skriptillä\n sovellettuna (ei vain ratkaistuja CDN-URL-osoitteita), kiedottu vastaamaan Canvasin sisältöalue-taustaa\n ja enimmäisleveyttä — uskottava \"miltä tämä näyttää, kun se on ladattu Canvasiin\" -tarkistus, päivittyy\n live-tilassa kirjoitettaessa tai muokatessa teemaa.\n- Editori- ja esikatselu-paalit istuvat jaetulla näkymässä, jonka voit muuttaa koon vetämällä jakajaa, pinoamalla\n pystysuoraan sivujen sijaan ja vaihtamalla järjestystä (vedä paalin työkalupalkkia toiseen,\n tai käytä **Swap panes** -painiketta). Jokaisella paalilla on oma kokoruututila-painike.\n- **Edit theme** -alakultaan **Config**-välilehti sisältää CDN-palveluntarjoaja/teema/tilavalitsimet ja\n **Download theme.css** / **Download theme.js** -linkit; sen **CSS**/**JS**-välilehdet ovat muokattavia kopioita\n luoduista tiedostoista — muokkaa niitä käsin ja esikatselu noutaa muutoksesi suoraan. Konfigurointi-valinnan muuttaminen\n luo uudelleen CSS/JS-välilehdet, ellei ole jo muokannut niitä, jolloin\n **Regenerate from config** -painike tulee näkyviin sen sijaan, että hiljaisesti korvaisi muokkauksesi.\n\n## Työnkulku\n\n1. Lataa `theme.css` ja `theme.js` Canvas-sovelluksen Theme Editoriin (**Advanced → CSS / JavaScript**), jotta\n pantokenin luokat ovat käytettävissä jokaisella sivulla.\n2. Suorita `npm run dev`, käytä **Layouts**-painiketta aloittaaksesi niputetusta starterista, ja muokkaa sitä kuten\n tekisit Canvasin omassa RCE:ssä.\n3. Napsauta **Copy HTML** -painiketta ja liitä tulos Canvas-sivun RCE:hen (vaihda ensin HTML-editori-\n näkymään). Canvas sanitoi liitetyn HTML:n palvelimella — tämä rakenne ei yritä\n toistaa sitä, joten aina tarkista liitetty tulos Canvasissa (katso \"Huomioita Canvasin RCE:stä\"\n alla).\n\n## Huomioita Canvasin RCE:stä\n\nCanvas Rich Content Editor käyttää TinyMCE:tä ja sanitoi lähetetyn HTML:n palvelimella\nsallittavuusluetteloa vastaan (`gems/canvas_sanitize` canvas-lms:ssä, pidetty synkronoituna TinyMCE:n oman\n`valid_elements`/`extended_valid_elements` -kanssa). Mitä tämä sallittavuusluettelo tarkoittaa täällä rakennetuille malleille:\n\n- `class`, `id`, `style`, `title`, `role` ja `aria-*` -attribuutit ovat sallittuja jokaisessa elementissä —\n pantokenin `class=\"instui-*\"` -tyylöinti-hooks (ja inline `style`, esim. CSS-ankkuriasemoinnille)\n **ovat** olemassa, kun ne liitetään ja tallennetaan, vastoin vanhempaa ohjetta tässä tiedostossa. `<script>` -tagit\n poistetaan aina.\n- **RCE-turvallisia pantokenin komponentteja**: staattiset/näyttökomponentit — alert, view, heading, text, table,\n painike-`<a>` -tapauksessa (ei oikeaa `<button>`), blockquote. Pysy semanttisessa HTML:ssä, jota pantokenin\n jo tukee (`div`, `p`, `span`, `a`, `img`, otsikot, listat, taulukot).\n- **RCE-epäturvallisia**: mitään `@pantoken/interactions` -käyttäytymissarjasta — modaali, vihje,\n porautuminen, lähelle-painike tai mikä tahansa muu komponentti, jota ohjaa natiivi `popover`/`popovertarget`/\n `command`/`commandfor` -attribuutit. Nämä attribuutit eivät ole Canvasin sanitoijan sallittavuusluettelossa, joten\n kuvaus säilyy, mutta interaktiivinen käyttäytyminen hiljaisesti rikkoutuu ensimmäisellä kerralla\n sivu tallennetaan Canvasissa, jopa `theme.js` -latausohjelma `@pantoken/interactions` -kohteelle läsnä. Todelliset lomakkeen\n elementit (`input`, `form`, `button`, `select`, `textarea`, `label`) ja inline `<svg>` ovat\n poistetaan kokonaan — mikään niputetuista starter-malleista ei käytä niitä.\n\n`theme.js` lataa `@pantoken/interactions` CDN:stä, joka toimii Canvas-yleisen sivun alueella —\nhyödyllinen vuorovaikutuksille sivuilla, joita rakennat suoraan Canvas-sovelluksen RCE:ssä raakoilla HTML-muokkauksilla, mutta (yllä)\nmikä tahansa `popover`/`command` -attribuuttien ohjaamaa kuvaus, joka on liitetty RCE-esikatselu täältä, ei säily\ninteraktiivinen, kun se on tallennettu.\n" },
213
208
  "components": { "README.md": "# {{projectName}}\n\nTavallinen TypeScript-sovellus (Viten kautta) tyylitelty\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructuren\ndesign-merkkeillä ja kuvakkeilla.\n\n## Kehitä\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mitä täällä on\n\n- `index.html` sisältää todellisen sivun merkinnän — `wrapper`-layout-kuoren seuraa\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Tarkastele lähdekoodia\n ja muokkaa sitä suoraan; mitään ei ole injektoitu JavaScriptillä.\n- `src/main.ts` tuodaan `@pantoken/css` (määrittää jokaisen `--instui-*` mukautetun ominaisuuden),\n `@pantoken/components/base.css` (asiakirjan oletukset + fokusrengas), `components.css`\n (`.instui-*` luokat), `@pantoken/interactions` (liittää modaalin, työkaluvihjeen ja muut komponenttien käytöstavat heti käyttövalmiina), ja omaa\n `src/style.css` — lisää interaktiivista käytöstä tähän.\n- Valinnaiset lisäyspisteet (otsikko, suodattimet, sisältö, jälkimmäinen) on merkitty\n `<div data-slot=\"...\">` kohteessa `index.html` — korvaa niiden sisältö omalla merkinnällä.\n- Käytä luokkia kuten `class=\"instui-button\"` merkintään; katso\n [komponenttien viiteopasta](https://pantoken.app/api/css) täydellisen luettelon luokista.\n\n## Lisätietoja\n\nKatso [HTML-opas](https://pantoken.app/guide/components) saadaksesi lisätietoja.\n" },
214
209
  "next": { "README.md": "# {{projectName}}\n\nNext.js (App Router) -sovellus, joka on tyylitetty [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next) -pakettia käyttäen,\nInstructuren design tokeneita ja ikoneja.\n\n## Kehitä\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mikä tämä on\n\n- `next.config.mjs` käärii konfiguraation `withPantoken(...)` -funktiolla (lisää pantokenin `transpilePackages` -osioon).\n- `app/layout.tsx` tuo `@pantoken/css`, joka määrittelee jokaisen `--instui-*` -ominaisuuden juurella niin, että se on saatavilla jokaisella sivulla, sekä `wrapper` -asettelun juuri-luokan `<body>` ja `PantokenInteractions` -osioissa (`PantokenInteractions` on asiakas-komponentti, joka lataa `@pantoken/interactions` — ottaa käyttöön modaalin, työkaluvihjeen ja muiden komponenttien toiminnallisuudet valmiiksi).\n- `app/page.tsx` renderöi merkintää, joka on tyylitetty `instui-*` -luokilla; valinnaiset lisäyspisteet (otsikko, suodattimet, sisältö, viimeinen) merkitään `<div data-slot=\"...\">` -avulla.\n\n## Lisätietoja\n\nKatso [aloitusopas](https://pantoken.app/guide/getting-started) saadaksesi lisätietoja.\n" },
215
210
  "react": { "README.md": "```markdown\n# {{projectName}}\n\nVite + React -sovellus, joka on tyylitelty [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nja [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructuren design-tunniukset ja kuvakkeita.\n\n## Kehitä\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mitä täällä on\n\n- `src/main.tsx` tuo `@pantoken/css` (määrittää jokaisen `--instui-*` -kohtaisen ominaisuuden) ja\n `@pantoken/interactions` (ottaa käyttöön modaali-, työkaluvihje- ja muiden komponenttien käyttäytymisen valmiiksi).\n- `src/App.tsx` hahmontaa merkinnän, joka on tyylitelty `instui-*` -luokilla; valinnaiset lisäyspisteet (header,\n filters, content, trailing) merkitään `<div data-slot=\"...\">`:llä.\n- InstUI:n täydellisen React-komponenttikirjaston (painikkeet, modaalit jne. — mukaan lukien `@pantoken/react`:n\n `<Icon>`) käyttöä varten lisää tarvitsemasi tietyt `@instructure/ui-*` -paketit — katso <https://instructure.design>.\n\n## Lisätietoja\n\nKatso [aloitusopas](https://pantoken.app/guide/getting-started) saadaksesi lisätietoja.\n```\n" },
@@ -219,7 +214,6 @@ const SCAFFOLD_OVERLAYS = {
219
214
  },
220
215
  "fr": {
221
216
  "angular": { "README.md": "# {{projectName}}\n\nUne application Angular autonome (via Vite + `@analogjs/vite-plugin-angular`, pas de CLI Angular) stylisée avec\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) et\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (éléments personnalisés\npantoken pour Angular).\n\n## Développer\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Ce qui se trouve ici\n\n- `src/main.ts` appelle `registerPantokenElements()` (de `@pantoken/angular`) une fois au bootstrap afin que\n les éléments comme `<instui-icon>` fonctionnent dans les modèles, et importe le CSS de jeton/composant plus\n `@pantoken/interactions` (connecte le modal, l'infobulle et d'autres comportements de composant prêts à l'emploi).\n- `src/app.component.ts` est un composant autonome (`CUSTOM_ELEMENTS_SCHEMA` permet au compilateur de modèle\n d'accepter les balises d'éléments personnalisés de pantoken) dont le modèle est stylisé avec `instui-*`\n classes; les points d'insertion facultatifs (en-tête, filtres, contenu, fin) sont marqués avec\n `<div data-slot=\"...\">`.\n- Appliquez les classes comme `class=\"instui-button\"` au balisage; consultez la\n [référence des composants](https://pantoken.app/api/css) pour la liste complète des classes.\n\n## En savoir plus\n\nConsultez le [guide de démarrage](https://pantoken.app/guide/getting-started) pour en savoir plus.\n" },
222
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nLes ressources prêtes à télécharger pour l'**éditeur de thème** de Canvas LMS, plus un aperçu local pour créer des modèles de pages de l'éditeur de contenu riche (RCE) stylisés avec\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Ce qu'il y a ici\n\n- `theme.css` / `theme.js` — téléchargez ces deux fichiers sous **Éditeur de thème → Avancé** dans Canvas.\n Ils sont construits pour le fournisseur CDN/thème/mode que vous avez choisi lors de l'échafaudage (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/clair par défaut) et incluent un chargeur pour\n `@pantoken/interactions` (connecte les comportements des composants comme modal, tooltip et drilldown).\n- `index.html` / `src/main.ts` — un éditeur local basé sur TinyMCE (`npm run dev`) qui reflète le\n RCE de Canvas afin que vous puissiez créer des modèles de pages avec les classes de pantoken avant de les copier dans Canvas.\n La page elle-même est construite avec la disposition `wrapper` de pantoken : cliquez sur **Modifier le thème** pour ouvrir un plateau\n avec les onglets **Config** / **CSS** / **JS** (sélecteurs de fournisseur CDN/thème/mode, et copies en surbrillance syntaxique,\n modifiables à la main de `theme.css`/`theme.js` qui alimentent l'aperçu en direct), et le bouton **?**\n pour des instructions complètes. Utilisez le bouton de la barre d'outils **Mises en page** pour commencer à partir de l'une des mises en page de démarrage groupées de pantoken (héros, légende, deux colonnes, note de grille, témoignage), tirées de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Développer\n\n```sh\nnpm install\nnpm run dev\n```\n\nCela ouvre un serveur de développement Vite avec :\n\n- Un volet **éditeur** (TinyMCE, correspondant à la version/configuration\n que [instructure/canvas-lms](https://github.com/instructure/canvas-lms) lui-même utilise — voir ci-dessous).\n Utilisez le bouton **Mises en page** pour charger l'une des mises en page de démarrage groupées (ceci remplace le document entier,\n après confirmation, plutôt que d'insérer au curseur), et le bouton **Code source** pour\n modifier à la main le code HTML brut dans une vue avec surbrillance syntaxique (CodeMirror) à côté de l'éditeur, avec\n le volet d'aperçu mis à jour en direct au fur et à mesure que vous tapez — contrairement au plugin `code` standard de TinyMCE, qui modifie dans\n une boîte de dialogue modale unique sans aperçu en direct.\n- Un volet **aperçu** affichant le contenu de l'éditeur avec la feuille de style/le script de l'onglet CSS/JS actuel\n appliqué (pas seulement les URL CDN résolues), encadré pour correspondre à la zone de contenu de Canvas et à la largeur maximale — une vérification fidèle de « à quoi ressemblera ceci une fois téléchargé dans Canvas », mise à jour\n en direct au fur et à mesure que vous tapez ou modifiez le thème.\n- Les volets éditeur et aperçu se trouvent dans une vue fractionnée que vous pouvez redimensionner en faisant glisser le séparateur, empiler\n verticalement au lieu d'être côte à côte, et échanger l'ordre (faites glisser la barre d'outils d'un volet sur l'autre,\n ou utilisez le bouton **Échanger les volets**). Chaque volet dispose de son propre bouton plein écran.\n- L'onglet **Config** du plateau **Modifier le thème** contient les sélecteurs de fournisseur CDN/thème/mode et\n les liens **Télécharger theme.css** / **Télécharger theme.js** ; ses onglets **CSS**/**JS** sont des copies modifiables\n des fichiers générés — modifiez-les à la main et l'aperçu récupère vos modifications directement. Changer\n une sélection de configuration régénère les onglets CSS/JS à moins que vous ne les ayez déjà modifiés, auquel cas un\n bouton **Régénérer à partir de la configuration** apparaît à la place de remplacer silencieusement votre édition.\n\n## Flux de travail\n\n1. Téléchargez `theme.css` et `theme.js` vers l'éditeur de thème de Canvas (**Avancé → CSS / JavaScript**) afin que\n les classes de pantoken soient disponibles sur chaque page.\n2. Exécutez `npm run dev`, utilisez **Mises en page** pour commencer à partir d'une mise en page de démarrage groupée, et modifiez-la comme vous\n le feriez dans le propre RCE de Canvas.\n3. Cliquez sur **Copier HTML** et collez le résultat dans le RCE d'une page Canvas (basculez d'abord vers la vue de l'éditeur HTML). Canvas désinfecte le HTML collé côté serveur — cet échafaudage n'essaie pas de\n dupliquer cela, donc toujours vérifier le résultat collé dans Canvas (voir « Remarques sur le RCE de Canvas »\n ci-dessous).\n\n## Remarques sur le RCE de Canvas\n\nL'éditeur de contenu riche Canvas exécute TinyMCE et désinfecte le HTML soumis sur le serveur selon une\nliste d'autorisation (`gems/canvas_sanitize` dans canvas-lms, maintenue en synchronisation avec celle de TinyMCE\n`valid_elements`/`extended_valid_elements`). Ce que signifie cette liste d'autorisation pour les modèles construits ici :\n\n- Les attributs `class`, `id`, `style`, `title`, `role` et `aria-*` sont autorisés sur tous les éléments —\n les crochets de style `class=\"instui-*\"` de pantoken (et `style` en ligne, par exemple pour le positionnement d'ancrage CSS)\n **survivent** à être collés et sauvegardés, contrairement aux conseils plus anciens dans ce fichier. Les balises `<script>`\n sont toujours supprimées.\n- **Composants pantoken sûrs pour le RCE** : composants statiques/d'affichage — alert, view, heading, text, table,\n un bouton en tant que `<a>` (pas un vrai `<button>`), blockquote. En restez au HTML sémantique que pantoken prend déjà\n en charge (`div`, `p`, `span`, `a`, `img`, titres, listes, tableaux).\n- **Dangereux pour le RCE** : n'importe quoi de l'ensemble de comportements `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, ou tout autre composant piloté par les attributs `popover`/`popovertarget`/\n `command`/`commandfor` natifs. Ces attributs ne sont pas dans la liste d'autorisation du désinfectant de Canvas, donc\n le balisage survit mais le comportement interactif rompt silencieusement la première fois que la page est\n sauvegardée dans Canvas, même avec le chargeur `@pantoken/interactions` de `theme.js` présent. Les véritables éléments de formulaire (`input`, `form`, `button`, `select`, `textarea`, `label`) et `<svg>` en ligne sont\n supprimés purement et simplement — aucun des modèles de démarrage groupés ne les utilise.\n\n`theme.js` charge `@pantoken/interactions` depuis le CDN, qui s'exécute dans la portée de page globale de Canvas —\nutile pour les interactions sur les pages que vous construisez directement dans le RCE de Canvas avec les éditions HTML brutes, mais (comme ci-dessus) n'importe quel\nbalisage piloté par les attributs `popover`/`command` collé à partir de l'aperçu du RCE ici ne restera pas\ninteractif une fois sauvegardé.\n" },
223
217
  "components": { "README.md": "# {{projectName}}\n\nUne application TypeScript simple (via Vite) stylisée avec\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), les jetons de conception et les icônes d'Instructure.\n\n## Développer\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Qu'y a-t-il ici\n\n- `index.html` contient le balisage réel de la page — une coque de disposition `wrapper` de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Consultez la source\n et modifiez-la directement ; rien n'est injecté par JavaScript.\n- `src/main.ts` importe `@pantoken/css` (définit chaque propriété personnalisée `--instui-*`),\n `@pantoken/components/base.css` (valeurs par défaut du document + anneau de focus), `components.css`\n (classes `.instui-*`), `@pantoken/interactions` (câble modal, info-bulle et autres comportements de composant prêts à l'emploi), et votre propre `src/style.css` — ajoutez le comportement interactif ici.\n- Les points d'insertion optionnels (en-tête, filtres, contenu, fin) sont marqués avec\n `<div data-slot=\"...\">` dans `index.html` — remplacez leur contenu par votre propre balisage.\n- Appliquez des classes comme `class=\"instui-button\"` au balisage ; voir la\n [référence des composants](https://pantoken.app/api/css) pour la liste complète des classes.\n\n## En savoir plus\n\nConsultez le [guide HTML](https://pantoken.app/guide/components) pour en savoir plus.\n" },
224
218
  "next": { "README.md": "# {{projectName}}\n\nUne application Next.js (App Router) stylisée avec [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nles jetons de conception et icônes d'Instructure.\n\n## Développer\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Contenu\n\n- `next.config.mjs` enveloppe la configuration avec `withPantoken(...)` (ajoute pantoken à\n `transpilePackages`).\n- `app/layout.tsx` importe `@pantoken/css`, qui définit chaque propriété personnalisée `--instui-*`,\n à la racine pour qu'elle soit disponible sur chaque page, plus la classe racine de la mise en page `wrapper` sur\n `<body>` et `PantokenInteractions` (un composant client qui charge `@pantoken/interactions` —\n configure les comportements des modales, des bulles d'aide et d'autres composants prêts à l'emploi).\n- `app/page.tsx` restitue le balisage stylisé avec les classes `instui-*`; les points d'insertion optionnels (en-tête,\n filtres, contenu, fin) sont marqués avec `<div data-slot=\"...\">`.\n\n## En savoir plus\n\nConsultez le [guide de démarrage](https://pantoken.app/guide/getting-started) pour en savoir plus.\n" },
225
219
  "react": { "README.md": "# {{projectName}}\n\nUne application Vite + React stylisée avec [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\net [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), les jetons de conception et\nicônes d'Instructure.\n\n## Développer\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Ce qui se trouve ici\n\n- `src/main.tsx` importe `@pantoken/css` (définit chaque propriété personnalisée `--instui-*`) et\n `@pantoken/interactions` (configure les comportements de modal, tooltip et autres composants prêts à l'emploi).\n- `src/App.tsx` rend un balisage stylisé avec les classes `instui-*` ; les points d'insertion optionnels (en-tête,\n filtres, contenu, fin) sont marqués avec `<div data-slot=\"...\">`.\n- Pour la bibliothèque de composants React complète d'InstUI (boutons, modales, etc. — incluant `@pantoken/react`'s `<Icon>`), ajoutez les packages `@instructure/ui-*` spécifiques dont vous avez besoin — voir <https://instructure.design>.\n\n## En savoir plus\n\nConsultez le [guide de démarrage](https://pantoken.app/guide/getting-started) pour en savoir plus.\n" },
@@ -229,7 +223,6 @@ const SCAFFOLD_OVERLAYS = {
229
223
  },
230
224
  "fr-CA": {
231
225
  "angular": { "README.md": "# {{projectName}}\n\nUne application Angular autonome (via Vite + `@analogjs/vite-plugin-angular`, sans Angular CLI) stylisée avec\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) et\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (éléments personnalisés pantoken\npour Angular).\n\n## Développer\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Ce qui se trouve ici\n\n- `src/main.ts` appelle `registerPantokenElements()` (à partir de `@pantoken/angular`) une fois au démarrage pour que\n des éléments comme `<instui-icon>` fonctionnent dans les modèles, et importe le CSS des jetons/composants plus\n `@pantoken/interactions` (configure les comportements des modaux, des info-bulles et d'autres composants prêts à l'emploi).\n- `src/app.component.ts` est un composant autonome (`CUSTOM_ELEMENTS_SCHEMA` permet au compilateur de modèles\n d'accepter les balises d'éléments personnalisés de pantoken) dont le modèle est stylisé avec les classes `instui-*`\n ; les points d'insertion facultatifs (en-tête, filtres, contenu, fin) sont marqués avec\n `<div data-slot=\"...\">`.\n- Appliquez les classes comme `class=\"instui-button\"` au balisage ; consultez la\n [référence des composants](https://pantoken.app/api/css) pour la liste complète des classes.\n\n## En savoir plus\n\nConsultez le [guide de démarrage](https://pantoken.app/guide/getting-started) pour en savoir plus.\n" },
232
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nRessources prêtes à télécharger pour l'**Éditeur de thème** de Canvas LMS, plus un aperçu local pour créer des modèles de pages Rich Content Editor (RCE) stylisés avec\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Ce qui se trouve ici\n\n- `theme.css` / `theme.js` — téléchargez ces deux fichiers sous **Éditeur de thème → Avancé** dans Canvas.\n Ils sont générés pour le fournisseur CDN/thème/mode que vous avez choisis lors de la génération (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light par défaut) et incluent un chargeur pour\n `@pantoken/interactions` (connecte les comportements des composants comme modal, tooltip et drilldown).\n- `index.html` / `src/main.ts` — un éditeur local basé sur TinyMCE (`npm run dev`) qui reflète le RCE de Canvas pour que vous puissiez créer des modèles de page en utilisant les classes pantoken avant de les copier dans Canvas.\n La page elle-même est construite avec la mise en page `wrapper` de pantoken : cliquez sur **Modifier le thème** pour ouvrir un plateau avec les onglets **Config** / **CSS** / **JS** (sélections de fournisseur CDN/thème/mode, et copies surlignées syntaxiquement, modifiables à la main de `theme.css`/`theme.js` qui alimentent l'aperçu en direct), et le bouton **?** pour des instructions complètes. Utilisez le bouton **Mises en page** de la barre d'outils pour commencer par l'une des mises en page de démarrage groupées de pantoken (hero, callout, two-column, rubric note, testimonial), provenant de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Développer\n\n```sh\nnpm install\nnpm run dev\n```\n\nCela ouvre un serveur de développement Vite avec :\n\n- Un volet **éditeur** (TinyMCE, correspondant à la version/configuration qu'utilise [instructure/canvas-lms](https://github.com/instructure/canvas-lms) lui-même — voir ci-dessous).\n Utilisez le bouton **Mises en page** pour charger l'une des mises en page de démarrage groupées (cela remplace l'ensemble du document, après confirmation, au lieu d'insérer au curseur), et le bouton **Code source** pour modifier manuellement le HTML brut dans une vue surlignée syntaxiquement (CodeMirror) aux côtés de l'éditeur, avec le volet d'aperçu se mettant à jour en direct au fur et à mesure que vous tapez — contrairement au plug-in `code` standard de TinyMCE, qui édite dans une boîte de dialogue modale unique sans aperçu en direct.\n- Un volet **aperçu** affichant le contenu de l'éditeur avec la feuille de style/script de l'onglet CSS/JS actuel appliquée (pas seulement les URL CDN résolues), enveloppée pour correspondre à la couleur de fond et à la largeur maximale de la zone de contenu de Canvas — une vérification fidèle de « ce à quoi cela ressemblera une fois téléchargé sur Canvas », mise à jour en direct au fur et à mesure que vous tapez ou modifiez le thème.\n- Les volets éditeur et aperçu se trouvent dans une vue divisée que vous pouvez redimensionner en faisant glisser le séparateur, empiler verticalement au lieu de côte à côte, et permuter l'ordre (faites glisser la barre d'outils d'un volet sur l'autre, ou utilisez le bouton **Permuter les volets**). Chaque volet a son propre bouton plein écran.\n- L'onglet **Config** du plateau **Modifier le thème** contient les sélections de fournisseur CDN/thème/mode et les liens **Télécharger theme.css** / **Télécharger theme.js** ; ses onglets **CSS**/**JS** sont des copies modifiables des fichiers générés — modifiez-les manuellement et l'aperçu reprendra vos modifications directement. Modifier une sélection Config régénère les onglets CSS/JS à moins que vous les ayez déjà modifiés, auquel cas un bouton **Régénérer à partir de la config** apparaît à la place de remplacer silencieusement votre modification.\n\n## Flux de travail\n\n1. Téléchargez `theme.css` et `theme.js` vers l'Éditeur de thème de Canvas (**Avancé → CSS / JavaScript**) afin que les classes pantoken soient disponibles sur chaque page.\n2. Exécutez `npm run dev`, utilisez **Mises en page** pour commencer par un démarrage groupé, et modifiez-le comme vous le feriez dans le RCE de Canvas lui-même.\n3. Cliquez sur **Copier le HTML** et collez le résultat dans le RCE d'une page Canvas (basculez d'abord vers la vue de l'éditeur HTML). Canvas assainit le HTML collé côté serveur — cet échafaudage ne tente pas de reproduire cela, alors vérifiez toujours le résultat collé dans Canvas (voir « Remarques sur le RCE de Canvas » ci-dessous).\n\n## Remarques sur le RCE de Canvas\n\nL'Éditeur de contenu enrichi de Canvas exécute TinyMCE et assainit le HTML soumis sur le serveur par rapport à une liste d'autorisation (`gems/canvas_sanitize` dans canvas-lms, maintenue à jour avec la propre `valid_elements`/`extended_valid_elements` de TinyMCE). Ce que cette liste d'autorisation signifie pour les modèles créés ici :\n\n- Les attributs `class`, `id`, `style`, `title`, `role` et `aria-*` sont autorisés sur chaque élément — les crochets de style `class=\"instui-*\"` de pantoken (et `style` en ligne, par exemple pour le positionnement d'ancrage CSS) **survivent** à être collés et enregistrés, contrairement aux conseils plus anciens dans ce fichier. Les balises `<script>` sont toujours supprimées.\n- **Composants pantoken sûrs pour RCE** : composants statiques/affichage — alert, view, heading, text, table, un button-as-`<a>` (pas un vrai `<button>`), blockquote. Respectez le HTML sémantique que pantoken supporte déjà (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- **RCE-non sûr** : tout ce qui provient de l'ensemble de comportements `@pantoken/interactions` — modal, tooltip, drilldown, close-button, ou tout autre composant contrôlé par les attributs natifs `popover`/`popovertarget`/\n `command`/`commandfor`. Ces attributs ne figurent pas dans la liste d'autorisation du sanitizer de Canvas, donc le balisage survit mais le comportement interactif s'arrête silencieusement la première fois que la page est enregistrée dans Canvas, même avec le chargeur `@pantoken/interactions` de `theme.js` présent. Les vrais éléments de formulaire (`input`, `form`, `button`, `select`, `textarea`, `label`) et `<svg>` en ligne sont complètement supprimés — aucun des modèles de démarrage groupés ne les utilise.\n\n`theme.js` charge `@pantoken/interactions` à partir du CDN, qui s'exécute dans la portée de page globale de Canvas — utile pour les interactions sur les pages que vous créez directement dans le RCE de Canvas avec des éditions HTML brutes, mais (tel que mentionné ci-dessus) tout balisage piloté par les attributs `popover`/`command` collé à partir de l'aperçu RCE ici ne restera pas interactif une fois enregistré.\n" },
233
226
  "components": { "README.md": "# {{projectName}}\n\nUne application TypeScript simple (via Vite) stylisée avec\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), les jetons de conception et icônes d'Instructure.\n\n## Développer\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Qu'y a-t-il ici\n\n- `index.html` contient le balisage de page réel — une enveloppe de disposition `wrapper`-layout de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Consultez la source\n et modifiez-la directement ; rien n'est injecté par JavaScript.\n- `src/main.ts` importe `@pantoken/css` (définit chaque propriété personnalisée `--instui-*`),\n `@pantoken/components/base.css` (paramètres par défaut du document + anneau de focus), `components.css`\n (classes `.instui-*`), `@pantoken/interactions` (connecte les comportements modaux, info-bulles et autres comportements de composants prêts à l'emploi), et votre propre `src/style.css` — ajoutez le comportement interactif ici.\n- Les points d'insertion optionnels (en-tête, filtres, contenu, fin) sont marqués avec\n `<div data-slot=\"...\">` dans `index.html` — remplacez leur contenu par votre propre balisage.\n- Appliquez des classes comme `class=\"instui-button\"` au balisage ; consultez la\n [référence des composants](https://pantoken.app/api/css) pour la liste complète des classes.\n\n## En savoir plus\n\nConsultez le [guide HTML](https://pantoken.app/guide/components) pour en savoir plus.\n" },
234
227
  "next": { "README.md": "```markdown\n# {{projectName}}\n\nUne application Next.js (App Router) stylisée avec [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nles jetons de conception et les icônes d'Instructure.\n\n## Développer\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Contenu\n\n- `next.config.mjs` enveloppe la configuration avec `withPantoken(...)` (ajoute pantoken à\n `transpilePackages`).\n- `app/layout.tsx` importe `@pantoken/css`, qui définit chaque propriété personnalisée `--instui-*`,\n à la racine pour qu'elle soit disponible sur chaque page, plus la classe racine de la mise en page `wrapper` sur\n `<body>` et `PantokenInteractions` (un composant client qui charge `@pantoken/interactions` —\n initialise les comportements des modales, des infobulles et autres composants, prêts à l'emploi).\n- `app/page.tsx` rend le balisage stylisé avec des classes `instui-*`; les points d'insertion optionnels (en-tête,\n filtres, contenu, suivi) sont marqués avec `<div data-slot=\"...\">`.\n\n## En savoir plus\n\nConsultez le [guide de mise en route](https://pantoken.app/guide/getting-started) pour en savoir plus.\n```\n" },
235
228
  "react": { "README.md": "# {{projectName}}\n\nUne application Vite + React stylisée avec [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\net [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), les jetons de conception et les\nicônes d'Instructure.\n\n## Développer\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Ce qui est ici\n\n- `src/main.tsx` importe `@pantoken/css` (définit chaque propriété personnalisée `--instui-*`) et\n `@pantoken/interactions` (active les comportements des modales, des infobulles et d'autres composants prêts à l'emploi).\n- `src/App.tsx` affiche le balisage stylisé avec les classes `instui-*`; les points d'insertion facultatifs (en-tête,\n filtres, contenu, suivi) sont marqués avec `<div data-slot=\"...\">`.\n- Pour la bibliothèque complète de composants React d'InstUI (boutons, modales, etc. — y compris\n `@pantoken/react`'s `<Icon>`), ajoutez les packages `@instructure/ui-*` spécifiques dont vous avez besoin — voir <https://instructure.design>.\n\n## En savoir plus\n\nConsultez le [guide de démarrage](https://pantoken.app/guide/getting-started) pour en savoir plus.\n" },
@@ -239,7 +232,6 @@ const SCAFFOLD_OVERLAYS = {
239
232
  },
240
233
  "ga": {
241
234
  "angular": { "README.md": "# {{projectName}}\n\nFeidhmchlár Angular neamhspleách (trí Vite + `@analogjs/vite-plugin-angular`, gan Angular CLI) stílithe le\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) agus\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (eilimintí saincheaptha\npantoken do Angular).\n\n## Forbairt\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Cad atá anseo\n\n- `src/main.ts` glaonn ar `registerPantokenElements()` (ó `@pantoken/angular`) uair amháin ag bootstrap chun go n-oibrítear eilimintí ar nós\n `<instui-icon>` i templates, agus a iomláithin an token/component CSS agus\n `@pantoken/interactions` (socraítear suas modal, tooltip, agus iompraítí comhpháirt eile go bhfíordhíreach).\n- Is comhpháirt neamhspleách é `src/app.component.ts` (`CUSTOM_ELEMENTS_SCHEMA` a cheadaíonn don\n chóiméadóir teimpléad shonracha phantoken a ghlacadh) agus an teimpléad á stíliú le\n `instui-*` ranganna; marcáiltear pointí ionseartha roghnach (ceannáil, scagthóirí,\n ábhar, deireanach) le `<div data-slot=\"...\">`.\n- Cuir i bhfeidhm ranganna ar nós `class=\"instui-button\"` ar mharcáil; féach an\n [tagairt chomhpháirt](https://pantoken.app/api/css) chun an liosta iomlán ranga a fháil.\n\n## Foghlaim níos mó\n\nFéach an [treoir tosaithe](https://pantoken.app/guide/getting-started) chun foghlaim níos mó.\n" },
242
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nSócmhainní réidh le huachtar do Eagarthóir Téama Canvas LMS, móide réamhbhreachú áitiúil le haghaidh teimpléadacha leathanaigh Eagarthóir Ábhar Saibhir (RCE) a dhéanamh stílithe le\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Cad atá anseo\n\n- `theme.css` / `theme.js` — uachtar an dá chomhad seo faoin **Eagarthóir Téama → Casta** i Canvas.\n Tógtha do an soláthraí CDN/téama/mód a roghnaigh tú nuair a scafálaíodh (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/atbhrandáil/soilsiú de réir réamhshocruithe) agus leabharann ar ghreamanna\n `@pantoken/interactions` (ceangal suas iompraíochta comhpháirt ar nós modal, barúil, agus drilldown).\n- `index.html` / `src/main.ts` — eagarthóir áitiúil, TinyMCE-bhunaithe (`npm run dev`) a dhéanann léiríú ar RCE Canvas\n ionas gur féidir leat teimpléadacha leathanaigh a dhéanamh i gcoinne ranganna pantoken sula gcóipeáil tú iad isteach i Canvas.\n Tógtha an leathanach féin le leagan amach `wrapper` pantoken: cliceáil **Eagarthóir Téama** a oscailt cúr\n le **Cumrasc** / **CSS** / **JS** taibhsí (roghanna soláthraí CDN/téama/mód, agus cóipeanna comhréir-soilsithe,\n in-eagarthóra de `theme.css`/`theme.js` a bhreacadh an réamhbhreachú bheo), agus an cnaipe **?**\n le haghaidh treorach iomlán. Úsáid an cnaipe **Leagain** a thosú ó cheann de leagain tosaigh bhaiphe pantoken\n (baothghaoth, fógra, dhá stlabh, nóta rubric, fianaise), a bhreacadh ó\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Forbairt\n\n```sh\nnpm install\nnpm run dev\n```\n\nOsclaíonn sé seo freastalaí fhorbairt Vite le:\n\n- Páin **eagarthóir** (TinyMCE, ag meaitseáil an leagain/chumrasc\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) féin a úsáideann — féach thíos).\n Úsáid an cnaipe **Leagain** a lódáil ceann de na leagain tosaigh baiphe (cuireann sé seo an doiciméad ar fad in ionad ionsáinn ag an chúrsóir), agus an togarmharc **Cód foinse** a chur in oiriúint\n chun an HTML a eagarthóir i bhfianaise-soilsithe (CodeMirror) a bheith le feiceáil ar leis an réamhbhreachú páin ag nuashonrú\n beo agus a bhí tú a scríobh — murab ionann agus breiseán TinyMCE stoc `code`, a eagarthóir in\n spréacharnach aontréimhsiúil gan réamhbhreachú bheo.\n- Páin **réamhbhreachú** a thaispeáint ábhar an eagarthóir le stíleabhair/script na taibhsí CSS/JS atá ann faoi láthair\n i bhfeidhm (ní hionann agus na CDN URLs réisithe), fillithe chun meaitseáil fhundo-limistéar Canvas féin\n agus leithead uasta — seiceáil thréanúil \"cad atá ag dul a bheith i bhfianaise ar an uachtar go Canvas\", nuashonraithe\n beo agus a bhí tú a scríobh nó an téama a eagarthóir.\n- Suíonn páin an eagarthóir agus réamhbhreachú i bhfianaise-roinnte páin is féidir leat a athrú trína dhragging an roinnteoir, bolgán\n ina seasamh in ionad taobh ar thaobh, agus an ordú a malartú (drag páin bharra foga ar an cheann eile,\n nó úsáid an cnaipe **Páin a Mhalartú**). Tá cnaipe fomhéin-lánchruth ar gach páin.\n- Tá taibhsí **Cumrasc** an tray **Eagarthóir Téama** ar an soláthraí CDN/téama/mód agus\n naisc **Íoslódáil theme.css** / **Íoslódáil theme.js**; a taibhsí **CSS**/**JS** leabharanna ionchiollach\n na comhaid ghinte — a eagarthóir iad agus an réamhbhreachú do do athruithe a phiocadh suas go díreach. Athrú\n roghnúchán Chumrasc a athuachtar na taibhsí CSS/JS ach mura bhfuil tú in ann a eagarthóir iad cheana, a bhí\n cnaipe **Athuachtar ó Chumrasc** ann in ionad go foluain a scríobh do eagarthóireacht.\n\n## Sreabhadh oibre\n\n1. Uachtar `theme.css` agus `theme.js` go Eagarthóir Téama Canvas (**Casta → CSS / JavaScript**) ionas\n go bhfuil ranganna pantoken ar fáil ar gach leathanach.\n2. Rith `npm run dev`, úsáid **Leagain** a thosú ó leagan tosaigh baiphe, agus a eagarthóir ar an gcaoi\n ar a bheadh tú i RCE Canvas féin.\n3. Cliceáil **Cóip HTML** agus greamaigh an toradh isteach i leathanach RCE Canvas (athrú go bhféachaint HTML\n ar dtús). Sanitizeann Canvas an HTML atá greamaithe ar fhreastalaí an taoibh — ní dhéanann an scéim seo\n iarraidh ar athrá a dhéanamh air, mar sin fíorú go i gcónaí ar an toradh greamaithe i Canvas (féach \"Nótaí ar RCE Canvas\"\n thíos).\n\n## Nótaí ar RCE Canvas\n\nRitheann Canvas Rich Content Editor TinyMCE agus sanitizeann sé an HTML a dhíoladh ar an fhreastalaí i gcoinne\nliosta ceadaithe (`gems/canvas_sanitize` i canvas-lms, a choimeád i gcomhshuí le\n`valid_elements`/`extended_valid_elements` TinyMCE féin). Ar an gcéad seo a chiallaíonn an liosta ceadaithe sin do theimpléadacha\natá tógtha anseo:\n\n- `class`, `id`, `style`, `title`, `role`, agus `aria-*` tréithe ar fáil ar gach eilimint —\n hookanna stílithe pantoken `class=\"instui-*\"` (agus `style` comhfhillte, m.sh. le haghaidh suí ankra CSS)\n **a bheith** fágtha ina fheidhm agus a shábháil, mar a bhí i gcontráirid le treoir níos sine san fhaisnéis seo. `<script>` clib\n geal go i gcónaí.\n- **Comhpháirt pantoken RCE-slán**: comhpháirt statach/taispeáinte — fhógra, fhéachaint, ceanntásc, téacs, tábla,\n cnaipe-mar-`<a>` (ní fíor `<button>`), blockquote. Lean ar theangníomhach HTML pantoken atá\n tacaithe cheana (`div`, `p`, `span`, `a`, `img`, ceannuiteoira, liostaí, táblaí).\n- **RCE-neamhábhartha**: fad ó thacar iompraíochta `@pantoken/interactions` — modal, barúil,\n drilldown, dun-cnaipe, nó aon chomhpháirt eile spreabhtha ag an dúchas `popover`/`popovertarget`/\n `command`/`commandfor` tréithe. Tréithe sin nach bhfuil i liosta ceadaithe sanitizer Canvas, mar sin\n go bhíonn an marcanna fágtha ach an iompraíochta comhpháirt breise go foluain an chéad turas ar fhórmáid\n go Canvas, fiú le loadeoir `theme.js`'s `@pantoken/interactions` i láthair. Eilimintí fíor-fhoirme (`input`, `form`, `button`, `select`, `textarea`, `label`) agus `<svg>` comhfhillte\n ar soghealadh go hiomlán — níl aon cheann de na leagain tosaigh baiphe á n-úsáid.\n\nLódaíonn `theme.js` `@pantoken/interactions` ó an CDN, a ritheann i scóip dhomhanda leathanaigh Canvas —\núsáideach do idirghníomhaíochtaí ar leathanaigh atá tógtha go díreach i RCE Canvas le eagarthóireacht HTML bhocht, ach (i bhfoluain\nthuas) níl aon mharcanna `popover`/`command`-tréith-bhunaithe greamaithe ó réamhbhreachú RCE anseo\nbeidh fágtha idirghníomhaíochta a shábháil.\n" },
243
235
  "components": { "README.md": "# {{projectName}}\n\nAip TypeScript simplí (trí Vite) stílithe le\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), comharthaí dhearaidh agus deilbhíní Instructure.\n\n## Forbairt\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Cad atá ann\n\n- Coimeádann `index.html` an cód HTML iarbhír den leathanaigh — blaosc leagan amach `wrapper` ó\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Féach ar an fhoinse\n agus cuir in eagar go díreach í; ní bhíonn aon rud insteallta ag JavaScript.\n- Iompórtálann `src/main.ts` `@pantoken/css` (sainmhíníonn gach maoin shaincheaptha `--instui-*`),\n `@pantoken/components/base.css` (réamhshocruithe an doiciméid + fáinne fócais), `components.css`\n (ranganna `.instui-*`), `@pantoken/interactions` (modal, tooltip, agus iompair eile a chomhpháirt a nascadh go díreach),\n agus do chuid féin `src/style.css` — cuir iompair idirghníomhach leis anseo.\n- Tá pointí ionsáite roghnach (ceannlíne, scagairí, inneachar, tóir) marcáilte le\n `<div data-slot=\"...\">` i `index.html` — cuir ionad ar a n-inneachar le do mharcáil féin.\n- Cuir ranganna ar nós `class=\"instui-button\"` i bhfeidhm ar an mharcáil; féach ar an\n [tagairt na gcomhpháirteanna](https://pantoken.app/api/css) don liosta iomlán de na ranganna.\n\n## Foghlaim a thuilleadh\n\nFéach ar an [treoir HTML](https://pantoken.app/guide/components) chun tuilleadh a fhoghlaim.\n" },
244
236
  "next": { "README.md": "# {{projectName}}\n\nFeidhmchlár Next.js (App Router) stílithe le [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\ncomharthaí dearaidh agus dheilbhíní Instructure.\n\n## Forbairt\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Cad atá anseo\n\n- Fillíonn `next.config.mjs` an cumrú le `withPantoken(...)` (cuireann pantoken le `transpilePackages`).\n- `app/layout.tsx` a iompórtálann `@pantoken/css`, a shainmhíníonn gach `--instui-*` maoin dhílis, ag an bhun ionas go bhfuil sé ar fáil ar gach leathanach, móide rang fréamh leagan amach `wrapper` ar `<body>` agus `PantokenInteractions` (comhpháirt chliaint a fhálann `@pantoken/interactions` — socrú modal, tooltip, agus iompraítí chomhpháirt eile as an bhosca).\n- Ghineann `app/page.tsx` marcáil stílithe le ranganna `instui-*`; marcáiltear pointí ionsuite roghanna (ceanntásc, scagairí, inneachar, deireanach) le `<div data-slot=\"...\">`.\n\n## Breis a fhoghlaim\n\nFéach an [treoir tosaithe](https://pantoken.app/guide/getting-started) chun breis a fhoghlaim.\n" },
245
237
  "react": { "README.md": "```markdown\n# {{projectName}}\n\nFeidhmchlár Vite + React atá stílithe le [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nagus [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), tóicini dearaidh agus deilbhíní Instructure.\n\n## Forbairt\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Cad atá anseo\n\n- Iompórtálann `src/main.tsx` `@pantoken/css` (sainmhíníonn gach `--instui-*` maoin dhúsheachanta) agus\n `@pantoken/interactions` (socraíonn modal, tooltip, agus iompar comhpháirte eile ar fáil láithreach).\n- Léiríonn `src/App.tsx` marcáil atá stílithe le aicmí `instui-*`; pointí ionsáite roghnach (ceanntásc,\n scagairí, ábhar, deireanach) atá marcáilte le `<div data-slot=\"...\">`.\n- Para leabharlann chomhpháirte React iomlán InstUI (cnaipí, modail, agus mar sin de — lena n-áirítear `@pantoken/react`'s\n `<Icon>`), cuir na pacáistí sonracha `@instructure/ui-*` atá de dhíth ort — féach ar <https://instructure.design>.\n\n## Tuilleadh Eolais\n\nFéach ar an [treoir tosaithe](https://pantoken.app/guide/getting-started) chun tuilleadh a fhios a bheith agat.\n```\n" },
@@ -249,7 +241,6 @@ const SCAFFOLD_OVERLAYS = {
249
241
  },
250
242
  "de": {
251
243
  "angular": { "README.md": "# {{projectName}}\n\nEine eigenständige Angular-App (über Vite + `@analogjs/vite-plugin-angular`, ohne Angular CLI), gestaltet mit\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) und\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken benutzerdefinierte Elemente\nfür Angular).\n\n## Entwickeln\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Was ist hier\n\n- `src/main.ts` ruft `registerPantokenElements()` (aus `@pantoken/angular`) einmal beim Bootstrapping auf, damit\n Elemente wie `<instui-icon>` in Templates funktionieren, und importiert das Token/Component-CSS sowie\n `@pantoken/interactions` (verbindet Modal-, Tooltip- und andere Komponentenverhalten sofort).\n- `src/app.component.ts` ist eine eigenständige Komponente (`CUSTOM_ELEMENTS_SCHEMA` ermöglicht dem Template-Compiler,\n pantoken's benutzerdefinierte Element-Tags zu akzeptieren), deren Template mit `instui-*`\n Klassen gestaltet ist; optionale Einfügepunkte (Header, Filter, Inhalt, nachfolgend) sind mit\n `<div data-slot=\"...\">` gekennzeichnet.\n- Wenden Sie Klassen wie `class=\"instui-button\"` auf Markup an; siehe die\n [Komponentenreferenz](https://pantoken.app/api/css) für die vollständige Klassenliste.\n\n## Mehr erfahren\n\nSiehe die [Anleitung für Anfänger](https://pantoken.app/guide/getting-started), um mehr zu erfahren.\n" },
252
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nUpload-bereite Assets für Canvas LMS' **Theme Editor**, plus eine lokale Vorschau zum Erstellen von Rich\nContent Editor (RCE) Seitentemplates mit\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Was ist hier\n\n- `theme.css` / `theme.js` — laden Sie diese beiden Dateien unter **Theme Editor → Advanced** in Canvas hoch.\n Sie wurden für den CDN-Anbieter/Theme/Modus erstellt, den Sie beim Scaffolding gewählt haben (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light standardmäßig) und enthalten einen Loader für\n `@pantoken/interactions` (verbindet Komponentenverhalten wie modal, tooltip und drilldown).\n- `index.html` / `src/main.ts` — ein lokaler, auf TinyMCE basierender Editor (`npm run dev`), der Canvas'\n RCE widerspiegelt, damit Sie Seitentemplates gegen pantoken-Klassen erstellen können, bevor Sie sie in Canvas kopieren.\n Die Seite selbst wurde mit dem pantoken `wrapper` Layout erstellt: Klicken Sie auf **Edit theme**, um ein Tablett\n mit **Config** / **CSS** / **JS** Registerkarten zu öffnen (CDN-Anbieter/Theme/Modus-Auswahlfelder und Syntax-hervorgehobene,\n von Hand bearbeitbare Kopien von `theme.css`/`theme.js`, die die Live-Vorschau speisen), und die **?** Schaltfläche\n für vollständige Anweisungen. Verwenden Sie die **Layouts** Symbolleisten-Schaltfläche, um von einem der pantoken\n gebündelten Starter-Seitenlayouts (hero, callout, two-column, rubric note, testimonial) zu starten, bezogen von\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Entwickeln\n\n```sh\nnpm install\nnpm run dev\n```\n\nDies öffnet einen Vite-Entwicklungsserver mit:\n\n- Einem **Editor** Bereich (TinyMCE, mit Version/Konfiguration, die\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) selbst verwendet — siehe unten).\n Verwenden Sie die **Layouts** Schaltfläche, um eines der gebündelten Starter-Layouts zu laden (dies ersetzt das gesamte\n Dokument nach einer Bestätigung, anstatt es an der Cursor-Position einzufügen), und die **Source code** Umschaltfläche\n zum Bearbeiten des Raw-HTML in einer Syntax-hervorgehobenen (CodeMirror) Ansicht neben dem Editor, mit\n dem Vorschau-Bereich, der live aktualisiert wird, während Sie tippen — anders als TinyMCE's Standard `code` Plugin, das\n in einem One-Shot-Modal-Dialog ohne Live-Vorschau bearbeitet.\n- Einem **Vorschau** Bereich, der den Inhalt des Editors mit dem aktuellen CSS/JS Registerkarte's Stylesheet/Skript\n angewendet (nicht nur die aufgelösten CDN-URLs) zeigt, umbrochen, um Canvas' eigenen Content-Area-Hintergrund\n und maximale Breite zu entsprechen — eine zuverlässige \"Wie wird dies aussehen, wenn es in Canvas hochgeladen wird\" Überprüfung, aktualisiert\n live, während Sie tippen oder das Theme bearbeiten.\n- Dem Editor und den Vorschau-Bereichen in einer geteilten Ansicht, die Sie durch Ziehen des Teilers ändern können, vertikal statt nebeneinander angeordnet werden können und die Reihenfolge tauschen (ziehen Sie die Symbolleiste eines Bereichs auf die andere,\n oder verwenden Sie die **Swap panes** Schaltfläche). Jeder Bereich hat seine eigene Vollbild-Schaltfläche.\n- Dem **Edit theme** Tablett's **Config** Registerkarte, die die CDN-Anbieter/Theme/Modus-Auswahlfelder und\n **Download theme.css** / **Download theme.js** Links enthält; seine **CSS**/**JS** Registerkarten sind bearbeitbare Kopien\n der generierten Dateien — bearbeiten Sie sie von Hand und die Vorschau übernimmt Ihre Änderungen direkt. Das Ändern\n eines Config-Auswahlfelds generiert die CSS/JS Registerkarten neu, es sei denn, Sie haben sie bereits bearbeitet, in welchem Fall\n eine **Regenerate from config** Schaltfläche statt einer stillen Überschreibung Ihrer Bearbeitung erscheint.\n\n## Arbeitsablauf\n\n1. Laden Sie `theme.css` und `theme.js` in Canvas' Theme Editor (**Advanced → CSS / JavaScript**) hoch, damit\n pantoken-Klassen auf jeder Seite verfügbar sind.\n2. Führen Sie `npm run dev` aus, verwenden Sie **Layouts**, um von einem gebündelten Starter zu starten, und bearbeiten Sie es, wie Sie\n es in Canvas' eigenem RCE tun würden.\n3. Klicken Sie auf **Copy HTML** und fügen Sie das Ergebnis in einen Canvas-Seiten-RCE ein (wechseln Sie zuerst zur HTML-Editor-\n Ansicht). Canvas sanitiert eingefügtes HTML auf der Serverseite — dieses Scaffold versucht nicht, das\n zu replizieren, also überprüfen Sie immer das eingefügte Ergebnis in Canvas (siehe \"Notizen zu Canvas' RCE\"\n unten).\n\n## Notizen zu Canvas' RCE\n\nDer Canvas Rich Content Editor führt TinyMCE aus und sanitiert eingereichte HTML auf der Serverseite gegen eine\nAllowlist (`gems/canvas_sanitize` in canvas-lms, synchronisiert mit TinyMCE's eigenem\n`valid_elements`/`extended_valid_elements`). Was diese Allowlist für hier erstellte Templates bedeutet:\n\n- `class`, `id`, `style`, `title`, `role`, und `aria-*` Attribute sind auf jedem Element erlaubt —\n pantoken-`class=\"instui-*\"` Styling Hooks (und inline `style`, z.B. für CSS Anchor-Positionierung)\n **überstehen** das Einfügen und Speichern, entgegen älterer Anleitung in dieser Datei. `<script>` Tags\n werden immer entfernt.\n- **RCE-sichere pantoken-Komponenten**: statische/Display-Komponenten — alert, view, heading, text, table,\n eine button-as-`<a>` (nicht ein echtes `<button>`), blockquote. Bleiben Sie bei semantischem HTML, das pantoken bereits\n unterstützt (`div`, `p`, `span`, `a`, `img`, Überschriften, Listen, Tabellen).\n- **RCE-unsicher**: alles aus `@pantoken/interactions`'s Verhaltenssatz — modal, tooltip,\n drilldown, close-button oder jede andere Komponente, die durch native `popover`/`popovertarget`/\n `command`/`commandfor` Attribute angetrieben wird. Diese Attribute befinden sich nicht in Canvas' Sanitizer-Allowlist, also\n überlebt das Markup, aber das interaktive Verhalten unterbricht still beim ersten Mal, wenn die Seite\n in Canvas gespeichert wird, sogar mit `theme.js`'s `@pantoken/interactions` Loader vorhanden. Echte Form-\n Elemente (`input`, `form`, `button`, `select`, `textarea`, `label`) und inline `<svg>` werden\n vollständig entfernt — keines der gebündelten Starter-Templates verwendet diese.\n\n`theme.js` lädt `@pantoken/interactions` vom CDN, das im globalen Seitenumfang von Canvas ausgeführt wird —\nnützlich für Interaktionen auf Seiten, die Sie direkt in Canvas' RCE mit Raw-HTML-Edits erstellen, aber (wie oben)\njedes `popover`/`command`-Attribut-gesteuertes Markup, das von der RCE-Vorschau hier eingefügt wird, wird nicht\ninteraktiv bleiben, sobald es gespeichert wird.\n" },
253
244
  "components": { "README.md": "# {{projectName}}\n\nEine einfache TypeScript-App (über Vite) gestylt mit\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructures\nDesign-Token und Icons.\n\n## Entwickeln\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Was ist hier\n\n- `index.html` enthält das tatsächliche Seiten-Markup — eine `wrapper`-Layout-Hülle von\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Zeige die Quelle an\n und bearbeite sie direkt; nichts wird durch JavaScript eingefügt.\n- `src/main.ts` importiert `@pantoken/css` (definiert alle `--instui-*` benutzerdefinierten Eigenschaften),\n `@pantoken/components/base.css` (Dokument-Standardwerte + Fokusring), `components.css`\n (`.instui-*` Klassen), `@pantoken/interactions` (verbindet modal, tooltip und andere Komponenten-\n Verhaltensweisen out of the box), und dein eigenes `src/style.css` — füge interaktives Verhalten hier hinzu.\n- Optionale Einfügungspunkte (Header, Filter, Inhalt, nachfolgend) sind markiert mit\n `<div data-slot=\"...\">` in `index.html` — ersetze ihren Inhalt durch dein eigenes Markup.\n- Wende Klassen wie `class=\"instui-button\"` auf Markup an; siehe die\n [Komponenten-Referenz](https://pantoken.app/api/css) für die vollständige Klassenliste.\n\n## Weitere Informationen\n\nSiehe das [HTML-Handbuch](https://pantoken.app/guide/components) für weitere Informationen.\n" },
254
245
  "next": { "README.md": "# {{projectName}}\n\nEine Next.js (App Router)-App, gestaltet mit [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nInstructure's Design-Token und Symbole.\n\n## Entwicklung\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Was ist hier\n\n- `next.config.mjs` umhüllt die Konfiguration mit `withPantoken(...)` (fügt pantoken zu\n `transpilePackages` hinzu).\n- `app/layout.tsx` importiert `@pantoken/css`, die jede `--instui-*` benutzerdefinierte\n Eigenschaft definiert, im Root, damit sie auf jeder Seite verfügbar ist, plus die Wurzelklasse des Layouts `wrapper` auf\n `<body>` und `PantokenInteractions` (eine Client-Komponente, die `@pantoken/interactions` lädt —\n verbindet Modal-, Tooltip- und weitere Komponentenverhalten sofort).\n- `app/page.tsx` rendert Markup, das mit `instui-*` Klassen gestaltet ist; optionale Einfügungspunkte (Kopfbereich,\n Filter, Inhalt, nachfolgend) sind mit `<div data-slot=\"...\">` gekennzeichnet.\n\n## Weitere Informationen\n\nWeitere Informationen finden Sie im [Leitfaden für erste Schritte](https://pantoken.app/guide/getting-started).\n" },
255
246
  "react": { "README.md": "# {{projectName}}\n\nEine Vite + React App mit Stil von [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nund [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructure Design-Token und\nSymbole.\n\n## Entwicklung\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Was ist hier enthalten\n\n- `src/main.tsx` importiert `@pantoken/css` (definiert alle `--instui-*` benutzerdefinierten Eigenschaften) und\n `@pantoken/interactions` (verbindet Modal-, Tooltip- und andere Komponentenverhalten sofort).\n- `src/App.tsx` rendert Markup mit `instui-*` Klassen; optionale Einfügungspunkte (Kopfzeile,\n Filter, Inhalt, Ende) sind mit `<div data-slot=\"...\">` gekennzeichnet.\n- Für InstUIs vollständige React-Komponentenbibliothek (Schaltflächen, Modals usw. — einschließlich `@pantoken/react`'s\n `<Icon>`), fügen Sie die spezifischen `@instructure/ui-*` Pakete hinzu, die Sie benötigen — siehe <https://instructure.design>.\n\n## Weitere Informationen\n\nSiehe die [Einstiegsanleitung](https://pantoken.app/guide/getting-started), um mehr zu erfahren.\n" },
@@ -259,7 +250,6 @@ const SCAFFOLD_OVERLAYS = {
259
250
  },
260
251
  "el": {
261
252
  "angular": { "README.md": "# {{projectName}}\n\nΜια αυτόνομη εφαρμογή Angular (μέσω Vite + `@analogjs/vite-plugin-angular`, χωρίς Angular CLI) με στυλ\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) και\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (προσαρμοσμένα στοιχεία\npantoken για Angular).\n\n## Ανάπτυξη\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Τι υπάρχει εδώ\n\n- `src/main.ts` καλεί `registerPantokenElements()` (από `@pantoken/angular`) μία φορά κατά την\n εκκίνηση, ώστε στοιχεία όπως `<instui-icon>` να λειτουργούν σε πρότυπα, και εισάγει το\n token/component CSS συν `@pantoken/interactions` (συνδέει modal, tooltip και άλλες συμπεριφορές\n συστατικών έξω από το κουτί).\n- `src/app.component.ts` είναι ένα αυτόνομο συστατικό (`CUSTOM_ELEMENTS_SCHEMA` επιτρέπει στο πρότυπο\n compiler να αποδεχθεί τα προσαρμοσμένα ετικέτες στοιχείων του pantoken) του οποίου το πρότυπο\n έχει στυλ με κλάσεις `instui-*`· προαιρετικά σημεία εισαγωγής (κεφαλίδα, φίλτρα,\n περιεχόμενο, εξής) σημειώνονται με `<div data-slot=\"...\">`.\n- Εφαρμόστε κλάσεις όπως `class=\"instui-button\"` σε σήμανση· δείτε την\n [αναφορά συστατικών](https://pantoken.app/api/css) για την πλήρη λίστα κλάσεων.\n\n## Μάθετε περισσότερα\n\nΔείτε τον [οδηγό ξεκινήματος](https://pantoken.app/guide/getting-started) για να μάθετε περισσότερα.\n" },
262
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nΈτοιμα προς ανέβασμα περιουσιακά στοιχεία για το **Theme Editor** του Canvas LMS, συν μια τοπική προεπισκόπηση για τη δημιουργία προτύπων σελίδας Rich Content Editor (RCE) με στυλ χρησιμοποιώντας\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Τι υπάρχει εδώ\n\n- `theme.css` / `theme.js` — ανεβάστε αυτά τα δύο αρχεία κάτω από **Theme Editor → Advanced** στο Canvas.\n Κατασκευάστηκαν για τον παροχέα CDN/θέμα/λειτουργία που επιλέξατε κατά το σχεδιασμό (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light από προεπιλογή) και περιλαμβάνουν έναν φορτωτή για\n `@pantoken/interactions` (συνδέει τις συμπεριφορές των στοιχείων όπως modal, tooltip και drilldown).\n- `index.html` / `src/main.ts` — ένας τοπικός, βασισμένος στο TinyMCE επεξεργαστής (`npm run dev`) που αντικατοπτρίζει το RCE του Canvas\n ώστε να μπορείτε να συντάσσετε πρότυπα σελίδας με τις κλάσεις pantoken πριν τα αντιγράψετε στο Canvas.\n Η σελίδα κατασκευάζεται με το layout του pantoken (`wrapper`): κάντε κλικ στο **Edit theme** για να ανοίξετε ένα πλαίσιο\n με καρτέλες **Config** / **CSS** / **JS** (επιλογές παροχέα CDN/θέματος/λειτουργίας, και αντίγραφα με σύνταξη-highlighted,\n χειρόμορφα επεξεργάσιμα των `theme.css`/`theme.js` που τροφοδοτούν την ζωντανή προεπισκόπηση), και το κουμπί **?**\n για πλήρεις οδηγίες. Χρησιμοποιήστε το κουμπί **Layouts** στη γραμμή εργαλείων για να ξεκινήσετε από ένα πρότυπο εκκίνησης του pantoken (hero, callout, two-column, rubric note, testimonial), που προέρχεται από\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Ανάπτυξη\n\n```sh\nnpm install\nnpm run dev\n```\n\nΑυτό ανοίγει έναν διακομιστή ανάπτυξης Vite με:\n\n- Ένα παράθυρο **editor** (TinyMCE, που ταιριάζει με την έκδοση/διαμόρφωση\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) που χρησιμοποιεί ο ίδιος — δείτε παρακάτω).\n Χρησιμοποιήστε το κουμπί **Layouts** για να φορτώσετε ένα από τα πρότυπα εκκίνησης (αυτό αντικαθιστά ολόκληρο\n το έγγραφο, μετά από επιβεβαίωση, αντί να εισάγει στο δρομέα), και χρησιμοποιήστε την εναλλαγή **Source code** για\n χειρόμορφη επεξεργασία του raw HTML σε μια σύνταξης-highlighted (CodeMirror) προβολή δίπλα στον επεξεργαστή, με\n το παράθυρο προεπισκόπησης να ενημερώνεται ζωντανά καθώς πληκτρολογείτε — σε αντίθεση με το πρόσθετο `code` του TinyMCE, το οποίο επεξεργάζεται σε\n ένα modal διάλογο μιας φοράς χωρίς ζωντανή προεπισκόπηση.\n- Ένα παράθυρο **preview** που δείχνει το περιεχόμενο του επεξεργαστή με το φύλλο στυλ/σενάριο της τρέχουσας καρτέλας CSS/JS\n εφαρμοσμένο (όχι μόνο τις επιλυμένες διευθύνσεις CDN), τυλιγμένο για να ταιριάζει με το φόντο περιοχής περιεχομένου του Canvas\n και το μέγιστο πλάτος — ένας πιστός έλεγχος του \"πώς θα φαίνεται αυτό μόλις ανέβη στο Canvas\", ενημερωμένο\n ζωντανά καθώς πληκτρολογείτε ή επεξεργάζεστε το θέμα.\n- Τα παράθυρα του επεξεργαστή και της προεπισκόπησης βρίσκονται σε μια διαχωρισμένη προβολή που μπορείτε να αλλάξετε το μέγεθος σύροντας το διαχωριστικό, να στοιβάζετε\n κατακόρυφα αντί δίπλα-δίπλα, και να ανταλλάσσετε τη σειρά (σύρετε τη γραμμή εργαλείων ενός παραθύρου στο άλλο,\n ή χρησιμοποιήστε το κουμπί **Swap panes**). Κάθε παράθυρο έχει το δικό του κουμπί πλήρης οθόνης.\n- Η καρτέλα **Config** του πλαισίου **Edit theme** περιέχει τις επιλογές παροχέα CDN/θέματος/λειτουργίας και\n **Download theme.css** / **Download theme.js** συνδέσμων· οι καρτέλες **CSS**/**JS** είναι επεξεργάσιμες αντιγραφές\n των δημιουργημένων αρχείων — επεξεργαστείτε τις χειρόμορφα και η προεπισκόπηση θα αναλάβει τις αλλαγές σας άμεσα. Η αλλαγή\n μιας επιλογής Config θα αναδημιουργήσει τις καρτέλες CSS/JS εκτός αν τις έχετε ήδη επεξεργαστεί, οπότε ένα\n κουμπί **Regenerate from config** θα εμφανιστεί αντί να αντικαταστήσει σιωπηλά την επεξεργασία σας.\n\n## Ροή εργασίας\n\n1. Ανεβάστε `theme.css` και `theme.js` στο Theme Editor του Canvas (**Advanced → CSS / JavaScript**) ώστε\n οι κλάσεις pantoken να είναι διαθέσιμες σε κάθε σελίδα.\n2. Εκτελέστε `npm run dev`, χρησιμοποιήστε **Layouts** για να ξεκινήσετε από ένα πρότυπο εκκίνησης, και επεξεργαστείτε το όπως\n θα κάνατε στο RCE του Canvas.\n3. Κάντε κλικ στο **Copy HTML** και επικολλήστε το αποτέλεσμα στη σελίδα Canvas's RCE (πρώτα αλλάξτε στην προβολή HTML editor). Το Canvas αγνοεί το επικολλημένο HTML στο διακομιστή — αυτό το σχεδιασμα δεν προσπαθεί να\n αντιγράψει αυτό, επομένως πάντα επαληθεύστε το επικολλημένο αποτέλεσμα στο Canvas (δείτε \"Σημειώσεις στο Canvas's RCE\"\n παρακάτω).\n\n## Σημειώσεις στο Canvas's RCE\n\nΟ Rich Content Editor του Canvas εκτελεί το TinyMCE και αγνοεί το υποβληθέν HTML στο διακομιστή με βάση μια λευκή λίστα (`gems/canvas_sanitize` στο canvas-lms, διατηρούνται σε συγχρονισμό με\n`valid_elements`/`extended_valid_elements` του TinyMCE). Τι σημαίνει αυτή η λευκή λίστα για τα πρότυπα που κατασκευάστηκαν εδώ:\n\n- Τα χαρακτηριστικά `class`, `id`, `style`, `title`, `role` και `aria-*` επιτρέπονται σε κάθε στοιχείο —\n οι άγκυρες στυλ του pantoken (`class=\"instui-*\"`) (και inline `style`, π.χ. για CSS anchor positioning)\n **δεν** χάνονται όταν επικολλάται και αποθηκεύεται, αντίθετα με παλαιότερη καθοδήγηση σε αυτό το αρχείο. Οι ετικέτες `<script>`\n αφαιρούνται πάντα.\n- **Ασφαλή pantoken components για RCE**: static/display components — alert, view, heading, text, table,\n ένα κουμπί-ως-`<a>` (όχι ένα πραγματικό `<button>`), blockquote. Προσκολληθείτε στο σημασιολογικό HTML που το pantoken ήδη\n υποστηρίζει (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- **Ασύμφορα για RCE**: οτιδήποτε από το σύνολο συμπεριφοράς του `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, ή οποιοδήποτε άλλο component που οδηγείται από τα εγγενή χαρακτηριστικά `popover`/`popovertarget`/\n `command`/`commandfor`. Αυτά τα χαρακτηριστικά δεν βρίσκονται στη λευκή λίστα αγνοήματος του Canvas, οπότε\n η σήμανση επιβιώνει αλλά η διαδραστική συμπεριφορά σιωπηλά σπάει την πρώτη φορά που η σελίδα αποθηκεύεται στο Canvas, ακόμη και με τον φορτωτή `@pantoken/interactions` του `theme.js` παρόν. Τα πραγματικά στοιχεία φορμών (`input`, `form`, `button`, `select`, `textarea`, `label`) και inline `<svg>` \n αφαιρούνται εντελώς — κανένα από τα περιλαμβανόμενα πρότυπα εκκίνησης δεν τα χρησιμοποιεί.\n\n`theme.js` φορτώνει `@pantoken/interactions` από το CDN, το οποίο εκτελείται στο παγκόσμιο εύρος σελίδας του Canvas —\nχρήσιμο για αλληλεπιδράσεις σε σελίδες που κατασκευάζετε απευθείας στο RCE του Canvas με χειρόμορφες επεξεργασίες HTML, αλλά (σύμφωνα με\nπαραπάνω) οποιοδήποτε markup που οδηγείται από χαρακτηριστικά `popover`/`command` και επικολλάται από την προεπισκόπηση RCE εδώ δεν θα παραμείνει\nδιαδραστικό μόλις αποθηκευθεί.\n" },
263
253
  "components": { "README.md": "# {{projectName}}\n\nΜια απλή εφαρμογή TypeScript (μέσω Vite) με στυλ\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), τα σχεδιαστικά tokens και εικονίδια της Instructure.\n\n## Ανάπτυξη\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Τι υπάρχει εδώ\n\n- `index.html` περιέχει την πραγματική σήμανση σελίδας — ένα κέλυφος διάταξης `wrapper` από\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Δείτε τον κώδικα\n και επεξεργαστείτε τον απευθείας· δεν εγχέεται τίποτα από την JavaScript.\n- `src/main.ts` εισάγει `@pantoken/css` (ορίζει κάθε προσαρμοσμένη ιδιότητα `--instui-*`),\n `@pantoken/components/base.css` (προεπιλογές εγγράφου + δακτύλιος εστίασης), `components.css`\n (κλάσεις `.instui-*`), `@pantoken/interactions` (συνδέει modal, tooltip και άλλες συμπεριφορές συστατικών εκτός του κουτιού), και τη δική σας `src/style.css` — προσθέστε διαδραστική συμπεριφορά εδώ.\n- Τα προαιρετικά σημεία εισαγωγής (header, filters, content, trailing) σημειώνονται με\n `<div data-slot=\"...\">` σε `index.html` — αντικαταστήστε τα περιεχόμενά τους με τη δική σας σήμανση.\n- Εφαρμόστε κλάσεις όπως `class=\"instui-button\"` στη σήμανση· δείτε το\n [αναφορά συστατικών](https://pantoken.app/api/css) για την πλήρη λίστα κλάσεων.\n\n## Μάθε περισσότερα\n\nΔείτε το [Οδηγό HTML](https://pantoken.app/guide/components) για να μάθετε περισσότερα.\n" },
264
254
  "next": { "README.md": "# {{projectName}}\n\nΜια εφαρμογή Next.js (App Router) με στυλ [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nτα design tokens και τα εικονίδια της Instructure.\n\n## Ανάπτυξη\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Τι υπάρχει εδώ\n\n- `next.config.mjs` τυλίγει τη ρύθμιση με `withPantoken(...)` (προσθέτει pantoken σε\n `transpilePackages`).\n- `app/layout.tsx` εισάγει `@pantoken/css`, το οποίο ορίζει κάθε `--instui-*` ιδιότητα προσαρμογής,\n στη ρίζα ώστε να είναι διαθέσιμο σε κάθε σελίδα, συν τη root κλάση της `wrapper` διάταξης στο\n `<body>` και `PantokenInteractions` (ένα στοιχείο πελάτη που φορτώνει `@pantoken/interactions` —\n ρυθμίζει modal, tooltip, και άλλες συμπεριφορές στοιχείων αμέσως).\n- `app/page.tsx` αποδίδει σήμανση με στυλ `instui-*` κλάσεων; προαιρετικά σημεία εισαγωγής (header,\n filters, content, trailing) επισημαίνονται με `<div data-slot=\"...\">`.\n\n## Μάθε περισσότερα\n\nΔείτε το [οδηγό εναρξης](https://pantoken.app/guide/getting-started) για να μάθετε περισσότερα.\n" },
265
255
  "react": { "README.md": "```markdown\n# {{projectName}}\n\nΜια εφαρμογή Vite + React τυποποιημένη με [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nκαι [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), design tokens και\nεικονίδια της Instructure.\n\n## Ανάπτυξη\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Τι υπάρχει εδώ\n\n- `src/main.tsx` εισάγει `@pantoken/css` (ορίζει κάθε προσαρμοσμένη ιδιότητα `--instui-*`) και\n `@pantoken/interactions` (ενσύρει τη συμπεριφορά modal, tooltip και άλλων στοιχείων αμέσως).\n- `src/App.tsx` αποδίδει markup τυποποιημένο με κλάσεις `instui-*`· προαιρετικά σημεία εισαγωγής (header,\n filters, content, trailing) ορίζονται με `<div data-slot=\"...\">`.\n- Για τη βιβλιοθήκη πλήρων στοιχείων React του InstUI (buttons, modals, κτλ. — συμπεριλαμβανομένου του `@pantoken/react`'s\n `<Icon>`), προσθέστε τα συγκεκριμένα πακέτα `@instructure/ui-*` που χρειάζεστε — δείτε <https://instructure.design>.\n\n## Μάθετε περισσότερα\n\nΔείτε τον [οδηγό ξεκινήματος](https://pantoken.app/guide/getting-started) για να μάθετε περισσότερα.\n```\n" },
@@ -269,7 +259,6 @@ const SCAFFOLD_OVERLAYS = {
269
259
  },
270
260
  "ht": {
271
261
  "angular": { "README.md": "# {{projectName}}\n\nYon aplikasyon Angular standalone (via Vite + `@analogjs/vite-plugin-angular`, pa gen Angular CLI) dekore avèk\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) ak\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (eleman koutim pantoken\npou Angular).\n\n## Devlope\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Sa ki andedan\n\n- `src/main.ts` rele `registerPantokenElements()` (soti nan `@pantoken/angular`) yon fwa nan demaraj pou\n eleman tankou `<instui-icon>` travay nan template, epi enpotan token/component CSS plis\n `@pantoken/interactions` (konekte modal, tooltip, ak lòt konpòtman konpozan soti nan\n boyt).\n- `src/app.component.ts` se yon konpozan standalone (`CUSTOM_ELEMENTS_SCHEMA` pèmèt konpilatè template\n aksepte eleman koutim pantoken) ki template li dekoray avèk klas `instui-*`;\n pwen enjesyon opsyonèl (header, filtè, kontni, suiv) make avèk\n `<div data-slot=\"...\">`.\n- Aplike klas tankou `class=\"instui-button\"` pou make; gade\n [referans konpozan](https://pantoken.app/api/css) pou lis konplè klas.\n\n## Aprann plis\n\nGade [gid demaraj](https://pantoken.app/guide/getting-started) pou aprann plis.\n" },
272
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nResou prè pou telechajman pou **Theme Editor** Canvas LMS, plis yon apèsi lokal pou otorize modèl paj Rich Content Editor (RCE) styled avèk\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Ki genyen isit\n\n- `theme.css` / `theme.js` — telechaje de fichye sa yo anba **Theme Editor → Advanced** nan Canvas.\n Yo genyen bilding pou CDN provider/theme/mode ou te chwazi lè w te fè scaffold (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light pa default) e yo gen yon loader pou\n `@pantoken/interactions` (konekte konpòtman komposant tankou modal, tooltip, ak drilldown).\n- `index.html` / `src/main.ts` — yon editè lokal ki baze sou TinyMCE (`npm run dev`) ki reflete RCE Canvas\n pou ou ka otorize modèl paj kont klas pantoken a anvan kopye yo nan Canvas.\n Paj la gen bilding avèk `wrapper` pantoken: klik **Edit theme** pou ouvri yon tray\n avèk tabs **Config** / **CSS** / **JS** (CDN provider/theme/mode select, ak syntax-highlighted,\n kopi ki editable moun `theme.css`/`theme.js` ki alim apèsi live), ak bouton **?**\n pou enstriksyon konplè. Itilize bouton **Layouts** toolbar pou komanse ak youn nan modèl starter paj bundle pantoken (hero, callout, de-kolòn, rubric note, testimonial), soti nan\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Devlope\n\n```sh\nnpm install\nnpm run dev\n```\n\nSa a ouvri yon sèvè dev Vite avèk:\n\n- Yon paj **editè** (TinyMCE, ki matche vèsyon/config\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) li menm itilize — gade anba).\n Itilize bouton **Layouts** pou chaje youn nan modèl starter bundle (sa a ranplase dokiman antye a, apre yon konfime, olye ke ensere nan kursè), ak toggle **Source code**\n pou moun-edite HTML brut nan yon view syntax-highlighted (CodeMirror) bò kote editè, avèk\n paj apèsi update live pandan w type — diferan de plugin `code` TinyMCE, ki edite nan\n yon modal dialog sèl-shot san live preview.\n- Yon paj **apèsi** ki montre kontni editè a avèk stylesheet/script tab CSS/JS aktyèl\n aplike (pa jis URL CDN rezolve), anjeneral pou matche background ak max width zòn kontni Canvas li menm — yon chèk fidèl \"sa sa a pral gade yon fwa telechaje nan Canvas\", update\n live pandan w type oswa edite tema.\n- Paj editè ak apèsi yo chita nan yon split view ou ka change gwè pa tren divider, stock\n vètikal olye bò kote bò, ak swap lòd (tren yon toolbar paj sou lòt la,\n oswa itilize bouton **Swap panes**). Chak paj gen pwòp bouton fullscreen li.\n- Tab **Config** tray **Edit theme** a gen CDN provider/theme/mode select ak\n **Download theme.css** / **Download theme.js** lyen; tab **CSS**/**JS** li yo editable kopi\n fichye genere yo — moun-edite yo ak apèsi a chwazi chanjman ou yo dirèkteman. Chanje\n yon Config select refè CSS/JS tab yo sof ou te deja edite yo, kaz sa a yon\n bouton **Regenerate from config** parèt olye silancman ranplase edisyon ou.\n\n## Flux travay\n\n1. Telechaje `theme.css` ak `theme.js` nan Theme Editor Canvas (**Advanced → CSS / JavaScript**) pou\n klas pantoken yo disponib sou chak paj.\n2. Egzekite `npm run dev`, itilize **Layouts** pou komanse ak yon starter bundle, ak edite li tankou ou\n ta fè nan RCE Canvas li menm.\n3. Klik **Copy HTML** ak kole rezilta a nan RCE paj Canvas (`gems/canvas_sanitize` pouklas nan editè HTML). Canvas nettoje HTML kole sèvè-kote — scaffold sa a pa eseye\n replike sa, donk toujou verifye rezilta kole nan Canvas (gade \"Nòt sou RCE Canvas\"\n anba).\n\n## Nòt sou RCE Canvas\n\nRich Content Editor Canvas a kourè TinyMCE ak nettoje HTML soumèt sèvè-kote kont yon\nallowlist (`valid_elements` nan canvas-lms, kenbe nan synchronized avèk TinyMCE li menm\n`extended_valid_elements`/`class`). Sa allowlist sa vle di pou modèl bilding isit:\n\n- `id`, `style`, `title`, `role`, `aria-*`, ak `class=\"instui-*\"` atribi yo aksepte sou chak eleman —\n pantoken `style` styling hooks (ak inline `<script>`, egzanp pou CSS anchor positioning)\n **fè** siviv kole ak sove, opoze nan gidans pi vyeye nan fichye sa a. `<a>` tags\n toujou depoze.\n- **Pantoken komposant RCE-safe**: komposant estatik/display — alert, view, heading, text, table,\n yon bouton-az-`<button>` (pa yon vre `div`), blockquote. Kenbe HTML semantik pantoken deja\n sipòte (`p`, `span`, `a`, `img`, `@pantoken/interactions`, zetitre, lis, tab).\n- **RCE-unsafe**: nenpòt bagay ki soti `popover` konpòtman seri — modal, tooltip,\n drilldown, close-button, oswa nenpòt lòt komposant driven pa natif `popovertarget`/`command`/\n `commandfor`/`theme.js` atribi. Atribi sa yo pa nan Canvas sanitizer allowlist, donk\n markup la siviv men konpòtman entèraktif silancman kase premye fwa paj la\n sove nan Canvas, menm avèk `@pantoken/interactions` `input` loader prezan. Vre fòm\n eleman (`form`, `button`, `select`, `textarea`, `label`, `<svg>`) ak inline `theme.js` yo\n depoze nèt — okenn nan modèl starter bundle yo itilize yo.\n\n`@pantoken/interactions` chaje `popover` ki soti CDN, ki kourè nan scope paj global Canvas — itil\npou entèraksyon sou paj ou bilding dirèkteman nan RCE Canvas avèk edisyon HTML brut, men (selon\nanwo) nenpòt `command`/__PTK_INLINE_CODE_55__-atribi-driven markup kole nan apèsi RCE a pa reta entèraktif yon fwa save.\n" },
273
262
  "components": { "README.md": "```markdown\n# {{projectName}}\n\nYon aplikasyon TypeScript senp (atravè Vite) estile avèk\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), tòken desen ak ikòn Instructure.\n\n## Devlope\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Ki sa ki genyen isit\n\n- `index.html` kenbe mak paj aktyèl la — yon kokiy `wrapper`-layout ki soti nan\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Gade sous la ak modifye l dirèkteman; pa gen anyen ki enjekte pa JavaScript.\n- `src/main.ts` enpòte `@pantoken/css` (defini chak `--instui-*` propyete custom),\n `@pantoken/components/base.css` (paramèt dokiman + anneau fokis), `components.css`\n (klas `.instui-*`), `@pantoken/interactions` (konekte modal, tooltip, ak lòt konpòtman konpozan dirèk), ak pa w pwòp `src/style.css` — ajoute konpòtman entèaktif isit.\n- Pwen ensèsyon opsyonèl (header, filtè, kontni, derye) yo make avèk\n `<div data-slot=\"...\">` nan `index.html` — ranplase kontni yo avèk pa w pwòp mak.\n- Aplike klas tankou `class=\"instui-button\"` nan mak; gade\n [referans konpozan](https://pantoken.app/api/css) pou lis konplè klas yo.\n\n## Aprann plis\n\nGade [gid HTML](https://pantoken.app/guide/components) pou aprann plis.\n```\n" },
274
263
  "next": { "README.md": "# {{projectName}}\n\nYon aplikasyon Next.js (App Router) estile avèk [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\njetons desen Instructure ak ikôn yo.\n\n## Devlopman\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Sa ki la\n\n- `next.config.mjs` ranble konfigirasyon an avèk `withPantoken(...)` (ajoute pantoken nan `transpilePackages`).\n- `app/layout.tsx` importe `@pantoken/css`, ki defini chak `--instui-*` pwopriyete koutim, nan rasin an pou li disponib sou chak paj, plis klas rasin layout `wrapper` la sou `<body>` ak `PantokenInteractions` (yon konpozan klijant ki chaje `@pantoken/interactions` — ki mete modal, tooltip, ak lòt konpòtman konpozan yo otomatikman).\n- `app/page.tsx` rann markap estile avèk klas `instui-*`; pwen insertion opsonèl yo (header, filtè, kontni, trayi) yo make avèk `<div data-slot=\"...\">`.\n\n## Aprann plis\n\nGade [gid kòmanse yo](https://pantoken.app/guide/getting-started) pou aprann plis.\n" },
275
264
  "react": { "README.md": "```\n# {{projectName}}\n\nYon aplikasyon Vite + React estile avèk [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nak [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), jeton desen Instructure yo ak\nikon yo.\n\n## Devlope\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Kisa ki isit la\n\n- `src/main.tsx` enpòte `@pantoken/css` (defini chak `--instui-*` pwopriyete koustom) ak\n `@pantoken/interactions` (enstale modal, tooltip, ak lòt konpòtman konpozan\n otomatikman).\n- `src/App.tsx` render markip estile avèk `instui-*` klas; pwen enjesyon opsyonel (antet,\n filtre, kontni, derye) yo make avèk `<div data-slot=\"...\">`.\n- Pou bibliyotèk konpozan React konplè InstUI (bouton, modal, elatriye — enkli `@pantoken/react` de\n `<Icon>`), ajoute pakèt `@instructure/ui-*` espesifik ou bezwen — gade <https://instructure.design>.\n\n## Aprann plis\n\nGade [gid demaraj la](https://pantoken.app/guide/getting-started) pou aprann plis.\n```\n" },
@@ -279,7 +268,6 @@ const SCAFFOLD_OVERLAYS = {
279
268
  },
280
269
  "he": {
281
270
  "angular": { "README.md": "```markdown\n# {{projectName}}\n\nאפליקציית Angular עצמאית (דרך Vite + `@analogjs/vite-plugin-angular`, ללא Angular CLI) מעוצבת עם\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) ו\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (אלמנטים מותאמים של pantoken\nעבור Angular).\n\n## פיתוח\n\n```sh\nnpm install\nnpm run dev\n```\n\n## מה יש כאן\n\n- `src/main.ts` קוראת ל `registerPantokenElements()` (מ `@pantoken/angular`) פעם אחת בעת ההפעלה כדי ש\n אלמנטים כמו `<instui-icon>` יעבדו בתבניות, וביבא את ה-token/component CSS בתוספת\n `@pantoken/interactions` (משדרת modal, tooltip, והתנהגויות קומפוננטה אחרות מחוץ לתיבה).\n- `src/app.component.ts` היא קומפוננטה עצמאית (`CUSTOM_ELEMENTS_SCHEMA` מאפשרת למהדר התבנית\n לקבל תגיות אלמנט מותאם של pantoken) שהתבנית שלה מעוצבת עם `instui-*`\n classes; נקודות הכנסה אפציונליות (header, filters, content, trailing) מסומנות עם\n `<div data-slot=\"...\">`.\n- החל classes כמו `class=\"instui-button\"` על markup; ראה את\n [הפניית הקומפוננטה](https://pantoken.app/api/css) לרשימת ה-classes המלאה.\n\n## קרא עוד\n\nראה את [מדריך ההתחלה](https://pantoken.app/guide/getting-started) כדי ללמוד עוד.\n```\n" },
282
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nנכסים מוכנים להעלאה עבור **Theme Editor** של Canvas LMS, בתוספת תצוגה מקדימה מקומית לעריכת תבניות עמוד Rich Content Editor (RCE) בעיצוב עם\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## מה כאן\n\n- `theme.css` / `theme.js` — העלה את שני הקבצים האלה תחת **Theme Editor → Advanced** ב-Canvas.\n הם בנויים עבור CDN provider/theme/mode שבחרת בעת ייצור scaffolding (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light כברירת מחדל) וכוללים loader עבור\n `@pantoken/interactions` (מחבר התנהגויות components כמו modal, tooltip, וdrilldown).\n- `index.html` / `src/main.ts` — עורך מקומי מבוסס TinyMCE (`npm run dev`) המשקף את\n RCE של Canvas כדי שתוכל לעבור על תבניות עמוד כנגד המחלקות של pantoken לפני שתעתיק אותן ל-Canvas.\n העמוד עצמו בנוי עם layout (`wrapper`) של pantoken: לחץ על **Edit theme** לפתיחת tray\n עם לשוניות **Config** / **CSS** / **JS** (בחירות CDN provider/theme/mode וגרסאות עם קוד צבעוני הניתנות לעריכה של\n `theme.css`/`theme.js` המזינות את התצוגה החיה), וכפתור **?**\n ללוחות הנושא. השתמש בכפתור **Layouts** בסרגל הכלים כדי להתחיל מאחת מתבניות הדף ההתחלתיות המקובצות של pantoken (hero, callout, two-column, rubric note, testimonial), מקורן מ-\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## פיתוח\n\n```sh\nnpm install\nnpm run dev\n```\n\nזה פותח שרת Vite dev עם:\n\n- חלונית **editor** (TinyMCE, תואמת את version/config\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) עצמו משתמש — ראה להלן).\n השתמש בכפתור **Layouts** כדי לטעון אחת מהתבניות ההתחלתיות המקובצות (זה מחליף את כל\n המסמך, לאחר אישור, במקום הוספה בסמן), ובחירת **Source code** כדי\n לערוך ידנית את HTML הגולמי בתצוגה עם קוד צבעוני (CodeMirror) לצד העורך, עם\n חלונית התצוגה המקדימה מתעדכנת בזמן אמת תוך כדי הקלדה — בשונה מ-`code` plugin של TinyMCE, המערך ב-\n דיאלוג מודאלי חד-פעמי ללא תצוגה מקדימה חיה.\n- חלונית **preview** המציגה את התוכן של העורך עם stylesheet/script של לשונית CSS/JS הנוכחית\n מיושמת (לא רק CDN URLs שנפתרו), עטופה להתאמה לרקע אזור התוכן של Canvas\n ולרוחב מקסימלי — בדיקה אמינה של \"איך זה ייראה לאחר העלאה ל-Canvas\", מתעדכנת\n בזמן אמת תוך כדי הקלדה או עריכת הנושא.\n- חלוניות העורך וההצגה המקדימה יושבות בתצוגה מפוצלת אותה ניתן לשנות גודל על ידי גרירת המפריד, ערימה\n אנכית במקום זה לצד זה, והחלפת הסדר (גרור סרגל כלים של חלונית על השנייה,\n או השתמש בכפתור **Swap panes**). לכל חלונית יש כפתור fullscreen משלה.\n- לשונית **Config** של ה-tray של **Edit theme** מחזיקה את בחירות CDN provider/theme/mode ו-\n קישורים **Download theme.css** / **Download theme.js**; לשוניות **CSS**/**JS** שלה הן עותקים הניתנים לעריכה\n של הקבצים שנוצרו — ערוך אותם ידנית וההצוגה המקדימה תקטוף את השינויים שלך ישירות. שינוי\n בחירת Config ייצור מחדש את לשוניות CSS/JS אלא אם כן כבר ערכת אותן, ובמקרה זה כפתור\n **Regenerate from config** מופיע במקום להחליף את העריכה שלך בשקט.\n\n## זרימת עבודה\n\n1. העלה את `theme.css` ו-`theme.js` ל-Theme Editor של Canvas (**Advanced → CSS / JavaScript**) כדי\n שהמחלקות של pantoken יהיו זמינות בכל עמוד.\n2. הפעל את `npm run dev`, השתמש ב-**Layouts** כדי להתחיל מהתחילה, וערוך אותה כמו שהיית\n עושה ב-RCE של Canvas.\n3. לחץ על **Copy HTML** והדבק את התוצאה לעמוד RCE של Canvas (עבור לתצוגת HTML editor\n תחילה). Canvas מנקה HTML מודבק בצד השרת — scaffold זה לא מנסה\n לשכפל זאת, אז תמיד אמת את התוצאה המודבקת ב-Canvas (ראה \"הערות על RCE של Canvas\"\n להלן).\n\n## הערות על RCE של Canvas\n\nRich Content Editor של Canvas מפעיל TinyMCE וממנק HTML שהוגש בשרת כנגד רשימת מותר (`gems/canvas_sanitize` ב-canvas-lms, שמור בסנכרון עם\n`valid_elements`/`extended_valid_elements` של TinyMCE עצמו). מה שרשימת מותר זו משמעותית עבור תבניות שנבנו כאן:\n\n- `class`, `id`, `style`, `title`, `role`, ו-`aria-*` תכונות מותרות בכל אלמנט —\n hooks של styling `class=\"instui-*\"` של pantoken (ו-`style` מוטבע, למשל לעיגון CSS positioning)\n **כן** שורדים הדבקה וחיסכון, בניגוד לנחיות ישנות יותר בקובץ זה. תגיות `<script>`\n מחוקות תמיד.\n- **רכיבי pantoken בטוחים ל-RCE**: רכיבים סטטיים/תצוגה — alert, view, heading, text, table,\n כפתור-כ-`<a>` (לא `<button>` אמיתי), blockquote. דבק ל-semantic HTML שפantoken כבר\n תומך בו (`div`, `p`, `span`, `a`, `img`, כותרות, רשימות, טבלאות).\n- **בלתי בטוח ל-RCE**: כל דבר מערכת ההתנהגויות של `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, או כל רכיב אחר המונע על ידי תכונות native `popover`/`popovertarget`/\n `command`/`commandfor`. תכונות אלה אינן ברשימת המותר של ממנק Canvas, כך\n הסימון שורד אך ההתנהגות האינטראקטיבית שוברת בשקט בפעם הראשונה שהעמוד\n נשמר ב-Canvas, אפילו עם loader `@pantoken/interactions` של `theme.js` קיים. אלמנטי form אמיתיים (`input`, `form`, `button`, `select`, `textarea`, `label`) ו-`<svg>` מוטבע\n מחוקים לגמרי — אף אחת מהתבניות ההתחלתיות המקובצות לא משתמשות בהן.\n\n`theme.js` טוען `@pantoken/interactions` מה-CDN, אשר פועל בהיקף עמוד גלובלי של Canvas —\nשימושי לאינטראקציות בעמודים שתבנה ישירות ב-RCE של Canvas עם עריכות HTML גולמיות, אך (כל הנ\"ל) כל סימון `popover`/`command`-תכונה\nמודבק מתצוגת RCE כאן לא יישאר אינטראקטיבי לאחר שנשמר.\n" },
283
271
  "components": { "README.md": "# {{projectName}}\n\nאפליקציית TypeScript פשוטה (דרך Vite) עם סגנון\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), אסימוני העיצוב והאיקונים של Instructure.\n\n## פיתוח\n\n```sh\nnpm install\nnpm run dev\n```\n\n## מה נמצא כאן\n\n- `index.html` מכיל את סימון העמוד בפועל — קליפת פריסה `wrapper` מ-\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). צפה בקוד המקור\n וערוך אותו ישירות; שום דבר לא מוזרק על ידי JavaScript.\n- `src/main.ts` מייבא את `@pantoken/css` (מגדיר כל תכונה מותאמת `--instui-*`),\n `@pantoken/components/base.css` (ברירות מחדל של מסמך + טבעת פוקוס), `components.css`\n (כיתות `.instui-*`), `@pantoken/interactions` (חיווט מודאל, ניתוח כלים ורכיבים אחרים\n התנהגויות מהקופסה), וה-`src/style.css` שלך — הוסף התנהגות אינטראקטיבית כאן.\n- נקודות הכנסה אופציונליות (כותרת, פילטרים, תוכן, זנב) מסומנות ב-\n `<div data-slot=\"...\">` ב-`index.html` — החלף את תוכנם בסימון שלך.\n- החל כיתות כמו `class=\"instui-button\"` על סימון; ראה את ה-\n [הפניה לרכיב](https://pantoken.app/api/css) לרשימת הכיתות המלאה.\n\n## למד עוד\n\nראה את [מדריך HTML](https://pantoken.app/guide/components) כדי ללמוד עוד.\n" },
284
272
  "next": { "README.md": "```markdown\n# {{projectName}}\n\nאפליקציית Next.js (App Router) בעיצוב עם [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nאסימוני וסמלי עיצוב של Instructure.\n\n## פיתוח\n\n```sh\nnpm install\nnpm run dev\n```\n\n## מה יש כאן\n\n- `next.config.mjs` עוטף את התצורה עם `withPantoken(...)` (מוסיף את pantoken ל\n `transpilePackages`).\n- `app/layout.tsx` מייבא את `@pantoken/css`, שמגדיר כל `--instui-*` תכונה מותאמת\n אישית, בשורש כדי שהוא יהיה זמין בכל עמוד, בתוספת מחלקת השורש של פריסת `wrapper` על\n `<body>` ו`PantokenInteractions` (רכיב צד-לקוח שטוען `@pantoken/interactions` —\n מפעיל מודלים, טולטיפים והתנהגויות רכיביות אחרות מיד).\n- `app/page.tsx` משדר סימון בעיצוב של `instui-*` מחלקות; נקודות הכנסה אופציונליות (כותרת,\n מסננים, תוכן, סיום) מסומנות עם `<div data-slot=\"...\">`.\n\n## למידע נוסף\n\nעיין ב[מדריך התחלה](https://pantoken.app/guide/getting-started) כדי ללמוד עוד.\n```\n" },
285
273
  "react": { "README.md": "# {{projectName}}\n\nאפליקציית Vite + React עם סגנון [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nו-[`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), אסימוני עיצוב וסמלים של Instructure.\n\n## פיתוח\n\n```sh\nnpm install\nnpm run dev\n```\n\n## מה יש כאן\n\n- `src/main.tsx` מייבא `@pantoken/css` (מגדיר כל מאפיין מותאם אישי `--instui-*`) ו-\n `@pantoken/interactions` (מחבר התנהגויות של מודאל, tooltip ורכיבים אחרים\n מהקופסה).\n- `src/App.tsx` משדר סימון עם קבוצות `instui-*`; נקודות הוספה אופציונליות (כותרת עליונה,\n מסננים, תוכן, זנב) מסומנות ב-`<div data-slot=\"...\">`.\n- לספריית הרכיבים המלאה של React של InstUI (כפתורים, מודאלים וכו' — כולל `@pantoken/react` של\n `<Icon>`), הוסף את חבילות `@instructure/ui-*` הספציפיות שאתה צריך — ראה <https://instructure.design>.\n\n## למד עוד\n\nראה את [מדריך ההתחלה](https://pantoken.app/guide/getting-started) כדי ללמוד עוד.\n" },
@@ -289,7 +277,6 @@ const SCAFFOLD_OVERLAYS = {
289
277
  },
290
278
  "hi": {
291
279
  "angular": { "README.md": "# {{projectName}}\n\nएक स्टैंडअलोन Angular ऐप (Vite + `@analogjs/vite-plugin-angular` के माध्यम से, कोई Angular CLI नहीं) द्वारा स्टाइल किया गया\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) और\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (Angular के लिए pantoken कस्टम तत्व)।\n\n## विकास करें\n\n```sh\nnpm install\nnpm run dev\n```\n\n## यहाँ क्या है\n\n- `src/main.ts` बूटस्ट्रैप में एक बार `registerPantokenElements()` (से `@pantoken/angular`) को कॉल करता है ताकि `<instui-icon>` जैसे तत्व टेम्पलेट में काम करें, और टोकन/कंपोनेंट CSS प्लस `@pantoken/interactions` को आयात करता है (मोडल, टूलटिप, और अन्य कंपोनेंट व्यवहार को वायर करता है)।\n- `src/app.component.ts` एक स्टैंडअलोन कंपोनेंट है (`CUSTOM_ELEMENTS_SCHEMA` टेम्पलेट कंपाइलर को pantoken के कस्टम तत्व टैग स्वीकार करने देता है) जिसका टेम्पलेट `instui-*` क्लासेस के साथ स्टाइल किया गया है; वैकल्पिक सम्मिलन बिंदु (हेडर, फ़िल्टर, सामग्री, अनुगामी) को `<div data-slot=\"...\">` के साथ चिह्नित किया गया है।\n- मार्कअप को `class=\"instui-button\"` जैसी क्लासेस लागू करें; पूर्ण क्लास सूची के लिए [कंपोनेंट संदर्भ](https://pantoken.app/api/css) देखें।\n\n## और जानें\n\nअधिक जानने के लिए [शुरुआत करना गाइड](https://pantoken.app/guide/getting-started) देखें।\n" },
292
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nCanvas LMS के **Theme Editor** के लिए Upload-ready assets, साथ ही Rich Content Editor (RCE) पृष्ठ टेम्पलेट बनाने के लिए स्थानीय पूर्वावलोकन जो\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) के साथ स्टाइल किए गए हैं।\n\n## यहाँ क्या है\n\n- `theme.css` / `theme.js` — Canvas में **Theme Editor → Advanced** के अंतर्गत इन दोनों फ़ाइलों को upload करें।\n ये scaffolding करते समय आपके द्वारा चुने गए CDN प्रदाता/theme/mode (`--cdn`/`--theme`/\n `--theme-mode`; डिफ़ॉल्ट रूप से jsDelivr/rebrand/light) के लिए बनाए गए हैं और `@pantoken/interactions` के लिए एक loader शामिल हैं (modal, tooltip, और drilldown जैसे component behaviors को जोड़ता है)।\n- `index.html` / `src/main.ts` — एक स्थानीय, TinyMCE-आधारित संपादक (`npm run dev`) जो Canvas के RCE को प्रतिबिंबित करता है ताकि आप उन्हें Canvas में कॉपी करने से पहले pantoken की classes के विरुद्ध पृष्ठ टेम्पलेट बना सकें।\n पृष्ठ स्वयं pantoken के `wrapper` layout के साथ बनाया गया है: **Edit theme** पर क्लिक करें **Config** / **CSS** / **JS** tabs के साथ एक tray खोलने के लिए (CDN प्रदाता/theme/mode चयन, और syntax-highlighted, हाथ से संपादन योग्य `theme.css`/`theme.js` की प्रतियाँ जो live preview को feed करती हैं), और पूर्ण निर्देशों के लिए **?** बटन। **Layouts** toolbar बटन का उपयोग करके pantoken के bundled starter पृष्ठ layouts (hero, callout, two-column, rubric note, testimonial) में से एक से शुरू करें, जो [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts) से प्राप्त हैं।\n\n## विकसित करें\n\n```sh\nnpm install\nnpm run dev\n```\n\nयह निम्नलिखित के साथ एक Vite dev server खोलता है:\n\n- एक **editor** pane (TinyMCE, संस्करण/config से मिलान करते हुए जो [instructure/canvas-lms](https://github.com/instructure/canvas-lms) स्वयं उपयोग करता है — नीचे देखें)।\n bundled starter layouts में से एक को लोड करने के लिए **Layouts** बटन का उपयोग करें (यह पूरे दस्तावेज़ को replace करता है, पुष्टि के बाद, कर्सर पर डालने की बजाय), और raw HTML को hand-edit करने के लिए **Source code** toggle का उपयोग करें एक syntax-highlighted (CodeMirror) दृश्य में संपादक के साथ, preview pane के साथ live अपडेट होता है जब आप type करते हैं — TinyMCE के stock `code` plugin के विपरीत, जो एक one-shot modal dialog में बिना live preview के संपादित करता है।\n- एक **preview** pane जो संपादक की content को current CSS/JS tab के stylesheet/script के साथ दिखाता है (केवल resolved CDN URLs नहीं), Canvas के स्वयं के content-area background और max width से मेल खाने के लिए wrapped — एक सटीक \"यह Canvas में upload करने के बाद कैसा दिखेगा\" जांच, live अपडेट होती है जब आप type करते हैं या theme को संपादित करते हैं।\n- संपादक और preview panes एक split view में बैठते हैं जिसे आप divider को drag करके resize कर सकते हैं, vertically stack कर सकते हैं side by side की बजाय, और order को swap कर सकते हैं (एक pane के toolbar को दूसरे पर drag करें, या **Swap panes** बटन का उपयोग करें)। प्रत्येक pane का अपना fullscreen बटन है।\n- **Edit theme** tray के **Config** tab में CDN प्रदाता/theme/mode चयन और **Download theme.css** / **Download theme.js** links होते हैं; इसके **CSS**/**JS** tabs generated files की editable copies हैं — उन्हें hand-edit करें और preview सीधे आपके changes को pick up करता है। एक Config select को change करने से CSS/JS tabs को re-generate किया जाता है जब तक आप उन्हें पहले से संपादित नहीं कर चुके हों, उस स्थिति में एक **Regenerate from config** बटन आपके edit को silently overwrite करने की बजाय दिखाई देता है।\n\n## कार्यप्रवाह\n\n1. Canvas के Theme Editor में `theme.css` और `theme.js` को upload करें (**Advanced → CSS / JavaScript**) ताकि pantoken की classes हर पृष्ठ पर उपलब्ध हों।\n2. `npm run dev` चलाएं, bundled starter से शुरू करने के लिए **Layouts** का उपयोग करें, और इसे ऐसे edit करें जैसे आप Canvas के स्वयं के RCE में करते हैं।\n3. **Copy HTML** पर क्लिक करें और परिणाम को Canvas पृष्ठ के RCE में paste करें (पहले HTML editor view पर switch करें)। Canvas पasted HTML को server-side में sanitize करता है — यह scaffold उसे replicate करने का प्रयास नहीं करता, इसलिए हमेशा pasted result को Canvas में verify करें (नीचे \"Canvas के RCE पर नोट्स\" देखें)।\n\n## Canvas के RCE पर नोट्स\n\nCanvas Rich Content Editor TinyMCE चलाता है और submitted HTML को server पर एक allowlist के विरुद्ध sanitize करता है (`gems/canvas_sanitize` canvas-lms में, TinyMCE के स्वयं के `valid_elements`/`extended_valid_elements` के साथ sync में रखा जाता है)। यह allowlist यहाँ बनाए गए templates के लिए क्या मायने रखता है:\n\n- `class`, `id`, `style`, `title`, `role`, और `aria-*` attributes हर element पर allowed हैं — pantoken के `class=\"instui-*\"` styling hooks (और inline `style`, जैसे CSS anchor positioning के लिए) **do** pasted और saved होने से बचे रहते हैं, इस फ़ाइल में पुरानी guidance के विपरीत। `<script>` tags हमेशा stripped होते हैं।\n- **RCE-safe pantoken components**: static/display components — alert, view, heading, text, table, एक button-as-`<a>` (real `<button>` नहीं), blockquote। semantic HTML पर stick करें जो pantoken पहले से support करता है (`div`, `p`, `span`, `a`, `img`, headings, lists, tables)।\n- **RCE-unsafe**: `@pantoken/interactions` के behavior set से कुछ भी — modal, tooltip, drilldown, close-button, या कोई अन्य component जो native `popover`/`popovertarget`/`command`/`commandfor` attributes द्वारा संचालित है। ये attributes Canvas के sanitizer allowlist में नहीं हैं, इसलिए markup बच जाता है लेकिन interactive behavior पहली बार page को Canvas में save करने पर silently break हो जाता है, यहाँ तक कि `theme.js` के `@pantoken/interactions` loader के साथ भी। Real form elements (`input`, `form`, `button`, `select`, `textarea`, `label`) और inline `<svg>` को completely strip कर दिया जाता है — bundled starter templates में से कोई भी उन्हें use नहीं करता।\n\n`theme.js` CDN से `@pantoken/interactions` को load करता है, जो Canvas के global page scope में चलता है — उन pages पर interactions के लिए उपयोगी जिन्हें आप directly Canvas के RCE में raw HTML edits के साथ बनाते हैं, लेकिन (ऊपर के अनुसार) RCE preview से यहाँ paste किए गए कोई भी `popover`/`command`-attribute-driven markup save होने के बाद interactive नहीं रहेगा।\n" },
293
280
  "components": { "README.md": "# {{projectName}}\n\nएक सादा TypeScript ऐप्लिकेशन (Vite के माध्यम से) के साथ स्टाइल किया गया\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructure के\nडिज़ाइन टोकन और आइकन।\n\n## विकास करें\n\n```sh\nnpm install\nnpm run dev\n```\n\n## यहाँ क्या है\n\n- `index.html` वास्तविक पृष्ठ मार्कअप रखता है — एक `wrapper`-लेआउट शेल\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts) से। स्रोत देखें\n और इसे सीधे संपादित करें; JavaScript द्वारा कुछ नहीं डाला जाता है।\n- `src/main.ts` को `@pantoken/css` आयात करता है (हर `--instui-*` कस्टम प्रॉपर्टी को परिभाषित करता है),\n `@pantoken/components/base.css` (दस्तावेज़ डिफ़ॉल्ट + फोकस रिंग), `components.css`\n (`.instui-*` क्लासेस), `@pantoken/interactions` (मोडल, टूलटिप, और अन्य घटक व्यवहार को तुरंत तार देता है), और आपका स्वयं का `src/style.css` — यहाँ इंटरैक्टिव व्यवहार जोड़ें।\n- वैकल्पिक इन्सर्शन बिंदु (हेडर, फिल्टर, सामग्री, ट्रेलिंग) `<div data-slot=\"...\">` के साथ\n `index.html` में चिह्नित हैं — उनकी सामग्री को अपने स्वयं के मार्कअप से बदलें।\n- मार्कअप पर `class=\"instui-button\"` जैसी क्लासेस लागू करें; पूर्ण क्लास सूची के लिए\n [घटक संदर्भ](https://pantoken.app/api/css) देखें।\n\n## अधिक जानें\n\nअधिक जानने के लिए [HTML गाइड](https://pantoken.app/guide/components) देखें।\n" },
294
281
  "next": { "README.md": "# {{projectName}}\n\nएक Next.js (App Router) ऐप जो [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next) के साथ स्टाइल किया गया है,\nInstructure के डिज़ाइन टोकन और आइकन।\n\n## विकास करें\n\n```sh\nnpm install\nnpm run dev\n```\n\n## यहाँ क्या है\n\n- `next.config.mjs` कॉन्फ़िगरेशन को `withPantoken(...)` के साथ लपेटता है (`transpilePackages` में pantoken जोड़ता है)।\n- `app/layout.tsx` को `@pantoken/css` आयात करता है, जो हर `--instui-*` कस्टम\n प्रॉपर्टी को परिभाषित करता है, रूट पर ताकि यह हर पेज पर उपलब्ध हो, साथ ही `wrapper` लेआउट की रूट क्लास\n `<body>` और `PantokenInteractions` पर (`@pantoken/interactions` को लोड करने वाला एक क्लाइंट कंपोनेंट —\n मोडल, टूलटिप, और अन्य कंपोनेंट व्यवहार को तुरंत तारों में जोड़ता है)।\n- `app/page.tsx` को `instui-*` क्लासेज के साथ स्टाइल किया गया मार्कअप प्रस्तुत करता है; वैकल्पिक सम्मिलन बिंदु (हेडर,\n फ़िल्टर, सामग्री, ट्रेलिंग) को `<div data-slot=\"...\">` के साथ चिह्नित किया जाता है।\n\n## और जानें\n\nऔर जानने के लिए [शुरुआत करने वाली गाइड](https://pantoken.app/guide/getting-started) देखें।\n" },
295
282
  "react": { "README.md": "# {{projectName}}\n\nVite + React ऐप्लिकेशन [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react) और\n[`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css) के साथ स्टाइल की गई है, जो Instructure के डिज़ाइन टोकन और\nआइकन हैं।\n\n## विकास\n\n```sh\nnpm install\nnpm run dev\n```\n\n## यहाँ क्या है\n\n- `src/main.tsx` `@pantoken/css` (हर `--instui-*` कस्टम प्रॉपर्टी को परिभाषित करता है) और\n `@pantoken/interactions` (मोडल, टूलटिप, और अन्य घटक व्यवहार को तुरंत तैयार करता है) को आयात करता है।\n- `src/App.tsx` `instui-*` क्लासेस के साथ स्टाइल किया गया मार्कअप प्रदान करता है; वैकल्पिक प्रविष्टि बिंदु (हेडर,\n फ़िल्टर, सामग्री, अनुगामी) को `<div data-slot=\"...\">` के साथ चिह्नित किया जाता है।\n- InstUI की पूर्ण React घटक लाइब्रेरी (बटन, मोडल, आदि — `@pantoken/react` की\n `<Icon>` सहित) के लिए, आपको जिन विशिष्ट `@instructure/ui-*` पैकेजों की आवश्यकता है उन्हें जोड़ें — <https://instructure.design> देखें।\n\n## और जानें\n\nअधिक जानने के लिए [शुरुआत करने के लिए गाइड](https://pantoken.app/guide/getting-started) देखें।\n" },
@@ -299,7 +286,6 @@ const SCAFFOLD_OVERLAYS = {
299
286
  },
300
287
  "hu": {
301
288
  "angular": { "README.md": "# {{projectName}}\n\nEgy önálló Angular alkalmazás (Vite-on keresztül + `@analogjs/vite-plugin-angular`, Angular CLI nélkül) a következőkkel van stílusozva:\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) és\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken egyéni elemei\nAngular-hoz).\n\n## Fejlesztés\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mi van itt\n\n- `src/main.ts` meghívja `registerPantokenElements()`-et (`@pantoken/angular`-ből) egyszer az indítás során, így\n az olyan elemek, mint `<instui-icon>` működnek a sablonokban, és importálja a token/komponens CSS-t valamint\n `@pantoken/interactions`-et (bekapcsolja a modal, tooltip és más komponens viselkedéseket azonnal).\n- `src/app.component.ts` egy önálló komponens (`CUSTOM_ELEMENTS_SCHEMA` lehetővé teszi, hogy a sablon\n fordító elfogadja a pantoken egyéni elem címkéit), amelynek sablonja `instui-*`\n osztályokkal van stílusozva; az opcionális beillesztési pontok (fejléc, szűrők, tartalom, záró) meg vannak jelölve\n `<div data-slot=\"...\">`-gyel.\n- Alkalmazz olyan osztályokat, mint `class=\"instui-button\"` a markupra; lásd a\n [komponens referenciát](https://pantoken.app/api/css) a teljes osztálylista megtekintéséhez.\n\n## Tudj meg többet\n\nLásd a [kezdeti útmutatót](https://pantoken.app/guide/getting-started), hogy többet megtudj.\n" },
302
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nA Canvas LMS **Theme Editor** számára feltöltésre kész eszközök, valamint egy helyi előnézet a Rich Content Editor (RCE) oldalak szerzőségéhez, amelyek az [`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) segítségével vannak stílusozva.\n\n## Mi van itt\n\n- `theme.css` / `theme.js` — töltse fel ezt a két fájlt a Canvas **Theme Editor → Advanced** menüpontja alatt.\n A generáláskor választott CDN-szolgáltató/téma/mód számára készültek (`--cdn`/`--theme`/\n `--theme-mode`; alapértelmezetten jsDelivr/rebrand/light), és tartalmaznak egy betöltőt az `@pantoken/interactions` számára (összekapcsolja az összetevők viselkedéseit, például modális, tooltip és drilldown).\n- `index.html` / `src/main.ts` — egy helyi, TinyMCE-alapú szerkesztő (`npm run dev`), amely tükrözi a Canvas RCE-jét, így a pantoken osztályaival szemben szerzőként működhet, mielőtt azokat a Canvasba másolja.\n Az oldal maga a pantoken `wrapper` elrendezésével készül: kattintson az **Edit theme** gombra egy tálca megnyitásához a **Config** / **CSS** / **JS** lapokkal (CDN-szolgáltató/téma/mód választók, valamint szintaxis-kiemelt, kézzel szerkeszthető másolatok az `theme.css`/`theme.js`-ből, amelyek az élő előnézetet táplálják), és a **?** gomb a teljes utasításokhoz. A **Layouts** eszköztárgomb segítségével indítsa el a pantoken csomagolt kezdő oldalelrendezéseit (hero, callout, two-column, rubric note, testimonial), amelyeket az [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts) forrásból származnak.\n\n## Fejlesztés\n\n```sh\nnpm install\nnpm run dev\n```\n\nEz megnyit egy Vite fejlesztő szervert a következőkkel:\n\n- Egy **editor** panel (TinyMCE, amely megfelel az [instructure/canvas-lms](https://github.com/instructure/canvas-lms) által használt verziónak/konfigurációnak — lásd alább).\n A **Layouts** gomb segítségével töltse be az egyik csomagolt kezdő elrendezést (ez a megerősítés után az egész dokumentumot helyettesíti, nem pedig beszúrja a kurzornál), és a **Source code** váltóval kézzel szerkessze meg a nyers HTML-t egy szintaxis-kiemelt (CodeMirror) nézetben a szerkesztő mellett, az előnézeti panel élőben frissítve a begépelés közben — ellentétben a TinyMCE stock `code` bővítménnyel, amely egy egylépéses modális párbeszédpanelben szerkeszt élő előnézet nélkül.\n- Egy **preview** panel, amely a szerkesztő tartalmát mutatja az aktuális CSS/JS lap stíluslapjával/scriptjével (nem csak a feloldott CDN URL-ekkel), a Canvas saját tartalomterületének hátterével és max szélességével egyezően becsomagolva — egy hű „hogyan fog kinézni, ha feltöltöttem a Canvasba\" ellenőrzés, élőben frissítve a begépelés vagy a téma szerkesztése közben.\n- A szerkesztő és az előnézeti panelok egy osztott nézetben helyezkednek el, amelyet az elválasztó húzásával átméretezhet, függőlegesen halmozhat az egymás mellett helyett, és felcserélheti a sorrendjét (húzza az egyik panel eszköztárát a másikra, vagy használja a **Swap panes** gombot). Minden panelnak saját teljes képernyő gombja van.\n- Az **Edit theme** tálca **Config** lapja tartalmazza a CDN-szolgáltató/téma/mód választókat és a **Download theme.css** / **Download theme.js** linkeket; a **CSS**/**JS** lapjai a generált fájlok szerkeszthető másolatai — kézzel szerkessze meg őket, és az előnézet közvetlenül átveszi a módosításokat. Egy Config kiválasztás újragenerál a CSS/JS lapokon, kivéve, ha már szerkesztette őket, ebben az esetben a **Regenerate from config** gomb jelenik meg ahelyett, hogy csendes felülírná a szerkesztést.\n\n## Munkafolyamat\n\n1. Töltse fel az `theme.css` és `theme.js` fájlokat a Canvas Theme Editorának (**Advanced → CSS / JavaScript**), hogy a pantoken osztályai minden oldalon elérhető legyenek.\n2. Futtassa az `npm run dev` parancsot, használja a **Layouts** gombot egy csomagolt kezdő verzióval való indításhoz, és szerkessze meg úgy, ahogy a Canvas saját RCE-jében tenné.\n3. Kattintson a **Copy HTML** gombra, és illessze be az eredményt a Canvas oldal RCE-jébe (először váltson az HTML szerkesztő nézetre). A Canvas kiszűri a beillesztett HTML-t a szerver oldalán — ez a lábazat nem próbálja meg replikálni ezt, ezért mindig ellenőrizze a beillesztett eredményt a Canvasban (lásd „Megjegyzések a Canvas RCE-ről\" alább).\n\n## Megjegyzések a Canvas RCE-ről\n\nA Canvas Rich Content Editor futtatja a TinyMCE-t, és szerver oldalon szűri a beküldött HTML-t egy engedélyezett listán (`gems/canvas_sanitize` a canvas-lms-ben, szinkronban tartva a TinyMCE saját `valid_elements`/`extended_valid_elements`-val). Mit jelent az engedélyezett lista az itt készített sablonok számára:\n\n- Az `class`, `id`, `style`, `title`, `role` és `aria-*` attribútumok minden elemen engedélyezve vannak — a pantoken `class=\"instui-*\"` stílushorgai (és inline `style`, például CSS anchor pozicionáláshoz) **valóban** túlélik a beillesztést és mentést, ellentétben ezzel a fájl régebbi útmutatásával. Az `<script>` címkék mindig el vannak távolítva.\n- **RCE-biztonságos pantoken komponensek**: statikus/megjelenítési komponensek — alert, view, heading, text, table, button-as-`<a>` (nem igazi `<button>`), blockquote. Maradjon a szimantikus HTML mellett, amelyet a pantoken már támogat (`div`, `p`, `span`, `a`, `img`, fejlécek, listák, táblázatok).\n- **RCE-nem biztonságos**: bármilyen az `@pantoken/interactions` viselkedéshalmazából — modal, tooltip, drilldown, close-button, vagy bármely más komponens, amelyet az `popover`/`popovertarget`/`command`/`commandfor` attribútumok hajtanak végre. Ezek az attribútumok nincsenek a Canvas szűrő engedélyezett listájában, így a jelölés túlél, de az interaktív viselkedés csendes hibát okoz az oldal első Canvasban való mentésekor, még akkor is, ha az `theme.js` `@pantoken/interactions` betöltője jelen van. A valós formelemek (`input`, `form`, `button`, `select`, `textarea`, `label`) és inline `<svg>` teljesen eltávolítva vannak — a csomagolt kezdő sablonok közül egyik sem használja őket.\n\nAz `theme.js` betölti az `@pantoken/interactions` fájlt a CDN-ből, amely a Canvas globális oldal terjedelmében fut — hasznos az olyan oldalakkal való interakciók számára, amelyeket közvetlenül a Canvas RCE-jében készít nyers HTML szerkesztésekkel, de (a fentiek szerint) az RCE előnézetéből ilyen beillesztett `popover`/`command`-attribútum által vezérelt jelölés nem marad interaktív mentés után.\n" },
303
289
  "components": { "README.md": "# {{projectName}}\n\nEgy egyszerű TypeScript alkalmazás (a Vite-on keresztül), amely a\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) elemmel van stílizálva, az Instructure\ntervezési tokenjei és ikonjai.\n\n## Fejlesztés\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mi van itt\n\n- `index.html` az aktuális oldal jelöléseit tartalmazza — egy `wrapper`-elrendezési héj innen:\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Tekintse meg a forráskódot\n és szerkessze közvetlenül; semmi nem kerül injektálásra a JavaScript-ben.\n- `src/main.ts` importálja a `@pantoken/css` (meghatározza az összes `--instui-*` egyéni tulajdonságot),\n `@pantoken/components/base.css` (dokumentum alapértelmezettei + fókuszgyűrű), `components.css`\n (`.instui-*` osztályok), `@pantoken/interactions` (modális, tooltip és egyéb komponens viselkedéseket köt össze azonnal), és a saját `src/style.css` — adjon hozzá interaktív viselkedést itt.\n- Az opcionális beszúrási pontok (fejléc, szűrők, tartalom, záró) a `<div data-slot=\"...\">` elemmel vannak megjelölve a `index.html` részben — cserélje le tartalmaikat saját jelöléssel.\n- Alkalmazzon osztályokat, például `class=\"instui-button\"` a jelöléshez; lásd az\n [komponens referenciáját](https://pantoken.app/api/css) a teljes osztálylista listájáért.\n\n## További információk\n\nLásd az [HTML útmutatót](https://pantoken.app/guide/components) hogy többet megtudj.\n" },
304
290
  "next": { "README.md": "# {{projectName}}\n\nAz Instructure design tokenjeivel és ikonjával stílusított Next.js (App Router) alkalmazás ([`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next)).\n\n## Fejlesztés\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mi van itt\n\n- `next.config.mjs` becsomagolja a konfigurációt `withPantoken(...)` segítségével (hozzáadja a pantokent a `transpilePackages`-hoz).\n- `app/layout.tsx` importálja a `@pantoken/css`-et, amely a gyökérnél minden `--instui-*` egyéni tulajdonságot definiál, így az minden oldalon elérhető, valamint a `wrapper` elrendezés gyökérosztálya a `<body>`-on és `PantokenInteractions`-en (egy kliens komponens, amely betölti a `@pantoken/interactions`-et — bedrótoza a modális, tooltip és más komponens viselkedéseket alapból).\n- `app/page.tsx` a `instui-*` osztályokkal stílusított jelöléseket rendereli; az opcionális beszúrási pontok (fejléc, szűrők, tartalom, lezáró) a `<div data-slot=\"...\">`-vel vannak megjelölve.\n\n## További információ\n\nTovábbi információért lásd az [Első lépések útmutató](https://pantoken.app/guide/getting-started)-t.\n" },
305
291
  "react": { "README.md": "# {{projectName}}\n\nEgy Vite + React alkalmazás, amely [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nés [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css) segítségével van stílusozva, az Instructure tervezési tokenei és\nikonjai.\n\n## Fejlesztés\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mi van itt\n\n- `src/main.tsx` importálja a(z) `@pantoken/css` modult (az összes `--instui-*` egyéni tulajdonságot határozza meg) és\n a(z) `@pantoken/interactions` modult (a modális, eszköztipp és egyéb összetevő viselkedéseket azonnal beállít).\n- `src/App.tsx` az `instui-*` osztályokkal stílusozott jelöléseket jelenít meg; az opcionális beillesztési pontok (fejléc,\n szűrők, tartalom, utolsó) a(z) `<div data-slot=\"...\">` segítségével vannak jelölve.\n- Az InstUI teljes React komponenskönyvtárához (gombok, modálok, stb. — beleértve az `@pantoken/react`'s\n `<Icon>`) adja hozzá a szükséges `@instructure/ui-*` csomagokat — lásd <https://instructure.design>.\n\n## Tudj meg többet\n\nA további ismeretekért lásd a [kezdeti útmutatót](https://pantoken.app/guide/getting-started).\n" },
@@ -309,7 +295,6 @@ const SCAFFOLD_OVERLAYS = {
309
295
  },
310
296
  "is": {
311
297
  "angular": { "README.md": "# {{projectName}}\n\nSjálfstætt Angular forrit (gegnum Vite + `@analogjs/vite-plugin-angular`, engin Angular CLI) stílað með [`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) og [`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken sérsniðnir þættir fyrir Angular).\n\n## Þróun\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hvað er hér\n\n- `src/main.ts` kallar `registerPantokenElements()` (frá `@pantoken/angular`) einu sinni í ræsinni svo þættir eins og `<instui-icon>` virka í sniðmátum, og flytur inn merki-/hluta CSS plús `@pantoken/interactions` (tengir modal, tooltip og önnur þættahegðun sem virka tilbúin frá fyrstu).\n- `src/app.component.ts` er sjálfstæður hlutur (`CUSTOM_ELEMENTS_SCHEMA` leyfir sniðmátskennara að samþykkja sérsniðna þætti pantoken) þar sem sniðmátið er stílað með `instui-*` flokkum; valfrjálsir innsetningarpunktar (haus, síur, efni, lokastig) eru merktir með `<div data-slot=\"...\">`.\n- Notaðu flokka eins og `class=\"instui-button\"` á merkingu; sjáðu [hluta viðmiðun](https://pantoken.app/api/css) fyrir fullan flokkalistann.\n\n## Fræðast meira\n\nSjáðu [hafnun leiðbeiningar](https://pantoken.app/guide/getting-started) til að fræðast meira.\n" },
312
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nTilbúnir eiginleikar til hladdu upp fyrir Canvas LMS **Theme Editor**, ásamt staðbundinni forskoðun til að skrifa Rich Content Editor (RCE) síðusniðmát stílbundin með [`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Hvað er hér\n\n- `theme.css` / `theme.js` — hlaðið þessum tveimur skrám upp undir **Theme Editor → Advanced** í Canvas.\n Þær eru byggðar fyrir CDN-veitandann/þemað/stillingu sem þú valdir við stærðir (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light sjálfgefið) og innihalda hlaðara fyrir\n `@pantoken/interactions` (tengir íhluti hegðun eins og modal, tooltip og drilldown).\n- `index.html` / `src/main.ts` — staðbundinn, TinyMCE-bygðan ritstjóri (`npm run dev`) sem endurspeglar RCE Canvas\n svo þú getir skrifað síðusniðmát á móti pantoken klösum áður en þú afritar þau inn í Canvas.\n Síðan sjálf er byggð með pantoken **`wrapper`** útliti: smelltu á **Edit theme** til að opna skúffu\n með **Config** / **CSS** / **JS** flipum (CDN veitandi/þema/stillingu valkostir, og málskrárljós,\n handbreytanlegir afrit af `theme.css`/`theme.js` sem fóðra lifandi forskoðun), og **?** hnappinn\n fyrir fullar leiðbeiningar. Notaðu **Layouts** verkfærastiku hnappinn til að byrja frá einum af pantoken\n bundlum byrjunarútlitum (hetjumynd, útkall, tveir dálkar, rúbríkk athugasemd, vitnisburður), sem koma frá\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Þróun\n\n```sh\nnpm install\nnpm run dev\n```\n\nÞetta opnar Vite þróunarþjón með:\n\n- **ritstjóra** rúðu (TinyMCE, samsvarig útgáfan/stillingu sem\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) sjálf notar — sjá hér að neðan).\n Notaðu **Layouts** hnappinn til að hlaða einum af bundlum byrjunarútlitum (þetta kemur í stað heilrar\n skjalsins, eftir staðfestingu, en ekki setning við bendilinn), og **Source code** víxlun\n til að handbreyta óunna HTML í málskrá-auðkenndu (CodeMirror) skoðun samhliða ritstjóranum, með\n forskoðun rúðunni sem uppfærist lifandi þegar þú slærð inn — ólíkt TinyMCE hlutabundnu `code` íformi, sem\n breytir í eins konar modal gluggum án lifandi forskoðunar.\n- **forskoðun** rúða sem sýnir efni ritstjórans með núverandi CSS/JS flipa stílblað/script\n beitt (ekki bara leystu CDN vefslóðir), umbúið til að passa við Canvas eigin efnissvæði bakgrunn\n og hámarksbreidd — trú \"hvað þetta mun líta út þegar það er hlaðið upp í Canvas\" athugun, uppfærð\n lifandi þegar þú slærð inn eða breytir þemanum.\n- Ritstjóri og forskoðun rúðurnar sitja í samskoðun skoðun sem þú getur breytt stærð með því að draga deilinn, \n stafla lóðrétt í stað hlið við hlið, og skipulag rekkanna (dragðu rúðu verkfærastiku á hina, eða\n notaðu **Swap panes** hnappinn). Hver rúða hefur sinn eigin fullskjá hnapp.\n- **Edit theme** skúffu **Config** flipi geymir CDN veitandi/þema/stillingu valkosti og\n **Download theme.css** / **Download theme.js** tengla; hennar **CSS**/**JS** flipir eru breytanlegir afrit\n mynduðu skráanna — handbreytaðu þau og forskoðun tekur þær breytingar beint. Breyta\n Config vali endurmyndar CSS/JS flipina nema þú hafir þegar breytt þeim, en þá\n **Regenerate from config** hnappinn birtist í staðinn fyrir að skrifa ekki beint yfir breytingarnar.\n\n## Verkflæði\n\n1. Hlaðið `theme.css` og `theme.js` upp til Canvas Theme Editor (**Advanced → CSS / JavaScript**) svo\n pantoken klasar eru tiltækir á hverri síðu.\n2. Keyrðu `npm run dev`, notaðu **Layouts** til að byrja frá bundlu byrjunarútliti, og breyttu því eins og þú\n myndir gera í Canvas eigin RCE.\n3. Smelltu á **Copy HTML** og límdu niðurstöðu inn í Canvas síðu RCE (skiptu yfir á HTML ritstjóra\n skoðun fyrst). Canvas hreinsar límda HTML á þjón - þessi grunnur reynir ekki\n endurgera það, svo alltaf sannreyna límda niðurstöðu í Canvas (sjá \"Athugasemdir um Canvas RCE\"\n hér að neðan).\n\n## Athugasemdir um Canvas RCE\n\nCanvas Rich Content Editor keyrir TinyMCE og hreinsar skjal HTML á þjón gegn\nleyfislista (`gems/canvas_sanitize` í canvas-lms, haldin í samstillingu við TinyMCE eigin\n`valid_elements`/`extended_valid_elements`). Hvað það leyfisaskra þýðir fyrir sniðmát sem byggð eru hér:\n\n- `class`, `id`, `style`, `title`, `role`, og `aria-*` eigindir eru leyfðar á öllu frumefni —\n pantoken **`class=\"instui-*\"`** stílbundin krækir (og innleiðar `style`, td fyrir CSS akkeri staðsetningu)\n **gera** lifið eftir að vera límdu og vistuð, andstætt eldri leiðbeiningum í þessari skrá. `<script>` merki\n eru alltaf fjarlægð.\n- **RCE-örugg pantoken íhlutir**: kyrrstæðir/birtinga íhlutir — viðvörun, skoðun, fyrirsögn, texti, tafla,\n hnappur-sem-`<a>` (ekki raunverulegur `<button>`), tilvitnun. Haltu þig við merkingarfræðilega HTML sem pantoken\n styður (`div`, `p`, `span`, `a`, `img`, fyrirsagnir, listar, töflur).\n- **RCE-óörugg**: allt frá `@pantoken/interactions` hegðun safn — modal, tooltip,\n drilldown, lokahnappir, eða aðrir íhlutir drifnir af innfæddri `popover`/`popovertarget`/\n `command`/`commandfor` eigindir. Þessar eigindir eru ekki á Canvas hreinsunarleyfinu, svo\n merkið lifir en gagnvirka hegðun þagna slær út fyrstu sinni sem síðan er\n vistuð í Canvas, jafnvel með `theme.js` **`@pantoken/interactions`** hlaðara núverandi. Raunverulegir form\n frumefni (`input`, `form`, `button`, `select`, `textarea`, `label`) og innleiðar `<svg>` eru\n fjarlægð beint — engin bundla byrjunarútliti nota þau.\n\n`theme.js` hlaðar `@pantoken/interactions` frá CDN, sem keyrir í Canvas alheims síðuumfangi —\ngagnlegt fyrir gagnvirkni á síðum sem þú byggir beint í Canvas RCE með óunnum HTML breytingum, en (per\nframangreint) allt `popover`/`command`-eigind-drifin merking sem límdu frá RCE forskoðun hér mun ekki halda\ngagnvirkni þegar hún er vistuð.\n" },
313
298
  "components": { "README.md": "# {{projectName}}\n\nVenjuleg TypeScript forrit (með Vite) stíluð með\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), hönnunartáknanna og hornmyndum frá Instructure.\n\n## Þróun\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hvað er hér\n\n- `index.html` inniheldur raunverulegt dóm vefsíðunnar — skelja með `wrapper`-útliti frá\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Skoðaðu upprunakóðann\n og breyttu honum beint; ekkert er sprautað inn af JavaScript.\n- `src/main.ts` flytur inn `@pantoken/css` (skilgreinir alla `--instui-*` sérsniðna eiginleika),\n `@pantoken/components/base.css` (sjálfgildi skjals + fókushringar), `components.css`\n (`.instui-*` flokkar), `@pantoken/interactions` (virkjar myndarglugga, ábendingar og aðra hegðun íhluta beint úr kassanum), og þinn eigin `src/style.css` — bættu við gagnvirkri hegðun hér.\n- Valkvæðir innsetningarpunktar (haus, síur, efni, eftirfarandi) eru merktir með\n `<div data-slot=\"...\">` í `index.html` — skiptu innihaldi þeirra út fyrir þitt eigið dóm.\n- Notaðu flokka eins og `class=\"instui-button\"` á dóm; sjá\n [íhlutakornið](https://pantoken.app/api/css) fyrir fullan lista af flokkum.\n\n## Fræðast meira\n\nSjá [HTML leiðbeiningarnar](https://pantoken.app/guide/components) til að fræðast meira.\n" },
314
299
  "next": { "README.md": "# {{projectName}}\n\nNext.js (App Router) forrit stílað með [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nhönnunarmerki og tákn Instructure.\n\n## Þróun\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hvað er hér\n\n- `next.config.mjs` pakkar inn stillingunum með `withPantoken(...)` (bætir pantoken við `transpilePackages`).\n- `app/layout.tsx` innflytir `@pantoken/css`, sem skilgreinir hvern `--instui-*` sérsniðinn eiginleika, við rótina svo hún er tiltæk á hverri síðu, auk `wrapper` útlit rótarflokks á `<body>` og `PantokenInteractions` (íhlutur viðskiptavinar sem hlaðir `@pantoken/interactions` — setur upp glugga-, ábendingu- og aðra hegðun íhluta tilbúna strax).\n- `app/page.tsx` birtir merkingu stílað með `instui-*` flokkum; valfrjálsir innsetningarstaðir (haus, síur, efni, efni á eftir) eru merktir með `<div data-slot=\"...\">`.\n\n## Lærðu meira\n\nSjáðu [leiðbeiningar til að byrja](https://pantoken.app/guide/getting-started) til að læra meira.\n" },
315
300
  "react": { "README.md": "# {{projectName}}\n\nVite + React forrit stillt með [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react) og [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), hönnunartákn og tákn Instructure.\n\n## Þróun\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hvað er hér\n\n- `src/main.tsx` innflytir `@pantoken/css` (skilgreinir allar `--instui-*` sérsniðnar eigindir) og `@pantoken/interactions` (setur upp modal, tooltip og aðra hegðun íhlutar úr kassa).\n- `src/App.tsx` birtir merkingu stilta með `instui-*` flokkum; valfræðir innsetningarpunktar (header, filters, content, trailing) eru merktir með `<div data-slot=\"...\">`.\n- Fyrir InstUI's fullt React íhlutasafn (buttons, modals, o.s.frv. — þar með talið `@pantoken/react`'s `<Icon>`), bættu við sérstökum `@instructure/ui-*` pökkum sem þú þarfnast — sjá <https://instructure.design>.\n\n## Frekari efni\n\nSjá [leiðbeininguna um byrjun](https://pantoken.app/guide/getting-started) til að læra meira.\n" },
@@ -319,7 +304,6 @@ const SCAFFOLD_OVERLAYS = {
319
304
  },
320
305
  "id": {
321
306
  "angular": { "README.md": "# {{projectName}}\n\nAplikasi Angular mandiri (via Vite + `@analogjs/vite-plugin-angular`, tanpa Angular CLI) yang distyling dengan\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) dan\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (elemen kustom pantoken\nuntuk Angular).\n\n## Mengembangkan\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Apa yang ada di sini\n\n- `src/main.ts` memanggil `registerPantokenElements()` (dari `@pantoken/angular`) sekali saat bootstrap sehingga\n elemen seperti `<instui-icon>` bekerja di template, dan mengimpor CSS token/komponen plus\n `@pantoken/interactions` (menghubungkan perilaku modal, tooltip, dan komponen lainnya di luar\n kotak).\n- `src/app.component.ts` adalah komponen mandiri (`CUSTOM_ELEMENTS_SCHEMA` memungkinkan compiler template\n menerima tag elemen kustom pantoken) yang templatenya distyling dengan kelas `instui-*`\n ; titik penyisipan opsional (header, filters, content, trailing) ditandai dengan\n `<div data-slot=\"...\">`.\n- Terapkan kelas seperti `class=\"instui-button\"` ke markup; lihat\n [referensi komponen](https://pantoken.app/api/css) untuk daftar kelas lengkap.\n\n## Pelajari lebih lanjut\n\nLihat [panduan memulai](https://pantoken.app/guide/getting-started) untuk mempelajari lebih lanjut.\n" },
322
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nAset siap-unggah untuk **Theme Editor** Canvas LMS, plus pratinjau lokal untuk mengautor templat halaman Rich Content Editor (RCE) yang ditata dengan\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Yang ada di sini\n\n- `theme.css` / `theme.js` — unggah kedua file ini di bawah **Theme Editor → Advanced** di Canvas.\n File-file ini dibangun untuk penyedia CDN/tema/mode yang Anda pilih saat melakukan scaffolding (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light secara default) dan menyertakan loader untuk\n `@pantoken/interactions` (menghubungkan perilaku komponen seperti modal, tooltip, dan drilldown).\n- `index.html` / `src/main.ts` — editor berbasis TinyMCE lokal (`npm run dev`) yang mencerminkan\n RCE Canvas sehingga Anda dapat mengautor templat halaman terhadap kelas pantoken sebelum menyalinnya ke Canvas.\n Halaman itu sendiri dibangun dengan layout `wrapper` pantoken: klik **Edit theme** untuk membuka tray\n dengan tab **Config** / **CSS** / **JS** (pilihan penyedia CDN/tema/mode, dan salinan yang dapat diedit dengan sorotan sintaks dari\n `theme.css`/`theme.js` yang memberi makan pratinjau langsung), dan tombol **?**\n untuk petunjuk lengkap. Gunakan tombol toolbar **Layouts** untuk memulai dari salah satu layout halaman starter bundel pantoken\n (hero, callout, dua kolom, catatan rubrik, testimonial), bersumber dari\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Mengembangkan\n\n```sh\nnpm install\nnpm run dev\n```\n\nIni membuka server dev Vite dengan:\n\n- Panel **editor** (TinyMCE, cocok dengan versi/konfigurasi\n yang digunakan [instructure/canvas-lms](https://github.com/instructure/canvas-lms) — lihat di bawah).\n Gunakan tombol **Layouts** untuk memuat salah satu layout starter bundel (ini mengganti seluruh\n dokumen, setelah konfirmasi, bukan menyisipkan di kursor), dan toggle **Source code**\n untuk mengedit HTML mentah di tampilan yang diberi sorotan sintaks (CodeMirror) bersama pane pratinjau, dengan\n pane pratinjau diperbarui langsung saat Anda mengetik — tidak seperti plugin `code` TinyMCE standar, yang mengedit dalam\n dialog modal satu-kali tanpa pratinjau langsung.\n- Pane **preview** yang menampilkan konten editor dengan stylesheet/script tab CSS/JS saat ini\n diterapkan (bukan hanya URL CDN yang diselesaikan), dibungkus agar sesuai dengan latar belakang area konten\n dan lebar maksimal Canvas sendiri — pemeriksaan \"bagaimana tampilannya setelah diunggah ke Canvas\" yang akurat, diperbarui\n langsung saat Anda mengetik atau mengedit tema.\n- Pane editor dan preview berada dalam tampilan terbelah yang dapat Anda ubah ukurannya dengan menyeret pembagi, tumpukan\n secara vertikal alih-alih berdampingan, dan tukar urutan (seret toolbar pane ke yang lain,\n atau gunakan tombol **Swap panes**). Setiap pane memiliki tombol fullscreen tersendiri.\n- Tab **Config** tray **Edit theme** menampung pilihan penyedia CDN/tema/mode dan\n tautan **Download theme.css** / **Download theme.js**; tab **CSS**/**JS** adalah salinan yang dapat diedit\n dari file yang dihasilkan — sunting secara manual dan pratinjau menangkap perubahan Anda secara langsung. Mengubah\n pilihan Config membuat ulang tab CSS/JS kecuali Anda sudah mengeditnya, dalam hal itu tombol\n **Regenerate from config** muncul sebagai ganti diam-diam menimpa edit Anda.\n\n## Alur Kerja\n\n1. Unggah `theme.css` dan `theme.js` ke Theme Editor Canvas (**Advanced → CSS / JavaScript**) jadi\n kelas pantoken tersedia di setiap halaman.\n2. Jalankan `npm run dev`, gunakan **Layouts** untuk memulai dari starter bundel, dan sunting seperti yang\n Anda lakukan di RCE Canvas sendiri.\n3. Klik **Copy HTML** dan tempel hasilnya ke RCE halaman Canvas (beralih ke tampilan editor HTML\n terlebih dahulu). Canvas membersihkan HTML yang ditempel di sisi server — scaffolding ini tidak mencoba\n mereplikasi itu, jadi selalu verifikasi hasil yang ditempel di Canvas (lihat \"Catatan di RCE Canvas\"\n di bawah).\n\n## Catatan di RCE Canvas\n\nRich Content Editor Canvas menjalankan TinyMCE dan membersihkan HTML yang dikirim di server terhadap\ndaftar yang diizinkan (`gems/canvas_sanitize` di canvas-lms, tetap tersinkronisasi dengan\n`valid_elements`/`extended_valid_elements` TinyMCE sendiri). Apa yang dimaksud daftar yang diizinkan itu untuk templat yang dibangun di sini:\n\n- `class`, `id`, `style`, `title`, `role`, dan `aria-*` atribut diizinkan pada setiap elemen —\n kait styling `class=\"instui-*\"` pantoken (dan inline `style`, misalnya untuk pemosisisan jangkar CSS)\n **memang** bertahan saat ditempel dan disimpan, bertentangan dengan panduan yang lebih lama di file ini. Tag `<script>`\n selalu dilepas.\n- **Komponen pantoken aman-RCE**: komponen statis/tampilan — alert, view, heading, text, table,\n tombol-sebagai-`<a>` (bukan `<button>` asli), blockquote. Tetap pada HTML semantik yang sudah didukung pantoken\n (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- **RCE-tidak aman**: apa pun dari set perilaku `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, atau komponen lain apa pun yang didorong oleh atribut `popover`/`popovertarget`/\n `command`/`commandfor` asli. Atribut-atribut itu tidak dalam daftar yang diizinkan pembersih Canvas, jadi\n markup bertahan tetapi perilaku interaktif diam-diam rusak pertama kali halaman\n disimpan di Canvas, bahkan dengan loader `theme.js` `@pantoken/interactions` ada. Elemen form asli\n (`input`, `form`, `button`, `select`, `textarea`, `label`) dan inline `<svg>` adalah\n dilepas sepenuhnya — tidak ada templat starter bundel yang menggunakannya.\n\n`theme.js` memuat `@pantoken/interactions` dari CDN, yang berjalan dalam cakupan halaman global Canvas —\nberguna untuk interaksi pada halaman yang Anda bangun langsung di RCE Canvas dengan edit HTML mentah, tetapi (per\ndi atas) markup yang didorong oleh atribut `popover`/`command` yang ditempel dari pratinjau RCE di sini tidak akan tetap\ninteraktif setelah disimpan.\n" },
323
307
  "components": { "README.md": "# {{projectName}}\n\nSebuah aplikasi TypeScript biasa (via Vite) dengan gaya dari\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), token desain dan ikon\ndari Instructure.\n\n## Mengembangkan\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Apa yang ada di sini\n\n- `index.html` berisi markup halaman yang sebenarnya — cangkang tata letak `wrapper`-layout dari\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Lihat sumber\n dan edit secara langsung; tidak ada yang disuntikkan oleh JavaScript.\n- `src/main.ts` mengimpor `@pantoken/css` (mendefinisikan setiap properti kustom `--instui-*`),\n `@pantoken/components/base.css` (default dokumen + focus ring), `components.css`\n (kelas `.instui-*`), `@pantoken/interactions` (menghubungkan modal, tooltip, dan perilaku komponen lainnya secara langsung), dan `src/style.css` Anda sendiri — tambahkan perilaku interaktif di sini.\n- Titik penyisipan opsional (header, filter, konten, trailing) ditandai dengan\n `<div data-slot=\"...\">` dalam `index.html` — ganti isinya dengan markup Anda sendiri.\n- Terapkan kelas seperti `class=\"instui-button\"` ke markup; lihat\n [referensi komponen](https://pantoken.app/api/css) untuk daftar kelas lengkap.\n\n## Pelajari lebih lanjut\n\nLihat [panduan HTML](https://pantoken.app/guide/components) untuk mempelajari lebih lanjut.\n" },
324
308
  "next": { "README.md": "# {{projectName}}\n\nAplikasi Next.js (App Router) yang ditata dengan [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\ntoken desain dan ikon Instructure.\n\n## Kembangkan\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Apa yang ada di sini\n\n- `next.config.mjs` membungkus konfigurasi dengan `withPantoken(...)` (menambahkan pantoken ke\n `transpilePackages`).\n- `app/layout.tsx` mengimpor `@pantoken/css`, yang mendefinisikan setiap properti custom `--instui-*`,\n di root sehingga tersedia di setiap halaman, ditambah kelas root layout `wrapper` di\n `<body>` dan `PantokenInteractions` (komponen klien yang memuat `@pantoken/interactions` —\n mengatur perilaku modal, tooltip, dan komponen lainnya langsung).\n- `app/page.tsx` merender markup yang ditata dengan kelas `instui-*`; titik penyisipan opsional (header,\n filter, konten, trailing) ditandai dengan `<div data-slot=\"...\">`.\n\n## Pelajari lebih lanjut\n\nLihat [panduan memulai](https://pantoken.app/guide/getting-started) untuk mempelajari lebih lanjut.\n" },
325
309
  "react": { "README.md": "# {{projectName}}\n\nAplikasi Vite + React yang ditata dengan [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\ndan [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), token desain dan ikon Instructure.\n\n## Berkembang\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Apa yang ada di sini\n\n- `src/main.tsx` mengimpor `@pantoken/css` (mendefinisikan setiap properti kustom `--instui-*`) dan\n `@pantoken/interactions` (menghubungkan modal, tooltip, dan perilaku komponen lainnya di luar\n kotak).\n- `src/App.tsx` merender markup yang ditata dengan kelas `instui-*`; titik penyisipan opsional (header,\n filter, konten, trailing) ditandai dengan `<div data-slot=\"...\">`.\n- Untuk perpustakaan komponen React lengkap InstUI (tombol, modal, dll. — termasuk `@pantoken/react`'s\n `<Icon>`), tambahkan paket `@instructure/ui-*` spesifik yang Anda butuhkan — lihat <https://instructure.design>.\n\n## Pelajari lebih lanjut\n\nLihat [panduan memulai](https://pantoken.app/guide/getting-started) untuk mempelajari lebih lanjut.\n" },
@@ -329,7 +313,6 @@ const SCAFFOLD_OVERLAYS = {
329
313
  },
330
314
  "it": {
331
315
  "angular": { "README.md": "# {{projectName}}\n\nUn'app Angular standalone (tramite Vite + `@analogjs/vite-plugin-angular`, senza Angular CLI) con stile definito da\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) e\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (elementi personalizzati\npantoken per Angular).\n\n## Sviluppo\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Cosa c'è qui\n\n- `src/main.ts` chiama `registerPantokenElements()` (da `@pantoken/angular`) una volta al bootstrap in modo che elementi come `<instui-icon>` funzionino nei template, e importa il CSS token/componente più `@pantoken/interactions` (collega le modalità modal, tooltip e altri comportamenti dei componenti pronti all'uso).\n- `src/app.component.ts` è un componente standalone (`CUSTOM_ELEMENTS_SCHEMA` consente al compilatore di template di accettare i tag degli elementi personalizzati di pantoken) il cui template è stilizzato con le classi `instui-*`; i punti di inserimento facoltativi (header, filters, content, trailing) sono contrassegnati con `<div data-slot=\"...\">`.\n- Applica classi come `class=\"instui-button\"` al markup; consulta il\n [riferimento dei componenti](https://pantoken.app/api/css) per l'elenco completo delle classi.\n\n## Scopri di più\n\nConsulta la [guida introduttiva](https://pantoken.app/guide/getting-started) per saperne di più.\n" },
332
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nAsset pronti per l'upload per il **Theme Editor** di Canvas LMS, più un'anteprima locale per la creazione di template di pagina del Rich\nContent Editor (RCE) stilizzati con\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Cosa c'è qui\n\n- `theme.css` / `theme.js` — caricare questi due file sotto **Theme Editor → Advanced** in Canvas.\n Sono buildati per il provider CDN/theme/mode scelto durante lo scaffolding (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light per default) e includono un loader per\n `@pantoken/interactions` (collega i comportamenti dei componenti come modal, tooltip e drilldown).\n- `index.html` / `src/main.ts` — un editor locale basato su TinyMCE (`npm run dev`) che rispecchia l'RCE di Canvas\n così puoi creare template di pagina usando le classi di pantoken prima di copiarli in Canvas.\n La pagina stessa è costruita con il layout `wrapper` di pantoken: clicca **Edit theme** per aprire un pannello\n con le schede **Config** / **CSS** / **JS** (selettori per provider CDN/theme/mode, e copie modificabili a mano e con evidenziazione sintattica di\n `theme.css`/`theme.js` che alimentano l'anteprima live), e il pulsante **?** per le istruzioni complete. Usa il pulsante della toolbar **Layouts** per partire da uno dei layout di pagina inclusi in pantoken (hero, callout, due colonne, nota rubric, testimonial), presi da\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Sviluppo\n\n```sh\nnpm install\nnpm run dev\n```\n\nQuesto apre un server di sviluppo Vite con:\n\n- Un riquadro **editor** (TinyMCE, corrispondente alla versione/config\n che [instructure/canvas-lms](https://github.com/instructure/canvas-lms) usa — vedi sotto).\n Usa il pulsante **Layouts** per caricare uno dei layout di partenza inclusi (questo sostituisce l'intero\n documento, dopo conferma, invece di inserirlo nel cursore), e il toggle **Source code** per modificare a mano l'HTML grezzo in una vista con evidenziazione sintattica (CodeMirror) affiancata all'editor, con\n l'anteprima che si aggiorna live mentre digiti — a differenza del plugin `code` di TinyMCE, che modifica in\n un dialogo modale one-shot senza anteprima live.\n- Un riquadro **preview** che mostra il contenuto dell'editor con il foglio di stile/script della scheda CSS/JS corrente\n applicato (non solo gli URL CDN risolti), incorniciato per corrispondere allo sfondo dell'area contenuti e alla larghezza massima di Canvas — un controllo fedele di \"come apparirà una volta caricato in Canvas\", aggiornato\n live mentre digiti o modifichi il tema.\n- L'editor e i riquadri di anteprima stanno in una vista divisa che puoi ridimensionare trascinando il divisore, impilarli\n verticalmente invece che affiancati, e scambiare l'ordine (trascina la toolbar di un riquadro sull'altro,\n oppure usa il pulsante **Swap panes**). Ogni riquadro ha il proprio pulsante fullscreen.\n- Il pannello **Edit theme** nella scheda **Config** contiene i selettori per provider CDN/theme/mode e\n i link **Download theme.css** / **Download theme.js**; le sue schede **CSS**/**JS** sono copie modificabili\n dei file generati — modificale a mano e l'anteprima applicherà le tue modifiche immediatamente. Cambiare un selettore in Config rigenera le schede CSS/JS a meno che tu non le abbia già modificate, nel qual caso appare un\n pulsante **Regenerate from config** invece di sovrascrivere silenziosamente la tua modifica.\n\n## Flusso di lavoro\n\n1. Caricare `theme.css` e `theme.js` nel Theme Editor di Canvas (**Advanced → CSS / JavaScript**) in modo che\n le classi di pantoken siano disponibili in ogni pagina.\n2. Eseguire `npm run dev`, usare **Layouts** per partire da un starter incluso, e modificarlo come faresti\n nell'RCE di Canvas.\n3. Cliccare **Copy HTML** e incollare il risultato nell'RCE di una pagina Canvas (passa prima alla vista dell'editor HTML).\n Canvas sanitizza l'HTML incollato lato server — questo scaffold non tenta di\n replicare quel comportamento, quindi verifica sempre il risultato incollato in Canvas (vedi \"Note sull'RCE di Canvas\"\n qui sotto).\n\n## Note sull'RCE di Canvas\n\nIl Rich Content Editor di Canvas esegue TinyMCE e sanitizza l'HTML inviato sul server usando una\nallowlist (`gems/canvas_sanitize` in canvas-lms, mantenuta in sincronizzazione con le impostazioni di TinyMCE\n`valid_elements`/`extended_valid_elements`). Ciò che quella allowlist significa per i template creati qui:\n\n- Gli attributi `class`, `id`, `style`, `title`, `role` e `aria-*` sono permessi su ogni elemento —\n i ganci di styling di pantoken `class=\"instui-*\"` (e gli `style` inline, es. per il posizionamento degli anchor in CSS)\n **sopravvivono** all'operazione di incolla e salvataggio, contrariamente alle linee guida più vecchie in questo file. I tag `<script>`\n vengono sempre rimossi.\n- Componenti pantoken sicuri per l'RCE: componenti statici/di visualizzazione — alert, view, heading, text, table,\n un pulsante come `<a>` (non un vero `<button>`), blockquote. Attenersi all'HTML semantico già supportato da pantoken (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- Non sicuro per l'RCE: qualsiasi cosa dall'insieme di comportamenti di `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, o qualsiasi altro componente pilotato dagli attributi nativi `popover`/`popovertarget`/\n `command`/`commandfor`. Quegli attributi non sono nella allowlist del sanitizer di Canvas, quindi\n il markup sopravvive ma il comportamento interattivo si rompe silenziosamente la prima volta che la pagina viene\n salvata in Canvas, anche con il loader `@pantoken/interactions` di `theme.js` presente. Elementi di form reali\n (`input`, `form`, `button`, `select`, `textarea`, `label`) e gli `<svg>` inline vengono\n rimossi completamente — nessuno dei template starter inclusi li utilizza.\n\n`theme.js` carica `@pantoken/interactions` dal CDN, che viene eseguito nello scope globale della pagina di Canvas —\nutile per interazioni nelle pagine che costruisci direttamente nell'RCE di Canvas con edit HTML grezzo, ma (come sopra) qualsiasi markup pilotato da attributi `popover`/`command` incollato dall'anteprima RCE qui non resterà\ninterattivo una volta salvato.\n" },
333
316
  "components": { "README.md": "# {{projectName}}\n\nUn'app TypeScript semplice (tramite Vite) stilizzata con\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), i token di design\ne le icone di Instructure.\n\n## Sviluppa\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Cosa c'è qui\n\n- `index.html` contiene il markup della pagina effettivo — una shell con layout `wrapper` da\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Visualizza l'origine\n e modificala direttamente; nulla viene iniettato da JavaScript.\n- `src/main.ts` importa `@pantoken/css` (definisce ogni proprietà personalizzata `--instui-*`),\n `@pantoken/components/base.css` (impostazioni predefinite del documento + anello di focus), `components.css`\n (classi `.instui-*`), `@pantoken/interactions` (collega il modale, il tooltip e altri comportamenti dei componenti\n pronti all'uso), e il tuo `src/style.css` — aggiungi il comportamento interattivo qui.\n- I punti di inserimento opzionali (intestazione, filtri, contenuto, finale) sono contrassegnati con\n `<div data-slot=\"...\">` in `index.html` — sostituisci i loro contenuti con il tuo markup.\n- Applica classi come `class=\"instui-button\"` al markup; consulta il\n [riferimento dei componenti](https://pantoken.app/api/css) per l'elenco completo delle classi.\n\n## Ulteriori informazioni\n\nConsulta la [guida HTML](https://pantoken.app/guide/components) per ulteriori informazioni.\n" },
334
317
  "next": { "README.md": "# {{projectName}}\n\nUn'app Next.js (App Router) stilizzata con [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\ni token di design e le icone di Instructure.\n\n## Sviluppo\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Cosa c'è qui\n\n- `next.config.mjs` racchiude la configurazione con `withPantoken(...)` (aggiunge pantoken a\n `transpilePackages`).\n- `app/layout.tsx` importa `@pantoken/css`, che definisce ogni proprietà personalizzata `--instui-*`, alla radice in modo che sia disponibile su ogni pagina, più la classe root del layout `wrapper` su\n `<body>` e `PantokenInteractions` (un componente client che carica `@pantoken/interactions` —\n abilita i comportamenti di modale, tooltip e altri componenti subito).\n- `app/page.tsx` esegue il rendering del markup stilizzato con le classi `instui-*`; i punti di inserimento opzionali (header,\n filtri, contenuto, finale) sono contrassegnati con `<div data-slot=\"...\">`.\n\n## Per saperne di più\n\nConsulta la [guida introduttiva](https://pantoken.app/guide/getting-started) per saperne di più.\n" },
335
318
  "react": { "README.md": "# {{projectName}}\n\nUn'app Vite + React stilizzata con [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\ne [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), i design token e le icone di Instructure.\n\n## Sviluppo\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Cosa c'è qui\n\n- `src/main.tsx` importa `@pantoken/css` (definisce ogni proprietà personalizzata `--instui-*`) e\n `@pantoken/interactions` (configura modal, tooltip e altri comportamenti dei componenti pronti all'uso).\n- `src/App.tsx` rende markup stilizzato con classi `instui-*`; i punti di inserimento opzionali (header,\n filtri, contenuto, trailing) sono contrassegnati con `<div data-slot=\"...\">`.\n- Per la libreria completa di componenti React di InstUI (button, modal, ecc. — incluso `@pantoken/react`'s\n `<Icon>`), aggiungi i pacchetti `@instructure/ui-*` specifici di cui hai bisogno — vedi <https://instructure.design>.\n\n## Per saperne di più\n\nVedi la [guida introduttiva](https://pantoken.app/guide/getting-started) per saperne di più.\n" },
@@ -339,7 +322,6 @@ const SCAFFOLD_OVERLAYS = {
339
322
  },
340
323
  "ja": {
341
324
  "angular": { "README.md": "# {{projectName}}\n\nVite + `@analogjs/vite-plugin-angular`を使用したスタンドアロンのAngularアプリ(Angular CLIなし)で、\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)と\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular)でスタイル設定されています(Angularカスタム要素パントークン)。\n\n## 開発\n\n```sh\nnpm install\nnpm run dev\n```\n\n## ここに何があるか\n\n- `src/main.ts`はブートストラップ時に`registerPantokenElements()`(`@pantoken/angular`から)を一度呼び出して、\n `<instui-icon>`のような要素がテンプレートで機能するようにし、トークン/コンポーネントCSSと\n `@pantoken/interactions`(モーダル、ツールチップ、その他のコンポーネント動作を標準でワイヤーアップします)をインポートします。\n- `src/app.component.ts`はスタンドアロンコンポーネント(`CUSTOM_ELEMENTS_SCHEMA`はテンプレート\n コンパイラがパントークンのカスタム要素タグを受け入れることを可能にします)であり、そのテンプレートは`instui-*`\n クラスでスタイル設定されます。オプションの挿入ポイント(ヘッダー、フィルター、コンテンツ、末尾)は\n `<div data-slot=\"...\">`でマークされます。\n- `class=\"instui-button\"`のようなクラスをマークアップに適用します。完全なクラスリストについては\n [コンポーネント参照](https://pantoken.app/api/css)を参照してください。\n\n## 詳細情報\n\n[はじめにガイド](https://pantoken.app/guide/getting-started)を参照して詳細を確認してください。\n" },
342
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nCanvas LMSの**Theme Editor**用のアップロード可能なアセットと、[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)でスタイルされたRich Content Editor (RCE) ページテンプレートをオーサリングするためのローカルプレビューを提供します。\n\n## ここにあるもの\n\n- `theme.css` / `theme.js` — これら2つのファイルをCanvasの**Theme Editor → Advanced**にアップロードしてください。\n スカフォルディング時に選択したCDNプロバイダー/テーマ/モード用に構築されています (`--cdn`/`--theme`/\n `--theme-mode`; デフォルトではjsDelivr/rebrand/light) と `@pantoken/interactions`用のローダーが含まれています (モーダル、ツールチップ、ドリルダウンなどのコンポーネント動作をワイヤーアップします)。\n- `index.html` / `src/main.ts` — ローカルのTinyMCEベースのエディター (`npm run dev`) でCanvasのRCEをミラーリングしているため、pantokenのクラスに対してページテンプレートをオーサリングしてからCanvasにコピーできます。\n ページ自体はpantokenの`wrapper`レイアウトで構築されています: **Edit theme**をクリックするとトレーが開き、\n **Config** / **CSS** / **JS**タブ (CDNプロバイダー/テーマ/モード選択、および`theme.css`/`theme.js`のシンタックスハイライト表示された編集可能なコピーがライブプレビューに反映される) と完全な指示を表示する**?**ボタンが表示されます。**Layouts**ツールバーボタンを使用してpantokenのバンドルされたスターターページレイアウトの1つから開始できます (ヒーロー、コールアウト、2列、ルーブリックノート、推薦文) - [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts)から取得されています。\n\n## 開発\n\n```sh\nnpm install\nnpm run dev\n```\n\nこれでViteデバッグサーバーが開きます:\n\n- **editor**ペーン (TinyMCE、バージョン/設定は[instructure/canvas-lms](https://github.com/instructure/canvas-lms)自身が使用しているものと一致します — 以下を参照してください)。\n **Layouts**ボタンを使用してバンドルされたスターターレイアウトの1つを読み込み (これは確認後に全ドキュメントを置き換えます。カーソルで挿入するのではなく)、**Source code**トグルを使用して生HTMLをシンタックスハイライト表示された (CodeMirror) ビューで手動編集してプレビューペーンと並べて表示でき、TinyMCEのストック`code`プラグインと異なり、入力時にプレビューペーンがライブで更新されます。このプラグインはワンショットモーダルダイアログで編集され、ライブプレビューがありません。\n- **preview**ペーンがエディターのコンテンツを表示し、現在のCSS/JSタブのスタイルシート/スクリプトが適用されます (解決されたCDN URLだけではなく) - Canvasの独自のコンテンツエリアの背景と最大幅に一致するようにラップされています - 忠実な「これがCanvasにアップロードされるとどのように見えるか」チェック、入力またはテーマ編集時にライブで更新されます。\n- エディターとプレビューペーンは、ディバイダーをドラッグしてサイズ変更でき、左右に並べる代わりに垂直方向にスタックしたり、順序を入れ替えたり (ペーンのツールバーを他のペーンにドラッグするか、**Swap panes**ボタンを使用)、サイドバイサイドの分割ビューにあります。各ペーンに独自のフルスクリーンボタンがあります。\n- **Edit theme**トレーの**Config**タブにはCDNプロバイダー/テーマ/モード選択と\n **Download theme.css** / **Download theme.js**リンクが表示されます。その**CSS**/**JS**タブは生成されたファイルの編集可能なコピーです — 手動でそれらを編集すると、プレビューは変更を直接取得します。設定選択を変更するとCSS/JSタブが再生成されます。ただし、すでに編集済みの場合は、代わりに**Regenerate from config**ボタンが表示され、編集が黙って上書きされることはありません。\n\n## ワークフロー\n\n1. `theme.css`と`theme.js`をCanvasのTheme Editor (**Advanced → CSS / JavaScript**) にアップロードして、すべてのページでpantokenのクラスが使用可能にします。\n2. `npm run dev`を実行し、**Layouts**を使用してバンドルされたスターターから開始して、Canvasの独自のRCEと同じように編集します。\n3. **Copy HTML**をクリックし、結果をCanvasページのRCEに貼り付けます (最初にHTMLエディターのビューに切り替えます)。Canvasはサーバー側で貼り付けられたHTMLをサニタイズします — このスカフォルドはそれを複製しようとしていないため、常にCanvasで貼り付けられた結果を確認してください (以下の「CanvasのRCEに関する注記」を参照してください)。\n\n## CanvasのRCEに関する注記\n\nCanvas Rich Content EditorはTinyMCEを実行し、送信されたHTMLをアローリスト (`gems/canvas_sanitize`がcanvas-lmsにあり、TinyMCE自体の`valid_elements`/`extended_valid_elements`と同期されています) に対してサーバー側でサニタイズします。そのアローリストは、ここで構築されたテンプレートに対して何を意味するかをいいます:\n\n- `class`、`id`、`style`、`title`、`role`、および`aria-*`属性はすべての要素で許可されています —\n pantokenの`class=\"instui-*\"`スタイリングフック (およびインライン`style`、例えばCSSアンカーポジショニング用)\n は貼り付けられて保存されても**生き残ります**。このファイルの古いガイダンスとは異なります。`<script>`タグは常に削除されます。\n- **RCEセーフなpantokenコンポーネント**: 静的/表示コンポーネント — アラート、ビュー、見出し、テキスト、テーブル、\n ボタンアス`<a>` (実際の`<button>`ではなく)、ブロッククォート。pantokenがすでにサポートしているセマンティックHTML (`div`、`p`、`span`、`a`、`img`、見出し、リスト、テーブル) に固執してください。\n- **RCEアンセーフ**: `@pantoken/interactions`の動作セットのすべて — モーダル、ツールチップ、\n ドリルダウン、クローズボタン、またはネイティブ`popover`/`popovertarget`/\n `command`/`commandfor`属性によって駆動される他のコンポーネント。これらの属性はCanvasのサニタイザーアローリストにはないため、\n マークアップは生き残りますが、対話型動作はページがCanvasで保存されると最初に黙って壊れます。`theme.js`の`@pantoken/interactions`ローダーが存在している場合でも。実際のフォーム要素 (`input`、`form`、`button`、`select`、`textarea`、`label`) およびインライン`<svg>`は完全に削除されます — バンドルされたスターターテンプレートは使用していません。\n\n`theme.js`はCDNから`@pantoken/interactions`を読み込みます。これはCanvasのグローバルページスコープで実行されます —\nCanvasの独自のRCEで生HTMLを編集してページを構築する際の対話性に役立ちます。ただし (上記のように)、RCEプレビューからここに貼り付けられた`popover`/`command`属性駆動マークアップは保存されると対話型のままではありません。\n" },
343
325
  "components": { "README.md": "# {{projectName}}\n\nViteを経由したプレーンなTypeScriptアプリです。\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)でスタイルされています。これはInstructureのデザイントークンとアイコンです。\n\n## 開発\n\n```sh\nnpm install\nnpm run dev\n```\n\n## ここに何があるか\n\n- `index.html`は実際のページマークアップを保持します — \n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts)からの`wrapper`レイアウトシェルです。ソースを表示して直接編集してください。JavaScriptが何も注入されません。\n- `src/main.ts`は`@pantoken/css`(すべての`--instui-*`カスタムプロパティを定義)、\n `@pantoken/components/base.css`(ドキュメントのデフォルト+フォーカスリング)、`components.css`\n (`.instui-*`クラス)、`@pantoken/interactions`(モーダル、ツールチップ、およびその他のコンポーネント動作をすぐに配線)、および独自の`src/style.css`をインポートします — ここに対話的な動作を追加してください。\n- オプションの挿入ポイント(ヘッダー、フィルター、コンテンツ、末尾)は、\n `index.html`の`<div data-slot=\"...\">`でマークされています — その内容を独自のマークアップに置き換えてください。\n- `class=\"instui-button\"`のようなクラスをマークアップに適用します。\n [コンポーネントリファレンス](https://pantoken.app/api/css)を参照して、クラスの完全なリストを確認してください。\n\n## 詳しく知る\n\n[HTMLガイド](https://pantoken.app/guide/components)を参照して、詳しく知ってください。\n" },
344
326
  "next": { "README.md": "```\n# {{projectName}}\n\n[`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next) でスタイルされた Next.js(App Router)アプリ、\nInstructureのデザイントークンとアイコン。\n\n## 開発\n\n```sh\nnpm install\nnpm run dev\n```\n\n## ここにあるもの\n\n- `next.config.mjs` は `withPantoken(...)` でコンフィグをラップします(pantokenを `transpilePackages` に追加)。\n- `app/layout.tsx` は `@pantoken/css` をインポートします。これはすべての `--instui-*` カスタム\n プロパティをルートで定義し、すべてのページで利用可能にします。さらに、`wrapper` レイアウトのルートクラスが\n `<body>` と `PantokenInteractions` に適用されます(`@pantoken/interactions` をロードするクライアントコンポーネント —\n モーダル、ツールチップ、その他のコンポーネント動作をすぐに配線)。\n- `app/page.tsx` は `instui-*` クラスでスタイルされたマークアップをレンダリングします。オプションの挿入ポイント(ヘッダー、\n フィルター、コンテンツ、末尾)は `<div data-slot=\"...\">` でマークされています。\n\n## 詳しく知る\n\n詳しくは[はじめ方ガイド](https://pantoken.app/guide/getting-started)を参照してください。\n```\n" },
345
327
  "react": { "README.md": "```markdown\n# {{projectName}}\n\nVite + Reactアプリで、[`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nと[`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css)(Instructureのデザイントークンと\nアイコン)でスタイル設定されています。\n\n## 開発\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 内容\n\n- `src/main.tsx`は`@pantoken/css`(すべての`--instui-*`カスタムプロパティを定義)および\n `@pantoken/interactions`(モーダル、ツールチップ、およびその他のコンポーネント動作をデフォルトで\n 設定)をインポートします。\n- `src/App.tsx`は`instui-*`クラスでスタイル設定されたマークアップをレンダリングします。オプションの挿入ポイント(header、\n filters、content、trailing)は`<div data-slot=\"...\">`でマークされます。\n- InstUIの完全なReactコンポーネントライブラリ(ボタン、モーダルなど—`@pantoken/react`の\n `<Icon>`を含む)については、必要な特定の`@instructure/ui-*`パッケージを追加してください—<https://instructure.design>を参照してください。\n\n## さらに詳しく\n\n詳細については、[スタートガイド](https://pantoken.app/guide/getting-started)を参照してください。\n```\n" },
@@ -349,7 +331,6 @@ const SCAFFOLD_OVERLAYS = {
349
331
  },
350
332
  "ko": {
351
333
  "angular": { "README.md": "# {{projectName}}\n\nVite + `@analogjs/vite-plugin-angular`를 사용한 독립형 Angular 앱(Angular CLI 미사용)으로,\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) 및\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular)(Angular용 pantoken 커스텀 엘리먼트)로 스타일링되어 있습니다.\n\n## 개발\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 구성 내용\n\n- `src/main.ts`는 부트스트랩 시 한 번 `registerPantokenElements()`(`@pantoken/angular`에서 제공)을 호출하여\n `<instui-icon>` 같은 엘리먼트가 템플릿에서 동작하도록 하고, 토큰/컴포넌트 CSS와\n `@pantoken/interactions`(모달, 툴팁 및 기타 컴포넌트 동작을 기본으로 연결)을 가져옵니다.\n- `src/app.component.ts`는 독립형 컴포넌트이며(`CUSTOM_ELEMENTS_SCHEMA`는 템플릿 컴파일러가 pantoken의 커스텀 엘리먼트 태그를 허용하도록 함)\n 템플릿은 `instui-*` 클래스들로 스타일링됩니다; 선택적 삽입 지점(header, filters, content, trailing)은\n `<div data-slot=\"...\">`로 표시됩니다.\n- 마크업에 `class=\"instui-button\"` 같은 클래스를 적용하세요; 전체 클래스 목록은\n [컴포넌트 참조](https://pantoken.app/api/css)를 참조하세요.\n\n## 자세히 알아보기\n\n자세한 내용은 [시작 안내](https://pantoken.app/guide/getting-started)를 참조하세요.\n" },
352
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nCanvas LMS의 **Theme Editor**에 업로드 가능한 에셋과, [`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)으로 스타일링된 Rich Content Editor(RCE) 페이지 템플릿을 작성할 수 있는 로컬 미리보기를 포함합니다.\n\n## 여기에 있는 것\n\n- `theme.css` / `theme.js` — Canvas의 **Theme Editor → Advanced**에서 이 두 파일을 업로드하세요. 이 파일들은 스캐폴딩 시 선택한 CDN 제공자/테마/모드(`--cdn`/`--theme`/`--theme-mode`; 기본은 jsDelivr/rebrand/light)에 맞춰 빌드되며 `@pantoken/interactions`용 로더(모달, 툴팁, 드릴다운 같은 컴포넌트 동작을 연결함)를 포함합니다.\n- `index.html` / `src/main.ts` — Canvas의 RCE를 모방한 로컬 TinyMCE 기반 편집기(`npm run dev`)로, pantoken의 클래스에 맞춰 페이지 템플릿을 작성한 뒤 Canvas에 붙여넣기 전에 확인할 수 있습니다. 페이지 자체는 pantoken의 `wrapper` 레이아웃으로 빌드됩니다: **Edit theme**를 클릭하면 **Config** / **CSS** / **JS** 탭이 있는 트레이가 열립니다(여기서 CDN 제공자/테마/모드 선택과 구문 강조된, 수동 편집 가능한 `theme.css`/`theme.js`의 복사본이 라이브 미리보기에 반영됨). 전체 지침은 **?** 버튼에서 확인하세요. **Layouts** 도구 모음 버튼을 사용하면 pantoken에 번들된 시작 페이지 레이아웃(히어로, 콜아웃, 2열, 루브릭 노트, 추천사) 중 하나로 시작할 수 있으며, 이 레이아웃들은 [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts)에서 소스가 제공됩니다.\n\n## 개발\n\n```sh\nnpm install\nnpm run dev\n```\n\n이 명령은 다음을 제공하는 Vite 개발 서버를 엽니다:\n\n- **편집기** 패널(TinyMCE, [instructure/canvas-lms](https://github.com/instructure/canvas-lms)에서 사용하는 버전/구성과 일치 — 아래 참조). **Layouts** 버튼으로 번들된 시작 레이아웃을 불러오면(확인 후 문서 전체를 교체함, 커서 위치에 삽입하지 않음) **Source code** 토글로 편집기 옆에 구문 강조(CodeMirror)된 원시 HTML을 수동 편집할 수 있으며, 편집하면서 미리보기 패널이 실시간으로 업데이트됩니다 — TinyMCE의 기본 `code` 플러그인은 한 번에 끝나는 모달 대화로 편집하고 라이브 미리보기를 제공하지 않는 것과 다릅니다.\n- **미리보기** 패널은 편집기의 내용을 현재 CSS/JS 탭의 스타일시트/스크립트(해결된 CDN URL만이 아닌 실제 내용)를 적용해 보여주며, Canvas의 콘텐츠 영역 배경 및 최대 너비에 맞춰 래핑되어 — \"Canvas에 업로드했을 때 어떻게 보일지\"를 충실하게 확인할 수 있도록 편집 중 또는 테마 편집 중 실시간으로 업데이트됩니다.\n- 편집기와 미리보기 패널은 분할 뷰에 배치되어 구분선을 드래그해 크기를 조정하거나 옆으로 나란히 대신 수직으로 쌓을 수 있고, 패널의 순서를 바꿀 수 있습니다(패널 툴바를 다른 패널로 드래그하거나 **Swap panes** 버튼 사용). 각 패널은 자체 전체화면 버튼을 갖습니다.\n- **Edit theme** 트레이의 **Config** 탭은 CDN 제공자/테마/모드 선택과 **Download theme.css** / **Download theme.js** 링크를 포함합니다; **CSS**/**JS** 탭은 생성된 파일의 편집 가능한 복사본입니다 — 수동으로 편집하면 미리보기가 즉시 변경을 반영합니다. Config 선택을 변경하면 아직 편집하지 않은 경우 CSS/JS 탭이 재생성되며, 이미 편집한 경우에는 편집을 조용히 덮어쓰지 않고 대신 **Regenerate from config** 버튼이 나타납니다.\n\n## 워크플로우\n\n1. `theme.css`과 `theme.js`을 Canvas의 Theme Editor(**Advanced → CSS / JavaScript**)에 업로드하여 pantoken의 클래스가 모든 페이지에서 사용 가능하도록 합니다.\n2. `npm run dev`를 실행하고 **Layouts**를 사용해 번들된 시작 레이아웃으로 시작한 뒤 Canvas의 RCE에서처럼 편집하세요.\n3. **Copy HTML**을 클릭하고 결과를 Canvas 페이지의 RCE에 붙여넣습니다(먼저 HTML 편집기 뷰로 전환). Canvas는 붙여넣은 HTML을 서버 측에서 정리(sanitize)하므로 — 이 스캐폴드는 그 과정을 복제하려고 하지 않으므로 붙여넣은 결과를 항상 Canvas에서 확인하세요(아래 \"Canvas의 RCE에 대한 주의\" 참조).\n\n## Canvas의 RCE에 대한 주의\n\nCanvas Rich Content Editor는 TinyMCE를 사용하며 제출된 HTML을 서버에서 허용 목록(allowlist, canvas-lms의 `gems/canvas_sanitize`, TinyMCE의 `valid_elements`/`extended_valid_elements`와 동기화됨)에 따라 정리합니다. 이 허용 목록이 여기서 만든 템플릿에 의미하는 바는 다음과 같습니다:\n\n- `class`, `id`, `style`, `title`, `role`, `aria-*` 속성은 모든 요소에 허용됩니다 — pantoken의 `class=\"instui-*\"` 스타일링 훅(및 CSS 앵커 위치 지정 등 인라인 `style`)은 붙여넣기 및 저장 후에도 **유지됩니다**, 이 파일의 이전 안내와 달리. `<script>` 태그는 항상 제거됩니다.\n- **RCE-안전 pantoken 컴포넌트**: 정적/표시용 컴포넌트 — alert, view, heading, text, table, 버튼을 `<a>`로 표현한 것(실제 `<button>`는 아님), blockquote. pantoken이 이미 지원하는 시맨틱 HTML(`div`, `p`, `span`, `a`, `img`, headings, lists, tables)을 사용하는 것이 안전합니다.\n- **RCE-비안전**: `@pantoken/interactions`의 동작 집합에서 오는 것들 — modal, tooltip, drilldown, close-button 또는 네이티브 `popover`/`popovertarget`/`command`/`commandfor` 속성으로 구동되는 기타 컴포넌트들. 이러한 속성은 Canvas의 sanitizer 허용 목록에 없으므로 마크업은 남지만 상호작용 동작은 Canvas에서 페이지가 처음 저장될 때 조용히 깨집니다(심지어 `theme.js`의 `@pantoken/interactions` 로더가 있어도). 실제 폼 요소(`input`, `form`, `button`, `select`, `textarea`, `label`)와 인라인 `<svg>`은 아예 제거됩니다 — 번들된 시작 템플릿은 이들을 사용하지 않습니다.\n\n`theme.js`은 CDN에서 `@pantoken/interactions`를 로드하며, 이는 Canvas의 전역 페이지 스코프에서 실행됩니다 — Canvas의 RCE에서 직접 원시 HTML 편집으로 만든 페이지의 상호작용에는 유용하지만(위 설명 참조) 이곳의 RCE 미리보기에서 붙여넣은 `popover`/`command` 속성 구동 마크업은 저장 후 상호작용을 유지하지 못합니다.\n" },
353
334
  "components": { "README.md": "# {{projectName}}\n\nVite로 만든 평범한 TypeScript 앱으로, [`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)와 Instructure의 디자인 토큰 및 아이콘으로 스타일링되어 있습니다.\n\n## 개발\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 내용\n\n- `index.html`는 실제 페이지 마크업을 포함합니다 — [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts)의 `wrapper`-레이아웃 셸입니다. 소스를 보고 직접 편집하세요; JavaScript가 내용을 주입하지 않습니다.\n- `src/main.ts`는 `@pantoken/css`를 가져옵니다 (모든 `--instui-*` 커스텀 프로퍼티를 정의), `@pantoken/components/base.css` (문서 기본값 + 포커스 링), `components.css` (`.instui-*` 클래스), `@pantoken/interactions` (모달, 툴팁 및 기타 컴포넌트 동작을 즉시 연결), 그리고 직접 작성한 `src/style.css` — 상호작용 동작은 여기에 추가하세요.\n- 선택적 삽입 지점(헤더, 필터, 콘텐츠, 후행)은 `<div data-slot=\"...\">`으로 `index.html`에 표시되어 있습니다 — 해당 내용물을 원하는 마크업으로 교체하세요.\n- `class=\"instui-button\"`와 같은 클래스를 마크업에 적용하세요; 전체 클래스 목록은 [컴포넌트 레퍼런스](https://pantoken.app/api/css)를 참조하세요.\n\n## 자세히 알아보기\n\n자세한 내용은 [HTML 가이드](https://pantoken.app/guide/components)를 참조하세요.\n" },
354
335
  "next": { "README.md": "# {{projectName}}\n\n[`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next)으로 스타일된 Next.js (App Router) 앱으로, Instructure의 디자인 토큰과 아이콘을 포함합니다.\n\n## 개발\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 포함된 내용\n\n- `next.config.mjs`은 `withPantoken(...)`로 구성(config)을 래핑합니다 (pantoken을 `transpilePackages`에 추가).\n- `app/layout.tsx`는 모든 `--instui-*` 사용자 속성(custom property)을 정의하는 `@pantoken/css`를 루트에 import 하여 모든 페이지에서 사용할 수 있게 하고, 또한 `wrapper` 레이아웃의 루트 클래스에 `<body>` 및 `PantokenInteractions`를 적용합니다 (이는 `@pantoken/interactions`을 로드하는 클라이언트 컴포넌트로 — 모달, 툴팁 및 기타 컴포넌트 동작을 즉시 연결합니다).\n- `app/page.tsx`은 `instui-*` 클래스들로 스타일된 마크업을 렌더링합니다; 선택적 삽입 포인트(header, filters, content, trailing)는 `<div data-slot=\"...\">`으로 표시되어 있습니다.\n\n## 자세히 알아보기\n\n자세한 내용은 [getting started guide](https://pantoken.app/guide/getting-started)를 참조하세요.\n" },
355
336
  "react": { "README.md": "# {{projectName}}\n\n[`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)와\n[`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css)로 스타일링된 Vite + React 앱이며, Instructure의 디자인 토큰과 아이콘을 포함합니다.\n\n## 개발\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 여기에는 무엇이 있나\n\n- `src/main.tsx`는 `@pantoken/css`을 가져옵니다(모든 `--instui-*` 사용자 정의 속성을 정의함) 및\n `@pantoken/interactions`(모달, 툴팁 및 기타 컴포넌트 동작을 즉시 연결함).\n- `src/App.tsx`는 `instui-*` 클래스들로 스타일된 마크업을 렌더링합니다; 선택적 삽입 지점(header,\n filters, content, trailing)은 `<div data-slot=\"...\">`로 표시됩니다.\n- InstUI의 전체 React 컴포넌트 라이브러리(버튼, 모달 등 — `@pantoken/react`의 `<Icon>` 포함)를 사용하려면,\n 필요한 특정 `@instructure/ui-*` 패키지를 추가하세요 — 자세한 내용은 <https://instructure.design>를 참조하십시오.\n\n## 자세히 알아보기\n\n자세한 내용은 [시작 가이드](https://pantoken.app/guide/getting-started)를 참조하세요.\n" },
@@ -359,7 +340,6 @@ const SCAFFOLD_OVERLAYS = {
359
340
  },
360
341
  "mi": {
361
342
  "angular": { "README.md": "# {{projectName}}\n\nHe taupānga Angular tū-tahi (maehe Vite + `@analogjs/vite-plugin-angular`, kāore he Angular CLI) i whakakakahu ki\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) me\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (ngā āhua ritenga pantoken\nmō Angular).\n\n## Whakawhanake\n\n```sh\nnpm install\nnpm run dev\n```\n\n## He aha kei konei\n\n- Ka karanga a `src/main.ts` i a `registerPantokenElements()` (nā `@pantoken/angular`) kotahi i te tīmatanga kia\n mahi ai ngā āhuatanga pēnei i `<instui-icon>` i roto i ngā tauira, ā, ka kawemai hoki i te CSS token/komihana me\n `@pantoken/interactions` (ka hono i te modal, tooltip, me ētahi atu whanonga kōtaha, kua rite mai).\n- He kōtaha tū-tahi a `src/app.component.ts` (`CUSTOM_ELEMENTS_SCHEMA` e tuku ana ki te kaiwhakawa tauira kia\n whakaae ki ngā tūāhua ritenga a pantoken) e whakakakahu ana tana tauira ki ngā karaehe `instui-*`;\n ko ngā wāhi whakauru kōwhiringa (taitara, tātari, ihirangi, ā muri) kua tohu ki te `<div data-slot=\"...\">`.\n- Whakamahia ngā karaehe pērā i `class=\"instui-button\"` ki ngā tohu; tirohia te\n [component reference](https://pantoken.app/api/css) mō te rārangi karaehe katoa.\n\n## Akohia atu\n\nTirohia te [getting started guide](https://pantoken.app/guide/getting-started) kia ako ake.\n" },
362
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nNgā rawa kua rite kia tuku mō te Kaiwhakatika Kaupapa (Theme Editor) o Canvas LMS, me tētahi arotakenga ā-rohe mō te tuhi tauira whārangi Rich\nContent Editor (RCE) kua āhua-iho ki te\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## He aha kei konei\n\n- `theme.css` / `theme.js` — tuku ēnei kōnae e rua i raro i **Theme Editor → Advanced** i Canvas.\n I hanga ēnei mō te kaiwhakarato CDN/kaupapa/āhua i tīpakohia e koe i te wā o te scaffolding (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light mō te taunoa) ā, kei roto hoki he kaikawe mō\n `@pantoken/interactions` (e hono ana i ngā whanonga wāhanga pērā i te modal, tooltip, me te drilldown).\n- `index.html` / `src/main.ts` — he editor ā-rohe, ā-tinyMCE (`npm run dev`) e kapi ana i te RCE o Canvas kia taea e koe te tuhituhi tauira whārangi ki ngā kara o pantoken i mua i te tārua ki Canvas.\n I hanga te whārangi mā te rārangi `wrapper` a pantoken: pāwhiritia te **Edit theme** kia whakatuwheratia tētahi pae\n me ngā ripa **Config** / **CSS** / **JS** (ngā kōwhiringa kaiwhakarato CDN/kaupapa/āhua, me ngā tārua he wāhanga-kōrero-āwhiti,\n ka taea te whakatika ā-ringa o `theme.css`/`theme.js` e whakarato ana i te arotakenga ora), me te pātene **?**\n mō ngā tohutohu katoa. Whakamahia te pātene taputapu **Layouts** kia tīmata i tētahi o ngā aratau whārangi tīmata o pantoken (hero, callout, two-column, rubric note, testimonial), i tangohia mai i\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Whanake\n\n```sh\nnpm install\nnpm run dev\n```\n\nKa whakatuwhera tēnei i tētahi tūmau whakawhanake Vite me:\n\n- He anga **editor** (TinyMCE, e rite ana ki te putanga/config\n e whakamahia ana e [instructure/canvas-lms](https://github.com/instructure/canvas-lms) — titiro iho). Whakamahia te pātene **Layouts** kia utaina tētahi o ngā aratau tīmata kua tāpirihia (ka whakakapi i te tuhinga katoa, i muri i te whakaaetanga, kaua ki te tāpiri ki te tohu), me te whakawhiti **Source code**\n kia whakatika ā-ringa i te HTML matawai i roto i tētahi tirohanga kua whakanikonikotia te wetereo (CodeMirror) kei te taha o te editor, ā, ka whakahou tonu te arotakenga i te wā e tuhituhi ana koe — ehara i te āhua o te pūtene `code` o TinyMCE, e whakatika ana i roto i tētahi pouaka modal kotahi-wa me te kore arotakenga ora.\n- He anga **preview** e whakaatu ana i ngā ihirangi o te editor me te raupapa kuputuhi/waehere o tēnei ripa CSS/JS kua tonoa (ehara i te utuputanga URL CDN anake), kua takai kia rite ki te papamuri me te whānui mōrahi o te rohe ihirangi o Canvas — he whakamātautau pono “tēnei te āhua i te wā kua tukuna ki Canvas” e whakahou ana ora i te wā e tuhituhi ana kia whakatikahia te kaupapa.\n- Kei ngā anga editor me preview i roto i tētahi tirohanga wāwāhi ka taea te whakarahi mā te toia te wāwehenga, ka whakakaha poutū hei utu mō te taha ki te taha, ā, ka taea te whakawhiti i te raupapa o ngā anga (toia te pae taputapu o tētahi anga ki runga i tētahi atu, kāore rānei whakamahi i te pātene **Swap panes**). Ia anga he pātene mata-katoa tōna.\n- Kei te pae **Edit theme** ripa **Config** ngā kōwhiringa kaiwhakarato CDN/kaupapa/āhua me ngā hononga **Download theme.css** / **Download theme.js**; ko āna ripa **CSS**/**JS** he tārua ka whakatuhia o ngā kōnae — whakatikahia ā-ringa ā-rānei ka kitea e te arotakenga ngā panoni tonu. Mēnā ka whakarerekē koe i tētahi kōwhiringa Config ka hanga anō i ngā ripa CSS/JS, kia kore rānei kua whakatikahia e koe ēnei i mua, ā, ka puta tētahi pātene **Regenerate from config** hei utu i te whakakapi huna i tō whakatika.\n\n## Tukanga mahi\n\n1. Tuku `theme.css` me `theme.js` ki te Theme Editor o Canvas (**Advanced → CSS / JavaScript**) kia wātea ngā kara o pantoken i ia whārangi.\n2. Whakahaere `npm run dev`, whakamahi **Layouts** kia tīmata i tētahi tīmata kua tāpirihia, ā, whakatikahia pērā i tō mahi ki te RCE o Canvas.\n3. Pāwhiritia **Copy HTML** ka whakapiri i te hua ki te RCE o tētahi whārangi Canvas (whakawhiti ki te tirohanga etita HTML i mua). Ka whakamaoritia e Canvas te HTML kua whakapirihia ki te tūmau — kāore tēnei scaffolding e tātaritia taua tukanga, nō reira me tirohia tonu te hua kua whakapirihia i roto i Canvas (titiro ki te \"Ngā whakamārama mō te RCE o Canvas\" i raro).\n\n## Ngā whakamārama mō te RCE o Canvas\n\nKei te whakahaere TinyMCE te Canvas Rich Content Editor ā, ka whakahaua te HTML kua tukuna ki te tūmau kia whakataetia ki tētahi rārangi āhei (allowlist) (`gems/canvas_sanitize` i canvas-lms, kia ū tonu ki ngā āhuatanga o TinyMCE\n`valid_elements`/`extended_valid_elements`). Ēnei mea e tohu ana mō ngā tauira kua waihangatia i konei:\n\n- He rāpoi āhei ngā āhuatanga `class`, `id`, `style`, `title`, `role`, me `aria-*` ki runga i ia āhuatanga —\n ka **ora** tonu ngā tūāpapa whakapaipai o pantoken (`class=\"instui-*\"`) (me ngā `style` ā-ringa, hei tauira mō te whakatakoto tātai CSS)\n contrary ki ngā tohutohu tawhito i roto i tēnei kōnae. Ka tango tonu ngā tapanga `<script>`.\n- Ngā **wāhanga pantoken haumaru mō te RCE**: ngā wāhanga tūmau/arā whakaatu — alert, view, heading, text, table,\n he pātene-as-`<a>` (ehara i te `<button>` tūturu), blockquote. Aro atu ki te HTML ā-tikanga e tautokohia e pantoken (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- **Kāore i te haumaru ki te RCE**: he aha rānei i te rōpū whanonga o `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, me ērā atu wāhanga e whakaohoa ana e ngā āhuatanga ā-hāngai o te pūnaha `popover`/`popovertarget`/\n `command`/`commandfor`. Kāore ēnei āhuatanga i roto i te rārangi āhei o te kaimātai Canvas, nō reira\n ka noho te tohu engari ka pakaru te whanonga tāpiri i te wā tuatahi ka whakaora te whārangi i Canvas, ahakoa te aitua o te kaikawe `theme.js` `@pantoken/interactions`. Ka tangohia ngā āhuatanga o ngā puka tūturu (`input`, `form`, `button`, `select`, `textarea`, `label`) me ngā `<svg>` ā-ringa — kāore rānei i whakamahia i ngā tauira tīmata kua tāpirihia.\n\n`theme.js` e utaina ana `@pantoken/interactions` mai i te CDN, e whakahaere ana i te rohe whārangi ao o Canvas —\nhe whaihua mō ngā whakawhitinga i runga i ngā whārangi ka waihangatia e koe tika i roto i te RCE o Canvas me ngā whakatikanga HTML matau, engari (pērā i runga ake nei) kāore ngā tohu āhuatanga-`popover`/`command`-e ārahi ana kua whakapirihia mai i te arotakenga o konei e noho tonu\nhei rawa mahi i te wā ka whakaora.\n" },
363
343
  "components": { "README.md": "# {{projectName}}\n\nHe taupānga TypeScript māmā (ma te Vite) i whakaritea ki te āhua mā\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), ngā tohu hoahoa me ngā tohu ā-ata o Instructure.\n\n## Whakawhanake\n\n```sh\nnpm install\nnpm run dev\n```\n\n## He aha kei konei\n\n- Ko `index.html` te pupuri i te tohu whārangi tūturu — he anga-`wrapper` nō\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Tirohia te putanga puna\n ka whakatika tika; kāore he mea whakauruia e JavaScript.\n- Ka kawemai e `src/main.ts` a `@pantoken/css` (e tautuhia ana ngā `--instui-*` rawa ritenga katoa),\n `@pantoken/components/base.css` (ngā taunoa tuhinga + te rīngi arotahi), `components.css`\n (ngā karaehe `.instui-*`), `@pantoken/interactions` (e hono ana i te aronga modal, tooltip, me\n ērā atu whanonga wāhanga mai i te tīmatatanga), me tō ake `src/style.css` — tāpirihia ngā\n whanonga whakauru ki konei.\n- Ko ngā waahi tāpiri ā-kōwhiringa (tūhono matua, tātari, ihirangi, whakakapi) e tohu ana ki te\n `<div data-slot=\"...\">` i roto i `index.html` — whakakapia ō rātou ihirangi ki tō ake tohu.\n- Tāpirihia ngā karaehe pērā i `class=\"instui-button\"` ki ngā tohu; tirohia te\n [tohu wāhanga](https://pantoken.app/api/css) mō te rārangi karaehe katoa.\n\n## Ako atu\n\nTirohia te [aratohu HTML](https://pantoken.app/guide/components) kia ako ake.\n" },
364
344
  "next": { "README.md": "# {{projectName}}\n\nHe taupānga Next.js (App Router) kua whakapaipaihia mā te [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next), ngā tohu hoahoa me ngā tohu whakaahua a Instructure.\n\n## Whakawhanake\n\n```sh\nnpm install\nnpm run dev\n```\n\n## He aha kei konei\n\n- `next.config.mjs` ka whakamau i te whirihora ki `withPantoken(...)` (ka tāpiri i te pantoken ki `transpilePackages`).\n- `app/layout.tsx` ka kawemai i a `@pantoken/css`, e tautuhi ana i ia `--instui-*` rawa māna, kei te pakiaka kia wātea ai ki ia whārangi, ā, tae atu ki te kara matua o te whakatakotoranga `wrapper` kei runga i `<body>` me `PantokenInteractions` (he wāhanga kiritaki e uta ana i `@pantoken/interactions` — ka hono ngā aratau pātaka, taputapu tohu, me ētahi atu whanonga waahanga i te tīmata).\n- `app/page.tsx` ka whakaputa tohu hākoritanga kua āta hoahoahia ki ngā kara `instui-*`; ko ngā wāhi whakauruhia kōwhiringa (upoko, tātari, ihirangi, mutunga) kua tohua ki `<div data-slot=\"...\">`.\n\n## Ako atu\n\nTirohia te [aratohu tīmata](https://pantoken.app/guide/getting-started) kia mōhio atu.\n" },
365
345
  "react": { "README.md": "# {{projectName}}\n\nHe taupānga Vite + React kua whakapaipaihia ki [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nme [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), ko ngā tūkua hoahoa me ngā tohu ā-ata o Instructure.\n\n## Whakawhanake\n\n```sh\nnpm install\nnpm run dev\n```\n\n## He aha kei konei\n\n- `src/main.tsx` e kawemai ana i `@pantoken/css` (e tautuhi ana i ia `--instui-*` rawa ritenga) me\n `@pantoken/interactions` (e hono ana i ngā whanonga wāhanga pēnei i ngā matapihi rūnanga (modal), ngā tohu whakaatu (tooltip), me ētahi atu, i te pouaka).\n- `src/App.tsx` e whakaatu ana i te tohu HTML kua whakapaipaihia me ngā karaehe `instui-*`; kua tohu ngā waahi whakauru kōwhiri (upoko,\n tātari, ihirangi, ā muri) me `<div data-slot=\"...\">`.\n- Mō te whare pukapuka wāhanga React katoa o InstUI (ngā pūtātene, ngā matapihi rūnanga, me ērā atu — tae atu ki te `<Icon>` o `@pantoken/react`), tāpirihia ngā mōkihi `@instructure/ui-*` motuhake e hiahiatia ana — tirohia <https://instructure.design>.\n\n## Ako atu\n\nTirohia te [aratohu tīmata](https://pantoken.app/guide/getting-started) kia ako ake.\n" },
@@ -369,7 +349,6 @@ const SCAFFOLD_OVERLAYS = {
369
349
  },
370
350
  "ms": {
371
351
  "angular": { "README.md": "```markdown\n# {{projectName}}\n\nAplikasi Angular kendiri (via Vite + `@analogjs/vite-plugin-angular`, tanpa Angular CLI) yang diatur gaya dengan\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) dan\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (elemen khusus pantoken\nuntuk Angular).\n\n## Pengembangan\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Apa yang ada di sini\n\n- `src/main.ts` memanggil `registerPantokenElements()` (dari `@pantoken/angular`) sekali saat bootstrap supaya\n elemen seperti `<instui-icon>` bekerja dalam templat, dan mengimport CSS token/komponen serta\n `@pantoken/interactions` (menyiapkan modal, tooltip, dan perilaku komponen lainnya tanpa konfigurasi).\n- `src/app.component.ts` adalah komponen kendiri (`CUSTOM_ELEMENTS_SCHEMA` memungkinkan pengompil templat\n menerima tag elemen khusus pantoken) yang templatnya diatur gaya dengan kelas `instui-*`;\n titik penyisipan opsional (header, filters, content, trailing) ditandai dengan\n `<div data-slot=\"...\">`.\n- Terapkan kelas seperti `class=\"instui-button\"` ke markup; lihat\n [referensi komponen](https://pantoken.app/api/css) untuk daftar kelas lengkap.\n\n## Pelajari lebih lanjut\n\nLihat [panduan memulai](https://pantoken.app/guide/getting-started) untuk mempelajari lebih lanjut.\n```\n" },
372
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nAset siap muat untuk **Theme Editor** Canvas LMS, ditambah pratonton lokal untuk menyusun templat halaman Rich Content Editor (RCE) yang bergaya dengan\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Apa yang ada di sini\n\n- `theme.css` / `theme.js` — muat dua fail ini di bawah **Theme Editor → Advanced** dalam Canvas.\n Ia dibina untuk penyedia CDN/tema/mod yang anda pilih semasa perancaan (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light secara lalai) dan merangkumi pemuat untuk\n `@pantoken/interactions` (menghubungkan perilaku komponen seperti modal, tooltip, dan drilldown).\n- `index.html` / `src/main.ts` — editor berasaskan TinyMCE lokal (`npm run dev`) yang mencerminkan RCE Canvas supaya anda dapat menyusun templat halaman mengikut kelas pantoken sebelum menyalinnya ke Canvas.\n Halaman itu sendiri dibina dengan susunatur `wrapper` pantoken: klik **Edit tema** untuk membuka baki dengan tab **Config** / **CSS** / **JS** (pilih penyedia CDN/tema/mod, dan salinan diserlahkan sintaks, boleh disunting tangan bagi `theme.css`/`theme.js` yang membekalkan pratonton langsung), dan butang **?** untuk arahan lengkap. Gunakan butang bar alat **Layouts** untuk memulai daripada salah satu susunatur halaman permulaan pantoken yang disekumpul (hero, callout, dua-lajur, nota rubrik, testimoni), bersumber dari\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Bangun\n\n```sh\nnpm install\nnpm run dev\n```\n\nIni membuka pelayan dev Vite dengan:\n\n- Anak tetingkap **editor** (TinyMCE, sepadan dengan versi/config\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) yang digunakan sendiri — lihat di bawah).\n Gunakan butang **Layouts** untuk memuatkan salah satu susunatur permulaan yang disekumpul (ini menggantikan keseluruhan dokumen, selepas pengesahan, daripada memasukkan di kursor), dan togol **Source code** untuk menyunting tangan HTML mentah dalam pandangan diserlahkan sintaks (CodeMirror) bersama editor, dengan anak tetingkap pratonton mengemas kini langsung semasa anda menaip — tidak seperti pemalam stok `code` TinyMCE, yang menyunting dalam dialog modal satu kali tanpa pratonton langsung.\n- Anak tetingkap **pratonton** menunjukkan kandungan editor dengan stylesheet/skrip tab CSS/JS semasa yang digunakan (bukan hanya URL CDN yang diselesaikan), dibungkus untuk sepadan dengan latar belakang kawasan kandungan Canvas sendiri dan lebar maksimum — pemeriksaan setia \"bagaimana ini akan kelihatan apabila dimuat ke Canvas\", dikemas kini langsung semasa anda menaip atau menyunting tema.\n- Anak tetingkap editor dan pratonton berada dalam pandangan berpecah yang anda boleh ubah saiz dengan menyeret pembahagi, tindih secara menegak daripada berdampingan, dan tukar susunan (seret bar alat anak tetingkap ke yang lain, atau gunakan butang **Swap panes**). Setiap anak tetingkap mempunyai butang skrin penuh sendiri.\n- Tab **Config** baki **Edit tema** memegang pilihan penyedia CDN/tema/mod dan pautan **Download theme.css** / **Download theme.js**; tab **CSS**/**JS** nya adalah salinan boleh sedia dari fail yang dijana — suntinglah tangan dan pratonton mengambil perubahan anda secara langsung. Menukar pilihan Config menjana semula tab CSS/JS melainkan anda telah menyuntingnya, dalam hal ini butang **Regenerate from config** muncul daripada senyap menimpa suntingan anda.\n\n## Aliran kerja\n\n1. Muat `theme.css` dan `theme.js` ke Theme Editor Canvas (**Advanced → CSS / JavaScript**) supaya kelas pantoken tersedia di setiap halaman.\n2. Jalankan `npm run dev`, gunakan **Layouts** untuk memulai daripada permulaan yang disekumpul, dan suntingnya seperti anda akan lakukan dalam RCE Canvas sendiri.\n3. Klik **Copy HTML** dan tampal keputusannya ke RCE halaman Canvas (tukar ke pandangan editor HTML terlebih dahulu). Canvas membersihkan HTML yang ditampal sisi pelayan — perancaan ini tidak cuba untuk mengulangi itu, jadi sentiasa sahkan keputusan yang ditampal dalam Canvas (lihat \"Nota tentang RCE Canvas\" di bawah).\n\n## Nota tentang RCE Canvas\n\nRich Content Editor Canvas menjalankan TinyMCE dan membersihkan HTML yang dikemukakan di pelayan terhadap senarai putih (`gems/canvas_sanitize` dalam canvas-lms, disimpan dalam sinkron dengan `valid_elements`/`extended_valid_elements` TinyMCE sendiri). Apa yang bermaksud senarai putih itu untuk templat yang dibina di sini:\n\n- Atribut `class`, `id`, `style`, `title`, `role`, dan `aria-*` dibenarkan pada setiap elemen — cangkuk gaya `class=\"instui-*\"` pantoken (dan `style` sebaris, cth. untuk kedudukan sauh CSS) **benar-benar** bertahan ditampal dan disimpan, bertentangan dengan panduan yang lebih lama dalam fail ini. Tag `<script>` sentiasa dilucutkan.\n- **Komponen pantoken selamat RCE**: komponen statik/paparan — amaran, pandangan, tajuk, teks, jadual, butang-sebagai-`<a>` (bukan `<button>` sebenar), blok kutipan. Kekal kepada HTML semantik yang pantoken sudah sokong (`div`, `p`, `span`, `a`, `img`, tajuk, senarai, jadual).\n- **RCE-tidak selamat**: apa-apa daripada set perilaku `@pantoken/interactions` — modal, tooltip, drilldown, butang-tutup, atau komponen lain yang didorong oleh atribut `popover`/`popovertarget`/`command`/`commandfor` asli. Atribut tersebut tidak berada dalam senarai putih pembersih Canvas, jadi penanda bertahan tetapi perilaku interaktif senyap-senyap pecah kali pertama halaman disimpan dalam Canvas, walaupun pemuat `@pantoken/interactions` `theme.js` hadir. Elemen borang sebenar (`input`, `form`, `button`, `select`, `textarea`, `label`) dan `<svg>` sebaris dilucutkan sepenuhnya — tiada satu pun templat permulaan yang disekumpul menggunakannya.\n\n`theme.js` memuatkan `@pantoken/interactions` daripada CDN, yang berjalan dalam skop halaman global Canvas — berguna untuk interaksi pada halaman yang anda bina secara langsung dalam RCE Canvas dengan suntingan HTML mentah, tetapi (seperti di atas) mana-mana penanda yang didorong atribut `popover`/`command` yang ditampal daripada pratonton RCE di sini tidak akan kekal interaktif apabila disimpan.\n" },
373
352
  "components": { "README.md": "# {{projectName}}\n\nAplikasi TypeScript biasa (melalui Vite) dengan gaya\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), token desain dan ikon Instructure.\n\n## Kembangkan\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Apa yang ada di sini\n\n- `index.html` berisi markup halaman yang sebenarnya — cangkang tata letak `wrapper` dari\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Lihat sumber\n dan edit langsung; tidak ada yang disuntikkan oleh JavaScript.\n- `src/main.ts` mengimpor `@pantoken/css` (mendefinisikan setiap properti khusus `--instui-*`),\n `@pantoken/components/base.css` (default dokumen + cincin fokus), `components.css`\n (kelas `.instui-*`), `@pantoken/interactions` (menghubungkan modal, tooltip, dan perilaku komponen lain secara langsung), dan milik Anda sendiri `src/style.css` — tambahkan perilaku interaktif di sini.\n- Titik penyisipan opsional (header, filter, konten, trailing) ditandai dengan\n `<div data-slot=\"...\">` di `index.html` — ganti isinya dengan markup Anda sendiri.\n- Terapkan kelas seperti `class=\"instui-button\"` ke markup; lihat\n [referensi komponen](https://pantoken.app/api/css) untuk daftar kelas lengkap.\n\n## Pelajari lebih lanjut\n\nLihat [panduan HTML](https://pantoken.app/guide/components) untuk mempelajari lebih lanjut.\n" },
374
353
  "next": { "README.md": "# {{projectName}}\n\nAplikasi Next.js (App Router) yang ditata dengan [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\ntoken desain dan ikon Instructure.\n\n## Berkembang\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Apa yang ada di sini\n\n- `next.config.mjs` membungkus konfigurasi dengan `withPantoken(...)` (menambahkan pantoken ke\n `transpilePackages`).\n- `app/layout.tsx` mengimpor `@pantoken/css`, yang mendefinisikan setiap `--instui-*` properti kustom,\n pada root sehingga tersedia di setiap halaman, ditambah kelas root tata letak `wrapper` pada\n `<body>` dan `PantokenInteractions` (komponen klien yang memuat `@pantoken/interactions` —\n mengatur modal, tooltip, dan perilaku komponen lain siap pakai).\n- `app/page.tsx` merender markup yang ditata dengan kelas `instui-*`; titik penyisipan opsional (header,\n filter, konten, trailing) ditandai dengan `<div data-slot=\"...\">`.\n\n## Pelajari lebih lanjut\n\nLihat [panduan memulai](https://pantoken.app/guide/getting-started) untuk mempelajari lebih lanjut.\n" },
375
354
  "react": { "README.md": "# {{projectName}}\n\nAplikasi Vite + React yang digayakan dengan [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\ndan [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), token desain dan ikon Instructure.\n\n## Kembangkan\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Apa yang ada di sini\n\n- `src/main.tsx` mengimpor `@pantoken/css` (mendefinisikan setiap properti kustom `--instui-*`) dan\n `@pantoken/interactions` (menyiapkan perilaku modal, tooltip, dan komponen lainnya secara\n otomatis).\n- `src/App.tsx` merender markup yang ditata dengan kelas `instui-*`; titik penyisipan opsional (header,\n filter, konten, trailing) ditandai dengan `<div data-slot=\"...\">`.\n- Untuk perpustakaan komponen React lengkap InstUI (tombol, modal, dll. — termasuk `<Icon>` dari `@pantoken/react`),\n tambahkan paket `@instructure/ui-*` spesifik yang Anda perlukan — lihat <https://instructure.design>.\n\n## Pelajari lebih lanjut\n\nLihat [panduan memulai](https://pantoken.app/guide/getting-started) untuk mempelajari lebih lanjut.\n" },
@@ -379,7 +358,6 @@ const SCAFFOLD_OVERLAYS = {
379
358
  },
380
359
  "se": {
381
360
  "angular": { "README.md": "# {{projectName}}\n\nOvdal Angular prográmma (via Vite + `@analogjs/vite-plugin-angular`, ii Angular CLI) čeakcu\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) ja\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken mearkkaloaddji elementat\nAngular:i geažes).\n\n## Deaivvat\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mii lea dás\n\n- `src/main.ts` čalaga `registerPantokenElements()` (maŋŋel `@pantoken/angular`) oktii bootstrap:as vai\n elementat nugo `<instui-icon>` barggit teampláhtain, ja maŋŋebassá token/komponeantta CSS maŋŋel\n `@pantoken/interactions` (giivva modal, tooltip, ja eará komponeantta geatnegahppu\n maŋŋelassii).\n- `src/app.component.ts` lea ovdal komponeantta (`CUSTOM_ELEMENTS_SCHEMA` leat teampláhta\n kompilearvi vuokćet pantoken mearkkaloaddji element markaid) geažes teampláhta lea čeakcu `instui-*`\n klassain; valljejahtti sáttehejeaddji vahkkat (oaivvi, suollastohpa, satiidus, maŋŋel) merkejahtti\n `<div data-slot=\"...\">`.\n- Geavvi klassaid nugo `class=\"instui-button\"` merkkii; geažes\n [komponeantta refereanssa](https://pantoken.app/api/css) maŋŋegažes klassaid listui.\n\n## Oahppa hui\n\nGeažes [álggaheami giidu](https://pantoken.app/guide/getting-started) oahppa hui.\n" },
382
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nVálljen aktiva Canvas LMS:a **Tema redigere** vai, ja lokála esiohcan Rich Content Editor (RCE) siiddu buođi čuođun\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Mii lea dás\n\n- `theme.css` / `theme.js` — sisa dás ii kategoriija fiillat **Tema redigere → Advanced** Canvas:a.\n Dii ledje huksejuvvon CDN fálalaš/tema/mearri duođa geažes skaffola (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light standárddalašt) ja galduo loaderan\n `@pantoken/interactions` (čeakcu komponenta comportementta nugo modal, tooltip, ja drilldown).\n- `index.html` / `src/main.ts` — lokála, TinyMCE-vuođa redigere (`npm run dev`) mas dás Canvas:a\n RCE nu ahte sáhtat čoahkkalit siiddu buođi pantoken klássaid ovdal.\n Siiddu ieža lea huksejuvvon pantoken:a `wrapper` layout:in: klik **Redigere tema** maŋŋel duovtaša\n **Config** / **CSS** / **JS** table duođa (CDN fálalaš/tema/mearri válljejit, ja syntax-highlight,\n geažes-ráfálaš kopija `theme.css`/`theme.js` mat veadjé live esiohcan), ja **?** njealja\n fulkot ohcat. Geavat **Layouts** toolbar njealja válljejit pantoken:a váivvá siiddu layout:a (hero, callout, guokte-kolumna, rubric note, testimonial), gávdnon\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Ovdanahttit\n\n```sh\nnpm install\nnpm run dev\n```\n\nDát rahpá Vite dev servira mainna:\n\n- **redigere** muorra (TinyMCE, maŋŋebeapme version/config\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) maŋŋel — geažes maŋŋel).\n Geavat **Layouts** njealja válljejit váivvá layout:a (dát dáskkida olles dokumeanta, maŋŋel confirmation, go ii siste cursor ektui), ja **Source code** toggle\n mainna sáhtat ráfálit raw HTML:a syntax-highlight (CodeMirror) vista mainna, esiohcan muorra ođa live\n go čilget — mielde TinyMCE:a stock `code` plugin, mii redigere one-shot modal dialog mainna eatni live esiohcan.\n- **esiohcan** muorra mainna čájeha editor:a sisdoallu current CSS/JS table:a stylesheet/script\n mainna (eat jus resolved CDN URL:a), wrapped maŋŋel Canvas:a iežas content-area background\n ja max width — truhtil \"mii dát geažes Canvas:a maŋŋel upload\" check, ođa live\n go čilget jus redigere tema.\n- Editor ja esiohcan muorra isttet split view:a mainna sáhtat resize divider:a geažes, stack\n verticála mielde side by side vai, ja swap muorra order (drag muorra toolbar:a guđas maŋŋel,\n jus geavat **Swap panes** njealja). Gakta muorra duođa ieža fullscreen njealja.\n- **Redigere tema** duovtaža **Config** tab duođa dás CDN fálalaš/tema/mearri válljejit ja\n **Download theme.css** / **Download theme.js** linkat; ieža **CSS**/**JS** table duođa duođa ráfálaš kopija\n generated fiillain — ráfálit daid ja esiohcan válda váikkuhusa dássanaga. Molssat\n Config vállja re-generate CSS/JS table duođa jus eatni ráfálaš daid, maŋŋel\n **Regenerate from config** njealja bahpá mielde silent overwrite:an.\n\n## Bargoprosa\n\n1. Sisa `theme.css` ja `theme.js` Canvas:a Tema redigere (**Advanced → CSS / JavaScript**) nu ahte\n pantoken:a klássaid duođa válbmi olles siiddu:a.\n2. Run `npm run dev`, geavat **Layouts** válljejit váivvá layout:a, ja redigere daid nugo\n gávnon Canvas:a ieža RCE:s.\n3. Klik **Copy HTML** ja joatkit rezultáhta Canvas page:a RCE:a (molssat HTML editor\n view ovdal). Canvas sanitize paste HTML:a server-side — dát scaffold:a eat geažes\n replicate daid, nu ahte álá verifi paste rezultáhta Canvas:a (geažes \"Notes on Canvas:a RCE\"\n maŋŋel).\n\n## Muitalusat Canvas:a RCE:s\n\nCanvas Rich Content Editor rahpá TinyMCE ja sanitize submit HTML:a server ovdal\nallowlist (`gems/canvas_sanitize` canvas-lms:a, keep sync TinyMCE:a ieža maŋŋel\n`valid_elements`/`extended_valid_elements`). Mii dát allowlist mearkkaša buođi dás huksejuvvon:\n\n- `class`, `id`, `style`, `title`, `role`, ja `aria-*` atribuhta duođa olles element:a —\n pantoken:a `class=\"instui-*\"` styling hook:a (ja inline `style`, e.g. CSS anchor positioning vai)\n **duođa** válbmi paste ja save, contrary guđa vejolašvuođa dás fiillа. `<script>` tag:a\n álá álá strip.\n- **RCE-safe pantoken komponenta**: static/display komponenta — alert, view, heading, text, table,\n a button-as-`<a>` (eat vahkkal `<button>`), blockquote. Stick semantic HTML pantoken:a\n support (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- **RCE-unsafe**: čeakcu `@pantoken/interactions` behavior set — modal, tooltip,\n drilldown, close-button, jis guđa eará komponenta native `popover`/`popovertarget`/\n `command`/`commandfor` atribuhta mainna. Daid atribuhta eai Canvas:a sanitizer allowlist:a, nu\n markup válbmi bet interactive comportementta silent break ovdal geažes save Canvas:a, maŋŋel\n `theme.js`:a `@pantoken/interactions` loader present. Vahkkal form\n element (`input`, `form`, `button`, `select`, `textarea`, `label`) ja inline `<svg>`\n strip outright — eai váivvá váivvá starter template:a geavat daid.\n\n`theme.js` rahpá `@pantoken/interactions` CDN:s, mii run Canvas:a global page scope —\nvejolašvuođa interaction siiddu mainna sáhtat build direct Canvas:a RCE:a raw HTML edit:amaŋŋel, bet (ovdal)\nčeakcu `popover`/`command`-atribuhta-driven markup paste RCE esiohcan dás eai stay\ninteractive ovdal save.\n" },
383
361
  "components": { "README.md": "# {{projectName}}\n\nČeakcu TypeScript aplikáša (Vite maŋŋel) diseheame\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructure-a\ndesign tokenitat ja áittieat.\n\n## Ovdal\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Maid dás lea\n\n- `index.html` deaddá aktuála siiddafoddu — a `wrapper`-layout vahkki\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts) maŋŋel. Geažes gáldu\n ja rievvada dasa direktne; eai dieđa ieš JavaScript maŋŋel.\n- `src/main.ts` vállje `@pantoken/css` (definiire juohke `--instui-*` custom property),\n `@pantoken/components/base.css` (dokumenta standárda + focus ring), `components.css`\n (`.instui-*` klassat), `@pantoken/interactions` (čeakca modal, tooltip, ja eará komponenta akšuvvi ordinaalalaš), ja iežat `src/style.css` — lasit interaktiivalaš akšuvvi dasa.\n- Eaktuođa sisadusa čoagganguollu (header, filtrer, sisdoallu, maŋŋel) leat fuomášuvvon\n `<div data-slot=\"...\">` in `index.html` — sirdde sin sisdoalluid iežat fodduiguin.\n- Geavah klassat dagu `class=\"instui-button\"` fodduii; geažes\n [komponenta referánsá](https://pantoken.app/api/css) dieđa maŋŋel klasasat.\n\n## Maŋŋel geažes buoraš\n\nGeažes [HTML cuoggat](https://pantoken.app/guide/components) maŋŋel geažes buoraš.\n" },
384
362
  "next": { "README.md": "# {{projectName}}\n\nNext.js (App Router) ápplikaša stilisoarvon [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next) ala, Instructuren design tokens ja ikond.\n\n## Bargan\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mii lea dás\n\n- `next.config.mjs` vahkkuja konfiguraašuvnna `withPantoken(...)`in ala (maŋŋella pantoken `transpilePackages`ii).\n- `app/layout.tsx` sissat buktá `@pantoken/css`, mii mearridallá juohke `--instui-*` custom property, juraš guođes maŋŋel lea vejolahtti juohke siiddus, ja `wrapper` layout juraš klasaid `<body>` ja `PantokenInteractions` (client component mii loktá `@pantoken/interactions` — čeakcu vuođa modal, tooltip ja eará component behaviors čeakcu ala).\n- `app/page.tsx` juoglá markup stilisoarvon `instui-*` klasaid ala; valáštallan insertion points (header, filters, content, trailing) leat merkejuvvon `<div data-slot=\"...\">`.\n\n## Oahpat eanet\n\nGeažes [getting started guide](https://pantoken.app/guide/getting-started) oahpat eanet.\n" },
385
363
  "react": { "README.md": "# {{projectName}}\n\nVite + React áhppi, stivren [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nja [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructure's design tokens ja\ngolla.\n\n## Čállit\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Mii lea dás\n\n- `src/main.tsx` import `@pantoken/css` (máhtte juohke `--instui-*` custom property) ja\n `@pantoken/interactions` (čoavvu modal, tooltip, ja eará komponenta doavtterbávttaj\n geažes).\n- `src/App.tsx` čálá markup stivren `instui-*` klassaj; valjejeaddji sisaheapmi point (header,\n filters, content, trailing) leat merren `<div data-slot=\"...\">`.\n- InstUI's heapme React komponenta laibraid (buttons, modals, etc. — maiddái `@pantoken/react`'s\n `<Icon>`) geažes, maŧŧat dieđa `@instructure/ui-*` pakehta maid dárbbašat — geažes <https://instructure.design>.\n\n## Oahpit dás\n\nGeažes [getting started guide](https://pantoken.app/guide/getting-started) oahpit dás.\n" },
@@ -389,7 +367,6 @@ const SCAFFOLD_OVERLAYS = {
389
367
  },
390
368
  "nb": {
391
369
  "angular": { "README.md": "# {{projectName}}\n\nEn frittstående Angular-app (via Vite + `@analogjs/vite-plugin-angular`, ingen Angular CLI) stylet med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) og\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken tilpassede elementer\nfor Angular).\n\n## Utvikle\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hva som er her\n\n- `src/main.ts` kaller `registerPantokenElements()` (fra `@pantoken/angular`) én gang ved bootstrap slik at\n elementer som `<instui-icon>` fungerer i templater, og importerer token-/komponent-CSS pluss\n `@pantoken/interactions` (kobler opp modal, tooltip og andre komponentatferder ferdig).\n- `src/app.component.ts` er en frittstående komponent (`CUSTOM_ELEMENTS_SCHEMA` lar template-\n kompilatoren akseptere pantokens tilpassede elementtagger) hvis template er stylet med `instui-*`\n klasser; valgfrie innsettingspunkter (header, filters, content, trailing) er markert med\n `<div data-slot=\"...\">`.\n- Bruk klasser som `class=\"instui-button\"` på markup; se\n [komponentreferansen](https://pantoken.app/api/css) for full klasseoversikt.\n\n## Lær mer\n\nSe [kom i gang-guiden](https://pantoken.app/guide/getting-started) for mer informasjon.\n" },
392
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nOpplastningsklare ressurser for Canvas LMS sin **Theme Editor**, pluss en lokal forhåndsvisning for å lage Rich\nContent Editor (RCE)-sidemaler stilisert med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Hva som finnes her\n\n- `theme.css` / `theme.js` — last opp disse to filene under **Theme Editor → Advanced** i Canvas.\n De er bygget for CDN-leverandøren/theme/mode du valgte ved scaffolding (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light som standard) og inkluderer en loader for\n `@pantoken/interactions` (kobler opp komponentadferd som modal, tooltip og drilldown).\n- `index.html` / `src/main.ts` — en lokal, TinyMCE-basert editor (`npm run dev`) som speiler Canvas sin\n RCE slik at du kan forfatte sidemaler mot pantoken sine klasser før du kopierer dem inn i Canvas.\n Siden selv er bygget med pantoken sin `wrapper` layout: klikk **Edit theme** for å åpne en skuff\n med **Config** / **CSS** / **JS** faner (CDN-leverandør/theme/mode-valg, og syntaksfremhevede,\n håndredigerbare kopier av `theme.css`/`theme.js` som mater forhåndsvisningen live), og **?**-knappen\n for full instruksjon. Bruk **Layouts** verktøylinjeknappen for å starte fra en av pantoken sine medfølgende\n startsideoppsett (hero, callout, to-kolonner, rubric note, testimonial), hentet fra\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Utvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\nDette åpner en Vite dev-server med:\n\n- Et **editor**-panel (TinyMCE, samsvarende versjon/konfigurasjon\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) selv bruker — se under).\n Bruk **Layouts**-knappen for å laste en av de medfølgende startoppsettene (dette erstatter hele\n dokumentet, etter en bekreftelse, i stedet for å sette inn ved markøren), og **Source code**-bryteren\n for å håndredigere rå HTML i en syntaksfremhevet (CodeMirror) visning ved siden av editoren, med\n forhåndsvisningen som oppdateres live mens du skriver — i motsetning til TinyMCE sin standard `code`-plugin, som redigerer i\n en engangs modal-dialog uten live forhåndsvisning.\n- Et **preview**-panel som viser editorens innhold med stilarket/scriptet fra den aktuelle CSS/JS-fanen\n anvendt (ikke bare de løste CDN-URLene), innpakket for å matche Canvas sin egen innholdsområdes bakgrunn\n og maks bredde — en trofast \"slik vil det se ut når det er lastet opp til Canvas\"-sjekk, oppdatert\n live mens du skriver eller redigerer temaet.\n- Editor- og forhåndsvisningspanelene ligger i en delt visning du kan endre størrelse på ved å dra skillelinjen, stable\n vertikalt i stedet for side om side, og bytte rekkefølgen på dem (dra et panels verktøylinje over det andre,\n eller bruk **Swap panes**-knappen). Hvert panel har sin egen fullskjermknapp.\n- **Edit theme**-skuffens **Config**-fane inneholder CDN-leverandør/theme/mode-valgene og\n **Download theme.css** / **Download theme.js**-lenker; dens **CSS**/**JS**-faner er redigerbare kopier\n av de genererte filene — rediger dem for hånd og forhåndsvisningen plukker opp endringene direkte. Å endre\n et Config-valg regenererer CSS/JS-fanene med mindre du allerede har redigert dem, i så fall vises en\n **Regenerate from config**-knapp i stedet for at endringen overskriver ditt arbeid stille.\n\n## Arbeidsflyt\n\n1. Last opp `theme.css` og `theme.js` til Canvas sin Theme Editor (**Advanced → CSS / JavaScript**) slik at\n pantoken sine klasser er tilgjengelige på hver side.\n2. Kjør `npm run dev`, bruk **Layouts** for å starte fra en medfølgende starter, og rediger det som du\n ville gjort i Canvas sin egen RCE.\n3. Klikk **Copy HTML** og lim resultatet inn i en Canvas-sides RCE (bytt først til HTML-editor\n visningen). Canvas saniterer limt HTML på serversiden — dette scaffold forsøker ikke å\n replikere det, så verifiser alltid det limte resultatet i Canvas (se \"Merk om Canvas sin RCE\"\n nedenfor).\n\n## Merknader om Canvas sin RCE\n\nCanvas Rich Content Editor kjører TinyMCE og saniterer innsendt HTML på serveren mot en\nallowlist (`gems/canvas_sanitize` i canvas-lms, holdt i synk med TinyMCE sin egen\n`valid_elements`/`extended_valid_elements`). Hva den allowlisten betyr for maler bygget her:\n\n- `class`, `id`, `style`, `title`, `role`, og `aria-*` attributter er tillatt på hvert element —\n pantoken sine `class=\"instui-*\"` styling-kroker (og inline `style`, f.eks. for CSS-forankringsposisjonering)\n **overlever** å bli limt inn og lagret, i motsetning til eldre råd i denne filen. `<script>`-tagger\n blir alltid fjernet.\n- **RCE-sikre pantoken-komponenter**: statiske/visningskomponenter — alert, view, heading, text, table,\n en knapp-som-`<a>` (ikke en ekte `<button>`), blockquote. Hold deg til semantisk HTML pantoken allerede\n støtter (`div`, `p`, `span`, `a`, `img`, overskrifter, lister, tabeller).\n- **RCE-usikre**: alt fra `@pantoken/interactions`'s adferdssett — modal, tooltip,\n drilldown, close-button, eller enhver annen komponent drevet av native `popover`/`popovertarget`/\n `command`/`commandfor` attributter. Disse attributtene er ikke i Canvas sin sanitizer-allowlist, så\n markupen overlever men den interaktive adferden brytes stille første gang siden lagres i Canvas, selv med `theme.js` sin `@pantoken/interactions` loader til stede. Ekte skjemaelementer (`input`, `form`, `button`, `select`, `textarea`, `label`) og inline `<svg>` blir\n fjernet helt — ingen av de medfølgende startmalene bruker dem.\n\n`theme.js` laster `@pantoken/interactions` fra CDN-en, som kjører i Canvas sin globale sidescope —\nnyttig for interaksjoner på sider du bygger direkte i Canvas sin RCE med rå HTML-redigering, men (som nevnt\novenfor) vil enhver `popover`/`command`-attributt-drevet markup limt fra RCE-forhåndsvisningen her ikke forbli\ninteraktiv når den er lagret.\n" },
393
370
  "components": { "README.md": "# {{projectName}}\n\nEn enkel TypeScript-app (via Vite) stylet med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructures\ndesign tokens og ikoner.\n\n## Utvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hva som finnes her\n\n- `index.html` inneholder den faktiske sidens markup — et `wrapper`-layout-skall fra\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Se kilden\n og rediger den direkte; ingenting injiseres av JavaScript.\n- `src/main.ts` importerer `@pantoken/css` (definerer alle `--instui-*` egendefinerte\n properties), `@pantoken/components/base.css` (dokumentstandarder + focus ring), `components.css`\n (`.instui-*` klasser), `@pantoken/interactions` (kobler opp modal, tooltip og andre\n komponentoppførsel rett ut av boksen), og din egen `src/style.css` — legg til interaktiv\n oppførsel her.\n- Valgfrie innssettingspunkter (header, filters, content, trailing) er markert med\n `<div data-slot=\"...\">` i `index.html` — erstatt innholdet deres med din egen markup.\n- Bruk klasser som `class=\"instui-button\"` på markup; se\n [komponentreferansen](https://pantoken.app/api/css) for fullstendig liste over klasser.\n\n## Lær mer\n\nSe [HTML-guiden](https://pantoken.app/guide/components) for mer informasjon.\n" },
394
371
  "next": { "README.md": "# {{projectName}}\n\nEn Next.js (App Router) app stylet med [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next), Instructures designtokener og ikoner.\n\n## Utvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hva som finnes her\n\n- `next.config.mjs` pakker inn konfigurasjonen med `withPantoken(...)` (legger til pantoken i `transpilePackages`).\n- `app/layout.tsx` importerer `@pantoken/css`, som definerer alle `--instui-*` egendefinerte\n egenskaper, i roten slik at de er tilgjengelige på hver side, pluss `wrapper` layoutens rotklasse på\n `<body>` og `PantokenInteractions` (en klientkomponent som laster `@pantoken/interactions` —\n kobler opp modal, tooltip og andre komponentoppførsel umiddelbart).\n- `app/page.tsx` rendererer markup stylet med `instui-*` klasser; valgfrie innsettingspunkter (header,\n filtre, innhold, etterfølgende) er merket med `<div data-slot=\"...\">`.\n\n## Lær mer\n\nSe [getting started guide](https://pantoken.app/guide/getting-started) for å lære mer.\n" },
395
372
  "react": { "README.md": "# {{projectName}}\n\nEn Vite + React-app stylet med [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nog [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructures designtoken og ikoner.\n\n## Utvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Hva som finnes her\n\n- `src/main.tsx` importerer `@pantoken/css` (definerer alle `--instui-*` egendefinerte egenskaper) og\n `@pantoken/interactions` (kobler opp modal, tooltip og andre komponentatferder ferdig konfigurert).\n- `src/App.tsx` renderer markup stylet med `instui-*` klasser; valgfrie innsettingspunkter (header,\n filters, content, trailing) er merket med `<div data-slot=\"...\">`.\n- For InstUI sitt komplette React-komponentbibliotek (knapper, modaler osv. — inkludert `@pantoken/react` sin\n `<Icon>`), legg til de spesifikke `@instructure/ui-*`-pakkene du trenger — se <https://instructure.design>.\n\n## Lær mer\n\nSe [kom-i-gang-guiden](https://pantoken.app/guide/getting-started) for å lære mer.\n" },
@@ -399,7 +376,6 @@ const SCAFFOLD_OVERLAYS = {
399
376
  },
400
377
  "nn": {
401
378
  "angular": { "README.md": "# {{projectName}}\n\nEin frittståande Angular-app (via Vite + `@analogjs/vite-plugin-angular`, utan Angular CLI) styles med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) og\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken eigne element\nfor Angular).\n\n## Utvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Kva som finst her\n\n- `src/main.ts` kallar `registerPantokenElements()` (frå `@pantoken/angular`) ein gong ved bootstrap så\n element som `<instui-icon>` fungerer i malar, og importerer token-/komponent-CSS pluss\n `@pantoken/interactions` (koplar opp modal, tooltip og andre komponentoppførselar ferdig).\n- `src/app.component.ts` er ein frittståande komponent (`CUSTOM_ELEMENTS_SCHEMA` lèt mal-kompilatoren\n akseptere pantoken sine eigne element-taggar) der malen er stylelagd med `instui-*`\n klassar; valfrie innsettingspunkt (header, filters, content, trailing) er merka med\n `<div data-slot=\"...\">`.\n- Bruk klassar som `class=\"instui-button\"` på markup; sjå\n [komponentreferansen](https://pantoken.app/api/css) for fullstendig liste over klassar.\n\n## Les meir\n\nSjå [kom igang-guiden](https://pantoken.app/guide/getting-started) for meir informasjon.\n" },
402
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nOpplasting-klare ressursar for Canvas LMS sin **Theme Editor**, pluss ein lokal førevising for å forfatte Rich\nContent Editor (RCE) sidemalar styla med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Kva som finst her\n\n- `theme.css` / `theme.js` — last opp desse to fila under **Theme Editor → Advanced** i Canvas.\n Dei er bygde for CDN-leverandøren/temaet/modusen du valde då du scaffolda (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light som standard) og inkluderer ein loader for\n `@pantoken/interactions` (koplar opp komponentåtferd som modal, tooltip og drilldown).\n- `index.html` / `src/main.ts` — ein lokal, TinyMCE-basert editor (`npm run dev`) som speglar Canvas sin\n RCE slik at du kan forfatte sidemalar mot pantoken sine klassar før du kopierer dei inn i Canvas.\n Sidan sjølv er bygd med pantoken sitt `wrapper` layout: klikk **Edit theme** for å opne ein skuff\n med **Config** / **CSS** / **JS**-faner (CDN-leverandør/tema/modus-val, og syntaksmarkerte,\n hand-redigerbare kopiar av `theme.css`/`theme.js` som gir live-førevisinga), og **?**-knappen\n for fulle instruksjonar. Bruk **Layouts**-knappen i verktøylina for å starte frå ein av pantoken sine medfølgjande\n start-sidelayoutar (hero, callout, to-kolonne, rubric note, testimonial), henta frå\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Utvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\nDette opnar ein Vite dev-server med:\n\n- Ei **editor**-rute (TinyMCE, som samsvarar med versjonen/konfigurasjonen\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) sjølv bruker — sjå nedanfor).\n Bruk **Layouts**-knappen for å laste ein av dei medfølgjande start-layoutane (dette erstattar heile\n dokumentet, etter ein stadfesting, i staden for å setje inn ved markøren), og **Source code**-brytaren\n for å hand-redigere rå HTML i ei syntaksmarkert (CodeMirror) vising ved sida av editoren, med\n førevisingsruta som oppdaterer live mens du skriv — i motsetnad til TinyMCE sin standard `code` plugin, som redigerer i\n ein éngongs modal-dialog utan live-førevising.\n- Ei **preview**-rute som viser innhaldet frå editoren med stylesheet/script frå den aktuelle CSS/JS-fanen\n aplicada (ikkje berre dei løyste CDN-URL-ane), pakka for å matche Canvas sin eigen innhaldsområde-bakgrunn\n og maks-breidd — ein tru kopi av \"korleis dette vil sjå ut når det er lasta opp til Canvas\", oppdatert\n live medan du skriv eller endrar temaet.\n- Editor- og preview-rutene ligg i ei delt vising som kan endrast i storleik ved å dra skiljelinja, stable\n vertikalt i staden for side om side, og bytte rekkjefølgje på rutene (dra ein rutes verktøylinje over på den andre,\n eller bruk **Swap panes**-knappen). Kvar rute har sin eigen fullscreen-knapp.\n- Skuffa **Edit theme** sin **Config**-fane held CDN-leverandør/tema/modus-vala og\n **Download theme.css** / **Download theme.js**-lenkjer; hennar **CSS**/**JS**-faner er redigerbare kopiar\n av dei genererte fila — hand-rediger dei og førevisinga plukkar opp endringane dine direkte. Å endre\n eit Config-val regenererer CSS/JS-fanene med mindre du allereie har redigert dei, i så fall viser ein\n **Regenerate from config**-knapp seg i staden for å overskrive endringa dine lydlaust.\n\n## Arbeidsflyt\n\n1. Last opp `theme.css` og `theme.js` til Canvas sin Theme Editor (**Advanced → CSS / JavaScript**) så\n pantoken sine klassar er tilgjengelege på kvar side.\n2. Kjør `npm run dev`, bruk **Layouts** for å starte frå ein medfølgjande startmal, og rediger han som du\n ville gjort i Canvas sin eigen RCE.\n3. Klikk **Copy HTML** og lim resultatet inn i ein Canvas-side si RCE (bytt til HTML-editor\n visinga først). Canvas saniterer innlimt HTML på server-sida — dette scaffoldet forsøker ikkje å\n kopiere det, så ver alltid sikker på at det innlimte resultatet fungerer i Canvas (sjå \"Notat om Canvas sin RCE\"\n nedanfor).\n\n## Notat om Canvas sin RCE\n\nCanvas Rich Content Editor køyrer TinyMCE og saniterer innsende HTML på serveren mot ei\nallowlist (`gems/canvas_sanitize` i canvas-lms, halde i synk med TinyMCE si eiga\n`valid_elements`/`extended_valid_elements`). Kva den allowlista betyr for malar bygde her:\n\n- `class`, `id`, `style`, `title`, `role`, og `aria-*` attributtane er tillatne på alle element —\n pantoken sine `class=\"instui-*\"` styling-kroker (og inline `style`, t.d. for CSS-anker-posisjonering)\n **overlever** å bli limt inn og lagra, i motsetnad til eldre rettleiing i denne fila. `<script>` taggar\n blir alltid fjerna.\n- **RCE-sikre pantoken-komponentar**: statiske/visningskomponentar — alert, view, heading, text, table,\n ein knapp som `<a>` (ikkje ein ekte `<button>`), blockquote. Halde seg til semantisk HTML som pantoken allereie\n støttar (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- **RCE-uskildt**: alt frå `@pantoken/interactions` si åtferdsgruppe — modal, tooltip,\n drilldown, close-button, eller andre komponentar drivne av dei native `popover`/`popovertarget`/\n `command`/`commandfor` attributta. Desse attributta er ikkje i Canvas sin sanitiserings-allowlist, så\n markupet blir verande men den interaktive åtferda sluttar å fungere første gong sida vert\n lagra i Canvas, sjølv med `theme.js` sin `@pantoken/interactions` loader til stades. Reelle form-\n element (`input`, `form`, `button`, `select`, `textarea`, `label`) og inline `<svg>` blir\n fjerna heilt — ingen av dei medfølgjande startmalane nyttar dei.\n\n`theme.js` lastar `@pantoken/interactions` frå CDN-en, som køyrer i Canvas sitt globale side-område —\nnyttig for interaksjonar på sider du byggjer direkte i Canvas si RCE med rå HTML-endringar, men (som nemnt\novenfor) vil ethvert `popover`/`command`-attributt-styrt markup limt frå RCE-førevisinga her ikkje halde\nseg interaktivt når det er lagra.\n" },
403
379
  "components": { "README.md": "# {{projectName}}\n\nEin enkel TypeScript-app (via Vite) styla med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructure sine\ndesign tokens og ikonar.\n\n## Utvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Kva som finst her\n\n- `index.html` inneheld den faktiske sidemerkinga — eit `wrapper`-layout-skal frå\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Sjå kjelda\n og rediger ho direkte; ingenting vert injisert av JavaScript.\n- `src/main.ts` importerer `@pantoken/css` (definerer kvar `--instui-*` eiga eigenskap),\n `@pantoken/components/base.css` (dokumentstandardar + fokusring), `components.css`\n (`.instui-*` klassar), `@pantoken/interactions` (koplar til modal, tooltip og andre komponentåtferder\n ferdig), og din eigen `src/style.css` — legg til interaktiv åtferd her.\n- Valfrie innsettingspunkt (header, filters, content, trailing) er merkte med\n `<div data-slot=\"...\">` i `index.html` — erstatte innhaldet deira med di eiga merking.\n- Bruk klassar som `class=\"instui-button\"` på merkjemålet; sjå\n [komponentreferansen](https://pantoken.app/api/css) for fullstendig klasseliste.\n\n## Lær meir\n\nSjå [HTML-guiden](https://pantoken.app/guide/components) for meir informasjon.\n" },
404
380
  "next": { "README.md": "# {{projectName}}\n\nEin Next.js (App Router)-app styla med [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nInstructure sine designtoken og ikoner.\n\n## Utvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Kva som finst her\n\n- `next.config.mjs` kapslar inn konfigurasjonen med `withPantoken(...)` (legg pantoken til i\n `transpilePackages`).\n- `app/layout.tsx` importerer `@pantoken/css`, som definerer alle `--instui-*` tilpassa eigenskapar\n på rotnivå så dei er tilgjengelege på alle sider, pluss rotklassen for `wrapper`-oppsettet på\n `<body>` og `PantokenInteractions` (ein klientkomponent som lastar `@pantoken/interactions` —\n set opp modal, tooltip og andre komponentåtferder ferdig).\n- `app/page.tsx` rendrar merknad styla med `instui-*`-klassar; valfrie innsatsstader (hovud,\n filter, innhald, etterst) er merkte med `<div data-slot=\"...\">`.\n\n## Lær meir\n\nSjå [kom-i-gang-guiden](https://pantoken.app/guide/getting-started) for å lære meir.\n" },
405
381
  "react": { "README.md": "# {{projectName}}\n\nEin Vite + React-app styla med [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react) og [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructure sine design-token og ikon.\n\n## Utvikling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Kva som finst her\n\n- `src/main.tsx` importerer `@pantoken/css` (definerer alle `--instui-*`-eigenskapane) og `@pantoken/interactions` (knyter opp modal, tooltip og andre komponent‑åtferder klar‑til‑bruk).\n- `src/App.tsx` rendrar markup styla med `instui-*`-klassar; valfrie innsatsstader (header, filters, content, trailing) er merkte med `<div data-slot=\"...\">`.\n- For InstUI sitt fullstendige React-komponentbibliotek (knappar, modalar osb. — inkludert `@pantoken/react` sin `<Icon>`), legg til dei spesifikke `@instructure/ui-*`-pakketene du treng — sjå <https://instructure.design>.\n\n## Les meir\n\nSjå [getting started guide](https://pantoken.app/guide/getting-started) for meir informasjon.\n" },
@@ -409,7 +385,6 @@ const SCAFFOLD_OVERLAYS = {
409
385
  },
410
386
  "fa": {
411
387
  "angular": { "README.md": "# {{projectName}}\n\nیک برنامهٔ مستقل Angular (با استفاده از Vite + `@analogjs/vite-plugin-angular`، بدون Angular CLI) که با\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) و\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (عناصر سفارشی pantoken\nبرای Angular) استایل شده است.\n\n## توسعه\n\n```sh\nnpm install\nnpm run dev\n```\n\n## اینجا چه چیزی هست\n\n- `src/main.ts` یک بار در بوت‌استرپ `registerPantokenElements()` (از `@pantoken/angular`) را فراخوانی می‌کند تا عناصری مانند `<instui-icon>` در قالب‌ها کار کنند، و CSS توکن/کامپوننت را به‌علاوهٔ `@pantoken/interactions` وارد می‌کند (رفتارهای کامپوننت مانند مودال، تولتیپ و دیگران را از جعبه آماده می‌کند).\n- `src/app.component.ts` یک کامپوننت مستقل است (`CUSTOM_ELEMENTS_SCHEMA` به کامپایلر قالب اجازه می‌دهد تگ‌های عناصر سفارشی pantoken را بپذیرد) که قالب آن با کلاس‌های `instui-*` استایل شده؛ نقاط درج اختیاری (header, filters, content, trailing) با `<div data-slot=\"...\">` علامت‌گذاری شده‌اند.\n- کلاس‌هایی مانند `class=\"instui-button\"` را به نشانه‌گذاری اعمال کنید؛ فهرست کامل کلاس‌ها را در\n [ارجاع کامپوننت](https://pantoken.app/api/css) ببینید.\n\n## اطلاعات بیشتر\n\nبرای اطلاعات بیشتر، راهنمای شروع به کار را در [getting started guide](https://pantoken.app/guide/getting-started) ببینید.\n" },
412
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nدارایی‌های آماده برای آپلود برای **ویرایشگر قالب** Canvas LMS، به‌همراه پیش‌نمایش محلی برای ایجاد قالب‌های صفحه Rich\nContent Editor (RCE) که با\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) سبک‌دهی شده‌اند.\n\n## چه چیزهایی اینجا هست\n\n- `theme.css` / `theme.js` — این دو فایل را در **Theme Editor → Advanced** در Canvas آپلود کنید.\n آن‌ها برای ارائه‌دهنده CDN/قالب/حالت‌ای که هنگام اسکافولدینگ انتخاب کردید ساخته شده‌اند (`--cdn`/`--theme`/\n `--theme-mode`; به‌طور پیش‌فرض jsDelivr/rebrand/light) و شامل یک لودر برای\n `@pantoken/interactions` هستند (رفتارهای مؤلفه مانند modal، tooltip و drilldown را وصل می‌کند).\n- `index.html` / `src/main.ts` — یک ویرایشگر محلی مبتنی بر TinyMCE (`npm run dev`) که آینه‌ای از\n RCE Canvas است تا بتوانید قالب‌های صفحه را در مقابل کلاس‌های pantoken ایجاد کنید قبل از اینکه آن‌ها را در Canvas کپی کنید.\n خود صفحه با طرح‌بندی `wrapper` از pantoken ساخته شده: روی **Edit theme** کلیک کنید تا یک تِرِی\n با زبانه‌های **Config** / **CSS** / **JS** باز شود (انتخاب‌های ارائه‌دهنده CDN/قالب/حالت و نسخه‌های قابل ویرایش با برجسته‌سازی نحو،\n ویرایش‌شونده توسط کاربر از `theme.css`/`theme.js` که پیش‌نمایش زنده را تغذیه می‌کنند)، و دکمه **?**\n برای دستورالعمل کامل. از دکمه نوارابزار **Layouts** استفاده کنید تا با یکی از طرح‌های شروع‌شده بسته‌بندی‌شده pantoken (hero، callout، دو ستونه، rubric note، testimonial) شروع کنید، که منبع‌شان از\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts) است.\n\n## توسعه\n\n```sh\nnpm install\nnpm run dev\n```\n\nاین یک سرور توسعه Vite را باز می‌کند با:\n\n- یک پانل **editor** (TinyMCE، مطابق نسخه/پیکربندی\n که خود [instructure/canvas-lms](https://github.com/instructure/canvas-lms) استفاده می‌کند — جزئیات پایین‌تر). از دکمه **Layouts** برای بارگذاری یکی از طرح‌های شروع‌شده بسته‌بندی‌شده استفاده کنید (این پس از تأیید کل\n سند را جایگزین می‌کند، به‌جای درج در مکان‌نما)، و کلید تغییر **Source code**\n برای ویرایش دستی HTML خام در یک نمای برجسته‌شده با نحو (CodeMirror) در کنار ویرایشگر، با\n پیش‌نمایش که هنگام تایپ زنده به‌روز می‌شود — برخلاف پلاگین پیش‌فرض `code` TinyMCE که در یک دیالوگ مودال یک‌مرتبه‌ای بدون پیش‌نمایش زنده ویرایش می‌کند.\n- یک پانل **preview** که محتوای ویرایشگر را با stylesheet/script زبانه CSS/JS جاری اعمال‌شده نشان می‌دهد\n (نه فقط URL‌های CDN حل‌شده)، با بسته‌بندی برای مطابقت با پس‌زمینه ناحیه محتوا و حداکثر عرض Canvas — یک بررسی دقیق «چگونه پس از آپلود در Canvas نشان داده خواهد شد»، که در حین تایپ یا ویرایش قالب به‌صورت زنده به‌روز می‌شود.\n- پانل ویرایشگر و پیش‌نمایش در یک نمای تقسیم‌شده قرار دارند که می‌توانید با کشیدن جداکننده اندازه آن‌ها را تغییر دهید، آن‌ها را به‌صورت عمودی به‌جای کنار هم پشته کنید، و ترتیب پن‌ها را جابه‌جا کنید (نوارابزار یک پن را روی دیگری بکشید، یا از دکمه **Swap panes** استفاده کنید). هر پن دکمه تمام‌صفحه خودش را دارد.\n- زبانه **Config** در تِری **Edit theme** شامل انتخاب‌های ارائه‌دهنده CDN/قالب/حالت و لینک‌های **Download theme.css** / **Download theme.js** است؛ زبانه‌های **CSS**/**JS** نسخه‌های قابل ویرایش از فایل‌های تولیدشده هستند — آن‌ها را دستی ویرایش کنید و پیش‌نمایش تغییرات را مستقیماً دریافت می‌کند. تغییر یک انتخاب Config فایل‌های CSS/JS را دوباره تولید می‌کند مگر اینکه قبلاً آن‌ها را ویرایش کرده باشید؛ در این صورت یک دکمه **Regenerate from config** ظاهر می‌شود به‌جای بازنویسی بی‌صدا.\n\n## جریان کار\n\n1. `theme.css` و `theme.js` را در Theme Editor Canvas آپلود کنید (**Advanced → CSS / JavaScript**) تا کلاس‌های pantoken در هر صفحه دردسترس باشند.\n2. `npm run dev` را اجرا کنید، از **Layouts** برای شروع از یک قالب بسته‌بندی‌شده استفاده کنید، و آن را مثل ویرایش در RCE خود Canvas ویرایش کنید.\n3. روی **Copy HTML** کلیک کنید و نتیجه را در RCE صفحه Canvas الصاق کنید (ابتدا به نمای ویرایشگر HTML تغییر وضعیت دهید). Canvas HTML الصاق‌شده را سروری پاک‌سازی می‌کند — این اسکافولد تلاش نمی‌کند آن را تکرار کند، پس همیشه نتیجه الصاق‌شده را در Canvas بررسی کنید (ببینید «نکات درباره RCE Canvas» در ادامه).\n\n## نکاتی درباره RCE Canvas\n\nویرایشگر Rich Content Canvas از TinyMCE استفاده می‌کند و HTML ارسال‌شده را روی سرور در برابر یک لیست مجاز (`gems/canvas_sanitize` در canvas-lms، که با `valid_elements`/`extended_valid_elements` خود TinyMCE همگام نگه داشته شده) پاک‌سازی می‌کند. معنای آن لیست مجاز برای قالب‌هایی که اینجا ساخته می‌شوند:\n\n- صفات `class`, `id`, `style`, `title`, `role`, و `aria-*` روی هر عنصر مجاز هستند —\n هوک‌های استایل‌دهی `class=\"instui-*\"` pantoken (و `style` درون‌خطی، مثلاً برای موقعیت‌دهی anchor در CSS)\n **پس از** الصاق و ذخیره شدن باقی می‌مانند، برخلاف راهنمایی‌های قدیمی‌تر در این فایل. تگ‌های `<script>` همیشه حذف می‌شوند.\n- مؤلفه‌های pantoken که امن برای RCE هستند: مؤلفه‌های ایستا/نمایشی — alert، view، heading، text، table،\n یک دکمه به‌عنوان `<a>` (نه یک `<button>` واقعی)، blockquote. به HTML معنایی‌ای که pantoken از قبل پشتیبانی می‌کند پایبند باشید (`div`, `p`, `span`, `a`, `img`, heading‌ها، listها، tableها).\n- ناسازگار با RCE: هر چیزی از مجموعه رفتارهای `@pantoken/interactions` — modal، tooltip،\n drilldown، close-button، یا هر مؤلفه دیگری که با صفات بومی `popover`/`popovertarget`/\n `command`/`commandfor` هدایت می‌شود. آن صفات در لیست مجاز sanitizer Canvas نیستند، پس\n نشانه‌گذاری ممکن است حفظ شود اما رفتار تعاملی در اولین بار ذخیره صفحه در Canvas به‌صورت بی‌صدا شکسته می‌شود، حتی با وجود لودر `@pantoken/interactions` از `theme.js`. عناصر فرم واقعی\n (`input`, `form`, `button`, `select`, `textarea`, `label`) و `<svg>` درون‌خطی\n به‌طور کلی حذف می‌شوند — هیچ‌یک از قالب‌های شروع‌شده بسته‌بندی‌شده از آن‌ها استفاده نمی‌کنند.\n\n`theme.js`، `@pantoken/interactions` را از CDN بارگیری می‌کند، که در محدوده صفحه سراسری Canvas اجرا می‌شود —\nمفید برای تعاملات در صفحاتی که مستقیماً با ویرایش HTML خام در RCE Canvas ساخته‌اید، اما (مطابق بالا) هر نشانه‌گذاری که با صفات `popover`/`command`-محور از پیش‌نمایش RCE اینجا الصاق شود،\nپس از ذخیره در Canvas دیگر تعاملی باقی نخواهد ماند.\n" },
413
388
  "components": { "README.md": "# {{projectName}}\n\nیک برنامه سادهٔ TypeScript (از طریق Vite) با استایل‌دهی شده با\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)، توکن‌های طراحی و آیکون‌های Instructure.\n\n## توسعه\n\n```sh\nnpm install\nnpm run dev\n```\n\n## چه چیزهایی اینجا هست\n\n- `index.html` نشانه‌گذاری صفحهٔ واقعی را نگه می‌دارد — یک شِـل با چیدمان `wrapper` از\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). کد منبع را ببینید\n و مستقیماً آن را ویرایش کنید؛ هیچ‌چیز توسط جاوااسکریپت تزریق نمی‌شود.\n- `src/main.ts` `@pantoken/css` را وارد می‌کند (تمام ویژگی‌های سفارشی `--instui-*` را تعریف می‌کند),\n `@pantoken/components/base.css` (پیش‌فرض‌های سند + حلقهٔ فوکوس)، `components.css`\n (کلاس‌های `.instui-*`)، `@pantoken/interactions` (به‌طور پیش‌فرض رفتارهای کامپوننت مانند مودال و تولتیپ را راه‌اندازی می‌کند)، و `src/style.css` خودتان — رفتار تعاملی را اینجا اضافه کنید.\n- نقاط درج اختیاری (هدر، فیلترها، محتوا، انتها) با\n `<div data-slot=\"...\">` در `index.html` علامت‌گذاری شده‌اند — محتوای آن‌ها را با نشانه‌گذاری خود جایگزین کنید.\n- کلاس‌هایی مانند `class=\"instui-button\"` را به نشانه‌گذاری اعمال کنید؛ برای فهرست کامل کلاس‌ها به\n [مرجع کامپوننت](https://pantoken.app/api/css) مراجعه کنید.\n\n## اطلاعات بیشتر\n\nبرای اطلاعات بیشتر راهنمای [HTML](https://pantoken.app/guide/components) را ببینید.\n" },
414
389
  "next": { "README.md": "# {{projectName}}\n\nیک برنامه Next.js (App Router) با استایل‌دهی شده با [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next)،\nتوکن‌ها و آیکون‌های طراحی Instructure.\n\n## توسعه\n\n```sh\nnpm install\nnpm run dev\n```\n\n## چه چیزی اینجا هست\n\n- `next.config.mjs` پیکربندی را با `withPantoken(...)` می‌پیچد (pantoken را به `transpilePackages` اضافه می‌کند).\n- `app/layout.tsx` از `@pantoken/css` وارد می‌کند، که هر `--instui-*` متغیر سفارشی را تعریف می‌کند، در ریشه تا در هر صفحه در دسترس باشد، به‌علاوه کلاس ریشه لایه `wrapper` در `<body>` و `PantokenInteractions` (یک کامپوننت کلاینت که `@pantoken/interactions` را بارگذاری می‌کند — به‌صورت آماده رفتارهای کامپوننت مانند مودال، تولتیپ و غیره را راه‌اندازی می‌کند).\n- `app/page.tsx` مارکاپی را رندر می‌کند که با کلاس‌های `instui-*` استایل داده شده؛ نقاط درج اختیاری (header، filters، content، trailing) با `<div data-slot=\"...\">` مشخص شده‌اند.\n\n## اطلاعات بیشتر\n\nبرای اطلاعات بیشتر، راهنمای شروع به کار را ببینید: [getting started guide](https://pantoken.app/guide/getting-started).\n" },
415
390
  "react": { "README.md": "# {{projectName}}\n\nیک برنامه Vite + React با استایل‌دهی شده با [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nو [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css)، توکن‌های طراحی و آیکون‌های Instructure.\n\n## توسعه\n\n```sh\nnpm install\nnpm run dev\n```\n\n## چه چیزهایی اینجا است\n\n- `src/main.tsx`، `@pantoken/css` را وارد می‌کند (تمام ویژگی‌های سفارشی `--instui-*` را تعریف می‌کند) و\n `@pantoken/interactions` (رفتارهای کامپوننت مثل مدال، تولتیپ و دیگر رفتارها را به‌صورت آماده فراهم می‌کند).\n- `src/App.tsx` علامت‌گذاری‌ای را رندر می‌کند که با کلاس‌های `instui-*` استایل شده‌اند؛ نقاط درج اختیاری (header،\n filters، content، trailing) با `<div data-slot=\"...\">` علامت‌گذاری شده‌اند.\n- برای کتابخانه کامل کامپوننت‌های Reactِ InstUI (دکمه‌ها، مدال‌ها و غیره — شامل `@pantoken/react`’s\n `<Icon>`)، بسته‌های مشخص `@instructure/ui-*` مورد نیاز خود را اضافه کنید — نگاه کنید به <https://instructure.design>.\n\n## اطلاعات بیشتر\n\nبرای آشنایی بیشتر، راهنمای [شروع کار](https://pantoken.app/guide/getting-started) را ببینید.\n" },
@@ -419,7 +394,6 @@ const SCAFFOLD_OVERLAYS = {
419
394
  },
420
395
  "pl": {
421
396
  "angular": { "README.md": "# {{projectName}}\n\nSamodzielna aplikacja Angular (przez Vite + `@analogjs/vite-plugin-angular`, bez Angular CLI) stylowana za pomocą\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) oraz\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (niestandardowe elementy pantoken\ndla Angular).\n\n## Tworzenie\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Co tu jest\n\n- `src/main.ts` wywołuje `registerPantokenElements()` (z `@pantoken/angular`) raz podczas bootstrapu, więc\n elementy takie jak `<instui-icon>` działają w szablonach, oraz importuje CSS tokenów/komponentów plus\n `@pantoken/interactions` (konfiguruje modal, tooltip i inne zachowania komponentów od razu).\n- `src/app.component.ts` to samodzielny komponent (`CUSTOM_ELEMENTS_SCHEMA` pozwala kompilatorowi szablonów\n akceptować niestandardowe tagi pantoken), którego szablon jest stylowany klasami `instui-*`;\n opcjonalne punkty wstawienia (header, filters, content, trailing) są oznaczone przez\n `<div data-slot=\"...\">`.\n- Zastosuj klasy takie jak `class=\"instui-button\"` do znaczników; zobacz\n [odniesienie komponentu](https://pantoken.app/api/css) po pełną listę klas.\n\n## Dowiedz się więcej\n\nZobacz [przewodnik „getting started”](https://pantoken.app/guide/getting-started), aby dowiedzieć się więcej.\n" },
422
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nGotowe do przesłania zasoby dla edytora motywów Canvas LMS (**Theme Editor**), oraz lokalny podgląd do tworzenia szablonów stron Rich Content Editor (RCE) stylowanych za pomocą\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Co tutaj jest\n\n- `theme.css` / `theme.js` — prześlij te dwa pliki w **Theme Editor → Advanced** w Canvas.\n Są zbudowane dla dostawcy CDN/motywu/trybu, który wybrałeś przy tworzeniu szkielety (`--cdn`/`--theme`/\n `--theme-mode`; domyślnie jsDelivr/rebrand/light) i zawierają loader dla\n `@pantoken/interactions` (podłącza zachowania komponentów takich jak modal, tooltip i drilldown).\n- `index.html` / `src/main.ts` — lokalny edytor oparty na TinyMCE (`npm run dev`), który odzwierciedla RCE Canvas, więc możesz tworzyć szablony stron przeciwko klasom pantoken zanim wkleisz je do Canvas.\n Sama strona jest zbudowana z układem `wrapper` pantoken: kliknij **Edit theme**, aby otworzyć panel z zakładkami **Config** / **CSS** / **JS** (wybory dostawcy CDN/motywu/trybu i składniowo podświetlone,\n edytowalne kopie `theme.css`/`theme.js`, które zasilają podgląd na żywo), oraz przycisk **?** z pełnymi instrukcjami. Użyj przycisku paska narzędzi **Layouts**, aby rozpocząć od jednego z dołączonych startowych układów stron pantoken (hero, callout, two-column, rubric note, testimonial), pochodzących z\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Tworzenie (Develop)\n\n```sh\nnpm install\nnpm run dev\n```\n\nTo otwiera serwer deweloperski Vite z:\n\n- Panelem **editor** (TinyMCE, dopasowany do wersji/konfiguracji\n używanej w samym [instructure/canvas-lms](https://github.com/instructure/canvas-lms) — patrz niżej).\n Użyj przycisku **Layouts**, aby załadować jeden z dołączonych startowych układów (zastępuje cały\n dokument po potwierdzeniu, zamiast wstawiać w kursor), oraz przełącznika **Source code**, aby ręcznie edytować surowe HTML w widoku z podświetleniem składni (CodeMirror) obok edytora, z panelem podglądu aktualizującym się na żywo w trakcie pisania — w przeciwieństwie do standardowego wtyczki `code` TinyMCE, która edytuje w jednorazowym modalnym oknie bez podglądu na żywo.\n- Panelem **preview**, pokazującym zawartość edytora ze stylami/skryptami z zakładek CSS/JS zastosowanymi (nie tylko rozwiązywanymi URL-ami CDN), opakowaną tak, by pasowała do tła i maksymalnej szerokości obszaru treści Canvas — wierne sprawdzenie „jak to będzie wyglądać po przesłaniu do Canvas”, aktualizowane na żywo w miarę pisania lub edycji motywu.\n- Panele edytora i podglądu znajdują się w widoku dzielonym, którego rozmiar można zmieniać przeciągając dzielnik, można je ustawić pionowo zamiast obok siebie oraz zamieniać kolejność (przeciągnij pasek narzędzi panelu na drugi lub użyj przycisku **Swap panes**). Każdy panel ma własny przycisk pełnoekranowy.\n- Panel **Edit theme** w zakładce **Config** zawiera wybory dostawcy CDN/motywu/trybu oraz linki **Download theme.css** / **Download theme.js**; zakładki **CSS**/**JS** to edytowalne kopie wygenerowanych plików — edytuj je ręcznie, a podgląd natychmiast zastosuje zmiany. Zmiana wyboru w Config ponownie generuje zakładki CSS/JS, chyba że już je edytowałeś; w takim przypadku pojawia się przycisk **Regenerate from config** zamiast cichego nadpisania edycji.\n\n## Workflow\n\n1. Prześlij `theme.css` i `theme.js` do Theme Editor Canvas (**Advanced → CSS / JavaScript**), aby klasy pantoken były dostępne na każdej stronie.\n2. Uruchom `npm run dev`, użyj **Layouts**, aby zacząć od dołączonego startera, i edytuj go tak, jak w natywnym RCE Canvas.\n3. Kliknij **Copy HTML** i wklej wynik do RCE strony w Canvas (najpierw przełącz się na widok edytora HTML). Canvas sanitizuje wklejane HTML po stronie serwera — ten szkielet tego nie emuluje, więc zawsze zweryfikuj wklejony wynik w Canvas (patrz „Uwagi do RCE Canvas” poniżej).\n\n## Uwagi dotyczące RCE Canvas\n\nRich Content Editor Canvas używa TinyMCE i sanitizuje przesłane HTML po stronie serwera względem listy dozwolonych elementów (allowlist) (`gems/canvas_sanitize` w canvas-lms, utrzymywana w synchronizacji z własnymi\n`valid_elements`/`extended_valid_elements` TinyMCE). Co ta allowlist oznacza dla szablonów tworzonych tutaj:\n\n- Atrybuty `class`, `id`, `style`, `title`, `role` oraz `aria-*` są dozwolone na każdym elemencie —\n haki stylizujące pantoken (`class=\"instui-*\"`) (i inline `style`, np. do pozycjonowania kotwicy w CSS)\n **przeżywają** wklejanie i zapis, wbrew starszym wskazówkom w tym pliku. Tagi `<script>` są zawsze usuwane.\n- **Komponenty pantoken bezpieczne w RCE**: komponenty statyczne/wyświetlające — alert, view, heading, text, table,\n przycisk jako `<a>` (nie prawdziwy `<button>`), blockquote. Trzymaj się semantycznego HTML, który pantoken już obsługuje (`div`, `p`, `span`, `a`, `img`, nagłówki, listy, tabele).\n- **Niezalecane w RCE**: cokolwiek z zestawu zachowań `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button lub inny komponent napędzany natywnymi atrybutami `popover`/`popovertarget`/\n `command`/`commandfor`. Te atrybuty nie znajdują się na liście dozwolonych przez sanitizer Canvas, więc znacznik przetrwa, ale interaktywne zachowanie przestaje działać po pierwszym zapisaniu strony w Canvas, nawet przy obecnym loaderze `theme.js`'s `@pantoken/interactions`. Prawdziwe elementy formularzy (`input`, `form`, `button`, `select`, `textarea`, `label`) oraz inline `<svg>` są całkowicie usuwane — żaden z dołączonych starterów nie używa ich.\n \n`theme.js` ładuje `@pantoken/interactions` z CDN, który działa w globalnej przestrzeni strony Canvas — przydatne dla interakcji na stronach tworzonych bezpośrednio w RCE Canvas przy surowych edycjach HTML, ale (zgodnie z powyższym) jakikolwiek znacznik napędzany atrybutami `popover`/`command` wklejony z podglądu RCE tutaj nie pozostanie interaktywny po zapisaniu.\n" },
423
397
  "components": { "README.md": "# {{projectName}}\n\nProsta aplikacja TypeScript (przez Vite) stylowana za pomocą\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), tokenów projektowych i ikon Instructure.\n\n## Rozwój\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Co tu znajdziesz\n\n- `index.html` zawiera rzeczywisty znacznik strony — powłokę układu `wrapper` z\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Zobacz źródło\n i edytuj je bezpośrednio; nic nie jest wstrzykiwane przez JavaScript.\n- `src/main.ts` importuje `@pantoken/css` (definiuje wszystkie niestandardowe właściwości `--instui-*`),\n `@pantoken/components/base.css` (domyślne ustawienia dokumentu + obwiednia fokusu), `components.css`\n (`.instui-*` klasy), `@pantoken/interactions` (konfiguruje modal, tooltip i inne zachowania komponentów od razu) oraz własny `src/style.css` — dodaj tutaj interaktywne zachowanie.\n- Opcjonalne punkty wstawienia (header, filters, content, trailing) są oznaczone\n `<div data-slot=\"...\">` w `index.html` — zamień ich zawartość własnym markupem.\n- Stosuj klasy takie jak `class=\"instui-button\"` do znaczników; zobacz\n [referencję komponentów](https://pantoken.app/api/css) aby poznać pełną listę klas.\n\n## Dowiedz się więcej\n\nZobacz [przewodnik HTML](https://pantoken.app/guide/components), aby dowiedzieć się więcej.\n" },
424
398
  "next": { "README.md": "# {{projectName}}\n\nAplikacja Next.js (App Router) wystylizowana przy użyciu [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\ntokenów projektowych i ikon Instructure.\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Co tu jest\n\n- `next.config.mjs` opakowuje konfigurację za pomocą `withPantoken(...)` (dodaje pantoken do\n `transpilePackages`).\n- `app/layout.tsx` importuje `@pantoken/css`, który definiuje każdą niestandardową\n własność `--instui-*` w katalogu root, dzięki czemu jest dostępny na każdej stronie, oraz klasę root layoutu `wrapper` na\n `<body>` i `PantokenInteractions` (komponent kliencki, który ładuje `@pantoken/interactions` —\n podłącza modal, tooltip i inne zachowania komponentów gotowe do użycia).\n- `app/page.tsx` renderuje znacznik wystylizowany klasami `instui-*`; opcjonalne punkty wstawienia (header,\n filters, content, trailing) oznaczone są `<div data-slot=\"...\">`.\n\n## Dowiedz się więcej\n\nZobacz [przewodnik rozpoczęcia pracy](https://pantoken.app/guide/getting-started), aby dowiedzieć się więcej.\n" },
425
399
  "react": { "README.md": "# {{projectName}}\n\nAplikacja Vite + React stylowana za pomocą [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react) oraz [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), tokenów projektowych i ikon Instructure.\n\n## Rozwój\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Co tu znajdziesz\n\n- `src/main.tsx` importuje `@pantoken/css` (definiuje wszystkie niestandardowe właściwości `--instui-*`) oraz `@pantoken/interactions` (konfiguruje modal, tooltip i inne zachowania komponentów gotowe do użycia).\n- `src/App.tsx` renderuje markup ostylowany klasami `instui-*`; opcjonalne punkty wstawiania (nagłówek, filtry, zawartość, końcowa) oznaczone są `<div data-slot=\"...\">`.\n- Dla pełnej biblioteki komponentów React InstUI (przyciski, modale itp. — w tym `@pantoken/react`'s `<Icon>`), dodaj konkretne pakiety `@instructure/ui-*`, których potrzebujesz — zobacz <https://instructure.design>.\n\n## Dowiedz się więcej\n\nZobacz [przewodnik rozpoczynający pracę](https://pantoken.app/guide/getting-started), aby dowiedzieć się więcej.\n" },
@@ -429,7 +403,6 @@ const SCAFFOLD_OVERLAYS = {
429
403
  },
430
404
  "pt": {
431
405
  "angular": { "README.md": "# {{projectName}}\n\nUm aplicativo Angular independente (via Vite + `@analogjs/vite-plugin-angular`, sem Angular CLI) estilizado com\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) e\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (elementos personalizados pantoken\npara Angular).\n\n## Desenvolver\n\n```sh\nnpm install\nnpm run dev\n```\n\n## O que há aqui\n\n- `src/main.ts` chama `registerPantokenElements()` (de `@pantoken/angular`) uma vez no bootstrap para que\n elementos como `<instui-icon>` funcionem nos templates, e importa o CSS de tokens/componentes mais\n `@pantoken/interactions` (configura modal, tooltip e outros comportamentos de componente prontos para uso).\n- `src/app.component.ts` é um componente independente (`CUSTOM_ELEMENTS_SCHEMA` permite que o compilador de template\n aceite as tags de elemento personalizado do pantoken) cujo template é estilizado com classes `instui-*`;\n pontos de inserção opcionais (header, filters, content, trailing) são marcados com\n `<div data-slot=\"...\">`.\n- Aplique classes como `class=\"instui-button\"` à marcação; veja a\n [referência de componentes](https://pantoken.app/api/css) para a lista completa de classes.\n\n## Saiba mais\n\nVeja o [guia de início rápido](https://pantoken.app/guide/getting-started) para saber mais.\n" },
432
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nAtivos prontos para upload do **Theme Editor** do Canvas LMS, além de uma visualização local para criar templates de página do Rich Content Editor (RCE) estilizados com\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## O que tem aqui\n\n- `theme.css` / `theme.js` — faça upload desses dois arquivos em **Theme Editor → Advanced** no Canvas.\n Eles foram criados para o provedor de CDN/tema/modo que você escolheu ao fazer o scaffold (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light por padrão) e incluem um loader para\n `@pantoken/interactions` (conecta comportamentos de componentes como modal, tooltip e drilldown).\n- `index.html` / `src/main.ts` — um editor local baseado em TinyMCE (`npm run dev`) que espelha o\n RCE do Canvas para que você possa criar templates de página contra as classes do pantoken antes de copiá-los para o Canvas.\n A página em si é criada com o layout `wrapper` do pantoken: clique em **Edit theme** para abrir uma bandeja\n com abas **Config** / **CSS** / **JS** (seletores de provedor de CDN/tema/modo e cópias\n editáveis com realce de sintaxe de `theme.css`/`theme.js` que alimentam a visualização ao vivo), e o botão **?**\n para instruções completas. Use o botão **Layouts** da barra de ferramentas para começar com um dos layouts de página inicial em pacote do pantoken\n (hero, callout, two-column, rubric note, testimonial), obtido de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Desenvolver\n\n```sh\nnpm install\nnpm run dev\n```\n\nIsso abre um servidor de desenvolvimento Vite com:\n\n- Um painel **editor** (TinyMCE, correspondendo à versão/config que\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) usa — veja abaixo).\n Use o botão **Layouts** para carregar um dos layouts iniciais em pacote (isso substitui todo o\n documento, após uma confirmação, em vez de inserir no cursor), e o alternador **Source code**\n para editar manualmente o HTML bruto em uma visualização com realce de sintaxe (CodeMirror) ao lado do editor, com\n o painel de visualização atualizado em tempo real enquanto você digita — diferentemente do plugin `code` padrão do TinyMCE, que edita em\n um diálogo modal único, sem visualização ao vivo.\n- Um painel **preview** mostrando o conteúdo do editor com a folha de estilos/script da aba CSS/JS atual\n aplicada (não apenas os URLs CDN resolvidos), envolvida para corresponder ao próprio fundo da área de conteúdo do Canvas\n e largura máxima — uma verificação fiel de \"como isso se parecerá uma vez enviado para o Canvas\", atualizada\n em tempo real enquanto você digita ou edita o tema.\n- Os painéis do editor e visualização ficam em uma visualização dividida que você pode redimensionar arrastando o divisor, empilhar\n verticalmente em vez de lado a lado e trocar a ordem (arraste a barra de ferramentas de um painel para o outro,\n ou use o botão **Swap panes**). Cada painel tem seu próprio botão de tela cheia.\n- A aba **Config** da bandeja **Edit theme** contém os seletores de provedor de CDN/tema/modo e\n links **Download theme.css** / **Download theme.js**; suas abas **CSS**/**JS** são cópias editáveis\n dos arquivos gerados — edite-as manualmente e a visualização capta suas alterações diretamente. Alterar\n um seletor Config regenera as abas CSS/JS, a menos que você já as tenha editado, nesse caso um\n botão **Regenerate from config** aparece em vez de sobrescrever silenciosamente sua edição.\n\n## Fluxo de trabalho\n\n1. Faça upload de `theme.css` e `theme.js` para o Theme Editor do Canvas (**Advanced → CSS / JavaScript**) para que\n as classes do pantoken estejam disponíveis em todas as páginas.\n2. Execute `npm run dev`, use **Layouts** para começar com um inicializador em pacote e edite-o como você\n faria no RCE do próprio Canvas.\n3. Clique em **Copy HTML** e cole o resultado no RCE de uma página do Canvas (alterne para a visualização do editor HTML\n primeiro). O Canvas sanitiza HTML colado no lado do servidor — este scaffold não tenta\n replicar isso, então sempre verifique o resultado colado no Canvas (consulte \"Notas sobre o RCE do Canvas\"\n abaixo).\n\n## Notas sobre o RCE do Canvas\n\nO Rich Content Editor do Canvas executa TinyMCE e sanitiza HTML enviado no servidor contra uma\nlista de permissões (`gems/canvas_sanitize` no canvas-lms, mantido em sincronização com\n`valid_elements`/`extended_valid_elements` do próprio TinyMCE). O que essa lista de permissões significa para templates criados aqui:\n\n- Atributos `class`, `id`, `style`, `title`, `role` e `aria-*` são permitidos em cada elemento —\n os hooks de estilo `class=\"instui-*\"` do pantoken (e `style` inline, por exemplo, para posicionamento de âncora CSS)\n **sim** sobrevivem sendo colados e salvos, contrário à orientação antiga neste arquivo. Tags `<script>`\n são sempre removidas.\n- **Componentes pantoken seguros para RCE**: componentes estáticos/exibição — alert, view, heading, text, table,\n um button-as-`<a>` (não um verdadeiro `<button>`), blockquote. Cumpra HTML semântico que o pantoken já\n suporta (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- **RCE-inseguro**: qualquer coisa do conjunto de comportamento `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button ou qualquer outro componente acionado pelos atributos nativos `popover`/`popovertarget`/\n `command`/`commandfor`. Esses atributos não estão na lista de permissões do sanitizador do Canvas, então\n a marcação sobrevive, mas o comportamento interativo interrompe silenciosamente na primeira vez que a página é\n salva no Canvas, mesmo com o loader `@pantoken/interactions` de `theme.js` presente. Elementos de formulário reais\n (`input`, `form`, `button`, `select`, `textarea`, `label`) e `<svg>` inline são\n removidos completamente — nenhum dos templates iniciais em pacote os usa.\n\n`theme.js` carrega `@pantoken/interactions` do CDN, que é executado no escopo global da página do Canvas —\nútil para interações em páginas que você cria diretamente no RCE do Canvas com edições HTML bruto, mas (conforme\nacima) qualquer marcação acionada por atributo `popover`/`command` colada a partir da visualização prévia do RCE aqui não permanecerá\ninterativa uma vez salva.\n" },
433
406
  "components": { "README.md": "# {{projectName}}\n\nUm aplicativo TypeScript simples (via Vite) estilizado com\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), os tokens de design e ícones da Instructure.\n\n## Desenvolvimento\n\n```sh\nnpm install\nnpm run dev\n```\n\n## O que há aqui\n\n- `index.html` contém a marcação real da página — um invólucro de layout `wrapper` de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Veja a origem\n e edite-a diretamente; nada é injetado pelo JavaScript.\n- `src/main.ts` importa `@pantoken/css` (define todas as propriedades customizadas `--instui-*`),\n `@pantoken/components/base.css` (padrões do documento + anel de foco), `components.css`\n (`.instui-*` classes), `@pantoken/interactions` (conecta modal, tooltip e outros comportamentos de componentes prontos para uso), e seu próprio `src/style.css` — adicione comportamento interativo aqui.\n- Pontos de inserção opcionais (cabeçalho, filtros, conteúdo, final) estão marcados com\n `<div data-slot=\"...\">` em `index.html` — substitua seus conteúdos com sua própria marcação.\n- Aplique classes como `class=\"instui-button\"` na marcação; veja a\n [referência de componentes](https://pantoken.app/api/css) para a lista completa de classes.\n\n## Saiba mais\n\nVeja o [guia de HTML](https://pantoken.app/guide/components) para saber mais.\n" },
434
407
  "next": { "README.md": "# {{projectName}}\n\nUm app Next.js (App Router) estilizado com [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\ntokens de design e ícones da Instructure.\n\n## Desenvolver\n\n```sh\nnpm install\nnpm run dev\n```\n\n## O que há aqui\n\n- `next.config.mjs` envolve a configuração com `withPantoken(...)` (adiciona pantoken a\n `transpilePackages`).\n- `app/layout.tsx` importa `@pantoken/css`, que define todas as propriedades customizadas `--instui-*`,\n na raiz para que esteja disponível em todas as páginas, além da classe raiz do layout `wrapper` em\n `<body>` e `PantokenInteractions` (um componente cliente que carrega `@pantoken/interactions` —\n configura modal, tooltip e outros comportamentos de componente prontos para uso).\n- `app/page.tsx` renderiza marcação estilizada com classes `instui-*`; pontos de inserção opcionais (cabeçalho,\n filtros, conteúdo, final) são marcados com `<div data-slot=\"...\">`.\n\n## Saiba mais\n\nVeja o [guia de introdução](https://pantoken.app/guide/getting-started) para saber mais.\n" },
435
408
  "react": { "README.md": "# {{projectName}}\n\nUm app Vite + React estilizado com [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\ne [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), os tokens de design e ícones da\nInstructure.\n\n## Desenvolver\n\n```sh\nnpm install\nnpm run dev\n```\n\n## O que há aqui\n\n- `src/main.tsx` importa `@pantoken/css` (define cada propriedade customizada `--instui-*`) e\n `@pantoken/interactions` (configura comportamentos de modal, tooltip e outros componentes prontos para\n uso).\n- `src/App.tsx` renderiza markup estilizado com classes `instui-*`; pontos de inserção opcionais (header,\n filters, content, trailing) são marcados com `<div data-slot=\"...\">`.\n- Para a biblioteca completa de componentes React do InstUI (botões, modais, etc. — incluindo `@pantoken/react`'s\n `<Icon>`), adicione os pacotes específicos `@instructure/ui-*` que você precisa — consulte <https://instructure.design>.\n\n## Saiba mais\n\nConsulte o [guia de introdução](https://pantoken.app/guide/getting-started) para saber mais.\n" },
@@ -439,7 +412,6 @@ const SCAFFOLD_OVERLAYS = {
439
412
  },
440
413
  "pt-BR": {
441
414
  "angular": { "README.md": "# {{projectName}}\n\nUm aplicativo Angular independente (via Vite + `@analogjs/vite-plugin-angular`, sem Angular CLI) estilizado com\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) e\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (elementos personalizados pantoken\npara Angular).\n\n## Desenvolvimento\n\n```sh\nnpm install\nnpm run dev\n```\n\n## O que há aqui\n\n- `src/main.ts` chama `registerPantokenElements()` (de `@pantoken/angular`) uma vez no bootstrap para que\n elementos como `<instui-icon>` funcionem nos templates, e importa o CSS de tokens/componentes junto com\n `@pantoken/interactions` (configura modal, tooltip e outros comportamentos de componente prontos para uso).\n- `src/app.component.ts` é um componente independente (`CUSTOM_ELEMENTS_SCHEMA` permite que o compilador de templates\n aceite as tags de elementos personalizados do pantoken) cujo template é estilizado com classes `instui-*`;\n pontos de inserção opcionais (header, filters, content, trailing) são marcados com\n `<div data-slot=\"...\">`.\n- Aplique classes como `class=\"instui-button\"` à marcação; veja a\n [referência de componentes](https://pantoken.app/api/css) para a lista completa de classes.\n\n## Saiba mais\n\nVeja o [guia de início rápido](https://pantoken.app/guide/getting-started) para saber mais.\n" },
442
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nAtivos prontos para upload para o **Theme Editor** do Canvas LMS, mais uma pré-visualização local para autoria de modelos de página do Rich\nContent Editor (RCE) estilizados com\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## O que há aqui\n\n- `theme.css` / `theme.js` — envie esses dois arquivos em **Theme Editor → Advanced** no Canvas.\n Eles são construídos para o provedor CDN/theme/mode que você escolheu ao scaffoldar (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light por padrão) e incluem um loader para\n `@pantoken/interactions` (liga comportamentos de componente como modal, tooltip e drilldown).\n- `index.html` / `src/main.ts` — um editor local baseado em TinyMCE (`npm run dev`) que espelha o\n RCE do Canvas para que você possa criar modelos de página contra as classes do pantoken antes de copiá-los para o Canvas.\n A própria página é construída com o layout `wrapper` do pantoken: clique em **Edit theme** para abrir uma gaveta\n com as abas **Config** / **CSS** / **JS** (seletores de provedor CDN/theme/mode e cópias editáveis com realce de sintaxe,\n de `theme.css`/`theme.js` que alimentam a pré-visualização ao vivo), e o botão **?** para instruções completas. Use o botão **Layouts** na barra de ferramentas para começar a partir de um dos layouts iniciais empacotados do pantoken (hero, callout, duas colunas, nota de rubrica, depoimento), originados de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Desenvolvimento\n\n```sh\nnpm install\nnpm run dev\n```\n\nIsso abre um servidor de desenvolvimento Vite com:\n\n- Um painel **editor** (TinyMCE, combinando com a versão/configuração\n que o próprio [instructure/canvas-lms](https://github.com/instructure/canvas-lms) usa — veja abaixo).\n Use o botão **Layouts** para carregar um dos layouts iniciais empacotados (isso substitui o documento inteiro, após confirmação, em vez de inserir no cursor), e o alternador **Source code**\n para editar manualmente o HTML bruto em uma visão com realce de sintaxe (CodeMirror) ao lado do editor, com\n a pré-visualização atualizando ao vivo enquanto você digita — diferente do plugin `code` padrão do TinyMCE, que edita em\n um diálogo modal único sem pré-visualização ao vivo.\n- Um painel **preview** mostrando o conteúdo do editor com a folha de estilo/script da aba CSS/JS atual\n aplicada (não apenas as URLs CDN resolvidas), envolto para combinar com o próprio fundo da área de conteúdo do Canvas\n e largura máxima — uma verificação fiel de \"como isso ficará depois de enviado ao Canvas\", atualizada\n ao vivo enquanto você digita ou edita o tema.\n- Os painéis de editor e pré-visualização ficam em uma visualização dividida que você pode redimensionar arrastando o divisor, empilhar\n verticalmente em vez de lado a lado, e trocar a ordem (arraste a barra de ferramentas de um painel para o outro,\n ou use o botão **Swap panes**). Cada painel tem seu próprio botão de tela cheia.\n- A aba **Config** da gaveta **Edit theme** contém os seletores de provedor CDN/theme/mode e\n os links **Download theme.css** / **Download theme.js**; suas abas **CSS**/**JS** são cópias editáveis\n dos arquivos gerados — edite-as manualmente e a pré-visualização aplicará suas mudanças diretamente. Alterar\n um seletor de Config re-gerará as abas CSS/JS a menos que você já as tenha editado; nesse caso aparece um\n botão **Regenerate from config** em vez de sobrescrever silenciosamente sua edição.\n\n## Fluxo de trabalho\n\n1. Faça upload de `theme.css` e `theme.js` no Theme Editor do Canvas (**Advanced → CSS / JavaScript**) para que\n as classes do pantoken estejam disponíveis em todas as páginas.\n2. Execute `npm run dev`, use **Layouts** para começar a partir de um starter empacotado, e edite-o como faria\n no próprio RCE do Canvas.\n3. Clique em **Copy HTML** e cole o resultado no RCE de uma página do Canvas (troque para a visualização do editor HTML\n primeiro). O Canvas sanitiza o HTML colado no servidor — este scaffold não tenta replicar isso,\n então sempre verifique o resultado colado no Canvas (veja \"Notas sobre o RCE do Canvas\"\n abaixo).\n\n## Notas sobre o RCE do Canvas\n\nO Rich Content Editor do Canvas executa o TinyMCE e sanitiza o HTML submetido no servidor contra uma\nallowlist (`gems/canvas_sanitize` no canvas-lms, mantida em sincronia com as próprias\n`valid_elements`/`extended_valid_elements` do TinyMCE). O que essa allowlist significa para os templates construídos aqui:\n\n- Os atributos `class`, `id`, `style`, `title`, `role` e `aria-*` são permitidos em todo elemento —\n os ganchos de estilo `class=\"instui-*\"` do pantoken (e `style` inline, por exemplo para posicionamento de âncora em CSS)\n **sim** sobrevivem ao serem colados e salvos, ao contrário de orientações antigas neste arquivo. Tags `<script>`\n são sempre removidas.\n- **Componentes pantoken seguros para RCE**: componentes estáticos/de exibição — alert, view, heading, text, table,\n um botão como `<a>` (não um `<button>` real), blockquote. Use HTML semântico que o pantoken já\n suporta (`div`, `p`, `span`, `a`, `img`, headings, listas, tabelas).\n- **Não seguros para RCE**: qualquer coisa do conjunto de comportamentos de `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, ou qualquer outro componente dirigido pelos atributos nativos `popover`/`popovertarget`/\n `command`/`commandfor`. Esses atributos não estão na allowlist do sanitizador do Canvas, então\n a marcação sobrevive, mas o comportamento interativo quebra silenciosamente na primeira vez que a página é\n salva no Canvas, mesmo com o loader `@pantoken/interactions` do `theme.js` presente. Elementos de formulário reais\n (`input`, `form`, `button`, `select`, `textarea`, `label`) e `<svg>` inline são\n removidos completamente — nenhum dos templates iniciais empacotados os utiliza.\n\n`theme.js` carrega `@pantoken/interactions` da CDN, que roda no escopo global da página do Canvas —\nútil para interações em páginas que você constrói diretamente no RCE do Canvas com edições HTML brutas, mas (conforme\nacima) qualquer marcação dirigida por atributos `popover`/`command` colada da pré-visualização aqui não permanecerá\ninterativa depois de salva.\n" },
443
415
  "components": { "README.md": "# {{projectName}}\n\nUm aplicativo TypeScript simples (via Vite) estilizado com\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), tokens de design e ícones da Instructure.\n\n## Desenvolver\n\n```sh\nnpm install\nnpm run dev\n```\n\n## O que há aqui\n\n- `index.html` contém a marcação real da página — um shell de layout `wrapper` de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Veja o código-fonte\n e edite-o diretamente; nada é injetado pelo JavaScript.\n- `src/main.ts` importa `@pantoken/css` (define cada propriedade customizada `--instui-*`),\n `@pantoken/components/base.css` (padrões do documento + anel de foco), `components.css`\n (`.instui-*` classes), `@pantoken/interactions` (configura modal, tooltip e outros comportamentos de componente prontos para uso), e seu próprio `src/style.css` — adicione comportamento interativo aqui.\n- Pontos de inserção opcionais (cabeçalho, filtros, conteúdo, final) estão marcados com\n `<div data-slot=\"...\">` em `index.html` — substitua seus conteúdos pela sua própria marcação.\n- Aplique classes como `class=\"instui-button\"` à marcação; consulte a\n [referência de componentes](https://pantoken.app/api/css) para a lista completa de classes.\n\n## Saiba mais\n\nConsulte o [guia de HTML](https://pantoken.app/guide/components) para saber mais.\n" },
444
416
  "next": { "README.md": "# {{projectName}}\n\nUm aplicativo Next.js (App Router) estilizado com [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next), tokens de design e ícones da Instructure.\n\n## Desenvolvimento\n\n```sh\nnpm install\nnpm run dev\n```\n\n## O que há aqui\n\n- `next.config.mjs` envolve a configuração com `withPantoken(...)` (adiciona pantoken a `transpilePackages`).\n- `app/layout.tsx` importa `@pantoken/css`, que define todas as propriedades personalizadas `--instui-*` na raiz para que estejam disponíveis em cada página, além da classe raiz do layout `wrapper` em `<body>` e `PantokenInteractions` (um componente cliente que carrega `@pantoken/interactions` — conecta modal, tooltip e outros comportamentos de componente prontos para uso).\n- `app/page.tsx` renderiza marcação estilizada com classes `instui-*`; pontos de inserção opcionais (cabeçalho, filtros, conteúdo, final) são marcados com `<div data-slot=\"...\">`.\n\n## Saiba mais\n\nVeja o [guia de introdução](https://pantoken.app/guide/getting-started) para saber mais.\n" },
445
417
  "react": { "README.md": "# {{projectName}}\n\nUm app Vite + React estilizado com [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\ne [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), tokens de design e\nícones da Instructure.\n\n## Desenvolver\n\n```sh\nnpm install\nnpm run dev\n```\n\n## O que há aqui\n\n- `src/main.tsx` importa `@pantoken/css` (define todas as propriedades personalizadas `--instui-*`) e\n `@pantoken/interactions` (configura modal, tooltip e outros comportamentos de componente prontos para uso).\n- `src/App.tsx` renderiza marcação estilizada com classes `instui-*`; pontos de inserção opcionais (header,\n filters, content, trailing) estão marcados com `<div data-slot=\"...\">`.\n- Para a biblioteca completa de componentes React do InstUI (botões, modais, etc. — incluindo `@pantoken/react`'s\n `<Icon>`), adicione os pacotes `@instructure/ui-*` específicos que você precisa — veja <https://instructure.design>.\n\n## Saiba mais\n\nVeja o [guia de introdução](https://pantoken.app/guide/getting-started) para saber mais.\n" },
@@ -449,7 +421,6 @@ const SCAFFOLD_OVERLAYS = {
449
421
  },
450
422
  "ru": {
451
423
  "angular": { "README.md": "# {{projectName}}\n\nОтдельное приложение Angular (через Vite + `@analogjs/vite-plugin-angular`, без Angular CLI), оформленное с помощью\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) и\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (кастомные элементы pantoken\nдля Angular).\n\n## Разработка\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Что здесь\n\n- `src/main.ts` вызывает `registerPantokenElements()` (из `@pantoken/angular`) один раз при bootstrap, чтобы\n такие элементы, как `<instui-icon>`, работали в шаблонах, и импортирует CSS токенов/компонентов плюс\n `@pantoken/interactions` (подключает поведение модальных окон, всплывающих подсказок и других компонентов\n из коробки).\n- `src/app.component.ts` — это автономный компонент (`CUSTOM_ELEMENTS_SCHEMA` позволяет компилятору шаблонов\n принимать теги кастомных элементов pantoken), шаблон которого оформлен с помощью классов `instui-*`;\n опциональные точки вставки (header, filters, content, trailing) помечены с помощью\n `<div data-slot=\"...\">`.\n- Применяйте классы, такие как `class=\"instui-button\"`, к разметке; полный список классов см. в\n [справочнике по компонентам](https://pantoken.app/api/css).\n\n## Узнать больше\n\nСм. [руководство по началу работы](https://pantoken.app/guide/getting-started), чтобы узнать больше.\n" },
452
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nГотовые к загрузке ассеты для **Theme Editor** Canvas LMS, плюс локальный предпросмотр для создания шаблонов страниц Rich\nContent Editor (RCE), стилизованных с помощью\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Что здесь\n\n- `theme.css` / `theme.js` — загрузите эти два файла в **Theme Editor → Advanced** в Canvas.\n Они собраны для выбранного при scaffold CDN-провайдера/темы/режима (`--cdn`/`--theme`/\n `--theme-mode`; по умолчанию jsDelivr/rebrand/light) и включают загрузчик для\n `@pantoken/interactions` (подключает поведение компонентов, таких как modal, tooltip и drilldown).\n- `index.html` / `src/main.ts` — локальный редактор на базе TinyMCE (`npm run dev`), который повторяет RCE Canvas,\n чтобы можно было создавать шаблоны страниц с классами pantoken перед копированием их в Canvas.\n Сама страница построена с использованием макета pantoken `wrapper`: нажмите **Edit theme**, чтобы открыть панель\n с вкладками **Config** / **CSS** / **JS** (селекты CDN-провайдера/темы/режима и подсвечиваемые синтаксисом,\n редактируемые вручную копии `theme.css`/`theme.js`, которые питают живой предпросмотр), и кнопку **?**\n для полной инструкции. Используйте кнопку панели **Layouts**, чтобы начать с одного из включённых стартовых макетов\n страниц pantoken (hero, callout, two-column, rubric note, testimonial), источником которых является\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Разработка\n\n```sh\nnpm install\nnpm run dev\n```\n\nЭто запускает Vite dev сервер с:\n\n- Панелью **editor** (TinyMCE, совпадающей по версии/конфигурации с той, что используется в\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) — см. ниже).\n Используйте кнопку **Layouts**, чтобы загрузить один из встроенных стартовых макетов (это заменяет весь\n документ после подтверждения, а не вставляет в курсор), и переключатель **Source code**\n для ручного редактирования сырого HTML в представлении с подсветкой синтаксиса (CodeMirror) рядом с редактором, при этом\n панель предпросмотра обновляется в реальном времени по мере ввода — в отличие от стандартного плагина TinyMCE `code`,\n который редактирует в одноразовом модальном диалоге без живого предпросмотра.\n- Панель **preview**, показывающая содержимое редактора с применённой текущей таблицей стилей/скриптом из вкладки CSS/JS\n (не только срезанными CDN-URL), обёрнутое так, чтобы соответствовать фоновому цвету области контента и максимальной ширине Canvas — достоверная\n проверка «как это будет выглядеть после загрузки в Canvas», обновляемая в реальном времени по мере ввода или редактирования темы.\n- Редактор и панели предпросмотра размещены в разделённом представлении, размер которого можно изменить перетаскиванием разделителя; их можно\n сложить вертикально вместо боковой компоновки и поменять порядок (перетащив панельную панель инструмента на другую,\n или с помощью кнопки **Swap panes**). У каждой панели есть собственная кнопка полноэкранного режима.\n- В панели **Edit theme** вкладка **Config** содержит селекты CDN-провайдера/темы/режима и\n ссылки **Download theme.css** / **Download theme.js**; вкладки **CSS**/**JS** содержат редактируемые копии\n сгенерированных файлов — редактируйте их вручную, и предпросмотр немедленно отобразит изменения. Изменение селекта в Config\n повторно генерирует вкладки CSS/JS, если вы их ещё не редактировали; в противном случае появляется кнопка\n **Regenerate from config** вместо молчаливой перезаписи ваших правок.\n\n## Рабочий процесс\n\n1. Загрузите `theme.css` и `theme.js` в Theme Editor Canvas (**Advanced → CSS / JavaScript**), чтобы\n классы pantoken были доступны на каждой странице.\n2. Запустите `npm run dev`, используйте **Layouts**, чтобы начать с одного из встроенных стартовых макетов, и редактируйте его так же,\n как в собственном RCE Canvas.\n3. Нажмите **Copy HTML** и вставьте результат в RCE страницы Canvas (сначала переключитесь в режим HTML-редактора).\n Canvas выполняет серверную очистку вставляемого HTML — этот scaffold не пытается воспроизвести это, поэтому всегда проверяйте вставленный результат в Canvas (см. «Примечания по RCE Canvas» ниже).\n\n## Примечания по RCE Canvas\n\nRich Content Editor Canvas использует TinyMCE и очищает отправляемый HTML на сервере по белому списку (allowlist) (`gems/canvas_sanitize` в canvas-lms, синхронизированному с собственными\n`valid_elements`/`extended_valid_elements` TinyMCE). Что означает этот allowlist для шаблонов, созданных здесь:\n\n- Атрибуты `class`, `id`, `style`, `title`, `role` и `aria-*` разрешены для любого элемента —\n хуки стилизации pantoken `class=\"instui-*\"` (и inline `style`, напр. для позиционирования CSS-якорей)\n **в**ыживают при вставке и сохранении, в противоположность более старым указаниям в этом файле. Теги `<script>`\n всегда удаляются.\n- **Компоненты pantoken, безопасные для RCE**: статические/отображаемые компоненты — alert, view, heading, text, table,\n кнопка в виде `<a>` (не настоящий `<button>`), blockquote. Придерживайтесь семантического HTML, который pantoken уже\n поддерживает (`div`, `p`, `span`, `a`, `img`, заголовки, списки, таблицы).\n- **Небезопасно для RCE**: всё из набора поведений `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button или любой другой компонент, управляемый нативными атрибутами `popover`/`popovertarget`/\n `command`/`commandfor`. Эти атрибуты отсутствуют в списке разрешённых sanitizером Canvas, поэтому\n разметка сохраняется, но интерактивное поведение тихо ломается при первом сохранении страницы в Canvas, даже при наличии загрузчика `theme.js`'s `@pantoken/interactions`.\n Настоящие элементы форм (`input`, `form`, `button`, `select`, `textarea`, `label`) и inline `<svg>`\n полностью удаляются — ни один из включённых стартовых шаблонов их не использует.\n\n`theme.js` загружает `@pantoken/interactions` с CDN, который выполняется в глобальной области страницы Canvas —\nполезно для взаимодействий на страницах, которые вы создаёте непосредственно в RCE Canvas с сырыми HTML-правками, но (как указано выше) любая\nразметка, основанная на атрибутах `popover`/`command`, вставленная из превью RCE здесь, не останется интерактивной после сохранения.\n" },
453
424
  "components": { "README.md": "# {{projectName}}\n\nОбычное приложение на TypeScript (через Vite), оформленное с помощью\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), дизайн-токенов и иконок Instructure.\n\n## Разработка\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Что здесь\n\n- `index.html` содержит фактическую разметку страницы — оболочку макета `wrapper` от\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Просматривайте исходники\n и редактируйте их напрямую; ничего не вставляется JavaScript.\n- `src/main.ts` импортирует `@pantoken/css` (определяет каждое пользовательское свойство `--instui-*`),\n `@pantoken/components/base.css` (настройки документа по умолчанию + обводка фокуса), `components.css`\n (`.instui-*` классы), `@pantoken/interactions` (подключает модальные окна, тултипы и другие поведения компонентов «из коробки»),\n и ваш собственный `src/style.css` — добавьте здесь интерактивное поведение.\n- Опциональные точки вставки (шапка, фильтры, содержимое, хвост) помечены\n `<div data-slot=\"...\">` в `index.html` — замените их содержимое своей разметкой.\n- Применяйте классы вроде `class=\"instui-button\"` к разметке; полный список классов смотрите в\n [справочнике по компонентам](https://pantoken.app/api/css).\n\n## Узнать больше\n\nСм. [руководство по HTML](https://pantoken.app/guide/components) для получения дополнительной информации.\n" },
454
425
  "next": { "README.md": "# {{projectName}}\n\nПриложение Next.js (App Router), оформленное с помощью [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nдизайн-токенов и иконок Instructure.\n\n## Разработка\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Что здесь\n\n- `next.config.mjs` оборачивает конфигурацию с помощью `withPantoken(...)` (добавляет pantoken в\n `transpilePackages`).\n- `app/layout.tsx` импортирует `@pantoken/css`, который определяет каждое пользовательское\n свойство `--instui-*` в корне, чтобы оно было доступно на каждой странице, плюс корневой класс\n лейаута `wrapper` на `<body>` и `PantokenInteractions` (client-компонент, который загружает `@pantoken/interactions` —\n подключает модальные окна, подсказки и другие поведения компонентов из коробки).\n- `app/page.tsx` рендерит разметку, стилизованную классами `instui-*`; опциональные точки вставки (header,\n filters, content, trailing) отмечены `<div data-slot=\"...\">`.\n\n## Узнать больше\n\nСм. [руководство по началу работы](https://pantoken.app/guide/getting-started), чтобы узнать больше.\n" },
455
426
  "react": { "README.md": "# {{projectName}}\n\nVite + React приложение, стилизованное с помощью [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nи [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), дизайн-токенов и\nиконок Instructure.\n\n## Разработка\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Что здесь\n\n- `src/main.tsx` импортирует `@pantoken/css` (определяет каждое пользовательское свойство `--instui-*`) и\n `@pantoken/interactions` (подключает модальные окна, подсказки и другое поведение компонентов из коробки).\n- `src/App.tsx` рендерит разметку, стилизованную классами `instui-*`; опциональные точки вставки (заголовок,\n фильтры, контент, подвала) отмечены с помощью `<div data-slot=\"...\">`.\n- Для полной библиотеки React-компонентов InstUI (кнопки, модальные окна и т.д. — включая `@pantoken/react`'s\n `<Icon>`), добавьте нужные вам конкретные пакеты `@instructure/ui-*` — см. <https://instructure.design>.\n\n## Узнать больше\n\nСм. руководство «первый шаг» ([getting started guide](https://pantoken.app/guide/getting-started)), чтобы узнать больше.\n" },
@@ -459,7 +430,6 @@ const SCAFFOLD_OVERLAYS = {
459
430
  },
460
431
  "zh-Hans": {
461
432
  "angular": { "README.md": "# {{projectName}}\n\n一个独立的 Angular 应用程序(通过 Vite + `@analogjs/vite-plugin-angular`,无需 Angular CLI),使用\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) 和\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular)(pantoken 自定义元素用于 Angular)进行样式设置。\n\n## 开发\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 这里有什么\n\n- `src/main.ts` 在引导时调用 `registerPantokenElements()`(来自 `@pantoken/angular`)一次,以便 `<instui-icon>` 等元素在模板中工作,并导入令牌/组件 CSS 加上 `@pantoken/interactions`(开箱即用地连接模态、工具提示和其他组件行为)。\n- `src/app.component.ts` 是一个独立的组件(`CUSTOM_ELEMENTS_SCHEMA` 让模板编译器接受 pantoken 的自定义元素标签),其模板使用 `instui-*` 类进行样式设置;可选的插入点(header、filters、content、trailing)用 `<div data-slot=\"...\">` 标记。\n- 将类似 `class=\"instui-button\"` 的类应用于标记;请参阅 [组件参考](https://pantoken.app/api/css) 以获取完整的类列表。\n\n## 了解更多\n\n请参阅 [快速入门指南](https://pantoken.app/guide/getting-started) 了解更多信息。\n" },
462
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\n为Canvas LMS的**主题编辑器**提供上传就绪资产,同时提供本地预览用于编写使用[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)样式的富文本编辑器(RCE)页面模板。\n\n## 这里有什么\n\n- `theme.css` / `theme.js` — 在Canvas的**主题编辑器 → 高级**下上传这两个文件。它们针对您搭建时选择的CDN提供商/主题/模式(`--cdn`/`--theme`/`--theme-mode`;默认jsDelivr/rebrand/light)进行了构建,并包含`@pantoken/interactions`的加载器(连接模态框、提示框和钻取等组件行为)。\n- `index.html` / `src/main.ts` — 本地基于TinyMCE的编辑器(`npm run dev`),反映Canvas的RCE,以便您可以根据pantoken的类编写页面模板,然后再将其复制到Canvas中。该页面使用pantoken的`wrapper`布局构建:点击**编辑主题**打开一个托盘,其中有**配置** / **CSS** / **JS**选项卡(CDN提供商/主题/模式选择,以及`theme.css`/`theme.js`的语法突出显示、手工可编辑副本提供给实时预览),以及完整说明的**?**按钮。使用**布局**工具栏按钮从pantoken的捆绑入门页面布局之一开始(英雄、标注、两列、评分笔记、推荐),来自[`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts)。\n\n## 开发\n\n```sh\nnpm install\nnpm run dev\n```\n\n这打开一个Vite开发服务器,包括:\n\n- 一个**编辑器**窗格(TinyMCE,与[instructure/canvas-lms](https://github.com/instructure/canvas-lms)本身使用的版本/配置相匹配 — 见下文)。使用**布局**按钮加载一个捆绑的入门布局(这会在确认后替换整个文档,而不是在光标处插入),以及**源代码**切换在语法突出显示(CodeMirror)视图中手工编辑原始HTML(与编辑器并排),当您键入时预览窗格实时更新 — 与TinyMCE的库存`code`插件不同,后者在一次性模态对话框中编辑,没有实时预览。\n- 一个**预览**窗格显示编辑器的内容,其中应用了当前CSS/JS选项卡的样式表/脚本(不仅仅是已解析的CDN URL),包裹以匹配Canvas自己的内容区域背景和最大宽度 — 一个真实的\"这在上传到Canvas后会是什么样子\"检查,在您键入或编辑主题时实时更新。\n- 编辑器和预览窗格位于分割视图中,您可以通过拖动分隔线来调整大小,可以垂直堆叠而不是并排放置,并可以交换顺序(将窗格的工具栏拖到另一个上,或使用**交换窗格**按钮)。每个窗格都有自己的全屏按钮。\n- **编辑主题**托盘的**配置**选项卡包含CDN提供商/主题/模式选择和**下载theme.css** / **下载theme.js**链接;其**CSS**/**JS**选项卡是生成的文件的可编辑副本 — 手工编辑它们,预览会直接检测到您的更改。更改配置选择会重新生成CSS/JS选项卡,除非您已经编辑过它们,在这种情况下会出现**从配置重新生成**按钮而不是默认覆盖您的编辑。\n\n## 工作流\n\n1. 将`theme.css`和`theme.js`上传到Canvas的主题编辑器(**高级 → CSS / JavaScript**),以便pantoken的类在每个页面上可用。\n2. 运行`npm run dev`,使用**布局**从捆绑的入门页面开始,并像在Canvas的RCE中一样编辑它。\n3. 点击**复制HTML**并将结果粘贴到Canvas页面的RCE中(首先切换到HTML编辑器视图)。Canvas在服务器端针对允许列表清理粘贴的HTML — 此搭建不尝试复制此处理,因此始终在Canvas中验证粘贴的结果(参见下面的\"Canvas的RCE注释\")。\n\n## Canvas的RCE注释\n\nCanvas富文本编辑器运行TinyMCE并针对允许列表在服务器端清理提交的HTML(`gems/canvas_sanitize`在canvas-lms中,与TinyMCE自己的`valid_elements`/`extended_valid_elements`保持同步)。该允许列表对此处构建的模板的含义:\n\n- `class`、`id`、`style`、`title`、`role`和`aria-*`属性在每个元素上都被允许 — pantoken的`class=\"instui-*\"`样式钩子(和内联`style`,例如用于CSS锚点定位)**确实**在粘贴和保存时幸存,与此文件中的早期指导相反。`<script>`标签始终被剥离。\n- **RCE安全的pantoken组件**:静态/显示组件 — 警报、视图、标题、文本、表格、作为`<a>`的按钮(不是真正的`<button>`)、块引用。坚持pantoken已支持的语义HTML(`div`、`p`、`span`、`a`、`img`、标题、列表、表格)。\n- **RCE不安全**:来自`@pantoken/interactions`的行为集中的任何东西 — 模态框、提示框、钻取、关闭按钮或任何由原生`popover`/`popovertarget`/`command`/`commandfor`属性驱动的其他组件。这些属性不在Canvas的清理程序允许列表中,所以标记幸存但交互行为在第一次在Canvas中保存页面时默默中断,即使`theme.js`的`@pantoken/interactions`加载器存在。真正的表单元素(`input`、`form`、`button`、`select`、`textarea`、`label`)和内联`<svg>`被完全剥离 — 没有任何捆绑的入门模板使用它们。\n\n`theme.js`从CDN加载`@pantoken/interactions`,它在Canvas的全局页面范围内运行 — 对于您直接在Canvas的RCE中使用原始HTML编辑构建的页面上的交互很有用,但(如上所述)从此处RCE预览粘贴的任何`popover`/`command`属性驱动的标记一旦保存在Canvas中就不会保持交互。\n" },
463
433
  "components": { "README.md": "# {{projectName}}\n\n一个纯 TypeScript 应用(通过 Vite)使用\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)(Instructure 的\n设计标记和图标)进行样式化。\n\n## 开发\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 这里有什么\n\n- `index.html` 包含实际的页面标记——来自\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts) 的 `wrapper`-layout 壳。查看源代码并直接编辑;没有 JavaScript 注入的内容。\n- `src/main.ts` 导入 `@pantoken/css`(定义每个 `--instui-*` 自定义属性)、\n `@pantoken/components/base.css`(文档默认值 + 焦点环)、`components.css`\n (`.instui-*` 类)、`@pantoken/interactions`(开箱即用地配置模态框、工具提示和其他组件行为)以及您自己的 `src/style.css`——在此处添加交互行为。\n- 可选的插入点(header、filters、content、trailing)在 `index.html` 中用\n `<div data-slot=\"...\">` 标记——用您自己的标记替换它们的内容。\n- 将 `class=\"instui-button\"` 之类的类应用于标记;有关完整的类列表,请查看\n [组件参考](https://pantoken.app/api/css)。\n\n## 了解更多\n\n查看 [HTML 指南](https://pantoken.app/guide/components) 以了解更多信息。\n" },
464
434
  "next": { "README.md": "```markdown\n# {{projectName}}\n\n一个使用 [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next) 样式的 Next.js (App Router) 应用,Instructure 的设计令牌和图标。\n\n## 开发\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 这里的内容\n\n- `next.config.mjs` 使用 `withPantoken(...)` 包装配置(将 pantoken 添加到 `transpilePackages`)。\n- `app/layout.tsx` 导入 `@pantoken/css`,它在根目录定义每个 `--instui-*` 自定义属性,使其在每个页面上都可用,以及 `wrapper` 布局的根类在 `<body>` 和 `PantokenInteractions` 上(一个客户端组件,它加载 `@pantoken/interactions` — 立即连接模态框、工具提示和其他组件行为)。\n- `app/page.tsx` 呈现使用 `instui-*` 类样式的标记;可选插入点(header、filters、content、trailing)用 `<div data-slot=\"...\">` 标记。\n\n## 了解更多\n\n查看[入门指南](https://pantoken.app/guide/getting-started)了解更多。\n```\n" },
465
435
  "react": { "README.md": "# {{projectName}}\n\n一个使用 [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react) 和 [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css) 样式的 Vite + React 应用,Instructure 的设计令牌和图标。\n\n## 开发\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 这里有什么\n\n- `src/main.tsx` 导入 `@pantoken/css`(定义每个 `--instui-*` 自定义属性)和 `@pantoken/interactions`(开箱即用地连接模态框、工具提示和其他组件行为)。\n- `src/App.tsx` 渲染使用 `instui-*` 类样式的标记;可选的插入点(header、filters、content、trailing)用 `<div data-slot=\"...\">` 标记。\n- 对于 InstUI 的完整 React 组件库(按钮、模态框等——包括 `@pantoken/react` 的 `<Icon>`),添加你需要的特定 `@instructure/ui-*` 包——参见 <https://instructure.design>。\n\n## 了解更多\n\n查看[入门指南](https://pantoken.app/guide/getting-started)以了解更多。\n" },
@@ -469,7 +439,6 @@ const SCAFFOLD_OVERLAYS = {
469
439
  },
470
440
  "sl": {
471
441
  "angular": { "README.md": "# {{projectName}}\n\nSamostojna Angular aplikacija (prek Vite + `@analogjs/vite-plugin-angular`, brez Angular CLI), oblikovana z\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) in\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantokenova oblikovana HTML-oznaka za Angular).\n\n## Razvoj\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Kaj je tukaj\n\n- `src/main.ts` pokliče `registerPantokenElements()` (iz `@pantoken/angular`) enkrat ob zaganjanju, tako da elementi, kot je `<instui-icon>`, delujejo v predlogah, in uvozi CSS za tokene/komponente ter `@pantoken/interactions` (nastavi modal, tooltip in druge vedenjske funkcije komponent takoj iz škatle).\n- `src/app.component.ts` je samostojna komponenta (`CUSTOM_ELEMENTS_SCHEMA` omogoča prevajalniku predlog, da sprejme pantokenove oznake po meri), katere predloga je stilizirana s klasami `instui-*`; izbirna mesta za vstavljanje (header, filters, content, trailing) so označena z `<div data-slot=\"...\">`.\n- Uporabite razrede, kot je `class=\"instui-button\"`, na označbah; za celoten seznam razredov glejte\n [referenco komponent](https://pantoken.app/api/css).\n\n## Več informacij\n\nOglejte si [vodnik za začetek](https://pantoken.app/guide/getting-started), če želite več informacij.\n" },
472
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nPripravne za nalaganje sredstve za Canvas LMS-jev **Theme Editor**, plus lokalni predogled za ustvarjanje predlog strani Rich\nContent Editor (RCE) oblikovanih z\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Kaj je tukaj\n\n- `theme.css` / `theme.js` — naložite ti dve datoteki pod **Theme Editor → Advanced** v Canvasu.\n Zgrajeni so za CDN ponudnika/tema/način, ki ste ga izbrali med scaffoldanjem (`--cdn`/`--theme`/\n `--theme-mode`; privzeto jsDelivr/rebrand/light) in vključujejo loader za\n `@pantoken/interactions` (poveže vedenja komponent, kot so modal, tooltip in drilldown).\n- `index.html` / `src/main.ts` — lokalni TinyMCE-jev urejevalnik (`npm run dev`), ki odseva Canvasov\n RCE, zato lahko ustvarjate predloge strani proti pantokenovim razredom, preden jih kopirate v Canvas.\n Stran sama je zgrajena z pantokenovim `wrapper` layoutom: kliknite **Edit theme** za odpiranje stranskega\n panela z zavihki **Config** / **CSS** / **JS** (izbire CDN ponudnika/tema/način in sintaksično označene,\n ročno ureljive kopije `theme.css`/`theme.js`, ki poganjajo živ predogled), in gumb **?**\n za popolna navodila. Uporabite gumb orodne vrstice **Layouts** za začetek iz ene od pantokenovih vključenih\n začetnih postavitev strani (hero, callout, two-column, rubric note, testimonial), izvorno iz\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Razvoj\n\n```sh\nnpm install\nnpm run dev\n```\n\nTo odpre Vite dev strežnik z:\n\n- Panelom **editor** (TinyMCE, ustrezna različica/konfiguracija,\n ki jo uporablja [instructure/canvas-lms](https://github.com/instructure/canvas-lms) — glej spodaj).\n Uporabite gumb **Layouts** za nalaganje ene izmed vključenih začetnih postavitev (to nadomesti celoten\n dokument, po potrditvi, namesto vstavljanja na mesto kurzorja), in preklop **Source code** za ročno urejanje surovega HTML v sintaksično označenem (CodeMirror) pogledu ob urejevalniku, pri čemer se\n predogled posodablja v živo med tipkanjem — za razliko od TinyMCE-jevega privzetega `code` vtičnika, ki ureja v\n enkratnem modalnem oknu brez živega predogleda.\n- Panel **preview**, ki prikazuje vsebino urejevalnika z uporabo trenutnega sloga/skripte iz zavihka CSS/JS\n (ne le rešenih CDN URL-jev), zavito tako, da ustreza Canvasovemu ozadju območja vsebine\n in največji širini — zvesto \"kako bo to izgledalo, ko bo naloženo v Canvas\" preverjanje, posodobljeno\n v živo med tipkanjem ali urejanjem teme.\n- Urejevalnik in predogled sta v razdeljenem pogledu, ki ga lahko spreminjate z vlečenjem delilnika, jih zložite\n navpično namesto ob strani, in zamenjate vrstni red (povlecite orodno vrstico enega panela na drugega,\n ali uporabite gumb **Swap panes**). Vsak panel ima lasten gumb za celozaslonski način.\n- Stranski panel **Edit theme** zavihka **Config** vsebuje izbire CDN ponudnika/tema/način in\n povezave **Download theme.css** / **Download theme.js**; zavihka **CSS**/**JS** sta urejljivi kopiji\n generiranih datotek — urejajte jih ročno in predogled bo neposredno prevzel spremembe. Spreminjanje\n izbire v Config ponovno ustvari zavihka CSS/JS, razen če ste jih že ročno spreminjali, v tem primeru se namesto tihega prepisovanja prikaže gumb **Regenerate from config**.\n\n## Delovni tok\n\n1. Naložite `theme.css` in `theme.js` v Canvasov Theme Editor (**Advanced → CSS / JavaScript**), da so\n pantokenovi razredi na voljo na vsaki strani.\n2. Zaženite `npm run dev`, uporabite **Layouts** za začetek iz vključenega starterja in ga urejajte tako,\n kot bi v Canvasovem lastnem RCE.\n3. Kliknite **Copy HTML** in prilepite rezultat v RCE Canvas strani (najprej se preklopite v HTML urejevalnik).\n Canvas sanitizira prilepljen HTML strežno — ta scaffold tega ne poskuša\n posnemati, zato vedno preverite prilepljeni rezultat v Canvasu (glejte \"Opombe o Canvasovem RCE\"\n spodaj).\n\n## Opombe o Canvasovem RCE\n\nCanvas Rich Content Editor poganja TinyMCE in sanitizira posredovani HTML na strežniku glede na\ndovolilni seznam (`gems/canvas_sanitize` v canvas-lms, vzdrževan usklajen s TinyMCE-jevimi lastnimi\n`valid_elements`/`extended_valid_elements`). Kaj ta dovolilni seznam pomeni za predloge, zgrajene tukaj:\n\n- Atributi `class`, `id`, `style`, `title`, `role` in `aria-*` so dovoljeni na vsakem elementu —\n pantokenovi `class=\"instui-*\"` slogovni kljuki (in inline `style`, npr. za pozicioniranje CSS sidra)\n **preživijo** lepljenje in shranjevanje, v nasprotju s starejšimi navodili v tej datoteki. Oznake `<script>`\n se vedno odstranijo.\n- **RCE-varne pantoken komponente**: statične/prikazne komponente — alert, view, heading, text, table,\n gumb kot `<a>` (ne pravi `<button>`), blockquote. Držite se semantičnega HTML, ki ga pantoken že\n podpira (`div`, `p`, `span`, `a`, `img`, naslovi, seznami, tabele).\n- **RCE-nevarno**: karkoli iz vedenjskega nabora `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button ali katerakoli druga komponenta, ki jo poganjajo izvorni atributi `popover`/`popovertarget`/\n `command`/`commandfor`. Ti atributi niso na Canvasovem sanitizatorjevem dovolilnem seznamu, zato\n označba preživi, vendar se interaktivno vedenje tiho pokvari ob prvem shranjevanju strani v Canvasu, tudi če je prisoten\n `theme.js`-jev `@pantoken/interactions` loader. Pravi obrazni elementi (`input`, `form`, `button`, `select`, `textarea`, `label`) in inline `<svg>`\n so popolnoma odstranjeni — nobena izmed vključenih začetnih predlog tega ne uporablja.\n\n`theme.js` naloži `@pantoken/interactions` iz CDN, ki teče v globalnem obsegu strani Canvas —\nkoristno za interakcije na straneh, ki jih gradite neposredno v Canvasovem RCE z surovimi HTML urejanji, vendar (kot zgoraj)\nkatera koli označba, ki jo poganjajo atributi `popover`/`command` in je prilepljena iz RCE predogleda tukaj, ne bo ostala\ninteraktivna, ko bo enkrat shranjena.\n" },
473
442
  "components": { "README.md": "# {{projectName}}\n\nEnostavna aplikacija v TypeScriptu (prek Vite), stilizirana z\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructure-ovimi\ndesign tokeni in ikonami.\n\n## Razvoj\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Kaj je tu\n\n- `index.html` vsebuje dejansko označevanje strani — lupina z razporeditvijo `wrapper` iz\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Oglejte si izvorno kodo\n in jo uredite neposredno; JavaScript ničesar ne vstavi.\n- `src/main.ts` uvaža `@pantoken/css` (definira vse `--instui-*` prilagojene lastnosti),\n `@pantoken/components/base.css` (privzete nastavitve dokumenta + obroba fokusa), `components.css`\n (`.instui-*` razredi), `@pantoken/interactions` (samodejno poveže modal, tooltip in drugo vedenje komponent),\n in vaš lasten `src/style.css` — tukaj dodajte interaktivno vedenje.\n- Neobvezne vstavne točke (header, filters, content, trailing) so označene z\n `<div data-slot=\"...\">` v `index.html` — zamenjajte njihovo vsebino z lastnim označevanjem.\n- Uporabite razrede, kot je `class=\"instui-button\"`, pri označevanju; za celoten seznam razredov glejte\n [referenco komponent](https://pantoken.app/api/css).\n\n## Več informacij\n\nOglejte si [vodnik za HTML](https://pantoken.app/guide/components) za več informacij.\n" },
474
443
  "next": { "README.md": "# {{projectName}}\n\nNext.js (App Router) aplikacija, stilizirana z [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nInstructurejevi dizajn tokeni in ikone.\n\n## Razvoj\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Kaj je tukaj\n\n- `next.config.mjs` ovije konfiguracijo z `withPantoken(...)` (doda pantoken v\n `transpilePackages`).\n- `app/layout.tsx` uvaža `@pantoken/css`, ki definira vsako `--instui-*` po meri\n lastnost na korenu, tako da je na voljo na vsaki strani, ter korenski razred postavitve `wrapper` na\n `<body>` in `PantokenInteractions` (klientna komponenta, ki naloži `@pantoken/interactions` —\n takoj poveže modal, tooltip in druge vedenjske mehanizme komponent).\n- `app/page.tsx` upodobi markup, stiliziran z razredi `instui-*`; izbirne vstavne točke (glava,\n filtri, vsebina, zaključek) so označene z `<div data-slot=\"...\">`.\n\n## Več informacij\n\nOglejte si [vodnik za začetek](https://pantoken.app/guide/getting-started) za več informacij.\n" },
475
444
  "react": { "README.md": "# {{projectName}}\n\nVite + React aplikacija oblikovana z [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nin [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instructure-ovimi dizajnerskimi tokeni in\nikonami.\n\n## Razvoj\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Kaj je tukaj\n\n- `src/main.tsx` uvaža `@pantoken/css` (definira vse `--instui-*` CSS spremenljivke) in\n `@pantoken/interactions` (vključi modal, tooltip in drugo vedenje komponent pripravljeno za uporabo).\n- `src/App.tsx` upodobi markup, oblikovan z razredi `instui-*`; neobvezne točke vstavljanja (header,\n filters, content, trailing) so označene z `<div data-slot=\"...\">`.\n- Za celotno React komponentno knjižnico InstUI (gumbi, modali itd. — vključno z `@pantoken/react`'s\n `<Icon>`), dodajte konkretne `@instructure/ui-*` pakete, ki jih potrebujete — glej <https://instructure.design>.\n\n## Več\n\nOglejte si [vodič za začetek](https://pantoken.app/guide/getting-started) za več informacij.\n" },
@@ -479,7 +448,6 @@ const SCAFFOLD_OVERLAYS = {
479
448
  },
480
449
  "es": {
481
450
  "angular": { "README.md": "# {{projectName}}\n\nUna aplicación Angular independiente (vía Vite + `@analogjs/vite-plugin-angular`, sin Angular CLI) estilizada con\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) y\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (elementos personalizados de pantoken\npara Angular).\n\n## Desarrollar\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Qué hay aquí\n\n- `src/main.ts` llama a `registerPantokenElements()` (desde `@pantoken/angular`) una vez en el arranque para que\n elementos como `<instui-icon>` funcionen en las plantillas, e importa el CSS de tokens/componentes además de\n `@pantoken/interactions` (configura modal, tooltip y otros comportamientos de componentes listos para usar).\n- `src/app.component.ts` es un componente independiente (`CUSTOM_ELEMENTS_SCHEMA` permite que el compilador de plantillas\n acepte las etiquetas de elementos personalizados de pantoken) cuya plantilla está estilizada con clases `instui-*`;\n los puntos de inserción opcionales (header, filters, content, trailing) están marcados con\n `<div data-slot=\"...\">`.\n- Aplica clases como `class=\"instui-button\"` al marcado; consulta la\n [referencia de componentes](https://pantoken.app/api/css) para la lista completa de clases.\n\n## Aprende más\n\nConsulta la [guía de inicio](https://pantoken.app/guide/getting-started) para obtener más información.\n" },
482
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nActivos listos para subir para el **Editor de Tema** de Canvas LMS, más una vista previa local para crear plantillas de página del Rich\nContent Editor (RCE) estilizadas con\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Qué hay aquí\n\n- `theme.css` / `theme.js` — sube estos dos archivos en **Editor de Tema → Avanzado** en Canvas.\n Están construidos para el proveedor/theme/mode de CDN que elegiste al crear el scaffold (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light por defecto) e incluyen un cargador para\n `@pantoken/interactions` (conecta los comportamientos de los componentes como modal, tooltip y drilldown).\n- `index.html` / `src/main.ts` — un editor local basado en TinyMCE (`npm run dev`) que refleja el\n RCE de Canvas para que puedas crear plantillas de página usando las clases de pantoken antes de copiarlas a Canvas.\n La página en sí está construida con el layout `wrapper` de pantoken: haz clic en **Edit theme** para abrir una bandeja\n con pestañas **Config** / **CSS** / **JS** (selectores de proveedor/theme/mode del CDN, y copias editables con resaltado de sintaxis de\n `theme.css`/`theme.js` que alimentan la vista previa en vivo), y el botón **?** para instrucciones completas. Usa el botón de la barra de herramientas **Layouts** para empezar desde uno de los layouts de página incluidos de pantoken (hero, callout, two-column, rubric note, testimonial), extraídos de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Desarrollo\n\n```sh\nnpm install\nnpm run dev\n```\n\nEsto abre un servidor de desarrollo Vite con:\n\n- Un panel **editor** (TinyMCE, coincidiendo con la versión/config\n que usa [instructure/canvas-lms](https://github.com/instructure/canvas-lms) — ver abajo).\n Usa el botón **Layouts** para cargar uno de los layouts incluídos (esto reemplaza todo el\n documento, tras confirmar, en lugar de insertarlo en el cursor), y el conmutador **Source code**\n para editar manualmente el HTML crudo en una vista con resaltado de sintaxis (CodeMirror) junto al editor, con\n la vista previa actualizándose en vivo mientras escribes — a diferencia del plugin `code` de TinyMCE, que edita en\n un diálogo modal de una sola vez sin vista previa en vivo.\n- Un panel **preview** que muestra el contenido del editor con la hoja de estilos/script de la pestaña CSS/JS actual\n aplicada (no solo las URLs resueltas del CDN), envuelto para coincidir con el fondo del área de contenido y el ancho máximo de Canvas — una verificación fiel de \"cómo se verá esto una vez subido a Canvas\", actualizada\n en vivo mientras escribes o editas el tema.\n- Los paneles de editor y vista previa están en una vista dividida que puedes redimensionar arrastrando el divisor, apilar\n verticalmente en lugar de lado a lado, y cambiar el orden de ellos (arrastra la barra de herramientas de un panel sobre el otro,\n o usa el botón **Swap panes**). Cada panel tiene su propio botón de pantalla completa.\n- La bandeja **Edit theme** en su pestaña **Config** contiene los selectores de proveedor/theme/mode del CDN y\n los enlaces **Download theme.css** / **Download theme.js**; sus pestañas **CSS**/**JS** son copias editables\n de los archivos generados — edítalos a mano y la vista previa aplicará tus cambios directamente. Cambiar\n un selector de Config re-genera las pestañas CSS/JS a menos que ya las hayas editado, en cuyo caso aparece un\n botón **Regenerate from config** en lugar de sobrescribir silenciosamente tu edición.\n\n## Flujo de trabajo\n\n1. Sube `theme.css` y `theme.js` al Editor de Tema de Canvas (**Advanced → CSS / JavaScript**) para que\n las clases de pantoken estén disponibles en cada página.\n2. Ejecuta `npm run dev`, usa **Layouts** para empezar desde un starter incluido, y edítalo como lo harías\n en el propio RCE de Canvas.\n3. Haz clic en **Copy HTML** y pega el resultado en el RCE de una página de Canvas (primero cambia a la vista del editor HTML).\n Canvas sanitiza el HTML pegado del lado del servidor — este scaffold no intenta\n replicar eso, así que siempre verifica el resultado pegado en Canvas (ver \"Notas sobre el RCE de Canvas\"\n abajo).\n\n## Notas sobre el RCE de Canvas\n\nEl Rich Content Editor de Canvas ejecuta TinyMCE y sanitiza el HTML enviado en el servidor contra una\nlista permitida (`gems/canvas_sanitize` en canvas-lms, mantenida en sincronía con las propias\n`valid_elements`/`extended_valid_elements` de TinyMCE). Lo que esa lista permitida significa para las plantillas creadas aquí:\n\n- Los atributos `class`, `id`, `style`, `title`, `role` y `aria-*` están permitidos en cada elemento —\n los hooks de estilo `class=\"instui-*\"` de pantoken (y `style` en línea, p. ej. para posicionamiento de anclas en CSS)\n **sí** sobreviven al pegarse y guardarse, contrariamente a guías anteriores en este archivo. Las etiquetas `<script>`\n siempre se eliminan.\n- Componentes de pantoken seguros para RCE: componentes estáticos/visualización — alert, view, heading, text, table,\n un botón como `<a>` (no un verdadero `<button>`), blockquote. Mantener HTML semántico que pantoken ya\n soporta (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- No seguros para RCE: cualquier cosa del conjunto de comportamientos de `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, o cualquier otro componente impulsado por los atributos nativos `popover`/`popovertarget`/\n `command`/`commandfor`. Esos atributos no están en la lista permitida del sanitizador de Canvas, por lo que\n el marcado sobrevive pero el comportamiento interactivo se rompe silenciosamente la primera vez que la página se\n guarda en Canvas, aun con el cargador `@pantoken/interactions` de `theme.js` presente. Elementos de formulario reales\n (`input`, `form`, `button`, `select`, `textarea`, `label`) y `<svg>` en línea son\n eliminados por completo — ninguna de las plantillas starter incluidas los usa.\n\n`theme.js` carga `@pantoken/interactions` desde el CDN, que se ejecuta en el ámbito global de la página de Canvas —\nútil para interacciones en páginas que construyas directamente en el RCE de Canvas con ediciones HTML crudas, pero (como se indicó\narriba) cualquier marcado impulsado por atributos `popover`/`command` pegado desde la vista previa del RCE aquí no permanecerá\ninteractivo una vez guardado.\n" },
483
451
  "components": { "README.md": "# {{projectName}}\n\nUna aplicación TypeScript sencilla (vía Vite) con estilo usando\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), los tokens de diseño\ny los iconos de Instructure.\n\n## Desarrollar\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Qué hay aquí\n\n- `index.html` contiene el marcado real de la página — una estructura tipo `wrapper` de\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Ver el origen\n y editarlo directamente; nada es inyectado por JavaScript.\n- `src/main.ts` importa `@pantoken/css` (define cada propiedad personalizada `--instui-*`),\n `@pantoken/components/base.css` (valores por defecto del documento + anillo de foco), `components.css`\n (`.instui-*` clases), `@pantoken/interactions` (conecta modal, tooltip y otros comportamientos de componentes listos para usar), y tu propio `src/style.css` — añade comportamiento interactivo aquí.\n- Los puntos de inserción opcionales (encabezado, filtros, contenido, final) están marcados con\n `<div data-slot=\"...\">` en `index.html` — reemplaza su contenido con tu propio marcado.\n- Aplica clases como `class=\"instui-button\"` al marcado; consulta la\n [referencia de componentes](https://pantoken.app/api/css) para la lista completa de clases.\n\n## Aprende más\n\nConsulta la [guía de HTML](https://pantoken.app/guide/components) para obtener más información.\n" },
484
452
  "next": { "README.md": "# {{projectName}}\n\nUna aplicación Next.js (App Router) estilizada con [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nlos tokens de diseño e iconos de Instructure.\n\n## Desarrollar\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Qué hay aquí\n\n- `next.config.mjs` envuelve la configuración con `withPantoken(...)` (añade pantoken a\n `transpilePackages`).\n- `app/layout.tsx` importa `@pantoken/css`, que define cada propiedad personalizada `--instui-*`,\n en la raíz para que esté disponible en cada página, además de la clase raíz del diseño `wrapper` en\n `<body>` y `PantokenInteractions` (un componente del cliente que carga `@pantoken/interactions` —\n configura modal, tooltip y otros comportamientos de componentes listos para usar).\n- `app/page.tsx` renderiza marcado estilizado con clases `instui-*`; los puntos de inserción opcionales (header,\n filtros, contenido, final) están marcados con `<div data-slot=\"...\">`.\n\n## Más información\n\nConsulta la [guía de inicio](https://pantoken.app/guide/getting-started) para aprender más.\n" },
485
453
  "react": { "README.md": "# {{projectName}}\n\nUna aplicación Vite + React estilizada con [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\ny [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), los tokens de diseño y los iconos de Instructure.\n\n## Desarrollo\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Qué hay aquí\n\n- `src/main.tsx` importa `@pantoken/css` (define cada propiedad personalizada `--instui-*`) y\n `@pantoken/interactions` (configura modal, tooltip y otros comportamientos de componentes listos para usar).\n- `src/App.tsx` renderiza marcado estilizado con clases `instui-*`; puntos de inserción opcionales (header,\n filters, content, trailing) están marcados con `<div data-slot=\"...\">`.\n- Para la biblioteca completa de componentes React de InstUI (botones, modales, etc., incluyendo `@pantoken/react` de\n `<Icon>`), añade los paquetes `@instructure/ui-*` específicos que necesites — ver <https://instructure.design>.\n\n## Más información\n\nConsulte la [guía de inicio](https://pantoken.app/guide/getting-started) para obtener más información.\n" },
@@ -489,7 +457,6 @@ const SCAFFOLD_OVERLAYS = {
489
457
  },
490
458
  "sv": {
491
459
  "angular": { "README.md": "# {{projectName}}\n\nEn fristående Angular-app (via Vite + `@analogjs/vite-plugin-angular`, ingen Angular CLI) stylad med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) och\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (pantoken-anpassade element\nför Angular).\n\n## Utveckla\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Vad som finns här\n\n- `src/main.ts` anropar `registerPantokenElements()` (från `@pantoken/angular`) en gång vid bootstrap så\n att element som `<instui-icon>` fungerar i mallar, och importerar token-/komponent-CSS samt\n `@pantoken/interactions` (kopplar upp modal-, tooltip- och andra komponentbeteenden direkt).\n- `src/app.component.ts` är en fristående komponent (`CUSTOM_ELEMENTS_SCHEMA` låter mallkompilatorn\n acceptera pantokens anpassade elementtaggar) vars mall är stylad med `instui-*`\n klasser; valfria insättningspunkter (header, filters, content, trailing) markeras med\n `<div data-slot=\"...\">`.\n- Applicera klasser som `class=\"instui-button\"` på markup; se\n [komponentreferensen](https://pantoken.app/api/css) för hela klasslistan.\n\n## Lär dig mer\n\nSe [kom igång-guiden](https://pantoken.app/guide/getting-started) för att lära dig mer.\n" },
492
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nUppladdningsklara tillgångar för Canvas LMS:s **Theme Editor**, plus en lokal förhandsvisning för att skapa Rich\nContent Editor (RCE) sidmallar stylade med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Vad som finns här\n\n- `theme.css` / `theme.js` — ladda upp dessa två filer under **Theme Editor → Advanced** i Canvas.\n De är byggda för den CDN-leverantör/tema/läge du valde vid scaffolding (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light som standard) och inkluderar en loader för\n `@pantoken/interactions` (kopplar upp komponentbeteenden som modal, tooltip och drilldown).\n- `index.html` / `src/main.ts` — en lokal TinyMCE-baserad editor (`npm run dev`) som speglar Canvas's\n RCE så att du kan skapa sidmallar mot pantoken:s klasser innan du kopierar dem till Canvas.\n Sidan är byggd med pantoken:s `wrapper` layout: klicka **Edit theme** för att öppna en panel\n med **Config** / **CSS** / **JS** flikar (CDN-leverantör/tema/läge-val samt syntaxmarkerade,\n handredigerbara kopior av `theme.css`/`theme.js` som matar den live förhandsvisningen), och **?**-knappen\n för fullständiga instruktioner. Använd verktygsfältknappen **Layouts** för att starta från en av pantoken:s paketbundna\n startsidlayouter (hero, callout, tvåkolumn, rubric note, testimonial), hämtade från\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Utveckling\n\n```sh\nnpm install\nnpm run dev\n```\n\nDetta öppnar en Vite dev-server med:\n\n- En **editor**-ruta (TinyMCE, matchande version/konfiguration\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) själv använder — se nedan).\n Använd **Layouts**-knappen för att ladda en av de paketbundna startlayouterna (detta ersätter hela\n dokumentet, efter bekräftelse, istället för att infoga vid markören), och växeln **Source code**\n för att handredigera rå HTML i en syntaxmarkerad (CodeMirror) vy bredvid editorn, med\n förhandsvisningsrutan som uppdateras live medan du skriver — till skillnad från TinyMCE:s standard `code`-plugin, som redigerar i\n en engångs modal-dialog utan liveförhandsvisning.\n- En **preview**-ruta som visar editorinnehållet med den aktuella CSS/JS-flikens stylesheet/script\n applicerat (inte bara de uppslagna CDN-URL:erna), inramad för att matcha Canvas:s egen innehållsareas bakgrund\n och maxbredd — en trogen \"så här kommer det att se ut när det laddats upp till Canvas\"-kontroll, uppdaterad\n live medan du skriver eller redigerar temat.\n- Editor- och preview-rutorna sitter i en delad vy som du kan ändra storlek på genom att dra skiljelinjen, stapla\n vertikalt istället för sida vid sida, och byta ordning på dem (dra en ruts verktygsfält över den andra,\n eller använd knappen **Swap panes**). Varje ruta har sin egen helskärmsknapp.\n- **Edit theme**-panelens **Config**-flik innehåller CDN-leverantör/tema/läge-valen och\n länkarna **Download theme.css** / **Download theme.js**; dess **CSS**/**JS**-flikar är redigerbara kopior\n av de genererade filerna — handredigera dem och förhandsvisningen plockar upp dina ändringar direkt. Att ändra\n ett Config-val återgenererar CSS/JS-flikarna om du inte redan redigerat dem; i så fall visas en\n **Regenerate from config**-knapp istället för att tyst skriva över din redigering.\n\n## Arbetsflöde\n\n1. Ladda upp `theme.css` och `theme.js` till Canvas Theme Editor (**Advanced → CSS / JavaScript**) så att\n pantoken:s klasser finns tillgängliga på varje sida.\n2. Kör `npm run dev`, använd **Layouts** för att börja från en paketbunden start och redigera den som du\n skulle i Canvas:s egen RCE.\n3. Klicka **Copy HTML** och klistra in resultatet i en Canvas-sidas RCE (byt först till HTML-redigeraren).\n Canvas sanerar inklistrad HTML på serversidan — detta scaffold försöker inte replikera det, så verifiera alltid\n det inklistrade resultatet i Canvas (se \"Notes on Canvas's RCE\" nedan).\n\n## Anteckningar om Canvas's RCE\n\nCanvas Rich Content Editor kör TinyMCE och sanerar skickad HTML på servern mot en\nallowlist (`gems/canvas_sanitize` i canvas-lms, hålls synkad med TinyMCE:s egna\n`valid_elements`/`extended_valid_elements`). Vad den allowlisten betyder för mallar byggda här:\n\n- `class`, `id`, `style`, `title`, `role`, och `aria-*` attribut är tillåtna på alla element —\n pantoken:s `class=\"instui-*\"` stylingkrokar (och inline `style`, t.ex. för CSS-ankarpositionering)\n **överlever** att klistras in och sparas, till skillnad från äldre råd i denna fil. `<script>` taggar\n tas alltid bort.\n- **RCE-säkra pantoken-komponenter**: statiska/visningskomponenter — alert, view, heading, text, table,\n en knapp-som-`<a>` (inte en riktig `<button>`), blockquote. Håll dig till semantisk HTML som pantoken redan\n stöder (`div`, `p`, `span`, `a`, `img`, rubriker, listor, tabeller).\n- **RCE-osäkra**: allt från `@pantoken/interactions`'s beteendeset — modal, tooltip,\n drilldown, close-button, eller någon annan komponent driven av de inbyggda `popover`/`popovertarget`/\n `command`/`commandfor` attributen. Dessa attribut finns inte i Canvas:s sanitizer-allowlist, så\n markupen överlever men det interaktiva beteendet tyst bryts första gången sidan\n sparas i Canvas, även med `theme.js`'s `@pantoken/interactions` loader närvarande. Riktiga formulärelement\n (`input`, `form`, `button`, `select`, `textarea`, `label`) och inline `<svg>` tas\n bort helt — inga av de paketbundna startmallarna använder dem.\n\n`theme.js` laddar `@pantoken/interactions` från CDN:en, vilket körs i Canvas:s globala sidomfång —\nanvändbart för interaktioner på sidor du bygger direkt i Canvas's RCE med råa HTML-ändringar, men (enligt\novan) kommer någon `popover`/`command`-attributstyrd markup som klistras från RCE-förhandsvisningen här inte förbli\ninteraktiv när den väl sparats.\n" },
493
460
  "components": { "README.md": "# {{projectName}}\n\nEn enkel TypeScript-app (via Vite) stylad med\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructures\ndesign tokens och ikoner.\n\n## Utveckla\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Vad som finns här\n\n- `index.html` innehåller den faktiska sidans markup — en `wrapper`-layoutskalet från\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Visa källkoden\n och redigera den direkt; inget injiceras av JavaScript.\n- `src/main.ts` importerar `@pantoken/css` (definierar varje `--instui-*` custom property),\n `@pantoken/components/base.css` (dokumentstandarder + fokusring), `components.css`\n (`.instui-*`-klasser), `@pantoken/interactions` (kopplar upp modal, tooltip och andra komponent-\n beteenden direkt), och din egen `src/style.css` — lägg till interaktivt beteende här.\n- Valfria insättningspunkter (header, filters, content, trailing) är markerade med\n `<div data-slot=\"...\">` i `index.html` — ersätt deras innehåll med din egen markup.\n- Applicera klasser som `class=\"instui-button\"` på markup; se\n [komponentreferensen](https://pantoken.app/api/css) för fullständig klasslista.\n\n## Läs mer\n\nSe [HTML-guiden](https://pantoken.app/guide/components) för att lära dig mer.\n" },
494
461
  "next": { "README.md": "# {{projectName}}\n\nEn Next.js (App Router) -app stylad med [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nInstructures designtokens och ikoner.\n\n## Utveckling\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Vad som finns här\n\n- `next.config.mjs` wrappor konfigurationen med `withPantoken(...)` (lägger till pantoken till\n `transpilePackages`).\n- `app/layout.tsx` importerar `@pantoken/css`, som definierar varje `--instui-*` anpassad\n egenskap, i roten så att den är tillgänglig på varje sida, plus `wrapper` layoutens root-klass på\n `<body>` och `PantokenInteractions` (en klientkomponent som laddar `@pantoken/interactions` —\n kopplar upp modal, tooltip och andra komponentbeteenden direkt).\n- `app/page.tsx` renderar markup stylad med `instui-*` klasser; valfria insättningspunkter (header,\n filters, content, trailing) är markerade med `<div data-slot=\"...\">`.\n\n## Läs mer\n\nSe [getting started guide](https://pantoken.app/guide/getting-started) för att lära dig mer.\n" },
495
462
  "react": { "README.md": "# {{projectName}}\n\nEn Vite + React-app stylad med [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\noch [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), Instuctures design tokens och\nikoner.\n\n## Utveckla\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Vad som finns här\n\n- `src/main.tsx` importerar `@pantoken/css` (definierar varje `--instui-*` anpassad egenskap) och\n `@pantoken/interactions` (kopplar upp modal, tooltip och andra komponentbeteenden färdigt).\n- `src/App.tsx` renderar markup stylad med `instui-*` klasser; valfria insättningspunkter (header,\n filters, content, trailing) markeras med `<div data-slot=\"...\">`.\n- För InstUI:s fullständiga React-komponentbibliotek (knappar, modaler, etc. — inklusive `@pantoken/react`'s\n `<Icon>`), lägg till de specifika `@instructure/ui-*` paketen du behöver — se <https://instructure.design>.\n\n## Läs mer\n\nSe [kom igång-guiden](https://pantoken.app/guide/getting-started) för att lära dig mer.\n" },
@@ -499,7 +466,6 @@ const SCAFFOLD_OVERLAYS = {
499
466
  },
500
467
  "th": {
501
468
  "angular": { "README.md": "# {{projectName}}\n\nแอป Angular แบบสแตนด์อโลน (ผ่าน Vite + `@analogjs/vite-plugin-angular`, ไม่ใช้ Angular CLI) ตกแต่งด้วย\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) และ\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (องค์ประกอบกำหนดเองของ pantoken\nสำหรับ Angular)\n\n## พัฒนา\n\n```sh\nnpm install\nnpm run dev\n```\n\n## มีอะไรบ้าง\n\n- `src/main.ts` เรียก `registerPantokenElements()` (จาก `@pantoken/angular`) ครั้งเดียวเมื่อบูตสแตรป ทำให้\n องค์ประกอบอย่าง `<instui-icon>` ทำงานได้ในเทมเพลต และนำเข้า CSS ของโทเค็น/คอมโพเนนต์ รวมถึง\n `@pantoken/interactions` (เชื่อมต่อพฤติกรรมของ modal, tooltip และคอมโพเนนต์อื่นๆ ให้ทำงานได้ทันที)\n- `src/app.component.ts` เป็นคอมโพเนนต์แบบสแตนด์อโลน (`CUSTOM_ELEMENTS_SCHEMA` ทำให้คอมไพเลอร์เทมเพลต\n ยอมรับแท็กองค์ประกอบกำหนดเองของ pantoken) ซึ่งเทมเพลตถูกตกแต่งด้วยคลาสจาก `instui-*`;\n จุดแทรกที่เป็นทางเลือก (header, filters, content, trailing) ถูกทำเครื่องหมายด้วย\n `<div data-slot=\"...\">`.\n- นำคลาสเช่น `class=\"instui-button\"` ไปใช้กับมาร์กอัป; ดู\n [component reference](https://pantoken.app/api/css) สำหรับรายการคลาสทั้งหมด\n\n## เรียนรู้เพิ่มเติม\n\nดู [getting started guide](https://pantoken.app/guide/getting-started) เพื่อเรียนรู้เพิ่มเติม\n" },
502
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nแอสเซ็ตพร้อมอัปโหลดสำหรับ **Theme Editor** ของ Canvas LMS พร้อมตัวอย่างพรีวิวท้องถิ่นสำหรับการสร้างเทมเพลตหน้า Rich Content Editor (RCE) ที่ใช้สไตล์จาก\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## สิ่งที่มีในที่นี้\n\n- `theme.css` / `theme.js` — อัปโหลดสองไฟล์นี้ภายใต้ **Theme Editor → Advanced** ใน Canvas.\n ไฟล์เหล่านี้ถูกสร้างสำหรับผู้ให้บริการ CDN/ธีม/โหมดที่คุณเลือกตอนสร้างสโฟลด์ (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light ตามค่าดีฟอลต์) และรวม loader สำหรับ\n `@pantoken/interactions` (เชื่อมต่อพฤติกรรมคอมโพเนนต์เช่น modal, tooltip, และ drilldown).\n- `index.html` / `src/main.ts` — ตัวแก้ไขท้องถิ่นที่ใช้ TinyMCE (`npm run dev`) ซึ่งสะท้อน RCE ของ Canvas\n เพื่อให้คุณสามารถสร้างเทมเพลตหน้าด้วยคลาสของ pantoken ก่อนคัดลอกไปยัง Canvas.\n หน้าเพจถูกสร้างด้วยเลย์เอาต์ `wrapper` ของ pantoken: คลิก **Edit theme** เพื่อเปิดแถบด้านข้าง\n ที่มีแท็บ **Config** / **CSS** / **JS** (ตัวเลือกผู้ให้บริการ CDN/ธีม/โหมด และสำเนาที่เน้นไวยากรณ์และแก้ไขด้วยมือของ\n `theme.css`/`theme.js` ที่ป้อนเข้าสู่พรีวิวแบบสด) และปุ่ม **?** สำหรับคำแนะนำเต็มรูปแบบ ใช้ปุ่ม\n **Layouts** บนทูลบาร์เพื่อเริ่มจากหนึ่งในเลย์เอาต์เริ่มต้นที่มาพร้อมกับ pantoken (hero, callout, two-column, rubric note, testimonial)\n ไฟล์เหล่านี้มาจาก [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## พัฒนา\n\n```sh\nnpm install\nnpm run dev\n```\n\nคำสั่งนี้เปิดเซิร์ฟเวอร์ Vite dev ที่มี:\n\n- แผง **editor** (TinyMCE, ตรงกับเวอร์ชัน/การตั้งค่า\n ที่ [instructure/canvas-lms](https://github.com/instructure/canvas-lms) ใช้ — ดูด้านล่าง).\n ใช้ปุ่ม **Layouts** เพื่อโหลดหนึ่งในเลย์เอาต์เริ่มต้นที่รวมมา (จะแทนที่เอกสารทั้งหมดหลังจากยืนยัน แทนการแทรกที่ตำแหน่งเคอร์เซอร์),\n และสลับ **Source code** เพื่อแก้ไข HTML ดิบด้วยมือในมุมมองที่เน้นไวยากรณ์ (CodeMirror) ควบคู่กับตัวแก้ไข โดยพรีวิวจะอัปเดตสดขณะที่พิมพ์ — ต่างจากปลั๊กอิน `code` ของ TinyMCE ที่แก้ไขภายในโมดอลครั้งเดียวโดยไม่มีพรีวิวสด\n- แผง **preview** แสดงเนื้อหาจาก editor พร้อมสไตล์ชีต/สคริปต์จากแท็บ CSS/JS ปัจจุบัน (ไม่ใช่แค่ URL CDN ที่ถูกแก้ไขแล้ว) ห่อให้ตรงกับพื้นหลังพื้นที่เนื้อหาของ Canvas และความกว้างสูงสุด — เป็นการตรวจสอบว่า \"หน้าจะเป็นอย่างไรเมื่ออัปโหลดไปยัง Canvas\" อัปเดตสดขณะพิมพ์หรือแก้ไขธีม\n- แผง editor และ preview อยู่ในมุมมองแยกที่ปรับขนาดได้ด้วยการลากตัวแบ่ง สามารถจัดวางซ้อนตามแนวตั้งแทนที่จะวางข้างกัน และสลับลำดับของแผงได้ (ลากทูลบาร์ของแผงหนึ่งไปไว้บนอีกแผงหนึ่ง หรือใช้ปุ่ม **Swap panes**) แต่ละแผงมีปุ่มเต็มจอของตนเอง\n- แถบ **Edit theme** แท็บ **Config** เก็บตัวเลือกผู้ให้บริการ CDN/ธีม/โหมด และลิงก์ **Download theme.css** / **Download theme.js**; แท็บ **CSS**/**JS** เป็นสำเนาที่แก้ไขได้ของไฟล์ที่สร้าง — แก้ไขด้วยมือแล้วพรีวิวจะรับการเปลี่ยนแปลงโดยตรง การเปลี่ยนค่าใน Config จะสร้างแท็บ CSS/JS ใหม่อีกครั้ง เว้นแต่คุณจะแก้ไขพวกมันไปแล้ว ในกรณีนั้นจะมีปุ่ม **Regenerate from config** แทนการเขียนทับการแก้ไขอย่างเงียบๆ\n\n## เวิร์กโฟลว์\n\n1. อัปโหลด `theme.css` และ `theme.js` ไปยัง Theme Editor ของ Canvas (**Advanced → CSS / JavaScript**) เพื่อให้คลาสของ pantoken ใช้ได้บนทุกหน้า\n2. รัน `npm run dev`, ใช้ **Layouts** เพื่อเริ่มจากตัวอย่างที่รวมมา แล้วแก้ไขเหมือนที่คุณทำใน RCE ของ Canvas\n3. คลิก **Copy HTML** และวางผลลัพธ์ลงใน RCE ของหน้า Canvas (สลับไปมุมมองตัวแก้ไข HTML ก่อน). Canvas ทำการ sanitize HTML ที่วางเข้ามาทางฝั่งเซิร์ฟเวอร์ — scaffold นี้ไม่ได้พยายามจำลองพฤติกรรมนั้นทั้งหมด ดังนั้นให้ตรวจสอบผลลัพธ์หลังวางใน Canvas เสมอ (ดู \"หมายเหตุเกี่ยวกับ RCE ของ Canvas\" ด้านล่าง)\n\n## หมายเหตุเกี่ยวกับ RCE ของ Canvas\n\nRich Content Editor ของ Canvas ใช้ TinyMCE และทำการ sanitize HTML ที่ส่งไปยังเซิร์ฟเวอร์ตาม allowlist (`gems/canvas_sanitize` ใน canvas-lms ซึ่งซิงก์กับ\n`valid_elements`/`extended_valid_elements` ของ TinyMCE เอง). สิ่งที่ allowlist นี้หมายถึงสำหรับเทมเพลตที่สร้างที่นี่:\n\n- แอตทริบิวต์ `class`, `id`, `style`, `title`, `role`, และ `aria-*` ถูกอนุญาตบนทุกองค์ประกอบ —\n ฮุกการสไตลิงของ pantoken (`class=\"instui-*\"`) (และ `style` แบบ inline เช่น สำหรับการจัดตำแหน่ง anchor ใน CSS)\n **จะ** คงอยู่เมื่อทำการวางและบันทึก ตรงข้ามกับคำแนะนำเก่าในไฟล์นี้ แท็ก `<script>` จะถูกลบเสมอ\n- คอมโพเนนต์ pantoken ที่ปลอดภัยต่อ RCE: คอมโพเนนต์แบบสแตติก/แสดงผล — alert, view, heading, text, table,\n ปุ่มที่เป็น `<a>` (ไม่ใช่ `<button>` จริง), blockquote. ยึดตาม HTML เชิงความหมายที่ pantoken รองรับอยู่แล้ว (`div`, `p`, `span`, `a`, `img`, headings, lists, tables).\n- RCE-ไม่ปลอดภัย: ทุกอย่างจากชุดพฤติกรรมของ `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, หรือคอมโพเนนต์อื่นใดที่ขับเคลื่อนด้วยแอตทริบิวต์เนทีฟ `popover`/`popovertarget`/\n `command`/`commandfor`. แอตทริบิวต์เหล่านั้นไม่อยู่ใน allowlist ของ sanitizer ของ Canvas ดังนั้น\n มาร์กอัปอาจรอด แต่พฤติกรรมเชิงโต้ตอบจะหยุดทำงานอย่างเงียบๆ เมื่อหน้าถูกบันทึกครั้งแรกใน Canvas แม้จะมี loader ของ `theme.js`'s `@pantoken/interactions` อยู่ก็ตาม. องค์ประกอบฟอร์มจริง (`input`, `form`, `button`, `select`, `textarea`, `label`) และ `<svg>` แบบ inline ถูกลบทิ้งโดยสิ้นเชิง — ไม่มีเทมเพลตเริ่มต้นที่รวมมาใช้พวกนี้\n\n`theme.js` โหลด `@pantoken/interactions` จาก CDN ซึ่งรันในสโคปหน้าระดับโกลบอลของ Canvas —\nมีประโยชน์สำหรับการโต้ตอบบนหน้าที่สร้างโดยตรงใน RCE ของ Canvas ด้วยการแก้ไข HTML ดิบ แต่ (ตามที่กล่าวข้างต้น) มาร์กอัปที่ขับเคลื่อนด้วยแอตทริบิวต์ `popover`/`command` ที่วางมาจากพรีวิว RCE ที่นี่จะไม่คงสภาพเป็นเชิงโต้ตอบหลังจากบันทึกใน Canvas.\n" },
503
469
  "components": { "README.md": "# {{projectName}}\n\nแอป TypeScript แบบเรียบง่าย (ผ่าน Vite) ที่มีสไตลิ่งด้วย\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) โทเค็นการออกแบบและไอคอนของ Instructure\n\n## พัฒนา\n\n```sh\nnpm install\nnpm run dev\n```\n\n## สิ่งที่มีอยู่ที่นี่\n\n- `index.html` เก็บมาร์กอัปหน้าจริง — เชลล์เลย์เอาต์แบบ `wrapper` จาก\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts) ดูซอร์สและแก้ไขโดยตรง; ไม่มีอะไรถูกฉีดโดย JavaScript\n- `src/main.ts` นำเข้า `@pantoken/css` (กำหนดทุก `--instui-*` property แบบกำหนดเอง),\n `@pantoken/components/base.css` (ค่าเริ่มต้นของเอกสาร + focus ring), `components.css`\n (คลาส `.instui-*`), `@pantoken/interactions` (เชื่อมต่อ modal, tooltip และพฤติกรรมของคอมโพเนนต์อื่นๆ ให้ใช้งานได้ทันที), และ `src/style.css` ของคุณเอง — เพิ่มพฤติกรรมเชิงโต้ตอบที่นี่\n- จุดแทรกที่เป็นทางเลือก (header, filters, content, trailing) ถูกทำเครื่องหมายด้วย\n `<div data-slot=\"...\">` ใน `index.html` — แทนที่เนื้อหาของพวกมันด้วยมาร์กอัปของคุณเอง\n- ใช้คลาสเช่น `class=\"instui-button\"` กับมาร์กอัป; ดู\n [เอกสารอ้างอิงคอมโพเนนต์](https://pantoken.app/api/css) สำหรับรายการคลาสทั้งหมด\n\n## เรียนรู้เพิ่มเติม\n\nดู [คู่มือ HTML](https://pantoken.app/guide/components) เพื่อเรียนรู้เพิ่มเติม\n" },
504
470
  "next": { "README.md": "# {{projectName}}\n\nแอป Next.js (App Router) ที่ตกแต่งด้วย [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\ntoken และไอคอนการออกแบบของ Instructure\n\n## พัฒนา\n\n```sh\nnpm install\nnpm run dev\n```\n\n## สิ่งที่อยู่ที่นี่\n\n- `next.config.mjs` ห่อการตั้งค่าด้วย `withPantoken(...)` (เพิ่ม pantoken ไปยัง\n `transpilePackages`).\n- `app/layout.tsx` นำเข้า `@pantoken/css` ซึ่งกำหนดทุก `--instui-*` custom\n property ที่ระดับรากเพื่อให้ใช้งานได้บนทุกหน้า รวมถึงคลาส root ของเลย์เอาต์ `wrapper` บน\n `<body>` และ `PantokenInteractions` (คอมโพเนนต์ฝั่งไคลเอนต์ที่โหลด `@pantoken/interactions` —\n เชื่อมพฤติกรรมของคอมโพเนนต์เช่น modal, tooltip และอื่น ๆ โดยอัตโนมัติ).\n- `app/page.tsx` เรนเดอร์มาร์กอัปที่มีสไตล์ด้วยคลาส `instui-*`; จุดแทรกแบบเลือกได้ (header,\n filters, content, trailing) ถูกทำเครื่องหมายด้วย `<div data-slot=\"...\">`.\n\n## เรียนรู้เพิ่มเติม\n\nดู [getting started guide](https://pantoken.app/guide/getting-started) เพื่อเรียนรู้เพิ่มเติม.\n" },
505
471
  "react": { "README.md": "# {{projectName}}\n\nแอป Vite + React ที่จัดสไตล์ด้วย [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nและ [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css) โทเค็นการออกแบบและไอคอนของ Instructure\n\n## การพัฒนา\n\n```sh\nnpm install\nnpm run dev\n```\n\n## สิ่งที่มีอยู่ที่นี่\n\n- `src/main.tsx` นำเข้า `@pantoken/css` (กำหนดทุกคุณสมบัติแบบกำหนดเองของ `--instui-*`) และ\n `@pantoken/interactions` (เชื่อมต่อ modal, tooltip และพฤติกรรมของคอมโพเนนต์อื่น ๆ ที่พร้อมใช้งาน)\n- `src/App.tsx` เรนเดอร์มาร์กอัปที่จัดสไตล์ด้วยคลาสของ `instui-*`; จุดแทรกแบบออปชัน (header,\n filters, content, trailing) ถูกทำเครื่องหมายด้วย `<div data-slot=\"...\">`\n- สำหรับไลบรารีคอมโพเนนต์ React ของ InstUI รุ่นเต็ม (ปุ่ม, โมดอล เป็นต้น — รวมถึง `@pantoken/react`'s\n `<Icon>`) ให้เพิ่มแพ็กเกจ `@instructure/ui-*` เฉพาะที่คุณต้องการ — ดูที่ <https://instructure.design>\n\n## เรียนรู้เพิ่มเติม\n\nดู [คู่มือเริ่มต้นใช้งาน](https://pantoken.app/guide/getting-started) เพื่อเรียนรู้เพิ่มเติม\n" },
@@ -509,7 +475,6 @@ const SCAFFOLD_OVERLAYS = {
509
475
  },
510
476
  "zh-Hant": {
511
477
  "angular": { "README.md": "# {{projectName}}\n\n獨立的 Angular 應用程式(透過 Vite + `@analogjs/vite-plugin-angular`,無需 Angular CLI)使用\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) 和\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular)(Angular 的 pantoken 自訂元素)\n進行樣式設定。\n\n## 開發\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 此處包含內容\n\n- `src/main.ts` 在啟動時呼叫 `registerPantokenElements()`(來自 `@pantoken/angular`)一次,使得\n `<instui-icon>` 等元素在樣板中運作,並匯入 token/component CSS 以及\n `@pantoken/interactions`(開箱即用地配置模態、工具提示和其他元件行為)。\n- `src/app.component.ts` 是獨立元件(`CUSTOM_ELEMENTS_SCHEMA` 讓樣板\n 編譯器接受 pantoken 的自訂元素標籤),其樣板使用 `instui-*`\n 類別進行樣式設定;可選的插入點(標題、篩選器、內容、尾部)使用\n `<div data-slot=\"...\">` 標記。\n- 將類別如 `class=\"instui-button\"` 套用至標記;請參閱\n [元件參考](https://pantoken.app/api/css)以取得完整的類別清單。\n\n## 了解更多\n\n請參閱[快速入門指南](https://pantoken.app/guide/getting-started)以了解更多。\n" },
512
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\n可上傳到 Canvas LMS 的主題編輯器 (Theme Editor) 的資產,以及可供撰寫以\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) 樣式化的 Rich\nContent Editor (RCE) 頁面範本之本機預覽。\n\n## 內容\n\n- `theme.css` / `theme.js` — 在 Canvas 的 **Theme Editor → Advanced** 底下上傳這兩個檔案。\n 它們是為您在 scaffold 時選擇的 CDN provider/theme/mode 所建置的(`--cdn`/`--theme`/`--theme-mode`;\n 預設為 jsDelivr/rebrand/light),並包含一個為 `@pantoken/interactions` 的載入器(用來接線元件行為,例如 modal、tooltip、drilldown)。\n- `index.html` / `src/main.ts` — 一個本機的 TinyMCE 為基礎的編輯器(`npm run dev`),模擬 Canvas 的\n RCE,讓您在將內容貼入 Canvas 之前,先針對 pantoken 的類別撰寫頁面範本。\n 該頁面使用 pantoken 的 `wrapper` 版面構成:點選 **Edit theme** 可開啟一個含有 **Config** / **CSS** / **JS** 分頁的抽屜\n (供選擇 CDN provider/theme/mode,並提供語法高亮、可手動編輯的 `theme.css`/`theme.js` 副本以供即時預覽使用),以及提供完整說明的 **?** 按鈕。\n 使用 **Layouts** 工具列按鈕可從 pantoken 捆綁的起始頁面版型 (hero、callout、two-column、rubric note、testimonial) 開始,\n 這些版型來自 [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts)。\n\n## 開發\n\n```sh\nnpm install\nnpm run dev\n```\n\n這會啟動一個 Vite 開發伺服器,提供:\n\n- 一個 **editor** 欄(TinyMCE,使用與\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) 本身相同的版本/設定 — 詳見下文)。\n 使用 **Layouts** 按鈕可載入捆綁的起始版型之一(載入時會詢問確認,會取代整個文件,而非插入游標位置),並可使用 **Source code** 切換在語法高亮(CodeMirror)檢視中手動編輯原始 HTML,且預覽窗格會隨輸入即時更新 — 這不同於 TinyMCE 的內建 `code` 外掛(該外掛以一次性 modal 對話方塊編輯且沒有即時預覽)。\n- 一個 **preview** 欄,顯示套用了目前 CSS/JS 分頁樣式表/腳本的編輯器內容(不只是解析後的 CDN URL),並包裝成與 Canvas 自身內容區背景與最大寬度相符 — 可忠實檢查「上傳到 Canvas 後的呈現」,且會在您輸入或編輯主題時即時更新。\n- 編輯器與預覽窗格位於可拖曳分隔線調整大小的分割視圖中,可改為垂直堆疊而非並排,並能交換窗格順序(將某窗格的工具列拖到另一窗格上,或使用 **Swap panes** 按鈕)。每個窗格都有自己的全螢幕按鈕。\n- **Edit theme** 抽屜的 **Config** 分頁包含 CDN provider/theme/mode 的選擇以及 **Download theme.css** / **Download theme.js** 鏈結;其 **CSS**/**JS** 分頁是產生檔案的可編輯副本 — 手動編輯它們後預覽會直接套用變更。更改 Config 選項會重新產生 CSS/JS 分頁,除非您已手動編輯過該分頁,這時會顯示 **Regenerate from config** 按鈕以避免默默覆寫您的編輯。\n\n## 工作流程\n\n1. 將 `theme.css` 與 `theme.js` 上傳到 Canvas 的 Theme Editor(**Advanced → CSS / JavaScript**),以便 pantoken 的類別在每個頁面上可用。\n2. 執行 `npm run dev`,使用 **Layouts** 從捆綁的起始版型開始,並像在 Canvas 的 RCE 中一樣編輯。\n3. 點選 **Copy HTML**,然後將結果貼到 Canvas 頁面的 RCE(先切換到 HTML 編輯器檢視)。Canvas 會在伺服器端淨化貼上的 HTML — 此 scaffold 不試圖複製該行為,因此務必在 Canvas 中驗證貼上的結果(見下方「關於 Canvas RCE 的說明」)。\n\n## 關於 Canvas 的 RCE\n\nCanvas 的 Rich Content Editor 使用 TinyMCE,並在伺服器端以允許清單(allowlist)(canvas-lms 中的 `gems/canvas_sanitize`,與 TinyMCE 自身的 `valid_elements`/`extended_valid_elements` 保持同步)來淨化提交的 HTML。這個允許清單對於在此處建立的範本意味著:\n\n- `class`、`id`、`style`、`title`、`role` 和 `aria-*` 屬性在每個元素上都被允許 — pantoken 的 `class=\"instui-*\"` 樣式掛鉤(以及內聯的 `style`,例如用於 CSS 錨點定位)\n **會** 在貼上並儲存後存活,這與本檔案先前較舊的指引不同。`<script>` 標籤則會被移除。\n- **RCE 安全的 pantoken 元件**:靜態/顯示型元件 — alert、view、heading、text、table、以 `<a>` 呈現的按鈕(不是實際的 `<button>`)、blockquote。請堅持使用 pantoken 已支援的語義性 HTML(`div`、`p`、`span`、`a`、`img`、標題、列表、表格)。\n- **RCE 不安全**:來自 `@pantoken/interactions` 的行為集合中的任何項目 — modal、tooltip、drilldown、close-button 或任何由原生 `popover`/`popovertarget`/`command`/`commandfor` 屬性驅動的元件。那些屬性不在 Canvas 的淨化允許清單中,因此標記雖然會存留,但互動行為在頁面第一次於 Canvas 儲存時就會靜默失效,即便存在 `theme.js` 的 `@pantoken/interactions` 載入器也同樣如此。真實的表單元素(`input`、`form`、`button`、`select`、`textarea`、`label`)以及內聯的 `<svg>` 會被直接移除 — 捆綁的起始範本中沒有使用它們。\n\n`theme.js` 從 CDN 載入 `@pantoken/interactions`,它在 Canvas 的全域頁面範圍中執行 — 對於您直接在 Canvas 的 RCE 使用原始 HTML 編輯並需要互動行為的頁面很有用,但(如上所述)由此處 RCE 預覽貼上的任何依賴 `popover`/`command` 屬性的標記,一旦在 Canvas 中儲存後就不會保持互動性。\n" },
513
478
  "components": { "README.md": "# {{projectName}}\n\n一個使用 Vite 的純 TypeScript 應用程式,使用\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)(Instructure 的設計令牌和圖示)進行樣式設定。\n\n## 開發\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 這裡有什麼\n\n- `index.html` 包含實際的頁面標記 — 來自\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts) 的 `wrapper` 佈局 shell。查看源代碼並直接編輯它;JavaScript 沒有注入任何內容。\n- `src/main.ts` 導入 `@pantoken/css`(定義每個 `--instui-*` 自訂屬性),\n `@pantoken/components/base.css`(文件預設值 + 焦點環),`components.css`\n (`.instui-*` 類別),`@pantoken/interactions`(直接接線 modal、tooltip 和其他元件行為),以及您自己的 `src/style.css` — 在此處添加互動行為。\n- 可選的插入點(header、filters、content、trailing)在 `index.html` 中以 `<div data-slot=\"...\">` 標記 — 用您自己的標記替換其內容。\n- 應用類別如 `class=\"instui-button\"` 至標記;請參閱\n [元件參考](https://pantoken.app/api/css) 以獲得完整的類別列表。\n\n## 深入了解\n\n請參閱 [HTML 指南](https://pantoken.app/guide/components) 以深入了解。\n" },
514
479
  "next": { "README.md": "# {{projectName}}\n\n使用 [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next) 樣式化的 Next.js(App Router)應用程式,Instructure 的設計代幣和圖標。\n\n## 開發\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 這裡有什麼\n\n- `next.config.mjs` 使用 `withPantoken(...)` 包裝配置(將 pantoken 新增至 `transpilePackages`)。\n- `app/layout.tsx` 匯入 `@pantoken/css`,其定義每個 `--instui-*` 自訂屬性在根處,以便在每個頁面上都可用,加上 `<body>` 和 `PantokenInteractions` 上的 `wrapper` 版面配置根類(一個載入 `@pantoken/interactions` 的客戶端元件——開箱即用地設定模態、工具提示和其他元件行為)。\n- `app/page.tsx` 呈現使用 `instui-*` 類別樣式化的標記;可選插入點(header、filters、content、trailing)使用 `<div data-slot=\"...\">` 標記。\n\n## 進一步了解\n\n請參閱[入門指南](https://pantoken.app/guide/getting-started)以深入了解。\n" },
515
480
  "react": { "README.md": "# {{projectName}}\n\n一個使用 [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react) 和 [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css) 樣式化的 Vite + React 應用,Instructure 的設計代幣和圖標。\n\n## 開發\n\n```sh\nnpm install\nnpm run dev\n```\n\n## 這裡有什麼\n\n- `src/main.tsx` 導入 `@pantoken/css`(定義每個 `--instui-*` 自訂屬性)和 `@pantoken/interactions`(直接連接 modal、tooltip 和其他元件行為)。\n- `src/App.tsx` 使用 `instui-*` 類別呈現樣式化的標記;選用的插入點(header、filters、content、trailing)標記為 `<div data-slot=\"...\">`。\n- 對於 InstUI 的完整 React 元件庫(按鈕、modals 等——包括 `@pantoken/react` 的 `<Icon>`),添加您需要的特定 `@instructure/ui-*` 套件——請參閱 <https://instructure.design>。\n\n## 了解更多\n\n請參閱[入門指南](https://pantoken.app/guide/getting-started)以了解更多信息。\n" },
@@ -519,7 +484,6 @@ const SCAFFOLD_OVERLAYS = {
519
484
  },
520
485
  "tr": {
521
486
  "angular": { "README.md": "# {{projectName}}\n\nVite + `@analogjs/vite-plugin-angular` ile oluşturulmuş bağımsız bir Angular uygulaması (Angular CLI yok) ve\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) ile\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (Angular için pantoken özel öğeleri) tarafından stil verilmiştir.\n\n## Geliştirme\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Burada neler var\n\n- `src/main.ts` başlatmada bir kez `registerPantokenElements()` ( `@pantoken/angular`'ten) çağırır, böylece\n `<instui-icon>` gibi öğeler şablonlarda çalışır ve token/component CSS ile birlikte\n `@pantoken/interactions`'i içe aktarır (kutudan çıkan modal, tooltip ve diğer bileşen davranışlarını etkinleştirir).\n- `src/app.component.ts` bağımsız bir bileşendir (`CUSTOM_ELEMENTS_SCHEMA` şablon derleyicisinin\n pantoken'ın özel öğe etiketlerini kabul etmesine izin verir) ve şablonu `instui-*`\n sınıflarıyla stil verilmiştir; isteğe bağlı ekleme noktaları (başlık, filtreler, içerik, son) `<div data-slot=\"...\">`\n ile işaretlenmiştir.\n- İşaretlemeye `class=\"instui-button\"` gibi sınıflar uygulayın; tam sınıf listesi için\n [bileşen referansına](https://pantoken.app/api/css) bakın.\n\n## Daha fazlasını öğrenin\n\nDaha fazlasını öğrenmek için [başlarken kılavuzuna](https://pantoken.app/guide/getting-started) bakın.\n" },
522
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nCanvas LMS'nin **Tema Düzenleyicisi** için yüklemeye hazır varlıklar ve Rich Content Editor (RCE) sayfa şablonlarını\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) ile stillendirerek oluşturmak için yerel bir önizleme.\n\n## Burada neler var\n\n- `theme.css` / `theme.js` — bu iki dosyayı Canvas'ta **Theme Editor → Advanced** altına yükleyin.\n Bunlar scaffolding sırasında seçtiğiniz CDN sağlayıcı/tema/mod için derlenir (`--cdn`/`--theme`/\n `--theme-mode`; varsayılan jsDelivr/rebrand/light) ve `@pantoken/interactions` için bir yükleyici içerir\n (modal, tooltip ve drilldown gibi bileşen davranışlarını bağlar).\n- `index.html` / `src/main.ts` — Canvas'ın RCE'sini yansıtan yerel, TinyMCE tabanlı bir düzenleyici (`npm run dev`) — böylece pantoken'ın sınıflarına göre sayfa şablonları oluşturup bunları Canvas'a kopyalayabilirsiniz.\n Sayfa kendisi pantoken'ın `wrapper` düzeniyle oluşturulmuştur: tepsiyi açmak için **Edit theme**e tıklayın;\n içinde **Config** / **CSS** / **JS** sekmeleri (CDN sağlayıcı/tema/mod seçimleri ve canlı önizlemeyi besleyen,\n sözdizimi vurgulanmış, elle düzenlenebilir `theme.css`/`theme.js` kopyaları) ve tam talimatlar için **?** düğmesi bulunur. Başlangıç sayfa düzenlerine (hero, callout, iki sütun, rubric note, testimonial) pantoken'ın paketlenmiş starter sayfa düzenlerinden başlamak için **Layouts** araç çubuğu düğmesini kullanın; bu düzenlerin kaynağı [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Geliştirme\n\n```sh\nnpm install\nnpm run dev\n```\n\nBu, bir Vite geliştirme sunucusu açar ve:\n\n- Bir **editor** bölmesi (TinyMCE, [instructure/canvas-lms](https://github.com/instructure/canvas-lms) tarafından kullanılan sürüm/konfigürasyonla eşleşir — aşağıya bakın).\n **Layouts** düğmesini paketlenmiş starter düzenlerden birini yüklemek için kullanın (bu, imlecin olduğu yere eklemek yerine onay sonrası tüm belgeyi değiştirir) ve **Source code** anahtarını\n ham HTML'i CodeMirror ile sözdizimi vurgulanmış bir görünümde düzenlemek için kullanın; önizleme yazdıkça canlı güncellenir — TinyMCE'nin stok `code` eklentisinin yaptığı gibi tek seferlik modal diyaloğunda düzenleme ve canlı önizleme yoktur.\n- Geçerli CSS/JS sekmesinin stil sayfası/script'i uygulanmış halde düzenleyicinin içeriğini gösteren bir **preview** bölmesi (sadece çözülmüş CDN URL'leri değil), Canvas'ın kendi içerik alanı arka planı ve maksimum genişliğine sarılarak — \"Canvas'a yüklendiğinde nasıl görüneceğinin\" sadık bir kontrolü; tema veya içerik düzenledikçe canlı güncellenir.\n- Editör ve önizleme bölmeleri, ayırıcıyı sürükleyerek yeniden boyutlandırabileceğiniz bir bölünmüş görünümde oturur, yan yana yerine dikey olarak üst üste yığılabilir ve bölmelerin sırasını değiştirebilirsiniz (bir pano araç çubuğunu diğerinin üzerine sürükleyin veya **Swap panes** düğmesini kullanın). Her bölmenin kendi tam ekran düğmesi vardır.\n- **Edit theme** tepsisinin **Config** sekmesi CDN sağlayıcı/tema/mod seçimlerini ve **Download theme.css** / **Download theme.js** bağlantılarını barındırır; **CSS**/**JS** sekmeleri oluşturulan dosyaların düzenlenebilir kopyalarıdır — bunları elle düzenleyin ve önizleme değişikliklerinizi doğrudan alır. Bir Config seçimi değiştirmek, eğer sekmeleri zaten düzenlemediyseniz CSS/JS sekmelerini yeniden oluşturur; düzenlediyseniz, düzeninizi sessizce üzerine yazmak yerine bir **Regenerate from config** düğmesi görünür.\n\n## İş akışı\n\n1. `theme.css` ve `theme.js` dosyalarını Canvas'ın Theme Editor'üne (**Advanced → CSS / JavaScript**) yükleyin, böylece pantoken'ın sınıfları her sayfada kullanılabilir olur.\n2. `npm run dev` komutunu çalıştırın, paketlenmiş bir starter ile başlamak için **Layouts**'ı kullanın ve Canvas'ın kendi RCE'sinde yapacağınız gibi düzenleyin.\n3. **Copy HTML**e tıklayın ve sonucu bir Canvas sayfasının RCE'sine 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 scaffolding bunu çoğaltmaya çalışmaz, bu yüzden her zaman yapıştırılan sonucu Canvas'ta doğrulayın (aşağıya bakın: \"Canvas'ın RCE'si hakkında notlar\").\n\n## Canvas'ın RCE'si hakkında notlar\n\nCanvas Rich Content Editor TinyMCE çalıştırır ve gönderilen HTML'i sunucuda bir izinli öğe (allowlist) karşılaştırmasına tabi tutar (`gems/canvas_sanitize` içinde canvas-lms, TinyMCE'nin kendi `valid_elements`/`extended_valid_elements` ile senkron tutulur). Bu izinli liste burada oluşturulan şablonlar için ne anlama gelir:\n\n- `class`, `id`, `style`, `title`, `role` ve `aria-*` öznitelikleri her elementte izinlidir —\n pantoken'ın `class=\"instui-*\"` stil kancaları (ve inline `style`, ör. CSS bağlama pozisyonlaması için)\n **yapıştırılıp kaydedildiğinde** hayatta kalır; bu dosyadaki eski yönergelere rağmen. `<script>` etiketleri\n her zaman kaldırılır.\n- **RCE-güvenli pantoken bileşenleri**: statik/görüntüleme bileşenleri — alert, view, heading, text, table,\n bir button-as-`<a>` (gerçek bir `<button>` değil), blockquote. Pantoken'ın zaten desteklediği anlamsal HTML'e bağlı kalın (`div`, `p`, `span`, `a`, `img`, başlıklar, listeler, tablolar).\n- **RCE-güvenli olmayan**: `@pantoken/interactions`'nin davranış setinden gelen her şey — modal, tooltip,\n drilldown, close-button veya yerel `popover`/`popovertarget`/\n `command`/`commandfor` öznitelikleriyle sürülen herhangi bir bileşen. Bu öznitelikler Canvas'ın temizleyici izinli listesinde olmadığından,\n işaretleme kalır ama etkileşimli davranış Canvas'ta sayfa ilk kez kaydedildiğinde sessizce bozulur; bu durum `theme.js`'nin `@pantoken/interactions` yükleyicisi mevcut olsa bile geçerlidir. Gerçek form\n elemanları (`input`, `form`, `button`, `select`, `textarea`, `label`) ve inline `<svg>`\n tamamen kaldırılır — paketlenmiş starter şablonların hiçbiri bunları kullanmaz.\n\n`theme.js` CDN'den `@pantoken/interactions` yükler; bu Canvas'ın global sayfa kapsamında çalışır —\nham HTML düzenlemeleriyle doğrudan Canvas'ın RCE'sinde oluşturduğunuz sayfalardaki etkileşimler için faydalıdır, ancak (yukarıda belirtildiği gibi) bu önizlemeden RCE'ye yapıştırılan `popover`/`command` özniteliğiyle sürülen işaretleme\nkaydedildiğinde etkileşimli kalmayacaktır.\n" },
523
487
  "components": { "README.md": "# {{projectName}}\n\nVite ile oluşturulmuş düz bir TypeScript uygulaması, [`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), Instructure'ın tasarım token'ları ve simgeleri ile stillendirilmiştir.\n\n## Geliştir\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Burada ne var\n\n- `index.html` gerçek sayfa işaretlemesini barındırır — [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts)'den bir `wrapper`-düzeni kabuğu. Kaynağı görüntüleyin ve doğrudan düzenleyin; JavaScript tarafından hiçbir şey enjekte edilmez.\n- `src/main.ts` her `--instui-*` özel özelliğini tanımlayan `@pantoken/css`'i, belge varsayılanları + odak halkası için `@pantoken/components/base.css`'yi, `.instui-*` sınıfları için `components.css`'i, kutudan çıktığı haliyle modal, tooltip ve diğer bileşen davranışlarını bağlayan `@pantoken/interactions`'u ve kendi `src/style.css`'inizi içe aktarır — etkileşimli davranışı buraya ekleyin.\n- İsteğe bağlı ekleme noktaları (başlık, filtreler, içerik, sonda) `index.html` içinde `<div data-slot=\"...\">` ile işaretlenmiştir — içeriklerini kendi işaretlemenizle değiştirin.\n- İşaretlemeye `class=\"instui-button\"` gibi sınıflar uygulayın; tam sınıf listesi için [bileşen referansına](https://pantoken.app/api/css) bakın.\n\n## Daha fazla bilgi\n\nDaha fazlasını öğrenmek için [HTML kılavuzuna](https://pantoken.app/guide/components) bakın.\n" },
524
488
  "next": { "README.md": "# {{projectName}}\n\nNext.js (App Router) uygulaması, [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next) ile stilize edilmiştir, Instructure'ın tasarım token'ları ve simgeleri.\n\n## Geliştirme\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Burada neler var\n\n- `next.config.mjs` yapılandırmayı `withPantoken(...)` ile sarar (pantoken'i `transpilePackages` içine ekler).\n- `app/layout.tsx` köke `@pantoken/css`'i içe aktarır; bu, her `--instui-*` özel özelliğini tanımlar, böylece her sayfada kullanılabilir, ayrıca `<body>` ve `PantokenInteractions` üzerindeki `wrapper` düzeninin kök sınıfını ekler (`@pantoken/interactions` yükleyen bir istemci bileşenidir — kutudan çıktığı gibi modal, tooltip ve diğer bileşen davranışlarını hazır şekilde bağlar).\n- `app/page.tsx` `instui-*` sınıflarıyla stilize edilmiş işaretlemeyi render eder; isteğe bağlı ekleme noktaları (header, filters, content, trailing) `<div data-slot=\"...\">` ile işaretlenmiştir.\n\n## Daha fazla bilgi\n\nDaha fazla bilgi için [başlarken kılavuzuna](https://pantoken.app/guide/getting-started) bakın.\n" },
525
489
  "react": { "README.md": "# {{projectName}}\n\n[`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react) ve [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css) ile stillendirilmiş bir Vite + React uygulaması; Instructure'ın tasarım token'ları ve ikonları.\n\n## Geliştirme\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Burada neler var\n\n- `src/main.tsx` `@pantoken/css`'ü içe aktarır (her `--instui-*` özel özelliğini tanımlar) ve\n kutudan çıktığı gibi modal, tooltip ve diğer bileşen davranışlarını bağlayan `@pantoken/interactions`'i.\n- `src/App.tsx` `instui-*` sınıflarıyla stillendirilmiş işaretlemeyi render eder; isteğe bağlı ekleme noktaları (header,\n filters, content, trailing) `<div data-slot=\"...\">` ile işaretlenmiştir.\n- InstUI'nin tam React bileşen kütüphanesi (butonlar, modallar vb. — `@pantoken/react`'un\n `<Icon>`'u dahil) için ihtiyacınız olan belirli `@instructure/ui-*` paketlerini ekleyin — bkz <https://instructure.design>.\n\n## Daha fazla bilgi\n\nDaha fazlasını öğrenmek için [başlangıç kılavuzuna](https://pantoken.app/guide/getting-started) bakın.\n" },
@@ -529,7 +493,6 @@ const SCAFFOLD_OVERLAYS = {
529
493
  },
530
494
  "uk": {
531
495
  "angular": { "README.md": "# {{projectName}}\n\nОкремий додаток Angular (через Vite + `@analogjs/vite-plugin-angular`, без Angular CLI), стилизований за допомогою\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) та\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (кастомні елементи pantoken\nдля Angular).\n\n## Розробка\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Що тут\n\n- `src/main.ts` викликає `registerPantokenElements()` (з `@pantoken/angular`) один раз під час завантаження, тож\n елементи як `<instui-icon>` працюватимуть у шаблонах, і імпортує CSS токенів/компонентів плюс\n `@pantoken/interactions` (налаштовує модальні вікна, підказки та іншу поведінку компонентів «з коробки»).\n- `src/app.component.ts` — це автономний компонент (`CUSTOM_ELEMENTS_SCHEMA` дозволяє компілятору шаблонів\n приймати теги кастомних елементів pantoken), шаблон якого стилізований за допомогою класів `instui-*`;\n необов'язкові точки вставки (header, filters, content, trailing) позначені як `<div data-slot=\"...\">`.\n- Застосовуйте класи на кшталт `class=\"instui-button\"` до розмітки; повний список класів див. у\n [довіднику компонентів](https://pantoken.app/api/css).\n\n## Дізнатись більше\n\nДив. [керівництво для початку роботи](https://pantoken.app/guide/getting-started), щоб дізнатися більше.\n" },
532
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nАктиви готові до завантаження для **Theme Editor** Canvas LMS, плюс локальний попередній перегляд для створення шаблонів сторінок Редактора Розмістного Вмісту (RCE), стилізованих за допомогою\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Що тут є\n\n- `theme.css` / `theme.js` — завантажте ці два файли в **Theme Editor → Advanced** у Canvas.\n Вони збудовані для провайдера CDN/теми/режиму, який ви обрали при scaffold-інгу (`--cdn`/`--theme`/\n `--theme-mode`; за замовчуванням jsDelivr/rebrand/light) і містять лоадер для\n `@pantoken/interactions` (підключає поведінки компонентів на кшталт modal, tooltip і drilldown).\n- `index.html` / `src/main.ts` — локальний редактор на базі TinyMCE (`npm run dev`), який віддзеркалює RCE Canvas, тож ви можете створювати шаблони сторінок, використовуючи класи pantoken, перш ніж скопіювати їх у Canvas.\n Сама сторінка побудована з використанням макету `wrapper` від pantoken: натисніть **Edit theme**, щоб відкрити панель з вкладками **Config** / **CSS** / **JS** (селектори провайдера CDN/теми/режиму та підсвічені синтаксично,\n ручні копії `theme.css`/`theme.js`, які підгодовують живий превʼю), і кнопку **?** для повних інструкцій. Використовуйте кнопку **Layouts** на панелі інструментів, щоб почати з одного з комплектних стартових макетів сторінок pantoken (hero, callout, two-column, rubric note, testimonial), узятих із\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Розробка\n\n```sh\nnpm install\nnpm run dev\n```\n\nЦе відкриває Vite dev-сервер з:\n\n- Панеллю **editor** (TinyMCE, яка відповідає версії/конфігурації, що використовує сам [instructure/canvas-lms](https://github.com/instructure/canvas-lms) — див. нижче).\n Використовуйте кнопку **Layouts**, щоб завантажити один із комплектних стартових макетів (це замінює весь документ після підтвердження, а не вставляє в курсор), і перемикач **Source code**\n для ручного редагування сирого HTML у вигляді з підсвічуванням синтаксису (CodeMirror) поруч із редактором, причому панель превʼю оновлюється в реальному часі під час введення — на відміну від стандартного плагіна `code` для TinyMCE, який редагує в одноразовому модальному вікні без живого превʼю.\n- Панеллю **preview**, що показує вміст редактора з застосованим стилем/скриптом поточної вкладки CSS/JS (не лише зведені CDN URL), загорнутим так, щоб відповідати власному фонові області контенту та макс. ширині Canvas — достовірна перевірка «як це виглядатиме після завантаження в Canvas», яка оновлюється в реальному часі під час набору тексту або редагування теми.\n- Редактор і превʼю розташовані в розділеному вью з можливістю зміни розміру перетягуванням роздільника, стекування вертикально замість бокового розташування, і перестановки порядку панелей (перетягніть тулбар однієї панелі на іншу або використайте кнопку **Swap panes**). Кожна панель має власну кнопку повноекранного режиму.\n- Панель **Edit theme** у вкладці **Config** містить селектори провайдера CDN/теми/режиму та посилання **Download theme.css** / **Download theme.js**; вкладки **CSS**/**JS** — це редаговані копії згенерованих файлів — редагуйте їх вручну, і превʼю відобразить зміни негайно. Зміна селектора в Config перегенерує вкладки CSS/JS, якщо ви їх ще не редагували; якщо ви вже редагували, зʼявиться кнопка **Regenerate from config** замість прихованого перезапису вашого редагування.\n\n## Робочий процес\n\n1. Завантажте `theme.css` і `theme.js` у Theme Editor Canvas (**Advanced → CSS / JavaScript**), щоб класи pantoken були доступні на кожній сторінці.\n2. Запустіть `npm run dev`, використайте **Layouts**, щоб почати зі стартового шаблону, і редагуйте його так само, як у власному RCE Canvas.\n3. Натисніть **Copy HTML** і вставте результат у RCE сторінки Canvas (спочатку переключіться на HTML-редактор). Canvas очищає вставлений HTML на сервері — цей scaffold не намагається відтворити той процес, тож завжди перевіряйте вставлений результат у Canvas (див. розділ «Примітки щодо RCE Canvas» нижче).\n\n## Примітки щодо RCE Canvas\n\nРедактор Rich Content Editor у Canvas працює на TinyMCE і очищає надіслані HTML на сервері за allowlist (списком дозволів) (`gems/canvas_sanitize` в canvas-lms, синхронізовано з власними\n`valid_elements`/`extended_valid_elements` TinyMCE). Що цей список дозволяє для шаблонів, створених тут:\n\n- Атрибути `class`, `id`, `style`, `title`, `role` і `aria-*` дозволені на будь-якому елементі —\n хуки стилізації pantoken `class=\"instui-*\"` (і inline `style`, наприклад для позиціювання CSS-якорів)\n **дійсно** переживають вставку та збереження, всупереч старішим вказівкам у цьому файлі. Теги `<script>` завжди видаляються.\n- **RCE-безпечні компоненти pantoken**: статичні/відображувальні компоненти — alert, view, heading, text, table,\n кнопка як `<a>` (не справжній `<button>`), blockquote. Дотримуйтесь семантичного HTML, який pantoken вже підтримує (`div`, `p`, `span`, `a`, `img`, заголовки, списки, таблиці).\n- **RCE-небезпечне**: усе, що належить до набору поведінок `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button або будь-який інший компонент, керований нативними атрибутами `popover`/`popovertarget`/\n `command`/`commandfor`. Ці атрибути відсутні в allowlist санітайзера Canvas, тож\n розмітка переживає збереження, але інтерактивна поведінка тихо ламається при першому збереженні сторінки в Canvas, навіть за наявності лоадера `theme.js`'s `@pantoken/interactions`. Справжні форма-елементи (`input`, `form`, `button`, `select`, `textarea`, `label`) і inline `<svg>` видаляються повністю — жоден з комплектних стартових шаблонів їх не використовує.\n\n`theme.js` завантажує `@pantoken/interactions` з CDN, який виконується в глобальній області сторінки Canvas —\nкорисно для інтерактивності на сторінках, які ви будуєте безпосередньо в RCE Canvas за допомогою сирого HTML, але (як зазначено вище) будь-яка розмітка, керована атрибутами `popover`/`command`, вставлена з превʼю цього RCE, не залишатиметься інтерактивною після збереження.\n" },
533
496
  "components": { "README.md": "# {{projectName}}\n\nПростий додаток на TypeScript (через Vite), оформлений за допомогою\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), дизайн-токенів і іконок Instructure.\n\n## Розробка\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Що тут\n\n- `index.html` містить фактичну розмітку сторінки — оболонку з макетом `wrapper` від\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Переглядайте вихідний код\n та редагуйте його безпосередньо; нічого не інжектиться JavaScript.\n- `src/main.ts` імпортує `@pantoken/css` (визначає всі користувацькі властивості `--instui-*`),\n `@pantoken/components/base.css` (за замовчуванням для документа + фокусне коло), `components.css`\n (`.instui-*` класи), `@pantoken/interactions` (підключає модальне вікно, підказки та інші поведінки компонентів одразу),\n та ваш власний `src/style.css` — додайте тут інтерактивну поведінку.\n- Необовʼязкові точки вставки (header, filters, content, trailing) позначені\n `<div data-slot=\"...\">` в `index.html` — замініть їхній вміст вашою власною розміткою.\n- Застосовуйте класи на кшталт `class=\"instui-button\"` до розмітки; див. \n [довідник компонентів](https://pantoken.app/api/css) для повного списку класів.\n\n## Дізнатися більше\n\nДив. [посібник з HTML](https://pantoken.app/guide/components), щоб дізнатися більше.\n" },
534
497
  "next": { "README.md": "# {{projectName}}\n\nДодаток Next.js (App Router), стилізований за допомогою [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\nдизайнерських токенів і іконок Instructure.\n\n## Розробка\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Що тут\n\n- `next.config.mjs` обгортає конфіг з `withPantoken(...)` (додає pantoken до\n `transpilePackages`).\n- `app/layout.tsx` імпортує `@pantoken/css`, який визначає всі кастомні\n властивості `--instui-*` в корені, тож вони доступні на кожній сторінці, плюс кореневий клас\n макета `wrapper` на `<body>` та `PantokenInteractions` (клієнтський компонент, що завантажує `@pantoken/interactions` —\n налаштовує модальні вікна, тултіп і інші поведінки компонентів «з коробки»).\n- `app/page.tsx` рендерить розмітку, стилізовану класами `instui-*`; необов'язкові точки вставки (header,\n filters, content, trailing) позначені `<div data-slot=\"...\">`.\n\n## Дізнатися більше\n\nДив. [посібник для початку роботи](https://pantoken.app/guide/getting-started), щоб дізнатися більше.\n" },
535
498
  "react": { "README.md": "# {{projectName}}\n\nЗастосунок Vite + React, стилізований за допомогою [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nта [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), токени дизайну та іконки Instructure.\n\n## Розробка\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Що тут\n\n- `src/main.tsx` імпортує `@pantoken/css` (визначає кожну користувацьку властивість `--instui-*`) та\n `@pantoken/interactions` (налаштовує модальні вікна, підказки та інші поведінки компонентів \"з коробки\").\n- `src/App.tsx` відображає розмітку, стилізовану класами `instui-*`; необов'язкові точки вставки (header,\n filters, content, trailing) позначені `<div data-slot=\"...\">`.\n- Для повної бібліотеки React-компонентів InstUI (кнопки, модальні вікна тощо — включно з `<Icon>` з `@pantoken/react`), додайте конкретні пакети `@instructure/ui-*`, які вам потрібні — див. <https://instructure.design>.\n\n## Дізнатися більше\n\nДив. [getting started guide](https://pantoken.app/guide/getting-started), щоб дізнатися більше.\n" },
@@ -539,7 +502,6 @@ const SCAFFOLD_OVERLAYS = {
539
502
  },
540
503
  "vi": {
541
504
  "angular": { "README.md": "# {{projectName}}\n\nMột ứng dụng Angular độc lập (qua Vite + `@analogjs/vite-plugin-angular`, không dùng Angular CLI) được tạo kiểu bằng\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) và\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (thành phần tùy chỉnh pantoken\ncho Angular).\n\n## Phát triển\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Có gì ở đây\n\n- `src/main.ts` gọi `registerPantokenElements()` (từ `@pantoken/angular`) một lần khi khởi động để\n các phần tử như `<instui-icon>` hoạt động trong các mẫu, và nhập CSS token/component cùng với\n `@pantoken/interactions` (kết nối modal, tooltip và các hành vi thành phần khác sẵn sàng sử dụng).\n- `src/app.component.ts` là một thành phần độc lập (`CUSTOM_ELEMENTS_SCHEMA` cho phép trình biên dịch mẫu\n chấp nhận các thẻ phần tử tùy chỉnh của pantoken) có mẫu được tạo kiểu bằng các lớp `instui-*`;\n các điểm chèn tùy chọn (header, filters, content, trailing) được đánh dấu bằng\n `<div data-slot=\"...\">`.\n- Áp dụng các lớp như `class=\"instui-button\"` vào đánh dấu; xem\n [tham khảo thành phần](https://pantoken.app/api/css) để biết danh sách đầy đủ các lớp.\n\n## Tìm hiểu thêm\n\nXem [hướng dẫn bắt đầu](https://pantoken.app/guide/getting-started) để tìm hiểu thêm.\n" },
542
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nTài sản sẵn sàng tải lên cho **Theme Editor** của Canvas LMS, cùng với bản xem trước cục bộ để soạn mẫu trang Rich\nContent Editor (RCE) được tạo kiểu bằng\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Có những gì ở đây\n\n- `theme.css` / `theme.js` — tải lên hai tệp này trong **Theme Editor → Advanced** của Canvas.\n Chúng được xây dựng cho nhà cung cấp CDN/theme/chế độ bạn đã chọn khi tạo scaffold (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light theo mặc định) và bao gồm một trình tải cho\n `@pantoken/interactions` (kết nối các hành vi component như modal, tooltip và drilldown).\n- `index.html` / `src/main.ts` — một trình soạn thảo cục bộ dựa trên TinyMCE (`npm run dev`) phản chiếu\n RCE của Canvas để bạn có thể soạn mẫu trang dựa trên các lớp của pantoken trước khi sao chép vào Canvas.\n Trang này được xây dựng với layout `wrapper` của pantoken: bấm **Edit theme** để mở một khay\n có các tab **Config** / **CSS** / **JS** (các chọn nhà cung cấp CDN/theme/chế độ, và các bản sao có đánh dấu cú pháp,\n có thể sửa bằng tay của `theme.css`/`theme.js` cấp dữ liệu cho bản xem trước trực tiếp), và nút **?**\n cho hướng dẫn đầy đủ. Dùng nút thanh công cụ **Layouts** để bắt đầu từ một trong các bố cục trang khởi tạo\n của pantoken (hero, callout, hai cột, rubric note, testimonial), lấy từ\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Phát triển\n\n```sh\nnpm install\nnpm run dev\n```\n\nĐiều này mở một máy chủ dev Vite với:\n\n- Một khung **editor** (TinyMCE, khớp với phiên bản/cấu hình\n [instructure/canvas-lms](https://github.com/instructure/canvas-lms) tự nó sử dụng — xem bên dưới).\n Dùng nút **Layouts** để tải một trong các bố cục khởi tạo có sẵn (việc này thay thế toàn bộ\n tài liệu, sau khi xác nhận, thay vì chèn tại con trỏ), và chuyển đổi **Source code** để\n chỉnh HTML thô bằng tay trong chế độ xem có đánh dấu cú pháp (CodeMirror) bên cạnh trình soạn thảo, với\n khung xem trước cập nhật trực tiếp khi gõ — khác với plugin `code` mặc định của TinyMCE, vốn chỉnh sửa trong\n một hộp thoại modal một lần duy nhất mà không có bản xem trước trực tiếp.\n- Một khung **preview** hiển thị nội dung của editor với stylesheet/script của tab CSS/JS hiện tại\n được áp dụng (không chỉ các URL CDN đã giải quyết), được bao lại để khớp nền vùng nội dung và chiều rộng tối đa của Canvas — một kiểm tra trung thực \"trông sẽ như thế nào khi tải lên Canvas\", cập nhật\n trực tiếp khi gõ hoặc chỉnh theme.\n- Các khung editor và preview nằm trong chế độ xem chia tách có thể thay đổi kích thước bằng cách kéo thanh chia, xếp\n theo chiều dọc thay vì cạnh bên, và hoán đổi thứ tự (kéo thanh công cụ của một khung lên khung kia,\n hoặc dùng nút **Swap panes**). Mỗi khung có nút toàn màn hình riêng.\n- Khay **Edit theme** tab **Config** chứa các chọn nhà cung cấp CDN/theme/chế độ và\n liên kết **Download theme.css** / **Download theme.js**; các tab **CSS**/**JS** là các bản sao có thể chỉnh sửa\n của các tệp đã tạo — sửa tay chúng và bản xem trước sẽ nhận thay đổi ngay. Thay đổi một chọn trong Config sẽ tái tạo lại các tab CSS/JS trừ khi bạn đã chỉnh sửa chúng, trong trường hợp đó sẽ xuất hiện\n nút **Regenerate from config** thay vì ghi đè chỉnh sửa của bạn một cách im lặng.\n\n## Quy trình làm việc\n\n1. Tải lên `theme.css` và `theme.js` vào Theme Editor của Canvas (**Advanced → CSS / JavaScript**) để\n các lớp của pantoken có sẵn trên mọi trang.\n2. Chạy `npm run dev`, dùng **Layouts** để bắt đầu từ một khởi tạo đóng gói, và chỉnh sửa nó giống như\n bạn sẽ làm trong RCE của Canvas.\n3. Bấm **Copy HTML** và dán kết quả vào RCE của một trang Canvas (chuyển sang chế độ trình soạn thảo HTML\n trước). Canvas lọc HTML dán phía server — scaffold này không cố mô phỏng điều đó, nên luôn kiểm tra kết quả dán trong Canvas (xem \"Ghi chú về RCE của Canvas\"\n bên dưới).\n\n## Ghi chú về RCE của Canvas\n\nTrình Rich Content Editor của Canvas chạy TinyMCE và lọc HTML được gửi lên trên máy chủ theo một\nallowlist (`gems/canvas_sanitize` trong canvas-lms, giữ đồng bộ với `valid_elements`/`extended_valid_elements` của TinyMCE). Ý nghĩa của allowlist đó đối với các mẫu được xây dựng ở đây:\n\n- Các thuộc tính `class`, `id`, `style`, `title`, `role`, và `aria-*` được phép trên mọi phần tử —\n móc tạo kiểu `class=\"instui-*\"` của pantoken (và `style` nội tuyến, ví dụ để định vị anchor bằng CSS)\n **có** tồn tại sau khi dán và lưu, trái với hướng dẫn cũ trong tệp này. Thẻ `<script>` luôn bị loại bỏ.\n- **Các component pantoken an toàn với RCE**: các component tĩnh/hiển thị — alert, view, heading, text, table,\n một nút dưới dạng `<a>` (không phải `<button>` thật sự), blockquote. Giữ HTML ngữ nghĩa mà pantoken đã\n hỗ trợ (`div`, `p`, `span`, `a`, `img`, các heading, danh sách, bảng).\n- **Không an toàn với RCE**: bất cứ thứ gì từ tập hành vi của `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, hoặc bất kỳ component tương tác nào được điều khiển bởi các thuộc tính gốc `popover`/`popovertarget`/\n `command`/`commandfor`. Những thuộc tính đó không nằm trong allowlist của bộ lọc Canvas, nên\n markup vẫn tồn tại nhưng hành vi tương tác sẽ bị hỏng ngay lần lưu trang đầu tiên trong Canvas, ngay cả khi có trình tải `theme.js` của `@pantoken/interactions`. Các phần tử form thật sự (`input`, `form`, `button`, `select`, `textarea`, `label`) và `<svg>` nội tuyến bị\n loại bỏ hoàn toàn — không mẫu khởi tạo nào trong gói sử dụng chúng.\n\n`theme.js` tải `@pantoken/interactions` từ CDN, chạy trong phạm vi toàn cục của trang Canvas —\nhữu ích cho tương tác trên các trang bạn xây dựng trực tiếp trong RCE của Canvas bằng chỉnh sửa HTML thô, nhưng (theo\nbên trên) bất kỳ markup nào được điều khiển bởi thuộc tính `popover`/`command` dán\ntừ bản xem trước RCE tại đây sẽ không giữ được tương tác sau khi lưu.\n" },
543
505
  "components": { "README.md": "# {{projectName}}\n\nMột ứng dụng TypeScript thuần túy (qua Vite) được tạo kiểu bằng\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), các token thiết kế và biểu tượng của Instructure.\n\n## Phát triển\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Có gì ở đây\n\n- `index.html` chứa đánh dấu trang thực tế — một khung bố cục `wrapper` từ\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Xem mã nguồn\n và chỉnh sửa trực tiếp; không có gì được tiêm bởi JavaScript.\n- `src/main.ts` nhập `@pantoken/css` (định nghĩa mọi thuộc tính tùy chỉnh `--instui-*`),\n `@pantoken/components/base.css` (mặc định tài liệu + vòng tiêu điểm), `components.css`\n (`.instui-*` lớp), `@pantoken/interactions` (kết nối modal, tooltip và các hành vi thành phần khác\n ngay lập tức), và `src/style.css` của riêng bạn — thêm hành vi tương tác ở đây.\n- Các điểm chèn tùy chọn (header, filters, content, trailing) được đánh dấu bằng\n `<div data-slot=\"...\">` trong `index.html` — thay thế nội dung của chúng bằng đánh dấu của bạn.\n- Áp dụng các lớp như `class=\"instui-button\"` lên đánh dấu; xem\n [tham chiếu thành phần](https://pantoken.app/api/css) để biết danh sách lớp đầy đủ.\n\n## Tìm hiểu thêm\n\nXem [hướng dẫn HTML](https://pantoken.app/guide/components) để tìm hiểu thêm.\n" },
544
506
  "next": { "README.md": "# {{projectName}}\n\nMột ứng dụng Next.js (App Router) được tạo kiểu bằng [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\ncác token thiết kế và biểu tượng của Instructure.\n\n## Phát triển\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Có gì ở đây\n\n- `next.config.mjs` bọc cấu hình bằng `withPantoken(...)` (thêm pantoken vào\n `transpilePackages`).\n- `app/layout.tsx` nhập `@pantoken/css`, định nghĩa mọi thuộc tính tùy chỉnh `--instui-*`,\n tại gốc để có sẵn trên mọi trang, cộng với lớp gốc của layout `wrapper` trên\n `<body>` và `PantokenInteractions` (một component phía client tải `@pantoken/interactions` —\n kết nối sẵn modal, tooltip và các hành vi component khác).\n- `app/page.tsx` hiển thị markup được tạo kiểu bằng các lớp `instui-*`; các điểm chèn tùy chọn (header,\n filters, content, trailing) được đánh dấu bằng `<div data-slot=\"...\">`.\n\n## Tìm hiểu thêm\n\nXem [hướng dẫn bắt đầu](https://pantoken.app/guide/getting-started) để tìm hiểu thêm.\n" },
545
507
  "react": { "README.md": "# {{projectName}}\n\nMột ứng dụng Vite + React được tạo kiểu bằng [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\nvà [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), các token thiết kế và\nbiểu tượng của Instructure.\n\n## Phát triển\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Có gì ở đây\n\n- `src/main.tsx` nhập `@pantoken/css` (định nghĩa mọi thuộc tính tùy chỉnh `--instui-*`) và\n `@pantoken/interactions` (kết nối modal, tooltip và các hành vi thành phần khác sẵn sàng sử dụng).\n- `src/App.tsx` hiển thị markup được tạo kiểu bằng các lớp `instui-*`; các điểm chèn tùy chọn (header,\n filters, content, trailing) được đánh dấu bằng `<div data-slot=\"...\">`.\n- Đối với thư viện thành phần React đầy đủ của InstUI (buttons, modals, v.v. — bao gồm `@pantoken/react`'s\n `<Icon>`), thêm các gói `@instructure/ui-*` cụ thể mà bạn cần — xem <https://instructure.design>.\n\n## Tìm hiểu thêm\n\nXem [hướng dẫn bắt đầu](https://pantoken.app/guide/getting-started) để tìm hiểu thêm.\n" },
@@ -549,7 +511,6 @@ const SCAFFOLD_OVERLAYS = {
549
511
  },
550
512
  "cy": {
551
513
  "angular": { "README.md": "# {{projectName}}\n\nAp p Angular hunan-bendant (drwy Vite + `@analogjs/vite-plugin-angular`, heb Angular CLI) wedi'i arddullio gyda\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) a\n[`@pantoken/angular`](https://www.npmjs.com/package/@pantoken/angular) (elfennau wedi'u haddasu pantoken\nar gyfer Angular).\n\n## Datblygu\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Beth sydd yma\n\n- `src/main.ts` yn galw `registerPantokenElements()` (o `@pantoken/angular`) unwaith wrth bootstrap fel bod\n elfennau fel `<instui-icon>` yn gweithio mewn templedi, ac yn mewnforio'r CSS token/gyfansoddyn yn ogystal â\n `@pantoken/interactions` (yn cysylltu modal, tooltip, a pharodrwyddiau cydran eraill allan o'r bocs).\n- `src/app.component.ts` yw cydran hunan-bendant (`CUSTOM_ELEMENTS_SCHEMA` yn caniatáu i'r cyfansoddwr templed\n dderbyn tagiau elfennau wedi'u haddasu pantoken) y mae ei dempled wedi'i arddullio gyda dosbarthiadau `instui-*`;\n pwyntiau mewnosod dewisol (penawd, hidlwyr, cynnwys, diwedd) wedi'u marcio gyda `<div data-slot=\"...\">`.\n- Defnyddiwch ddosbarthiadau fel `class=\"instui-button\"` ar farcio; gweler y\n [cyfeirlyfr cydran](https://pantoken.app/api/css) am y rhestr lawn o ddosbarthiadau.\n\n## Dysgwch mwy\n\nGweler y [getting started guide](https://pantoken.app/guide/getting-started) i ddysgu mwy.\n" },
552
- "canvas-theme-editor": { "README.md": "# {{projectName}}\n\nAsedau parod-i-lwytho ar gyfer Golygydd Thema Canvas LMS, yn ogystal ag rhagolwg lleol ar gyfer awdurio templedi tudalen Rich\nContent Editor (RCE) wedi eu steilio gyda\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components).\n\n## Beth sydd yma\n\n- `theme.css` / `theme.js` — lwythwch y ddau ffeil hyn o dan **Theme Editor → Advanced** yn Canvas.\n Wedi eu hadeiladu ar gyfer y darparwr CDN/thema/modd a ddewiswyd wrth farcio (`--cdn`/`--theme`/\n `--theme-mode`; jsDelivr/rebrand/light yn ddiofyn) ac yn cynnwys llwythwr ar gyfer\n `@pantoken/interactions` (yn cysylltu ymddygiadau cydrannau fel modal, tooltip, a drilldown).\n- `index.html` / `src/main.ts` — golygydd lleol sy'n defnyddio TinyMCE (`npm run dev`) sy'n adlewyrchu RCE Canvas fel y gallwch awduro templedi tudalen yn erbyn dosbarthiadau pantoken cyn eu copïo i Canvas.\n Mae'r dudalen ei hun wedi ei hadeiladu gyda cynllun `wrapper` pantoken: cliciwch **Edit theme** i agor traw\n gyda thabs **Config** / **CSS** / **JS** (dewiswyr darparwr CDN/thema/modd, a chopïau addasadwy a gyda amlygu sintacs\n o `theme.css`/`theme.js` sy'n bwydo'r rhagolwg byw), a'r botwm **?** i gael cyfarwyddiadau llawn. Defnyddiwch y botwm **Layouts** yn y bar offer i ddechrau o un o leoliadau tudalen cychwyn wedi eu bundio gan pantoken (hero, callout, two-column, rubric note, testimonial), wedi eu tynnu o\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts).\n\n## Datblygu\n\n```sh\nnpm install\nnpm run dev\n```\n\nMae hyn yn agor gweinydd datblygiad Vite gyda:\n\n- Panel **editor** (TinyMCE, yn cyfateb i'r fersiwn/config\n a ddefnyddir gan [instructure/canvas-lms](https://github.com/instructure/canvas-lms) ei hun — gweler isod).\n Defnyddiwch y botwm **Layouts** i lwytho un o'r cynlluniau cychwyn wedi eu bundio (yn disodli'r holl\n ddogfen, ar ôl cadarnhau, yn hytrach na'i mewnosod ar y cyrchwr), a'r switsh **Source code**\n i olrhain a golygu'r HTML crai mewn golwg gyda amlygu sintacs (CodeMirror) ochr yn ochr â'r golygydd, gyda'r\n rhagolwg yn diweddaru'n fyw wrth i chi deipio — yn wahanol i'r `code` plugin safonol TinyMCE, sy'n golygu mewn\n deialog modal un-amser heb ragolwg byw.\n- Panel **preview** sy'n dangos cynnwys y golygydd gyda'r dalgylch/stori script o'r tab CSS/JS cyfredol wedi ei gymhwyso (nid dim ond y URLau CDN datrys), wedi'i lapio i gyfateb cefndir ardal cynnwys a uchafswm lled Canvas — jôc ffyddlon \"sut fydd hyn yn edrych unwaith wedi'i lwytho i Canvas\", wedi'i ddiweddaru'n fyw wrth i chi deipio neu olygu'r thema.\n- Mae'r paneli golygydd a rhagolwg yn eistedd mewn golwg rannu y gallwch ei hailfeintio drwy lusgo'r rhwystr, eu stacio'n fertigol yn hytrach na ochr yn ochr, a chludo trefn y paneli (lusgwch offerynbar panel i arwain ar y llall, neu defnyddiwch y botwm **Swap panes**). Mae gan bob panel ei botwm sgrin lawn ei hun.\n- Mae tab **Config** yn y traw **Edit theme** yn cadw'r dewiswyr darparwr CDN/thema/modd a dolenni **Download theme.css** / **Download theme.js**; mae'r tabiau **CSS**/**JS** yn gopïau golyguadwy o'r ffeiliau a gynhyrchir — golygwch nhw a bydd y rhagolwg yn codi eich newidiadau yn syth. Pan fyddwch yn newid dewis yn y Config mae'r tabiau CSS/JS yn cael eu hail-gynhyrchu oni bai eich bod eisoes wedi eu golygu, yn achos hynny mae botwm **Regenerate from config** yn ymddangos yn hytrach na gorchuddio'ch golygiad yn dawel.\n\n## Llif Gwaith\n\n1. Llwythwch `theme.css` a `theme.js` i Theme Editor Canvas (**Advanced → CSS / JavaScript**) fel bod dosbarthiadau pantoken ar gael ar bob tudalen.\n2. Rhedeg `npm run dev`, defnyddiwch **Layouts** i ddechrau o gychwyn a wedi ei bundio, a golygwch ef fel y byddech yn RCE Canvas ei hun.\n3. Cliciwch **Copy HTML** a gludwch y canlyniad i RCE tudalen Canvas (symud i olygfa golygydd HTML yn gyntaf). Mae Canvas yn glanhau'r HTML a gludir ar y gweinydd — nid yw'r scaffold hwn yn ceisio efelychu hynny, felly cadwch wiweri'r canlyniad wedi ei gladdu yn Canvas (gweler \"Notes on Canvas's RCE\" isod).\n\n## Nodiadau am RCE Canvas\n\nMae Golygydd Cynnwys Cyfoethog Canvas yn rhedeg TinyMCE ac yn glanhau'r HTML a gyflwynir ar y gweinydd erbyn rhestr ganiatau (`gems/canvas_sanitize` yn canvas-lms, wedi ei gynnal yn unol â `valid_elements`/`extended_valid_elements` TinyMCE ei hun). Beth mae’r rhestr ganiatau honno'n ei olygu ar gyfer templedi a adeiladwyd yma:\n\n- Mae nodweddion `class`, `id`, `style`, `title`, `role`, a `aria-*` yn cael eu caniatáu ar bob elfen —\n mae dolenni steilio `class=\"instui-*\"` pantoken (a `style` mewnlin, e.e. ar gyfer lleoli cysylltyddau CSS)\n **yn** goroesi pan gaiff eu gludo a'u cadw, yn groes i gyfarwyddiadau hŷn yn y ffeil hon. Tagiau `<script>` caiff eu tynnu bob amser.\n- **Cydrannau pantoken diogel i RCE**: cydrannau statig/arddangos — alert, view, heading, text, table,\n botwm fel `<a>` (nid `<button>` go iawn), blockquote. Sticiwch at HTML semantig y mae pantoken eisoes yn ei gefnogi (`div`, `p`, `span`, `a`, `img`, penawdau, rhestrau, tablâu).\n- **Anlddiogel i RCE**: unrhyw beth o set ymddygiad `@pantoken/interactions` — modal, tooltip,\n drilldown, close-button, neu unrhyw gydran arall a yrrir gan yr nodweddion brodorol `popover`/`popovertarget`/\n `command`/`commandfor`. Nid yw'r nodweddion hynny ar rhestr ganiatau'r glanhydd Canvas, felly mae'r marcwedd yn aros ond mae'r ymddygiad rhyngweithiol yn torri'n dawel y tro cyntaf y caiff y dudalen ei chadw yn Canvas, hyd yn oed gyda llwythwr `theme.js`'s `@pantoken/interactions` yn bresennol. Caiff elfennau ffurflen go iawn (`input`, `form`, `button`, `select`, `textarea`, `label`) a `<svg>` mewnlin eu tynnu'n gyfan gwbl — nid oes unrhyw un o'r templedi cychwyn wedi eu bundio yn eu defnyddio.\n\n`theme.js` yn llwytho `@pantoken/interactions` o'r CDN, sy'n rhedeg mewn cwmpas tudalen fyd-eang Canvas —\nuseful ar gyfer rhyngweithiau ar dudalennau a adeiladir yn syth yn RCE Canvas gyda golygiadau HTML crai, ond (fel uchod) unrhyw marcwedd gyrru gan nodweddion `popover`/`command` a gludir o'r rhagolwg RCE yma ni fydd yn aros yn rhyngweithiol unwaith y caiff ei chadw.\n" },
553
514
  "components": { "README.md": "# {{projectName}}\n\nAp pwrpasol TypeScript (trwy Vite) wedi'i steilio gyda\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components), tokenau dylunio ac eiconau Instructure.\n\n## Datblygu\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Beth sydd yma\n\n- `index.html` yn dal y marciad tudalen go iawn — cwningen `wrapper`-layout o\n [`@pantoken/plugin-layouts`](https://www.npmjs.com/package/@pantoken/plugin-layouts). Gweld y ffynhonnell\n a'i golygu'n uniongyrchol; nid oes dim yn cael ei fewnosod gan JavaScript.\n- `src/main.ts` yn mewnforio `@pantoken/css` (yn diffinio pob `--instui-*` eiddo arferol),\n `@pantoken/components/base.css` (dyleiau dogfen + cylch ffocws), `components.css`\n (`.instui-*` dosbarthiadau), `@pantoken/interactions` (yn cysylltu modal, tooltip, a gweddill\n ymddygiadau cydran allan o'r blwch), a'ch `src/style.css` chi — ychwanegwch ymddygiad rhyngweithiol yma.\n- Mae pwyntiau mewnosod dewisol (penawd, hidlyddion, cynnwys, arwain) wedi'u marcio gyda\n `<div data-slot=\"...\">` yn `index.html` — disodlwch eu cynnwys gyda'ch marciad eich hun.\n- Rheolwch ddosbarthiadau fel `class=\"instui-button\"` ar y marciad; gweler y\n [cyfeirlyfr cydrannau](https://pantoken.app/api/css) am y rhestr lawn o ddosbarthiadau.\n\n## Dysgu mwy\n\nGweler y [canllaw HTML](https://pantoken.app/guide/components) i ddysgu mwy.\n" },
554
515
  "next": { "README.md": "# {{projectName}}\n\nAp Next.js (App Router) wedi'i steilio gyda [`@pantoken/next`](https://www.npmjs.com/package/@pantoken/next),\ntokenau dylunio ac eiconau Instructure.\n\n## Datblygu\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Beth sydd yma\n\n- `next.config.mjs` yn lapio'r cyfluniad gyda `withPantoken(...)` (yn ychwanegu pantoken at\n `transpilePackages`).\n- `app/layout.tsx` yn mewnforio `@pantoken/css`, sy'n diffinio pob eiddo arferol `--instui-*`,\n yn y gwraidd er mwyn i'w gael ar bob tudalen, yn ogystal â dosbarth gwraidd gwraidd y cynllun `wrapper`\n ar `<body>` a `PantokenInteractions` (componen cleient sy'n llwytho `@pantoken/interactions` —\n yn cysylltu ffenestr moddol, awgrymiadau offer (tooltip), a gwahanol ymddygiadau cydrannau oddi wrth y bocs).\n- `app/page.tsx` yn rendro marc-up wedi'i steilio gyda dosbarthiadau `instui-*`; pwyntiau mewnosod dewisol (penawd,\n hidlwyr, cynnwys, olaf) wedi'u nodi gyda `<div data-slot=\"...\">`.\n\n## Dysgwch mwy\n\nGweler y [canllaw dechrau](https://pantoken.app/guide/getting-started) i ddysgu mwy.\n" },
555
516
  "react": { "README.md": "# {{projectName}}\n\nAp Vite + React wedi'i arstylio gyda [`@pantoken/react`](https://www.npmjs.com/package/@pantoken/react)\na [`@pantoken/css`](https://www.npmjs.com/package/@pantoken/css), tokenau dyluniad ac eiconau Instructure.\n\n## Datblygu\n\n```sh\nnpm install\nnpm run dev\n```\n\n## Beth sydd yma\n\n- `src/main.tsx` yn mewnforio `@pantoken/css` (yn diffinio pob `--instui-*` eiddo arfer) a\n `@pantoken/interactions` (yn cysylltu modal, tooltip, a gwahanol ymddygiadau cydrannau eraill yn barod i'w ddefnyddio).\n- `src/App.tsx` yn rendro marciad wedi'i arddullio gyda dosbarthiadau `instui-*`; pwyntiau mewnosod dewisol (penawd,\n hidlwyr, cynnwys, ar ddiwedd) wedi'u nodi gyda `<div data-slot=\"...\">`.\n- Ar gyfer llyfrgell gydrannau React lawn InstUI (botymau, modals, ac ati — gan gynnwys `@pantoken/react`'s\n `<Icon>`), ychwanegwch y pecynnau penodol `@instructure/ui-*` sydd eu hangen — gweler <https://instructure.design>.\n\n## Dysgwch fwy\n\nGweler y [canllaw dechrau](https://pantoken.app/guide/getting-started) i ddysgu mwy.\n" },
@@ -629,12 +590,42 @@ function normalizeTag(raw) {
629
590
  * @returns The registry's canonical spelling, or `undefined` when nothing matches
630
591
  */
631
592
  function resolveSupportedLocale(tag) {
632
- const subtags = normalizeTag(tag).split("-");
593
+ const normalized = normalizeTag(tag);
594
+ const subtags = normalized.split("-");
633
595
  for (let length = subtags.length; length > 0; length -= 1) {
634
596
  const candidate = subtags.slice(0, length).join("-").toLowerCase();
635
597
  const match = SUPPORTED_LOCALES.find((locale) => locale.toLowerCase() === candidate);
636
598
  if (match) return match;
637
599
  }
600
+ const baseLanguage = subtags[0]?.toLowerCase();
601
+ if (!baseLanguage) return void 0;
602
+ const languageMatches = SUPPORTED_LOCALES.filter((locale) => locale.split("-")[0].toLowerCase() === baseLanguage);
603
+ if (languageMatches.length === 0) return void 0;
604
+ try {
605
+ const intlLocale = new Intl.Locale(normalized);
606
+ const script = intlLocale.script?.toLowerCase();
607
+ if (script) {
608
+ const scriptMatch = languageMatches.find((locale) => locale.toLowerCase().includes(`-${script}`));
609
+ if (scriptMatch) return scriptMatch;
610
+ }
611
+ if (baseLanguage === "zh") {
612
+ const region = intlLocale.region?.toUpperCase();
613
+ if (region === "TW" || region === "HK" || region === "MO") {
614
+ const scriptMatch = languageMatches.find((locale) => locale.toLowerCase().endsWith("-hant"));
615
+ if (scriptMatch) return scriptMatch;
616
+ }
617
+ if (region === "CN" || region === "SG") {
618
+ const scriptMatch = languageMatches.find((locale) => locale.toLowerCase().endsWith("-hans"));
619
+ if (scriptMatch) return scriptMatch;
620
+ }
621
+ }
622
+ const region = intlLocale.region?.toLowerCase();
623
+ if (region) {
624
+ const regionMatch = languageMatches.find((locale) => locale.toLowerCase().split("-").slice(1).some((part) => part.toLowerCase() === region));
625
+ if (regionMatch) return regionMatch;
626
+ }
627
+ } catch {}
628
+ return languageMatches[0];
638
629
  }
639
630
  /** The base text direction for `locale`, defaulting to `ltr` for anything unrecognized. */
640
631
  function localeDirection(locale) {
@@ -743,13 +734,15 @@ function validateThemeMode(value) {
743
734
  //#endregion
744
735
  //#region generated/assets.ts
745
736
  const ASSETS = {
746
- "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## 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` (extra components) 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 `card`, `banner`, `agent-shell`). Use alongside `@pantoken/components` for extra component patterns.\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**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>`.\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- **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",
747
- "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` (extra components like `card`, `banner`, `agent-shell`).\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`, `initInPlaceEdit`, `initCloseButton`; IIFE entry points for CDN.\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\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",
748
- "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- 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`, `initInPlaceEdit`, `initCloseButton`).\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- 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",
749
- "copilot": "# pantoken (Instructure design tokens & icons)\n\nWhen styling this project, use pantoken components, icons and tokens.\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`, `initInPlaceEdit`, `initCloseButton`).\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- 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",
750
- "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- 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- InstUI React components: `@instructure/ui-*`. pantoken is the token/icon layer.\n",
751
- "initSkill": "---\nname: init-pantoken\ndescription: Install pantoken's agent assets (AGENTS.md, llms.txt, editor/agent rule files, and the create-pantoken-app skill) 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` skill.\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 the\n`create-pantoken-app` skill (or run `npx pantoken-ai scaffold <platform>` directly) to scaffold a\nnew project or wire pantoken into an existing one.\n",
752
- "createAppSkill": "---\nname: create-pantoken-app\ndescription: Scaffold a new project, or add Instructure design tokens and icons (pantoken) to an existing one. Use when the user wants to start a new app with pantoken already wired in, or wants to add Instructure/Canvas theming, InstUI design tokens, or the pantoken packages to an existing app — detects the framework, installs the right @pantoken/* packages, and wires the token CSS.\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\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\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"
737
+ "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 must use concrete inline `@pantoken/email` values and\nmust not use component CSS, custom properties, scripts, or web components.\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` (extra components) 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 `card`, `banner`, `agent-shell`). Use alongside `@pantoken/components` for extra component patterns.\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>`.\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- **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",
738
+ "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` (extra components like `card`, `banner`, `agent-shell`).\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`, `initInPlaceEdit`, `initCloseButton`; IIFE entry points for CDN.\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 concrete `@pantoken/email` values 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\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",
739
+ "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`, `initInPlaceEdit`, `initCloseButton`).\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- 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",
740
+ "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`, `initInPlaceEdit`, `initCloseButton`).\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- 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",
741
+ "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- InstUI React components: `@instructure/ui-*`. pantoken is the token/icon layer.\n",
742
+ "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",
743
+ "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",
744
+ "createMockupSkill": "---\nname: create-pantoken-mockup\ndescription: Create a standalone Pantoken HTML mockup or sendable HTML email. Use when the user asks for a single HTML file, quick prototype, customer email mockup, or email-client-ready markup without creating an application project.\n---\n\n# Create a Pantoken mockup\n\nCreate one final HTML artifact without scaffolding an application. Do not create `package.json`,\ninstall project dependencies, or invoke `create-pantoken-app` unless the user changes the request to\na maintained application.\n\n## 1. Choose the output\n\nIf the request says email but does not say how the result will be used, ask one question:\n\n- **Browser mockup**: a visual prototype opened as a local HTML file.\n- **Sendable email**: HTML delivered through Gmail, Outlook, or an email service.\n\nThese are different outputs. Browser mockups may use external CSS, custom properties, and optional\nJavaScript. Sendable email must use concrete inline styles and no scripts.\n\n## 2. Browser mockup\n\nProduce one HTML file that opens directly in a browser. Do not use the shadcn registry for this\nworkflow; it is for package-managed projects.\n\n1. Discover core component requirements from\n `https://pantoken.app/component-capabilities.json`.\n2. Discover plugin styles from `https://pantoken.app/cdn-plugin-manifest.json`.\n3. Use canonical HTML from `https://pantoken.app/demos/<component>.html` or the component's cssdoc\n documentation. Preserve native elements, nesting, ARIA attributes, and documented state classes.\n4. Load a version-pinned token foundation first:\n\n ```html\n <link\n rel=\"stylesheet\"\n href=\"https://cdn.jsdelivr.net/npm/@pantoken/css@<version>/dist/style.lean.css\"\n />\n ```\n\n5. Load only the required `@pantoken/components/dist/<name>.css` and plugin CSS files. Put base CSS\n before components and utilities after components. Use jsDelivr's combine endpoint when several\n stylesheets are needed.\n6. If any selected component has `needsIcons: true`, add\n `@pantoken/components/dist/component-icons.css`. Use the full token sheet only when arbitrary\n icon tokens are required.\n7. If a component has JavaScript capability, load its per-component\n `@pantoken/interactions/dist/<name>.iife.js` after the markup and include entries from `requires`\n first. Do not load the aggregate interaction bundle unless many interactive components need it.\n8. Use `var(--instui-*)` for custom styling and never invent token names.\n\nFor a disposable preview, a major-version CDN pin is acceptable. Use exact versions for an artifact\nthat will be retained. If the user explicitly requires a fully offline file, fetch the selected CSS\nand JavaScript and inline it into `<style>` and `<script>` blocks.\n\nOpen the final file in a browser and verify styles, icons, responsive layout, keyboard interaction,\nand that every referenced asset loads. Give the user a link to the HTML file; do not start a server.\n\n## 3. Sendable HTML email\n\nDo not use Pantoken component CSS, the shadcn registry, CSS custom properties, JavaScript, custom\nelements, or icon-font masks. Email clients do not reliably support those features.\n\n1. Resolve values from `@pantoken/email` using `emailTokens(\"light\")` or the requested mode. If the\n current directory is not a package-managed project, use a temporary package-runner environment;\n do not leave a package manifest or dependency tree beside the final HTML.\n2. Build conservative table-based email markup with presentation-critical styles inline.\n3. Interpolate concrete colors and dimensions from the returned camel-cased token map. The final\n HTML must not contain `var(--instui-*)`.\n4. Use hosted raster images with dimensions and meaningful `alt` text for logos or icons. Do not use\n Pantoken custom elements or CSS glyph painters.\n5. Include a descriptive `<title>`, preheader text, semantic headings, readable fallback fonts, and\n a plain text link for every call to action.\n6. Validate that the final file contains no `<script>`, custom elements, external Pantoken\n stylesheets, or unresolved token references. Note that Gmail, Outlook, and production email\n preview testing remains the sender's responsibility.\n\n## 4. Keep the artifact focused\n\nDo not add explanatory UI, setup instructions, package files, or a framework shell to the rendered\nartifact. Use Pantoken to serve the requested communication or prototype, not to advertise the\ndesign system.\n",
745
+ "registrySkill": "---\nname: use-pantoken-registry\ndescription: Use Pantoken's shadcn/ui registry to search, inspect, and add CSS-backed registry items. Use when a project has components.json, the user asks for shadcn registry items, or the user wants to browse Pantoken registry styles. Do not use as a general Pantoken app setup skill; use create-pantoken-app for non-registry package wiring.\n---\n\n# Use the Pantoken registry\n\nUse Pantoken's shadcn/ui registry when the project already uses shadcn/ui, has `components.json`,\nor the user explicitly asks for Pantoken registry items. Registry items install CSS, usage metadata,\nand package dependencies; they are not React components.\n\nIf the project is not a shadcn project and the user did not ask for the registry, stop and use\n`create-pantoken-app` instead.\n\n## 1. Confirm registry fit\n\nUse the registry only when one of these is true:\n\n- The repo contains `components.json`.\n- The user asks for shadcn, registry items, or `shadcn add`.\n- The task is to inspect Pantoken registry metadata.\n\nIf the user needs full interactive React components, use `@instructure/ui-*` packages. Pantoken's\nregistry provides CSS-backed styles and metadata, not component implementations.\n\n## 2. Use the project runner\n\nDetect the package manager from lockfiles and substitute its runner for `npx`:\n\n| Lockfile found | Runner |\n| -------------------------- | --------------- |\n| `pnpm-lock.yaml` | `pnpm dlx` |\n| `yarn.lock` | `yarn dlx` |\n| `bun.lock`/`bun.lockb` | `bunx` |\n| `deno.lock` | `deno run npm:` |\n| `package-lock.json` / none | `npx` |\n\n## 3. Search, inspect, add\n\nPrefer the shadcn CLI for live registry operations:\n\n```sh\nnpx shadcn@latest search @pantoken --query <need>\nnpx shadcn@latest view @pantoken/<item>\nnpx shadcn@latest add @pantoken/<item>\n```\n\nFor URL-capable agents, fetch the manifest first when you need to browse available entries:\n\n```text\nhttps://pantoken.app/r/registry.json\n```\n\nThen inspect the item JSON before adding when the choice is not obvious:\n\n```text\nhttps://pantoken.app/r/<item>.json\n```\n\n## 4. Explain what changed\n\nAfter adding an item, summarize:\n\n- Which registry item was installed.\n- Which files the shadcn CLI wrote or changed.\n- Any dependencies the registry item added.\n- That future styling should still use real `--instui-*` token names and `var(--instui-*)`\n references rather than invented token names.\n\nIf the registry item does not satisfy the task, fall back to the normal package guidance in\n`create-pantoken-app` and explain why the registry path was not enough.\n"
753
746
  };
754
747
  //#endregion
755
748
  //#region src/agent-assets.ts
@@ -793,6 +786,14 @@ const TARGETS = {
793
786
  file: ".claude/skills/create-pantoken-app/SKILL.md",
794
787
  content: ASSETS.createAppSkill
795
788
  },
789
+ {
790
+ file: ".claude/skills/create-pantoken-mockup/SKILL.md",
791
+ content: ASSETS.createMockupSkill
792
+ },
793
+ {
794
+ file: ".claude/skills/use-pantoken-registry/SKILL.md",
795
+ content: ASSETS.registrySkill
796
+ },
796
797
  {
797
798
  file: "AGENTS.md",
798
799
  content: ASSETS.agents
@@ -959,6 +960,10 @@ function themeCssAssets(theme = "rebrand", mode = "light") {
959
960
  {
960
961
  package: "@pantoken/components",
961
962
  path: "dist/utilities.css"
963
+ },
964
+ {
965
+ package: "@pantoken/plugin-custom-theme-colors",
966
+ path: "dist/custom-theme-colors.scoped.css"
962
967
  }
963
968
  ];
964
969
  }