@pantoken/scaffold 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.mts +4 -2
- package/dist/cli.mjs +23 -11
- package/dist/{index-D2-Dhvt8.d.mts → index-BloHpRKt.d.mts} +15 -16
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{src-DxBSPAO9.mjs → src-BTDVd_Xe.mjs} +147 -66
- package/package.json +7 -7
package/dist/cli.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as resolveScaffoldPlatform, c as ThemeVariant, i as isScaffoldPlatform, n as ScaffoldPackageManager, o as scaffoldProject, s as ThemeMode, t as SCAFFOLD_PLATFORMS } from "./index-BloHpRKt.mjs";
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
//#region src/locale.d.ts
|
|
4
4
|
/** Every locale tag pantoken supports, as `--lang` accepts them. */
|
|
@@ -116,6 +116,7 @@ export declare function scaffoldWithSpinner(platform: string, dir: string, t: Lo
|
|
|
116
116
|
mode?: ThemeMode;
|
|
117
117
|
cdn?: string;
|
|
118
118
|
locale?: string;
|
|
119
|
+
packageManager?: ScaffoldPackageManager;
|
|
119
120
|
}): Promise<string[]>;
|
|
120
121
|
/** Package managers `detectPackageManager` can identify. */
|
|
121
122
|
export type PackageManager = "npm" | "pnpm" | "yarn" | "bun" | "deno" | "vp";
|
|
@@ -156,7 +157,8 @@ export declare function installWithSpinner(dir: string, pm: PackageManager | und
|
|
|
156
157
|
* needed — regardless of platform. Otherwise, when `platform` has a `scaffold.json`-derived entry in
|
|
157
158
|
* `SCAFFOLD_METADATA`, next steps/notes/caveats are rendered from its (localized, `{{var}}`-
|
|
158
159
|
* substituted) authored strings; failing that, a generic cd/install/run-script fallback is used,
|
|
159
|
-
* with the run script itself detected from the scaffolded `package.json` (`dev`, else `preview`)
|
|
160
|
+
* with the run script itself detected from the scaffolded `package.json` (`dev`, else `preview`)
|
|
161
|
+
* or defaulted to `dev` for scaffolded app templates.
|
|
160
162
|
*
|
|
161
163
|
* @param dir - The scaffold directory
|
|
162
164
|
* @param written - The paths written by scaffoldProject
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { c as SUPPORTED_LOCALES, d as validateLocaleTag, i as scaffoldProject, l as createLocaleLookup, n as isScaffoldPlatform, o as validateThemeMode, r as resolveScaffoldPlatform, s as validateThemeVariant, t as SCAFFOLD_PLATFORMS, u as detectLocale } from "./src-
|
|
1
|
+
import { c as SUPPORTED_LOCALES, d as validateLocaleTag, i as scaffoldProject, l as createLocaleLookup, n as isScaffoldPlatform, o as validateThemeMode, r as resolveScaffoldPlatform, s as validateThemeVariant, t as SCAFFOLD_PLATFORMS, u as detectLocale } from "./src-BTDVd_Xe.mjs";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { basename, join } from "node:path";
|
|
4
|
-
import { CDN_PROVIDERS } from "@pantoken/canvas-theme-editor";
|
|
5
4
|
import { Argument, Command, CommanderError, InvalidArgumentError } from "commander";
|
|
6
5
|
import { cancel, isCancel, select, spinner, text } from "@clack/prompts";
|
|
7
6
|
import tab from "@bomb.sh/tab/commander";
|
|
@@ -2760,6 +2759,7 @@ function detectPackageManager(env, execPath) {
|
|
|
2760
2759
|
if (userAgent.includes("bun")) return "bun";
|
|
2761
2760
|
if (userAgent.includes("deno")) return "deno";
|
|
2762
2761
|
if (userAgent.includes("npm")) return "npm";
|
|
2762
|
+
if ("Deno" in globalThis) return "deno";
|
|
2763
2763
|
if ((execPath ?? process.execPath).includes("vite-plus")) return "vp";
|
|
2764
2764
|
}
|
|
2765
2765
|
/** Fully-composed command fragments per package manager, so callers never hand-compose them. */
|
|
@@ -2827,7 +2827,12 @@ function buildCreateUsageCommand(pm) {
|
|
|
2827
2827
|
* @returns Whether the install command exited successfully
|
|
2828
2828
|
*/
|
|
2829
2829
|
function installWithSpinner(dir, pm, t) {
|
|
2830
|
-
const
|
|
2830
|
+
const npmExecPath = pm === "npm" ? process.env.npm_execpath : void 0;
|
|
2831
|
+
const [command, ...args] = npmExecPath ? [
|
|
2832
|
+
process.execPath,
|
|
2833
|
+
npmExecPath,
|
|
2834
|
+
"install"
|
|
2835
|
+
] : pmCommands(pm).install.split(" ");
|
|
2831
2836
|
const s = spinner();
|
|
2832
2837
|
s.start(t("installSpinnerStart"));
|
|
2833
2838
|
try {
|
|
@@ -2874,7 +2879,8 @@ function buildDevStep(dir, dev) {
|
|
|
2874
2879
|
* needed — regardless of platform. Otherwise, when `platform` has a `scaffold.json`-derived entry in
|
|
2875
2880
|
* `SCAFFOLD_METADATA`, next steps/notes/caveats are rendered from its (localized, `{{var}}`-
|
|
2876
2881
|
* substituted) authored strings; failing that, a generic cd/install/run-script fallback is used,
|
|
2877
|
-
* with the run script itself detected from the scaffolded `package.json` (`dev`, else `preview`)
|
|
2882
|
+
* with the run script itself detected from the scaffolded `package.json` (`dev`, else `preview`)
|
|
2883
|
+
* or defaulted to `dev` for scaffolded app templates.
|
|
2878
2884
|
*
|
|
2879
2885
|
* @param dir - The scaffold directory
|
|
2880
2886
|
* @param written - The paths written by scaffoldProject
|
|
@@ -2885,8 +2891,7 @@ function buildDevStep(dir, dev) {
|
|
|
2885
2891
|
function printNextSteps(dir, written, t, platform, installed) {
|
|
2886
2892
|
const pm = detectPackageManager();
|
|
2887
2893
|
const { install, run } = pmCommands(pm);
|
|
2888
|
-
const
|
|
2889
|
-
const dev = script ? `${run} ${script}` : t("nextStepsDevServer");
|
|
2894
|
+
const dev = `${run} ${detectRunScript(written) ?? "dev"}`;
|
|
2890
2895
|
const vars = {
|
|
2891
2896
|
dir,
|
|
2892
2897
|
pm: pm ?? "npm",
|
|
@@ -2926,8 +2931,13 @@ function validateScaffoldPlatform(value) {
|
|
|
2926
2931
|
* @throws InvalidArgumentError if the value isn't a known CDN provider id
|
|
2927
2932
|
*/
|
|
2928
2933
|
function validateCdnProviderId(value) {
|
|
2929
|
-
|
|
2930
|
-
|
|
2934
|
+
const providers = [
|
|
2935
|
+
"jsdelivr",
|
|
2936
|
+
"unpkg",
|
|
2937
|
+
"esmsh"
|
|
2938
|
+
];
|
|
2939
|
+
if (providers.includes(value)) return value;
|
|
2940
|
+
throw new InvalidArgumentError(`CDN provider "${value}" is not valid. Expected one of: ${providers.join(", ")}.`);
|
|
2931
2941
|
}
|
|
2932
2942
|
/**
|
|
2933
2943
|
* Builds the full, ready-to-parse commander Command for pantoken-scaffold/create-pantoken-app.
|
|
@@ -2953,19 +2963,21 @@ function createScaffoldCommand(options) {
|
|
|
2953
2963
|
t
|
|
2954
2964
|
});
|
|
2955
2965
|
const expandedDir = expandHome(dir);
|
|
2966
|
+
const packageManager = detectPackageManager();
|
|
2956
2967
|
const written = await scaffoldWithSpinner(platform, expandedDir, t, {
|
|
2957
2968
|
theme: opts.theme,
|
|
2958
2969
|
mode: opts.themeMode,
|
|
2959
2970
|
cdn: opts.cdn,
|
|
2960
|
-
locale
|
|
2971
|
+
locale,
|
|
2972
|
+
packageManager
|
|
2961
2973
|
});
|
|
2962
2974
|
for (const path of written) console.log(t("wroteFile", { path }));
|
|
2975
|
+
const installed = opts.install !== false && installWithSpinner(expandedDir, packageManager, t);
|
|
2963
2976
|
let printDir = expandedDir;
|
|
2964
|
-
if (expandedDir !== ".") try {
|
|
2977
|
+
if (installed && expandedDir !== ".") try {
|
|
2965
2978
|
process.chdir(expandedDir);
|
|
2966
2979
|
printDir = ".";
|
|
2967
2980
|
} catch {}
|
|
2968
|
-
const installed = opts.install !== false && installWithSpinner(expandedDir, detectPackageManager(), t);
|
|
2969
2981
|
printNextSteps(printDir, written, t, resolveScaffoldPlatform(platform), installed);
|
|
2970
2982
|
} catch (err) {
|
|
2971
2983
|
if (err instanceof ScaffoldCliError) throw err;
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Registry of all available pantoken scaffold presets, keyed by platform name.
|
|
5
|
-
*/
|
|
6
|
-
declare const PRESET_LEDGER: Record<string, Preset>;
|
|
1
|
+
//#region generated/scaffolds.d.ts
|
|
2
|
+
declare const SCAFFOLDS: Record<string, Record<string, string>>;
|
|
7
3
|
//#endregion
|
|
8
4
|
//#region src/theme.d.ts
|
|
9
5
|
/** A pantoken token theme variant. */
|
|
@@ -26,11 +22,19 @@ declare function validateThemeVariant(value: string): ThemeVariant;
|
|
|
26
22
|
declare function validateThemeMode(value: string): ThemeMode;
|
|
27
23
|
//#endregion
|
|
28
24
|
//#region src/index.d.ts
|
|
25
|
+
/** Package managers whose commands can be reflected in scaffolded project files. */
|
|
26
|
+
type ScaffoldPackageManager = "npm" | "pnpm" | "yarn" | "bun" | "deno" | "vp";
|
|
27
|
+
interface ScaffoldProjectOptions {
|
|
28
|
+
theme?: ThemeVariant;
|
|
29
|
+
mode?: ThemeMode;
|
|
30
|
+
cdn?: string;
|
|
31
|
+
locale?: string;
|
|
32
|
+
packageManager?: ScaffoldPackageManager;
|
|
33
|
+
}
|
|
29
34
|
/**
|
|
30
|
-
* A platform pantoken can scaffold a starter project for
|
|
31
|
-
* or a legacy template-only entry (e.g. `canvas-theme-editor`) with no preset yet.
|
|
35
|
+
* A platform pantoken can scaffold a starter project for.
|
|
32
36
|
*/
|
|
33
|
-
type ScaffoldPlatform = keyof typeof
|
|
37
|
+
type ScaffoldPlatform = keyof typeof SCAFFOLDS;
|
|
34
38
|
/**
|
|
35
39
|
* Every scaffoldable platform key (discovered from available presets, plus any legacy
|
|
36
40
|
* template-only platforms not yet backed by a preset).
|
|
@@ -74,11 +78,6 @@ declare function resolveScaffoldPlatform(platform: string): ScaffoldPlatform;
|
|
|
74
78
|
* scaffoldProject("vue", "./my-vue-app", { theme: "canvas", locale: "hu" });
|
|
75
79
|
* ```
|
|
76
80
|
*/
|
|
77
|
-
declare function scaffoldProject(platform: string, dir?: string, options?:
|
|
78
|
-
theme?: ThemeVariant;
|
|
79
|
-
mode?: ThemeMode;
|
|
80
|
-
cdn?: string;
|
|
81
|
-
locale?: string;
|
|
82
|
-
}): Promise<string[]>;
|
|
81
|
+
declare function scaffoldProject(platform: string, dir?: string, options?: ScaffoldProjectOptions): Promise<string[]>;
|
|
83
82
|
//#endregion
|
|
84
|
-
export {
|
|
83
|
+
export { resolveScaffoldPlatform as a, ThemeVariant as c, validateThemeVariant as d, isScaffoldPlatform as i, themeStylesheetImport as l, ScaffoldPackageManager as n, scaffoldProject as o, ScaffoldPlatform as r, ThemeMode as s, SCAFFOLD_PLATFORMS as t, validateThemeMode as u };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { SCAFFOLD_PLATFORMS, ScaffoldPlatform, type ThemeMode, type ThemeVariant, isScaffoldPlatform, resolveScaffoldPlatform, scaffoldProject, themeStylesheetImport, validateThemeMode, validateThemeVariant };
|
|
1
|
+
import { a as resolveScaffoldPlatform, c as ThemeVariant, d as validateThemeVariant, i as isScaffoldPlatform, l as themeStylesheetImport, n as ScaffoldPackageManager, o as scaffoldProject, r as ScaffoldPlatform, s as ThemeMode, t as SCAFFOLD_PLATFORMS, u as validateThemeMode } from "./index-BloHpRKt.mjs";
|
|
2
|
+
export { SCAFFOLD_PLATFORMS, ScaffoldPackageManager, ScaffoldPlatform, type ThemeMode, type ThemeVariant, isScaffoldPlatform, resolveScaffoldPlatform, scaffoldProject, themeStylesheetImport, validateThemeMode, validateThemeVariant };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as themeStylesheetImport, i as scaffoldProject, n as isScaffoldPlatform, o as validateThemeMode, r as resolveScaffoldPlatform, s as validateThemeVariant, t as SCAFFOLD_PLATFORMS } from "./src-
|
|
1
|
+
import { a as themeStylesheetImport, i as scaffoldProject, n as isScaffoldPlatform, o as validateThemeMode, r as resolveScaffoldPlatform, s as validateThemeVariant, t as SCAFFOLD_PLATFORMS } from "./src-BTDVd_Xe.mjs";
|
|
2
2
|
export { SCAFFOLD_PLATFORMS, isScaffoldPlatform, resolveScaffoldPlatform, scaffoldProject, themeStylesheetImport, validateThemeMode, validateThemeVariant };
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
-
import { producePreset } from "bingo-stratum";
|
|
4
|
-
import { buildTheme } from "@pantoken/canvas-theme-editor";
|
|
5
|
-
import { presetComponents } from "@pantoken/components/scaffold-preset";
|
|
6
|
-
import { presetReact } from "@pantoken/react/scaffold-preset";
|
|
7
|
-
import { presetVue } from "@pantoken/vue/scaffold-preset";
|
|
8
|
-
import { presetWebComponents } from "@pantoken/web-components/scaffold-preset";
|
|
9
|
-
import { presetAngular } from "@pantoken/angular/scaffold-preset";
|
|
10
|
-
import { presetSvelte } from "@pantoken/svelte/scaffold-preset";
|
|
11
3
|
import { InvalidArgumentError } from "commander";
|
|
12
4
|
//#region generated/scaffolds.ts
|
|
13
5
|
const SCAFFOLDS = {
|
|
@@ -15,8 +7,8 @@ const SCAFFOLDS = {
|
|
|
15
7
|
".gitignore": "node_modules\ndist\n",
|
|
16
8
|
"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 behaviors 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",
|
|
17
9
|
"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}}</title>\n </head>\n <body class=\"instui-display-flex\">\n <app-root></app-root>\n <script type=\"module\" src=\"/src/main.ts\"><\/script>\n </body>\n</html>\n",
|
|
18
|
-
"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 \"@angular/common\": \"^22.1.3\",\n \"@angular/compiler\": \"^22.1.3\",\n \"@angular/core\": \"^22.1.3\",\n \"@angular/platform-browser\": \"^22.1.3\",\n \"@pantoken/angular\": \"latest\",\n \"@pantoken/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"rxjs\": \"^7.8.2\",\n \"zone.js\": \"^0.16.2\"\n },\n \"devDependencies\": {\n \"@analogjs/vite-plugin-angular\": \"^2.7.0\",\n \"@pantoken/pantoken\": \"latest\",\n \"typescript\": \"^7.0.2\",\n \"vite\": \"^8.2.2\"\n },\n \"allowScripts\": {\n \"core-js\": true,\n \"ttf2woff2\": true\n },\n \"trustedDependencies\": [\n \"core-js\",\n \"ttf2woff2\"\n ]\n}\n",
|
|
19
|
-
"pnpm-workspace.yaml": "# core-js/ttf2woff2 arrive transitively
|
|
10
|
+
"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 \"@angular/common\": \"^22.1.3\",\n \"@angular/compiler\": \"^22.1.3\",\n \"@angular/core\": \"^22.1.3\",\n \"@angular/platform-browser\": \"^22.1.3\",\n \"@pantoken/angular\": \"latest\",\n \"@pantoken/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"rxjs\": \"^7.8.2\",\n \"zone.js\": \"^0.16.2\"\n },\n \"devDependencies\": {\n \"@analogjs/vite-plugin-angular\": \"^2.7.0\",\n \"@pantoken/pantoken\": \"latest\",\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",
|
|
11
|
+
"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",
|
|
20
12
|
"tsconfig.json": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"module\": \"ESNext\",\n \"moduleResolution\": \"Bundler\",\n \"experimentalDecorators\": true,\n \"useDefineForClassFields\": false,\n \"types\": [\"vite/client\"],\n \"strict\": true,\n \"skipLibCheck\": true\n },\n \"include\": [\"src\"]\n}\n",
|
|
21
13
|
"vite.config.ts": "import angular from \"@analogjs/vite-plugin-angular\";\nimport { defineConfig } from \"vite\";\n\nexport default defineConfig({\n plugins: [angular()],\n});\n",
|
|
22
14
|
".vscode/extensions.json": "{\n \"recommendations\": [\"cssdoc.cssdoc-vscode\", \"angular.ng-template\"]\n}\n",
|
|
@@ -29,8 +21,8 @@ const SCAFFOLDS = {
|
|
|
29
21
|
".gitignore": "node_modules\ndist\n",
|
|
30
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",
|
|
31
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",
|
|
32
|
-
"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 \"ttf2woff2\": true\n },\n \"trustedDependencies\": [\n \"core-js\",\n \"ttf2woff2\"\n ]\n}\n",
|
|
33
|
-
"pnpm-workspace.yaml": "# core-js/ttf2woff2 arrive transitively
|
|
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",
|
|
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",
|
|
34
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",
|
|
35
27
|
"vite.config.ts": "import { defineConfig } from \"vite\";\n\nexport default defineConfig({});\n",
|
|
36
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",
|
|
@@ -43,8 +35,8 @@ const SCAFFOLDS = {
|
|
|
43
35
|
".gitignore": "node_modules\ndist\n",
|
|
44
36
|
"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 behaviors out of the box), and your own `src/style.css` — add interactive behavior 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",
|
|
45
37
|
"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}}</title>\n </head>\n <body class=\"instui-display-flex\">\n <div class=\"container\">\n <div class=\"header\">\n <div class=\"top\">\n <!-- breadcrumb -->\n <div class=\"utilities\"> <!-- optional -->\n <button class=\"instui-button\"></button>\n </div>\n </div>\n <div class=\"info\">\n <div class=\"title\">\n {{projectName}}\n </div>\n <div class=\"description\"> <!-- optional -->\n Styled with <code>@pantoken/components</code>.\n </div>\n </div>\n <div data-slot=\"header\"></div> <!-- optional -->\n <div class=\"actions\"> <!-- optional -->\n <button class=\"instui-button\"></button>\n </div>\n <div class=\"tabs\"> <!-- optional -->\n <!-- tabs -->\n </div>\n <div class=\"filters\"> <!-- optional -->\n <div data-slot=\"filters\"></div>\n </div>\n </div>\n <div class=\"content\">\n <div class=\"list\"></div> <!-- optional -->\n <div class=\"main\" data-slot=\"content\">\n <p>Get started building with pantoken.</p>\n <button class=\"instui-button -color-primary\" type=\"button\">Get started</button>\n </div>\n <div class=\"trailing\" data-slot=\"trailing\"></div> <!-- optional -->\n </div>\n </div>\n <script type=\"module\" src=\"/src/main.ts\"><\/script>\n </body>\n</html>\n",
|
|
46
|
-
"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/components\": \"latest\",\n \"@pantoken/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\n \"typescript\": \"^7.0.2\",\n \"vite\": \"^8.2.2\"\n },\n \"allowScripts\": {\n \"core-js\": true,\n \"ttf2woff2\": true\n },\n \"trustedDependencies\": [\n \"core-js\",\n \"ttf2woff2\"\n ]\n}\n",
|
|
47
|
-
"pnpm-workspace.yaml": "# core-js/ttf2woff2 arrive transitively
|
|
38
|
+
"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/components\": \"latest\",\n \"@pantoken/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\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",
|
|
39
|
+
"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",
|
|
48
40
|
"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 },\n \"include\": [\"src\"]\n}\n",
|
|
49
41
|
"vite.config.ts": "import { defineConfig } from \"vite\";\n\nexport default defineConfig({});\n",
|
|
50
42
|
".vscode/extensions.json": "{\n \"recommendations\": [\"cssdoc.cssdoc-vscode\"]\n}\n",
|
|
@@ -57,8 +49,8 @@ const SCAFFOLDS = {
|
|
|
57
49
|
".gitignore": "node_modules\n.next\n",
|
|
58
50
|
"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 behaviors 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",
|
|
59
51
|
"next.config.mjs": "import { withPantoken } from \"@pantoken/next\";\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nexport default withPantoken(nextConfig);\n",
|
|
60
|
-
"package.json": "{\n \"name\": \"{{projectName}}\",\n \"version\": \"0.0.0\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"next dev\",\n \"build\": \"next build\",\n \"start\": \"next start\"\n },\n \"dependencies\": {\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/next\": \"latest\",\n \"next\": \"^16.2.11\",\n \"react\": \"^19.2.8\",\n \"react-dom\": \"^19.2.8\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\n \"typescript\": \"^7.0.2\"\n },\n \"allowScripts\": {\n \"core-js\": true,\n \"ttf2woff2\": true\n },\n \"trustedDependencies\": [\n \"core-js\",\n \"ttf2woff2\"\n ]\n}\n",
|
|
61
|
-
"pnpm-workspace.yaml": "# core-js/ttf2woff2 arrive transitively
|
|
52
|
+
"package.json": "{\n \"name\": \"{{projectName}}\",\n \"version\": \"0.0.0\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"next dev\",\n \"build\": \"next build\",\n \"start\": \"next start\"\n },\n \"dependencies\": {\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/next\": \"latest\",\n \"next\": \"^16.2.11\",\n \"react\": \"^19.2.8\",\n \"react-dom\": \"^19.2.8\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\n \"typescript\": \"^7.0.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",
|
|
53
|
+
"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",
|
|
62
54
|
"tsconfig.json": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"module\": \"ESNext\",\n \"moduleResolution\": \"Bundler\",\n \"jsx\": \"preserve\",\n \"strict\": true,\n \"skipLibCheck\": true,\n \"plugins\": [{ \"name\": \"next\" }]\n },\n \"include\": [\"app\", \"next-env.d.ts\"]\n}\n",
|
|
63
55
|
".vscode/extensions.json": "{\n \"recommendations\": [\"cssdoc.cssdoc-vscode\"]\n}\n",
|
|
64
56
|
".vscode/settings.json": "{\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",
|
|
@@ -71,8 +63,8 @@ const SCAFFOLDS = {
|
|
|
71
63
|
".gitignore": "node_modules\ndist\n",
|
|
72
64
|
"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 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",
|
|
73
65
|
"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}}</title>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"/src/main.tsx\"><\/script>\n </body>\n</html>\n",
|
|
74
|
-
"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/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/react\": \"latest\",\n \"react\": \"^19.2.8\",\n \"react-dom\": \"^19.2.8\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\n \"@types/react\": \"^19.2.18\",\n \"@types/react-dom\": \"^19.2.5\",\n \"@vitejs/plugin-react\": \"^6.1.0\",\n \"typescript\": \"^7.0.2\",\n \"vite\": \"^8.2.2\"\n },\n \"allowScripts\": {\n \"core-js\": true,\n \"ttf2woff2\": true\n },\n \"trustedDependencies\": [\n \"core-js\",\n \"ttf2woff2\"\n ]\n}\n",
|
|
75
|
-
"pnpm-workspace.yaml": "# core-js/ttf2woff2 arrive transitively
|
|
66
|
+
"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/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/react\": \"latest\",\n \"react\": \"^19.2.8\",\n \"react-dom\": \"^19.2.8\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\n \"@types/react\": \"^19.2.18\",\n \"@types/react-dom\": \"^19.2.5\",\n \"@vitejs/plugin-react\": \"^6.1.0\",\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",
|
|
67
|
+
"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",
|
|
76
68
|
"tsconfig.json": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"module\": \"ESNext\",\n \"moduleResolution\": \"Bundler\",\n \"jsx\": \"react-jsx\",\n \"types\": [\"vite/client\"],\n \"strict\": true,\n \"skipLibCheck\": true\n },\n \"include\": [\"src\"]\n}\n",
|
|
77
69
|
"vite.config.ts": "import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\nexport default defineConfig({\n plugins: [react()],\n});\n",
|
|
78
70
|
".vscode/extensions.json": "{\n \"recommendations\": [\"cssdoc.cssdoc-vscode\"]\n}\n",
|
|
@@ -85,8 +77,8 @@ const SCAFFOLDS = {
|
|
|
85
77
|
".gitignore": "node_modules\ndist\n",
|
|
86
78
|
"README.md": "# {{projectName}}\n\nA Vite + Svelte app styled with [`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components)\nand [`@pantoken/svelte`](https://www.npmjs.com/package/@pantoken/svelte) (icon action + token reads).\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.ts` calls `register()` (from `@pantoken/svelte`) once at bootstrap 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 behaviors out of the box).\n- `src/App.svelte`'s markup 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",
|
|
87
79
|
"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}}</title>\n </head>\n <body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/src/main.ts\"><\/script>\n </body>\n</html>\n",
|
|
88
|
-
"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/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/svelte\": \"latest\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\n \"@sveltejs/vite-plugin-svelte\": \"^7.3.0\",\n \"svelte\": \"^5.56.10\",\n \"typescript\": \"^7.0.2\",\n \"vite\": \"^8.2.2\"\n },\n \"allowScripts\": {\n \"core-js\": true,\n \"ttf2woff2\": true\n },\n \"trustedDependencies\": [\n \"core-js\",\n \"ttf2woff2\"\n ]\n}\n",
|
|
89
|
-
"pnpm-workspace.yaml": "# core-js/ttf2woff2 arrive transitively
|
|
80
|
+
"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/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/svelte\": \"latest\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\n \"@sveltejs/vite-plugin-svelte\": \"^7.3.0\",\n \"svelte\": \"^5.56.10\",\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",
|
|
81
|
+
"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",
|
|
90
82
|
"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 },\n \"include\": [\"src\"]\n}\n",
|
|
91
83
|
"vite.config.ts": "import { defineConfig } from \"vite\";\nimport { svelte } from \"@sveltejs/vite-plugin-svelte\";\n\nexport default defineConfig({\n plugins: [svelte()],\n});\n",
|
|
92
84
|
".vscode/extensions.json": "{\n \"recommendations\": [\"cssdoc.cssdoc-vscode\", \"svelte.svelte-vscode\"]\n}\n",
|
|
@@ -99,8 +91,8 @@ const SCAFFOLDS = {
|
|
|
99
91
|
".gitignore": "node_modules\ndist\n",
|
|
100
92
|
"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 behaviors 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",
|
|
101
93
|
"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}}</title>\n </head>\n <body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/src/main.ts\"><\/script>\n </body>\n</html>\n",
|
|
102
|
-
"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/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/vue\": \"latest\",\n \"vue\": \"^3.5.41\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\n \"@vitejs/plugin-vue\": \"^6.0.8\",\n \"typescript\": \"^7.0.2\",\n \"vite\": \"^8.2.2\",\n \"vue-tsc\": \"^3.3.11\"\n },\n \"allowScripts\": {\n \"core-js\": true,\n \"ttf2woff2\": true\n },\n \"trustedDependencies\": [\n \"core-js\",\n \"ttf2woff2\"\n ]\n}\n",
|
|
103
|
-
"pnpm-workspace.yaml": "# core-js/ttf2woff2 arrive transitively
|
|
94
|
+
"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/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/vue\": \"latest\",\n \"vue\": \"^3.5.41\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\n \"@vitejs/plugin-vue\": \"^6.0.8\",\n \"typescript\": \"^7.0.2\",\n \"vite\": \"^8.2.2\",\n \"vue-tsc\": \"^3.3.11\"\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",
|
|
95
|
+
"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",
|
|
104
96
|
"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 },\n \"include\": [\"src\"]\n}\n",
|
|
105
97
|
"vite.config.ts": "import { defineConfig } from \"vite\";\nimport vue from \"@vitejs/plugin-vue\";\n\nexport default defineConfig({\n plugins: [vue()],\n});\n",
|
|
106
98
|
".vscode/extensions.json": "{\n \"recommendations\": [\"cssdoc.cssdoc-vscode\", \"Vue.volar\"]\n}\n",
|
|
@@ -113,8 +105,8 @@ const SCAFFOLDS = {
|
|
|
113
105
|
".gitignore": "node_modules\ndist\n",
|
|
114
106
|
"README.md": "# {{projectName}}\n\nA plain TypeScript app (via Vite) styled with\n[`@pantoken/components`](https://www.npmjs.com/package/@pantoken/components) and using\nframework-agnostic custom elements from\n[`@pantoken/web-components`](https://www.npmjs.com/package/@pantoken/web-components).\n\n## Develop\n\n```sh\nnpm install\nnpm run dev\n```\n\n## What's here\n\n- `src/main.ts` imports `@pantoken/css` (defines every `--instui-*` custom property),\n `@pantoken/components/base.css` + `components.css` (`.instui-*` classes),\n `@pantoken/interactions` (wires up modal, tooltip, and other component behaviors out of the\n box), and `@pantoken/web-components` (auto-registers elements like `<instui-icon>`), then\n renders markup into `#app`.\n- Optional insertion points (header, filters, content, trailing) are marked with\n `<div data-slot=\"...\">` — replace their contents with your own markup.\n- Use custom elements directly in markup, e.g. `<instui-button>`, `<instui-alert variant=\"success\">` —\n see the [`@pantoken/web-components` README](https://www.npmjs.com/package/@pantoken/web-components)\n for the full element list.\n\n## Learn more\n\nSee the [HTML guide](https://pantoken.app/guide/components) to learn more.\n",
|
|
115
107
|
"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}}</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",
|
|
116
|
-
"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/components\": \"latest\",\n \"@pantoken/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/web-components\": \"latest\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\n \"typescript\": \"^7.0.2\",\n \"vite\": \"^8.2.2\"\n },\n \"allowScripts\": {\n \"core-js\": true,\n \"ttf2woff2\": true\n },\n \"trustedDependencies\": [\n \"core-js\",\n \"ttf2woff2\"\n ]\n}\n",
|
|
117
|
-
"pnpm-workspace.yaml": "# core-js/ttf2woff2 arrive transitively
|
|
108
|
+
"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/components\": \"latest\",\n \"@pantoken/css\": \"latest\",\n \"@pantoken/interactions\": \"latest\",\n \"@pantoken/web-components\": \"latest\"\n },\n \"devDependencies\": {\n \"@pantoken/pantoken\": \"latest\",\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",
|
|
109
|
+
"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",
|
|
118
110
|
"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 },\n \"include\": [\"src\"]\n}\n",
|
|
119
111
|
"vite.config.ts": "import { defineConfig } from \"vite\";\n\nexport default defineConfig({});\n",
|
|
120
112
|
".vscode/extensions.json": "{\n \"recommendations\": [\"cssdoc.cssdoc-vscode\"]\n}\n",
|
|
@@ -567,19 +559,6 @@ const SCAFFOLD_OVERLAYS = {
|
|
|
567
559
|
}
|
|
568
560
|
};
|
|
569
561
|
//#endregion
|
|
570
|
-
//#region generated/preset-ledger.ts
|
|
571
|
-
/**
|
|
572
|
-
* Registry of all available pantoken scaffold presets, keyed by platform name.
|
|
573
|
-
*/
|
|
574
|
-
const PRESET_LEDGER = {
|
|
575
|
-
"components": presetComponents,
|
|
576
|
-
"react": presetReact,
|
|
577
|
-
"vue": presetVue,
|
|
578
|
-
"web-components": presetWebComponents,
|
|
579
|
-
"angular": presetAngular,
|
|
580
|
-
"svelte": presetSvelte
|
|
581
|
-
};
|
|
582
|
-
//#endregion
|
|
583
562
|
//#region generated/locale-registry.ts
|
|
584
563
|
/** Text direction per supported BCP47 tag; its keys are the tags `--lang` accepts. */
|
|
585
564
|
const LOCALE_DIRS = {
|
|
@@ -768,11 +747,50 @@ function validateThemeMode(value) {
|
|
|
768
747
|
* installed and wired in. Standalone; usable via `npx @pantoken/scaffold <platform>` without
|
|
769
748
|
* `@pantoken/ai`.
|
|
770
749
|
*
|
|
771
|
-
* Powered by
|
|
750
|
+
* Powered by generated template strings so the published CLI stays lean and package-manager-safe.
|
|
772
751
|
*
|
|
773
752
|
* @module
|
|
774
753
|
* @alpha
|
|
775
754
|
*/
|
|
755
|
+
const SCAFFOLD_PM_COMMANDS = {
|
|
756
|
+
npm: {
|
|
757
|
+
install: "npm install",
|
|
758
|
+
dev: "npm run dev"
|
|
759
|
+
},
|
|
760
|
+
pnpm: {
|
|
761
|
+
install: "pnpm install",
|
|
762
|
+
dev: "pnpm run dev"
|
|
763
|
+
},
|
|
764
|
+
yarn: {
|
|
765
|
+
install: "yarn install",
|
|
766
|
+
dev: "yarn run dev"
|
|
767
|
+
},
|
|
768
|
+
bun: {
|
|
769
|
+
install: "bun install",
|
|
770
|
+
dev: "bun run dev"
|
|
771
|
+
},
|
|
772
|
+
deno: {
|
|
773
|
+
install: "deno install",
|
|
774
|
+
dev: "deno task dev"
|
|
775
|
+
},
|
|
776
|
+
vp: {
|
|
777
|
+
install: "vp install",
|
|
778
|
+
dev: "vp run dev"
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
const CDN_PROVIDER_IDS = [
|
|
782
|
+
"jsdelivr",
|
|
783
|
+
"unpkg",
|
|
784
|
+
"esmsh"
|
|
785
|
+
];
|
|
786
|
+
const THEME_FONT_ASSETS = [{
|
|
787
|
+
package: "@pantoken/components",
|
|
788
|
+
path: "dist/fonts.css"
|
|
789
|
+
}];
|
|
790
|
+
const THEME_JS_ASSETS = [{
|
|
791
|
+
package: "@pantoken/interactions",
|
|
792
|
+
path: "dist/interactions.iife.js"
|
|
793
|
+
}];
|
|
776
794
|
/**
|
|
777
795
|
* Every scaffoldable platform key (discovered from available presets, plus any legacy
|
|
778
796
|
* template-only platforms not yet backed by a preset).
|
|
@@ -784,7 +802,7 @@ function validateThemeMode(value) {
|
|
|
784
802
|
* console.log(SCAFFOLD_PLATFORMS); // → ["components", "react", "vue", "web-components"]
|
|
785
803
|
* ```
|
|
786
804
|
*/
|
|
787
|
-
const SCAFFOLD_PLATFORMS = Array.from(
|
|
805
|
+
const SCAFFOLD_PLATFORMS = Array.from(new Set(Object.keys(SCAFFOLDS))).sort();
|
|
788
806
|
const SCAFFOLD_PLATFORM_SET = new Set(SCAFFOLD_PLATFORMS);
|
|
789
807
|
/** Alternate platform names accepted alongside the canonical preset key (e.g. the pre-Bingo `html`). */
|
|
790
808
|
const PLATFORM_ALIASES = {
|
|
@@ -812,39 +830,104 @@ function writeScaffoldFile(path, content) {
|
|
|
812
830
|
mkdirSync(dirname(path), { recursive: true });
|
|
813
831
|
writeFileSync(path, content);
|
|
814
832
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
options: { name: projectName }
|
|
823
|
-
});
|
|
824
|
-
return Object.entries(creation.files ?? {}).map(([file, rawContent]) => {
|
|
825
|
-
const path = join(dir, file);
|
|
826
|
-
writeScaffoldFile(path, rawContent instanceof ArrayBuffer ? Buffer.from(rawContent) : rawContent);
|
|
827
|
-
return path;
|
|
828
|
-
});
|
|
829
|
-
} catch {
|
|
830
|
-
return [];
|
|
831
|
-
}
|
|
833
|
+
function shouldWriteScaffoldFile(file, packageManager) {
|
|
834
|
+
return file !== "pnpm-workspace.yaml" || !packageManager || packageManager === "pnpm" || packageManager === "vp";
|
|
835
|
+
}
|
|
836
|
+
function applyPackageManagerCommands(file, content, packageManager) {
|
|
837
|
+
if (!packageManager || file !== "README.md" || typeof content !== "string") return content;
|
|
838
|
+
const commands = SCAFFOLD_PM_COMMANDS[packageManager];
|
|
839
|
+
return content.replaceAll("npm install", commands.install).replaceAll("npm run dev", commands.dev);
|
|
832
840
|
}
|
|
833
841
|
/** Writes `resolvedPlatform`'s legacy `SCAFFOLDS` templates (for platforms with no preset yet). */
|
|
834
|
-
function writeLegacyTemplateFiles(resolvedPlatform, dir, locale, substitutions) {
|
|
842
|
+
function writeLegacyTemplateFiles(resolvedPlatform, dir, locale, substitutions, packageManager) {
|
|
835
843
|
const templates = SCAFFOLDS[resolvedPlatform];
|
|
836
844
|
if (!templates) return [];
|
|
837
845
|
const localized = {
|
|
838
846
|
...templates,
|
|
839
847
|
...SCAFFOLD_OVERLAYS[locale]?.[resolvedPlatform]
|
|
840
848
|
};
|
|
841
|
-
return Object.entries(localized).
|
|
842
|
-
|
|
849
|
+
return Object.entries(localized).flatMap(([file, content]) => {
|
|
850
|
+
if (!shouldWriteScaffoldFile(file, packageManager)) return [];
|
|
851
|
+
const resolved = applyPackageManagerCommands(file, Object.entries(substitutions).reduce((text, [token, value]) => text.replaceAll(`{{${token}}}`, value), content), packageManager);
|
|
843
852
|
const path = join(dir, file);
|
|
844
|
-
writeScaffoldFile(path,
|
|
845
|
-
return path;
|
|
853
|
+
writeScaffoldFile(path, resolved);
|
|
854
|
+
return [path];
|
|
846
855
|
});
|
|
847
856
|
}
|
|
857
|
+
function themeCssAssets(theme = "rebrand", mode = "light") {
|
|
858
|
+
return [
|
|
859
|
+
{
|
|
860
|
+
package: "@pantoken/css",
|
|
861
|
+
path: `dist/${theme === "canvas" ? "style.canvas.lean.css" : theme === "canvasHighContrast" ? "style.canvas-high-contrast.lean.css" : mode === "light" ? "style.rebrand.light.lean.css" : "style.lean.css"}`
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
package: "@pantoken/components",
|
|
865
|
+
path: "dist/base.css"
|
|
866
|
+
},
|
|
867
|
+
{
|
|
868
|
+
package: "@pantoken/components",
|
|
869
|
+
path: "dist/component-icons.css"
|
|
870
|
+
},
|
|
871
|
+
{
|
|
872
|
+
package: "@pantoken/components",
|
|
873
|
+
path: "dist/components.css"
|
|
874
|
+
},
|
|
875
|
+
{
|
|
876
|
+
package: "@pantoken/components",
|
|
877
|
+
path: "dist/utilities.css"
|
|
878
|
+
}
|
|
879
|
+
];
|
|
880
|
+
}
|
|
881
|
+
function fileSpecifier(file) {
|
|
882
|
+
return `${file.package}/${file.path}`;
|
|
883
|
+
}
|
|
884
|
+
function cdnUrl(file, provider) {
|
|
885
|
+
const specifier = fileSpecifier(file);
|
|
886
|
+
if (provider === "unpkg") return `https://unpkg.com/${specifier}`;
|
|
887
|
+
if (provider === "esmsh") return `https://esm.sh/${specifier}?raw`;
|
|
888
|
+
return `https://cdn.jsdelivr.net/npm/${specifier}`;
|
|
889
|
+
}
|
|
890
|
+
function cdnImportLines(files, provider) {
|
|
891
|
+
if (provider === "jsdelivr" && files.length > 1) return `@import url("https://cdn.jsdelivr.net/combine/${files.map((file) => `npm/${fileSpecifier(file)}`).join(",")}");`;
|
|
892
|
+
return files.map((file) => `@import url("${cdnUrl(file, provider)}");`).join("\n");
|
|
893
|
+
}
|
|
894
|
+
function cdnScriptTags(files, provider) {
|
|
895
|
+
return files.map((file) => ` var script = document.createElement("script");\n script.src = "${cdnUrl(file, provider)}";\n document.head.appendChild(script);`).join("\n");
|
|
896
|
+
}
|
|
897
|
+
function resolveCdnProviderId(id) {
|
|
898
|
+
if (!id) return "jsdelivr";
|
|
899
|
+
if (CDN_PROVIDER_IDS.includes(id)) return id;
|
|
900
|
+
throw new Error(`Unknown CDN provider id "${id}". Valid ids: ${CDN_PROVIDER_IDS.join(", ")}.`);
|
|
901
|
+
}
|
|
902
|
+
function buildTheme(options = {}) {
|
|
903
|
+
const provider = resolveCdnProviderId(options.cdn);
|
|
904
|
+
return {
|
|
905
|
+
css: `/**
|
|
906
|
+
* Pantoken Canvas Theme Editor CSS.
|
|
907
|
+
* Upload this file in Canvas Theme Editor > Advanced > CSS.
|
|
908
|
+
*/
|
|
909
|
+
|
|
910
|
+
/* Component styles */
|
|
911
|
+
${cdnImportLines(themeCssAssets(options.theme, options.mode), provider)}
|
|
912
|
+
/* Fonts */
|
|
913
|
+
${cdnImportLines(THEME_FONT_ASSETS, provider)}
|
|
914
|
+
|
|
915
|
+
/* Add custom CSS overrides below. */
|
|
916
|
+
`,
|
|
917
|
+
js: `/**
|
|
918
|
+
* Pantoken Canvas Theme Editor JavaScript.
|
|
919
|
+
* Upload this file in Canvas Theme Editor > Advanced > JavaScript.
|
|
920
|
+
*/
|
|
921
|
+
(function pantokenTheme() {
|
|
922
|
+
"use strict";
|
|
923
|
+
|
|
924
|
+
${cdnScriptTags(THEME_JS_ASSETS, provider)}
|
|
925
|
+
})();
|
|
926
|
+
|
|
927
|
+
/* Add custom JavaScript overrides below. */
|
|
928
|
+
`
|
|
929
|
+
};
|
|
930
|
+
}
|
|
848
931
|
/**
|
|
849
932
|
* Builds canvas-theme-editor's `theme.css`/`theme.js` for the chosen CDN provider/theme/mode at
|
|
850
933
|
* scaffold time (rather than shipping a pre-baked jsDelivr/rebrand default); `[]` for every other
|
|
@@ -853,7 +936,7 @@ function writeLegacyTemplateFiles(resolvedPlatform, dir, locale, substitutions)
|
|
|
853
936
|
function writeCanvasThemeEditorAssets(resolvedPlatform, dir, options) {
|
|
854
937
|
if (resolvedPlatform !== "canvas-theme-editor") return [];
|
|
855
938
|
const { css, js } = buildTheme({
|
|
856
|
-
|
|
939
|
+
cdn: options?.cdn,
|
|
857
940
|
theme: options?.theme,
|
|
858
941
|
mode: options?.mode
|
|
859
942
|
});
|
|
@@ -888,14 +971,12 @@ async function scaffoldProject(platform, dir = ".", options) {
|
|
|
888
971
|
const resolvedPlatform = resolveScaffoldPlatform(platform);
|
|
889
972
|
const projectName = dir === "." ? "pantoken-app" : dir.split("/").pop() ?? "pantoken-app";
|
|
890
973
|
const locale = options?.locale ?? "en";
|
|
891
|
-
const
|
|
974
|
+
const written = writeLegacyTemplateFiles(resolvedPlatform, dir, locale, {
|
|
892
975
|
projectName,
|
|
893
976
|
pantokenCssImport: themeStylesheetImport(options?.theme, options?.mode),
|
|
894
977
|
locale,
|
|
895
978
|
dir: localeDirection(locale)
|
|
896
|
-
};
|
|
897
|
-
const written = writePresetFiles(resolvedPlatform, dir, projectName);
|
|
898
|
-
if (written.length === 0) written.push(...writeLegacyTemplateFiles(resolvedPlatform, dir, locale, substitutions));
|
|
979
|
+
}, options?.packageManager);
|
|
899
980
|
written.push(...writeCanvasThemeEditorAssets(resolvedPlatform, dir, options));
|
|
900
981
|
return written;
|
|
901
982
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pantoken/scaffold",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "npx @pantoken/scaffold <platform> — scaffold a starter project (html, react, next, angular, web-components, ...) with pantoken already installed and wired in.",
|
|
5
5
|
"homepage": "https://pantoken.app",
|
|
6
6
|
"bugs": "https://github.com/thedannywahl/pantoken/issues",
|
|
@@ -31,21 +31,21 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@bomb.sh/tab": "^0.0.22",
|
|
33
33
|
"@clack/prompts": "^1.8.0",
|
|
34
|
+
"commander": "^15.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
34
37
|
"@pantoken/angular": "0.1.30",
|
|
35
38
|
"@pantoken/canvas-theme-editor": "0.2.0",
|
|
36
39
|
"@pantoken/components": "1.1.2",
|
|
40
|
+
"@pantoken/i18n-engine": "0.3.0",
|
|
41
|
+
"@pantoken/plugin-layouts": "0.3.0",
|
|
37
42
|
"@pantoken/react": "0.1.31",
|
|
38
43
|
"@pantoken/scaffold-base": "0.3.0",
|
|
39
44
|
"@pantoken/svelte": "0.1.31",
|
|
40
45
|
"@pantoken/vue": "0.1.31",
|
|
41
46
|
"@pantoken/web-components": "0.6.2",
|
|
42
|
-
"bingo-stratum": "^0.5.13",
|
|
43
|
-
"commander": "^15.0.0"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@pantoken/i18n-engine": "0.3.0",
|
|
47
|
-
"@pantoken/plugin-layouts": "0.3.0",
|
|
48
47
|
"@types/node": "^26.5.0",
|
|
48
|
+
"bingo-stratum": "^0.5.13",
|
|
49
49
|
"typescript": "^7.0.2",
|
|
50
50
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.3.1",
|
|
51
51
|
"vite-plus": "0.3.1"
|