@webority/canvas-kit 0.90.0 → 0.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/build.js +3 -3
- package/dist/cli.js +3 -2
- package/dist/drawn.js +1 -1
- package/dist/ids.js +1 -0
- package/dist/kitModule.js +1 -1
- package/dist/manifest.d.ts +8 -1
- package/dist/manifest.js +1 -1
- package/dist/meta.d.ts +4 -0
- package/dist/metaCheck.d.ts +6 -2
- package/dist/metaCheck.js +1 -1
- package/dist/metas.js +2 -2
- package/dist/spec.d.ts +2 -0
- package/dist/tokens.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ The config is a JSON object with these keys. Paths are relative to the config fi
|
|
|
33
33
|
| `components` | A glob of `.meta.js` files, for example `src/components/*.meta.js`. |
|
|
34
34
|
| `tokens` | The path of a `webority-theme-tokens/2` file: `webority-web.json` for Web, `webority-phone.json` for Phone, written by `webority brand`. |
|
|
35
35
|
| `rolesFile` | Optional. A JSON object from component name to `title` or `navigation`. |
|
|
36
|
+
| `styles` | Optional. Style files bundled into `kit.css` ahead of the component styles, for a product whose components take their look from styles imported at the app entry. |
|
|
36
37
|
| `rendererProtocolVersion` | The renderer protocol number the kit is built for. |
|
|
37
38
|
|
|
38
39
|
A kit lists its components with `components`. A config that names `entry` fails the read with that message, and so does
|
|
@@ -125,7 +126,7 @@ The build stops with a named fix when:
|
|
|
125
126
|
- a meta lists a platform other than the kit's;
|
|
126
127
|
- the config names `entry`, or lacks `components` or `tokens`;
|
|
127
128
|
- the tokens file is not format `webority-theme-tokens/2`, is for the other platform, or has light and dark colours that differ;
|
|
128
|
-
- a colour has no meaning in `@webority/tokens` `dist/meanings.json
|
|
129
|
+
- a colour has no meaning in the tokens file's `colorMeanings` (where a brand's own colours carry theirs) nor in `@webority/tokens` `dist/meanings.json`, or a `colorMeanings` entry is not a description;
|
|
129
130
|
- a meta does not match its component's typed props, or fails one of the checks on a meta;
|
|
130
131
|
- a Phone kit is built without `--phone-renderer-support`.
|
|
131
132
|
|
package/dist/build.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{findPackageDir as e,readJson as t,toPosix as n}from"./files.js";import{KIT_MODULE_EXTERNALS as r}from"./kitModule.js";import{libraryFiles as i,readManifest as a}from"./manifest.js";import{digest as o,writeReleaseFolder as s}from"./release.js";import{existsSync as c}from"node:fs";import{dirname as l,join as u,resolve as d}from"node:path";import{fileURLToPath as f}from"node:url";import{build as p}from"vite";var m=19,h=[`react-redux`,`react-router-dom`,`axios`],g=[`kit`,`platform`,`libraryPackage`,`components`,`tokens`,`rolesFile`,`rendererProtocolVersion`],_=[`kit`,`platform`,`libraryPackage`,`components`,`tokens`,`rendererProtocolVersion`],v=`canvas-kit:entry`,y=`\0${v}`,b=u(l(f(import.meta.url)),`kitModule.js`),x={"process.env.NODE_ENV":JSON.stringify(`production`),"process.env":`{}`,__DEV__:`false`},S=/(?<![\w$."'`])(process\.env|__DEV__)(?![\w$])/;function C(e){let n=t(e);if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`${e} must be a JSON object.`);if(n.entry!==void 0)throw Error(`${e}: A kit lists its components with components, a glob of .meta.js files; entry is retired.`);for(let t of Object.keys(n))if(!g.includes(t))throw Error(`${e} has the unknown key ${t}. The keys are ${g.join(`, `)}.`);for(let t of _)if(n[t]===void 0)throw Error(`${e} needs the key ${t}.`);for(let t of[`kit`,`platform`,`libraryPackage`,`components`,`tokens`])if(typeof n[t]!=`string`)throw Error(`${e}: ${t} must be a string.`);for(let t of[`rolesFile`])if(n[t]!==void 0&&typeof n[t]!=`string`)throw Error(`${e}: ${t} must be a string path.`);return n}function w(n){let r=e(n,`react`);if(!r)throw Error(`react is not installed for ${n}. Run pnpm install there.`);let{version:i}=t(u(r,`package.json`));if(Number(String(i).split(`.`)[0])!==m)throw Error(`The product uses React ${i}; the Canvas renderer runs React ${m}. Pin react to ${m}.x and rebuild.`)}function T(e){let{version:n}=t(u(e,`package.json`));if(!n)throw Error(`${u(e,`package.json`)} needs a version; the release is stamped with it.`);return n}function E({
|
|
2
|
-
`)}function D(e){return{name:`canvas-kit-entry`,resolveId(e){return e===v?y:null},load(t){return t===y?e:null}}}function O(e){let t=`${n(u(e,`src`,`services`))}/`;return{name:`canvas-kit-banned-imports`,transform(e,r){let i=n(r.split(`?`)[0]),a=h.find(e=>i.includes(`/node_modules/${e}/`));if(a)throw Error(`The kit imports ${a} (${i}). A kit draws from its props only; the container that renders it holds the state and the calls.`);if(i.startsWith(t))throw Error(`The kit imports ${i}, which is in src/services. A kit draws from its props only; move the call into the container.`);return null}}}async function k({root:e,kit:t,platform:n,
|
|
3
|
-
`);return{script:
|
|
1
|
+
import{findPackageDir as e,readJson as t,toPosix as n}from"./files.js";import{KIT_MODULE_EXTERNALS as r}from"./kitModule.js";import{libraryFiles as i,readManifest as a}from"./manifest.js";import{digest as o,writeReleaseFolder as s}from"./release.js";import{existsSync as c}from"node:fs";import{dirname as l,join as u,resolve as d}from"node:path";import{fileURLToPath as f}from"node:url";import{build as p}from"vite";var m=19,h=[`react-redux`,`react-router-dom`,`axios`],g=[`kit`,`platform`,`libraryPackage`,`components`,`tokens`,`rolesFile`,`styles`,`rendererProtocolVersion`],_=[`kit`,`platform`,`libraryPackage`,`components`,`tokens`,`rendererProtocolVersion`],v=`canvas-kit:entry`,y=`\0${v}`,b=u(l(f(import.meta.url)),`kitModule.js`),x={"process.env.NODE_ENV":JSON.stringify(`production`),"process.env":`{}`,__DEV__:`false`},S=/(?<![\w$."'`])(process\.env|__DEV__)(?![\w$])/;function C(e){let n=t(e);if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`${e} must be a JSON object.`);if(n.entry!==void 0)throw Error(`${e}: A kit lists its components with components, a glob of .meta.js files; entry is retired.`);for(let t of Object.keys(n))if(!g.includes(t))throw Error(`${e} has the unknown key ${t}. The keys are ${g.join(`, `)}.`);for(let t of _)if(n[t]===void 0)throw Error(`${e} needs the key ${t}.`);for(let t of[`kit`,`platform`,`libraryPackage`,`components`,`tokens`])if(typeof n[t]!=`string`)throw Error(`${e}: ${t} must be a string.`);for(let t of[`rolesFile`])if(n[t]!==void 0&&typeof n[t]!=`string`)throw Error(`${e}: ${t} must be a string path.`);if(n.styles!==void 0){if(!Array.isArray(n.styles)||n.styles.some(e=>typeof e!=`string`||e===``))throw Error(`${e}: styles must be a list of style file paths.`);for(let t of n.styles){if(!/\.(css|scss)$/.test(t))throw Error(`${e}: styles names ${t}, which is not a .css or .scss file.`);if(!c(d(l(e),t)))throw Error(`${e}: styles names ${t}, which does not exist.`)}}return n}function w(n){let r=e(n,`react`);if(!r)throw Error(`react is not installed for ${n}. Run pnpm install there.`);let{version:i}=t(u(r,`package.json`));if(Number(String(i).split(`.`)[0])!==m)throw Error(`The product uses React ${i}; the Canvas renderer runs React ${m}. Pin react to ${m}.x and rebuild.`)}function T(e){let{version:n}=t(u(e,`package.json`));if(!n)throw Error(`${u(e,`package.json`)} needs a version; the release is stamped with it.`);return n}function E({styleFiles:e,libraryFile:t,chromeFile:r,manifest:i,libraryNames:a,chromeNames:o,productModules:s}){let c=[...s],l=[...a.map(({fixedProps:e})=>e),...c.map(([,{fixedProps:e}])=>e)].some(e=>e!==void 0),u=e.map(e=>`import ${JSON.stringify(n(e))};`);l&&u.push(`import { createElement } from "react";`),u.push(`import { ${l?`defineKit, withFixedProps`:`defineKit`} } from ${JSON.stringify(n(b))};`),c.forEach(([,{module:e,exportName:t}],r)=>{u.push(`import { ${t} as product${r} } from ${JSON.stringify(n(e))};`)});let d=[...new Set(a.map(({exportName:e})=>e))];d.length>0&&u.push(`import { ${d.join(`, `)} } from ${JSON.stringify(n(t))};`),o.length>0&&u.push(`import { ${o.join(`, `)} } from ${JSON.stringify(n(r))};`);let f=(e,t,n)=>n===void 0?e===t?e:`${e}: ${t}`:`${e}: withFixedProps(createElement, ${t}, ${JSON.stringify(n)}, ${JSON.stringify(e)})`,p=[...a.map(({name:e,exportName:t,fixedProps:n})=>f(e,t,n)),...o,...c.map(([e,{fixedProps:t}],n)=>f(e,`product${n}`,t))],m=Object.fromEntries(i.components.filter(({marker:e})=>e!==null).map(({name:e,marker:t})=>[e,t]));return u.push(`export default defineKit({ components: { ${p.join(`, `)} }, markers: ${JSON.stringify(m)}, tokenValues: ${JSON.stringify(i.tokenValues)}, manifest: ${JSON.stringify(i)} });`,``),u.join(`
|
|
2
|
+
`)}function D(e){return{name:`canvas-kit-entry`,resolveId(e){return e===v?y:null},load(t){return t===y?e:null}}}function O(e){let t=`${n(u(e,`src`,`services`))}/`;return{name:`canvas-kit-banned-imports`,transform(e,r){let i=n(r.split(`?`)[0]),a=h.find(e=>i.includes(`/node_modules/${e}/`));if(a)throw Error(`The kit imports ${a} (${i}). A kit draws from its props only; the container that renders it holds the state and the calls.`);if(i.startsWith(t))throw Error(`The kit imports ${i}, which is in src/services. A kit draws from its props only; move the call into the container.`);return null}}}async function k({root:e,kit:t,platform:n,styleFiles:i,libraryFile:a,chromeFile:o,libraryNames:s,chromeNames:c,productModules:l,manifest:u}){let d=r[n],f=await p({configFile:!1,root:e,logLevel:`warn`,publicDir:!1,envDir:!1,define:x,plugins:[D(E({styleFiles:i,libraryFile:a,chromeFile:o,manifest:u,libraryNames:s,chromeNames:c,productModules:l})),O(e)],esbuild:{jsx:`automatic`,jsxImportSource:`react`,include:/\.[cm]?[jt]sx?$/},build:{write:!1,minify:!0,target:`es2022`,cssCodeSplit:!1,lib:{entry:v,formats:[`es`],fileName:()=>`kit.js`},rollupOptions:{input:v,external:e=>d.some(t=>e===t||e.startsWith(`${t}/`)),output:{codeSplitting:!1}}}}),m=(Array.isArray(f)?f:[f]).flatMap(e=>e.output),h=m.find(e=>e.type===`chunk`&&e.isEntry);if(!h)throw Error(`The bundle of ${t} has no entry module.`);let g=S.exec(h.code);if(g)throw Error(`The bundle of ${t} still reads ${g[1]}, which the renderer does not define.`);let _=m.filter(e=>e.type===`chunk`&&!e.isEntry);if(_.length>0)throw Error(`The bundle of ${t} split ${_.map(e=>e.fileName).join(`, `)} out of kit.js; a kit must be one file.`);let y=m.filter(e=>e.type===`asset`&&e.fileName.endsWith(`.css`)).map(e=>typeof e.source==`string`?e.source:Buffer.from(e.source).toString(`utf8`)).join(`
|
|
3
|
+
`);return{script:h.code,styles:y}}async function A({configFile:e,outDir:t,styleKeysFile:n,phoneRendererSupportFile:r}){let u=d(e),f=d(t);if(c(f))throw Error(`${f} already exists. A release folder is never overwritten; choose a new folder.`);let p=C(u),m=l(u);if(p.platform!==`Phone`&&r!==void 0)throw Error(`Only a Phone kit reads --phone-renderer-support; a Web kit takes no phone support file.`);w(m);let h=p.rolesFile===void 0?void 0:d(m,p.rolesFile),{manifest:g,warnings:_,phoneChromeNames:v,productModules:y}=await a({projectRoot:m,kit:p.kit,platform:p.platform,components:p.components,tokens:p.tokens,libraryPackage:p.libraryPackage,rolesFile:h,rendererProtocolVersion:p.rendererProtocolVersion,phoneRendererSupportFile:r===void 0?void 0:d(r),styleKeysFile:n===void 0?void 0:d(n)}),b=i(m,p.libraryPackage),x=T(m),S=g.components.filter(({source:e,name:t})=>e===p.libraryPackage&&!v.includes(t)).map(({name:e,component:t,fixedProps:n})=>({name:e,exportName:t??e,...n===void 0?{}:{fixedProps:n}})),{script:E,styles:D}=await k({root:m,kit:p.kit,platform:p.platform,styleFiles:(p.styles??[]).map(e=>d(m,e)),libraryFile:b.entryFile,chromeFile:b.canvasKitFile,libraryNames:S,chromeNames:v,productModules:y,manifest:g}),O={"manifest.json":`${JSON.stringify(g,null,2)}\n`,"kit.js":E,"kit.css":D},A={name:p.kit,version:x,platform:p.platform,kitModuleVersion:2,rendererProtocolVersion:p.rendererProtocolVersion,library:g.library,files:Object.fromEntries(Object.entries(O).map(([e,t])=>[e,o(t)]))};return s(f,O,A),{outDir:f,release:A,manifest:g,warnings:_}}export{A as buildKitRelease,C as readConfig};
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{buildKitRelease as e}from"./build.js";import{writeGuidance as t}from"./guidance.js";import{
|
|
2
|
+
import{buildKitRelease as e}from"./build.js";import{writeGuidance as t}from"./guidance.js";import{proposeCanvasKeys as n}from"./ids.js";import{resolve as r}from"node:path";var i=`Usage: canvas-kit build --config <file> --out <dir> [--style-keys <file>] [--phone-renderer-support <file>]
|
|
3
3
|
canvas-kit guidance --config <file> --out <file>
|
|
4
|
+
canvas-kit ids <folder> [--write] proposes Canvas keys for list items, named blocks and conditional siblings; --write writes them.
|
|
4
5
|
|
|
5
6
|
build: builds a kit release into <dir>: kit.js, kit.css, manifest.json and release.json.
|
|
6
7
|
<dir> must not exist; a release folder is never overwritten.
|
|
7
8
|
--style-keys: the style key table the renderer draws from. Optional.
|
|
8
9
|
--phone-renderer-support: the phone renderer's support file. A Phone product kit needs it; a phone library's own kit release builds without it.
|
|
9
10
|
guidance: writes the usage guidance of every component the config's components glob lists to <file> (webority-guidance/1), replacing it.
|
|
10
|
-
Flag paths are relative to the working directory; the paths in the config are relative to the config file.`,
|
|
11
|
+
Flag paths are relative to the working directory; the paths in the config are relative to the config file.`,a=new Set([`--config`,`--out`,`--style-keys`,`--phone-renderer-support`]);function o(e){if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return{help:!0};let[t,...n]=e;if(t===`ids`){let e,r=!1;for(let t of n)if(t===`--write`)r=!0;else if(e===void 0&&!t.startsWith(`--`))e=t;else throw Error(`Unknown argument ${t}.`);return{command:t,options:{folder:e,write:r}}}let r={};for(let e=0;e<n.length;e+=1){let t=n[e];if(!a.has(t))throw Error(`Unknown argument ${t}.`);let i=n[e+1];if(i===void 0||i.startsWith(`--`))throw Error(`${t} needs a value.`);r[t.slice(2)]=i,e+=1}return{command:t,options:r}}async function s(a){let s=o(a);if(s.help){process.stdout.write(`${i}\n`);return}if(s.command!==`build`&&s.command!==`guidance`&&s.command!==`ids`)throw Error(`Unknown command ${s.command}. The commands are build, guidance and ids.`);if(s.command===`ids`){if(s.options.folder===void 0)throw Error(`ids needs a folder.`);let e=await n(r(s.options.folder),{write:s.options.write});for(let t of e.proposals)process.stdout.write(`${t.file}:${t.line} ${t.element} ${t.key}\n`);for(let t of e.noKey)process.stdout.write(`${t.file}:${t.line} ${t.element} no record key\n`);process.stdout.write(`${e.proposals.length} keys proposed, ${e.written} written, ${e.noKey.length} list items have no record key.\n`);return}if(s.command===`guidance`){if(!s.options.config||!s.options.out)throw Error(`guidance needs --config and --out.`);if(s.options[`style-keys`]!==void 0||s.options[`phone-renderer-support`]!==void 0)throw Error(`guidance takes only --config and --out.`);let e=await t({configFile:r(s.options.config),outFile:r(s.options.out)});process.stdout.write(`Guidance for ${e.components.length} components written to ${r(s.options.out)}.\n`);return}if(!s.options.config||!s.options.out)throw Error(`build needs --config and --out.`);let c=s.options[`style-keys`],l=s.options[`phone-renderer-support`],u=await e({configFile:r(s.options.config),outDir:r(s.options.out),styleKeysFile:c===void 0?void 0:r(c),phoneRendererSupportFile:l===void 0?void 0:r(l)});for(let e of u.warnings)process.stderr.write(`warning: ${e}\n`);process.stdout.write(`Built ${u.release.name} (${u.release.platform}): ${u.manifest.components.length} components. Release written to ${u.outDir}.\n`)}s(process.argv.slice(2)).catch(e=>{process.stderr.write(`canvas-kit: ${e.message}\n`),process.exitCode=1});export{};
|
package/dist/drawn.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import{readJson as e,toPosix as t}from"./files.js";import{TSC as n,specifierOf as r}from"./metaCheck.js";import{existsSync as i,mkdirSync as a,rmSync as o,writeFileSync as s}from"node:fs";import{join as c}from"node:path";import{execFileSync as l}from"node:child_process";var u=`src/components/not-drawn.json`;function d({root:e,typesFile:i}){let u=c(e,`node_modules`,`.canvas-kit-exports-${process.pid}`);try{a(u,{recursive:!0});let e=[`import type * as L from "${r(i)}";`,`type IsComponent<T> = 0 extends 1 & T ? true : T extends (...args: never[]) => unknown ? true : T extends abstract new (...args: never[]) => unknown ? true : T extends { $$typeof: symbol } ? true : false;`,`type Named<K> = K extends string ? (K extends Capitalize<K> ? (K extends Uncapitalize<K> ? never : K) : never) : never;`,`type Components = { [K in keyof typeof L]: Named<K> extends never ? never : IsComponent<(typeof L)[K]> extends true ? K : never }[keyof typeof L];`,`export const components: never = null as unknown as { [K in Components]: K };`];s(c(u,`check.ts`),`${e.join(`
|
|
2
2
|
`)}\n`),s(c(u,`tsconfig.json`),JSON.stringify({compilerOptions:{strict:!0,noEmit:!0,allowJs:!0,checkJs:!1,jsx:`react-jsx`,module:`esnext`,moduleResolution:`bundler`,target:`es2022`,skipLibCheck:!0,noErrorTruncation:!0,types:[]},files:[`check.ts`]}));let o=``;try{l(process.execPath,[n,`-p`,c(u,`tsconfig.json`),`--pretty`,`false`],{cwd:u,encoding:`utf8`,stdio:`pipe`})}catch(e){o=String(e.stdout??``)+String(e.stderr??``)}let d=o.split(/\r?\n/).find(e=>/^check\.ts\(5,\d+\): error TS2322: /.test(e)),f=d&&/Type '(\{[^']*\})' is not assignable to type 'never'/.exec(d);if(!f)throw Error(`tsc could not list the components ${t(i)} exports: ${o.split(/\r?\n/).slice(0,20).join(`
|
|
3
|
-
`)}`);return[...new Set([...f[1].matchAll(/(\w+): "\w+"/g)].map(e=>e[1]))].sort()}finally{o(u,{recursive:!0,force:!0})}}function f(t){if(!i(t))return{};let n=e(t);if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`${t} must be an object from component name to the reason the kit does not draw it.`);let r=Object.entries(n).filter(([,e])=>typeof e!=`string`||e.trim()===``).map(([e])=>e);if(r.length>0)throw Error(`${t}: ${r.join(`, `)} need a reason the kit does not draw them.`);return n}function p({libraryPackage:e,exported:t,
|
|
3
|
+
`)}`);return[...new Set([...f[1].matchAll(/(\w+): "\w+"/g)].map(e=>e[1]))].sort()}finally{o(u,{recursive:!0,force:!0})}}function f(t){if(!i(t))return{};let n=e(t);if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`${t} must be an object from component name to the reason the kit does not draw it.`);let r=Object.entries(n).filter(([,e])=>typeof e!=`string`||e.trim()===``).map(([e])=>e);if(r.length>0)throw Error(`${t}: ${r.join(`, `)} need a reason the kit does not draw them.`);return n}function p({libraryPackage:e,exported:t,drawnNames:n,notDrawn:r}){let i=new Set(t),a=[...new Map(n.map(e=>[`${e.name} ${e.component}`,e])).values()],o=new Set(a.map(({component:e})=>e)),s=Object.keys(r),c=[],l=t.filter(e=>!o.has(e)&&!(e in r));l.length>0&&c.push(`${e} exports ${l.join(`, `)} with no meta. Write a meta for each, or list it in ${u} with the reason the kit does not draw it.`);let d=s.filter(e=>o.has(e));d.length>0&&c.push(`${u} lists ${d.join(`, `)}, which have a meta. A component is drawn or not drawn; remove one.`);let f=s.filter(e=>!i.has(e));f.length>0&&c.push(`${u} lists ${f.join(`, `)}, which ${e} does not export as components. Remove them.`);let p=a.filter(({component:e})=>!i.has(e));if(p.length>0){let t=p.map(({name:e,component:t})=>e===t?e:`${e} (draws ${t})`);c.push(`${t.join(`, `)} have a meta, but ${e} does not export them as components.`)}if(c.length>0)throw Error(c.join(`
|
|
4
4
|
`))}export{u as NOT_DRAWN_FILE,p as checkDrawn,d as componentExports,f as readNotDrawn};
|
package/dist/ids.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{basename as e,extname as t,join as n,relative as r,sep as i}from"node:path";import a from"@babel/parser";import{readFile as o,readdir as s,writeFile as c}from"node:fs/promises";var l=new Set([`node_modules`,`dist`,`build`]),u=new Set([`.jsx`,`.tsx`,`.js`]),d=new Set([`@webority/mobile-ui`,`react-native`]),f=new Set([`@webority/ui-react`,`@webority/mobile-ui`]),p=new Set([`section`,`form`,`header`,`nav`,`main`,`aside`,`article`,`fieldset`]),m=[`aria-label`,`name`,`id`,`title`,`label`,`placeholder`],h=new Set([`ArrowFunctionExpression`,`FunctionExpression`,`FunctionDeclaration`,`ObjectMethod`,`ClassMethod`]),g=new Set([`loc`,`start`,`end`,`comments`,`leadingComments`,`trailingComments`,`innerComments`,`tokens`,`extra`,`errors`]),_=40;async function v(e,{write:t=!1}={}){let n=[],a=[],s=[];for(let t of await y(e)){let c=r(e,t).split(i).join(`/`),l=await o(t,`utf8`),u=b({source:l,file:t,label:c});n.push(...u.proposals),a.push(...u.noKey),u.insertions.length>0&&s.push({file:t,source:l,insertions:u.insertions})}let l=0;if(t)for(let e of s){let t=e.source;for(let n of[...e.insertions].sort((e,t)=>t.offset-e.offset))t=`${t.slice(0,n.offset)}${n.text}${t.slice(n.offset)}`;await c(e.file,t,`utf8`),l+=e.insertions.length}return{proposals:n,noKey:a,written:l}}async function y(e){let r=await s(e,{withFileTypes:!0});r.sort((e,t)=>e.name<t.name?-1:1);let i=[];for(let a of r){let r=n(e,a.name);a.isDirectory()?l.has(a.name)||i.push(...await y(r)):a.isFile()&&u.has(t(a.name))&&!a.name.includes(`.test.`)&&i.push(r)}return i}function b({source:e,file:t,label:n}){let r;try{r=a.parse(e,{sourceType:`module`,plugins:[`jsx`,`typescript`]})}catch(e){throw Error(`${n}: ${e.message}`)}let i=new Set,o=!1;for(let e of r.program.body){if(e.type!==`ImportDeclaration`)continue;let t=e.source.value;if(o||=d.has(t),f.has(t))for(let t of e.specifiers)t.type===`ImportSpecifier`&&i.add(t.local.name)}let s=o?`testID`:`data-canvas`,c=new Map,l=[];x(r.program,null,c,l);let u=M(t),p=t=>e.slice(t.start,t.end),m=new Map,h=[],g=[];for(let e of l){let t=e.openingElement,r=k(t,s),a=E(t,i),o=S(e,c);if(a!==null&&o===null&&T(m,e,a,r,c),!r)if(o!==null){let r=t.attributes.find(e=>e.type===`JSXAttribute`&&e.name.type===`JSXIdentifier`&&e.name.name===`key`)?.value,i=r?.type===`JSXExpressionContainer`?r.expression:null,a=o.params[1]?.type===`Identifier`?o.params[1].name:null;i===null||i.type===`JSXEmptyExpression`||I(i)||i.type===`Identifier`&&i.name===a?g.push({start:e.start,entry:{file:n,line:e.loc.start.line,element:p(t.name)}}):h.push({element:e,kind:`list`,keyExpression:i})}else a===null&&D(t)&&h.push({element:e,kind:`block`})}for(let e of m.values())for(let t of e.values())if(t.length>1&&t.some(e=>e.conditional))for(let e of t)e.skipped||h.push({element:e.element,kind:`sibling`});h.sort((e,t)=>e.element.start-t.element.start);let _=new Set,v=[],y=[];for(let e of h){let{element:t,kind:r}=e,a=t.openingElement,o=p(a.name),c=E(a,i),l=`${u}.${j(t,c===null?o:N(c))}`,d=r===`list`?`${l}.\${${p(e.keyExpression)}}`:l,f=d;if(_.has(f)){let e=2;for(;_.has(`${d}-${e}`);)e+=1;f=`${d}-${e}`}_.add(f);let m=r===`list`?` ${s}={\`${f}\`}`:` ${s}="${f}"`;v.push({file:n,line:t.loc.start.line,element:o,key:f}),y.push({offset:a.name.end,text:m})}return{proposals:v,noKey:g.sort((e,t)=>e.start-t.start).map(e=>e.entry),insertions:y}}function x(e,t,n,r){t!==null&&n.set(e,t),e.type===`JSXElement`&&r.push(e);for(let t of Object.keys(e)){if(g.has(t))continue;let i=e[t];for(let t of Array.isArray(i)?i:[i])typeof t==`object`&&t&&typeof t.type==`string`&&x(t,e,n,r)}}function S(e,t){let n=t.get(e),r=null;if(n?.type===`ArrowFunctionExpression`&&n.body===e)r=n;else if(n?.type===`ReturnStatement`){let e=t.get(n),i=t.get(e);e?.type===`BlockStatement`&&h.has(i?.type)&&i.body===e&&(r=i)}if(r===null)return null;let i=t.get(r);return i?.type===`CallExpression`&&i.arguments[0]===r&&i.callee.type===`MemberExpression`&&!i.callee.computed&&i.callee.property.type===`Identifier`&&i.callee.property.name===`map`?r:null}function C(e,t){for(let n=t.get(e);n!==void 0;n=t.get(n)){if(n.type===`JSXElement`||n.type===`JSXFragment`)return n;if(h.has(n.type))return null}return null}function w(e,t,n){for(let r=n.get(e);r!==t;r=n.get(r))if(r.type===`ConditionalExpression`||r.type===`LogicalExpression`&&r.operator===`&&`)return!0;return!1}function T(e,t,n,r,i){let a=C(t,i);if(a===null)return;e.has(a)||e.set(a,new Map);let o=e.get(a);o.has(n)||o.set(n,[]),o.get(n).push({element:t,skipped:r,conditional:w(t,a,i)})}function E(e,t){return e.name.type===`JSXIdentifier`&&t.has(e.name.name)?e.name.name:null}function D(e){if(e.name.type!==`JSXIdentifier`)return!1;let t=e.name.name;return p.has(t)||t===`div`&&(O(e,`id`)||O(e,`aria-label`))}function O(e,t){return e.attributes.some(e=>e.type===`JSXAttribute`&&e.name.type===`JSXIdentifier`&&e.name.name===t)}function k(e,t){return e.attributes.some(e=>e.type===`JSXSpreadAttribute`)||O(e,t)}function A(e,t){let n=e.attributes.find(e=>e.type===`JSXAttribute`&&e.name.type===`JSXIdentifier`&&e.name.name===t)?.value;if(n){if(n.type===`StringLiteral`)return n.value;if(n.type===`JSXExpressionContainer`){let e=n.expression;if(e.type===`StringLiteral`)return e.value;if(e.type===`TemplateLiteral`&&e.expressions.length===0)return e.quasis[0].value.cooked??void 0}}}function j(e,t){for(let t of m){let n=A(e.openingElement,t),r=n===void 0?``:F(P(n));if(r!==``)return r}let n=e.children.filter(e=>e.type===`JSXText`&&e.value.trim()!==``);if(n.length===1){let e=F(P(n[0].value));if(e!==``)return e}return F(P(t))}function M(n){return P(e(n,t(n))).replace(/-(screen|page)$/,``)}function N(e){return e.replace(/^App(?=[A-Z])/,``)}function P(e){return e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)}function F(e){if(e.length<=_)return e;let t=e.slice(0,41).lastIndexOf(`-`);return t>0?e.slice(0,t):e.slice(0,_)}function I(e){return e.type===`TemplateLiteral`?e.expressions.length===0:/Literal$/.test(e.type)}export{v as proposeCanvasKeys};
|
package/dist/kitModule.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=2,t=Object.freeze({Web:[`react`,`react-dom`,`react/jsx-runtime`],Phone:[`react`,`react-dom`,`react/jsx-runtime`,`react-native`,`react-native-svg`,`@webority/mobile-core`,`expo-image`,`expo-haptics`,`expo-file-system`,`react-hook-form`,`react-native-gesture-handler`,`react-native-keyboard-controller`,`react-native-reanimated`,`react-native-safe-area-context`,`react-native-worklets`]});function n({components:e,markers:n,tokenValues:r,manifest:i}){if(typeof i!=`object`||!i)throw Error(`defineKit needs the manifest, the kit's manifest object.`);if(!Object.hasOwn(t,i.platform))throw Error(`defineKit: platform ${JSON.stringify(i.platform)} is not Web or Phone.`);if(typeof e!=`object`||!e)throw Error(`defineKit: components must be an object of React components.`);let a={};for(let[t,n]of Object.entries(e)){if(n===null||typeof n!=`function`&&typeof n!=`object`)throw Error(`defineKit: component ${t} is not a React component.`);a[t]=n}if(typeof n!=`object`||!n)throw Error(`defineKit: markers must be an object of marker names by component name.`);for(let[e,t]of Object.entries(n))if(!Object.hasOwn(a,e)||typeof t!=`string`||t===``)throw Error(`defineKit: the marker of ${e} must name a component with a non-empty marker.`);if(r===void 0||r!==null&&typeof r!=`object`)throw Error(`defineKit: tokenValues must be an object, or null on a release built before it existed.`);return{components:Object.freeze(a),markers:Object.freeze({...n}),tokenValues:r,manifest:i}}export{t as KIT_MODULE_EXTERNALS,
|
|
1
|
+
var e=2,t=Object.freeze({Web:[`react`,`react-dom`,`react/jsx-runtime`],Phone:[`react`,`react-dom`,`react/jsx-runtime`,`react-native`,`react-native-svg`,`@webority/mobile-core`,`expo-image`,`expo-haptics`,`expo-file-system`,`react-hook-form`,`react-native-gesture-handler`,`react-native-keyboard-controller`,`react-native-reanimated`,`react-native-safe-area-context`,`react-native-worklets`]});function n(e,t,n,r){let i=r=>e(t,{...r,...n});return i.displayName=r,i}function r({components:e,markers:n,tokenValues:r,manifest:i}){if(typeof i!=`object`||!i)throw Error(`defineKit needs the manifest, the kit's manifest object.`);if(!Object.hasOwn(t,i.platform))throw Error(`defineKit: platform ${JSON.stringify(i.platform)} is not Web or Phone.`);if(typeof e!=`object`||!e)throw Error(`defineKit: components must be an object of React components.`);let a={};for(let[t,n]of Object.entries(e)){if(n===null||typeof n!=`function`&&typeof n!=`object`)throw Error(`defineKit: component ${t} is not a React component.`);a[t]=n}if(typeof n!=`object`||!n)throw Error(`defineKit: markers must be an object of marker names by component name.`);for(let[e,t]of Object.entries(n))if(!Object.hasOwn(a,e)||typeof t!=`string`||t===``)throw Error(`defineKit: the marker of ${e} must name a component with a non-empty marker.`);if(r===void 0||r!==null&&typeof r!=`object`)throw Error(`defineKit: tokenValues must be an object, or null on a release built before it existed.`);return{components:Object.freeze(a),markers:Object.freeze({...n}),tokenValues:r,manifest:i}}export{t as KIT_MODULE_EXTERNALS,r as defineKit,e as kitModuleVersion,n as withFixedProps};
|
package/dist/manifest.d.ts
CHANGED
|
@@ -54,6 +54,10 @@ export interface CanvasManifestComponent {
|
|
|
54
54
|
takesAction: string[];
|
|
55
55
|
// The package the component comes from. A product's own component names its source file.
|
|
56
56
|
source: string;
|
|
57
|
+
// The export the component draws, when it is not its name.
|
|
58
|
+
component?: string;
|
|
59
|
+
// Props the kit sets on every placement; code export writes them on the export.
|
|
60
|
+
fixedProps?: Record<string, unknown>;
|
|
57
61
|
role?: "title" | "navigation";
|
|
58
62
|
// Present on every Web component; absent on Phone until its metas carry usage.
|
|
59
63
|
usage?: ComponentUsage;
|
|
@@ -67,6 +71,8 @@ export interface CanvasManifestTokens {
|
|
|
67
71
|
shadow: string[];
|
|
68
72
|
font: string[];
|
|
69
73
|
text: string[];
|
|
74
|
+
// The line height roles, such as heading and body.
|
|
75
|
+
leading: string[];
|
|
70
76
|
colorMeanings?: Record<string, string>;
|
|
71
77
|
}
|
|
72
78
|
|
|
@@ -79,6 +85,8 @@ export interface CanvasManifestTokenValues {
|
|
|
79
85
|
shadow: Record<string, CanvasShadow | null>;
|
|
80
86
|
font: Record<string, CanvasManifestFontValue>;
|
|
81
87
|
text: Record<string, CanvasManifestTextValue>;
|
|
88
|
+
// Unitless line height per role.
|
|
89
|
+
leading: Record<string, number>;
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
// Lengths in px at scale 1. `color` is the resolved colour with its opacity in the alpha.
|
|
@@ -104,7 +112,6 @@ export interface CanvasManifestFontValue {
|
|
|
104
112
|
|
|
105
113
|
export interface CanvasManifestTextValue {
|
|
106
114
|
size: number;
|
|
107
|
-
lineHeight?: number | null;
|
|
108
115
|
weight?: number | null;
|
|
109
116
|
}
|
|
110
117
|
|
package/dist/manifest.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{findPackageDir as e,readJson as t,toPosix as n}from"./files.js";import"./kitModule.js";import{checkMetaTypes as r}from"./metaCheck.js";import{NOT_DRAWN_FILE as i,checkDrawn as a,componentExports as o,readNotDrawn as s}from"./drawn.js";import{componentModuleOf as c,manifestComponent as l,readMetas as u}from"./metas.js";import{applyPhoneActions as d,phoneChromeEntries as f,phoneIcons as p}from"./phone.js";import{tokensFromV2 as m,webIcons as h}from"./tokens.js";import{existsSync as g}from"node:fs";import{join as _,relative as v,resolve as y}from"node:path";var b=/^[a-z][a-z0-9-]{1,39}$/,ee=[`Web`,`Phone`],x=[`title`,`navigation`],S={Web:`WeborityWeb`,Phone:`WeborityPhone`},C={Web:`web`,Phone:`phone`};function w(n,r){let i=_(n,`package.json`),a=g(i)&&t(i).name===r,o=a?n:e(n,r);if(!o)throw Error(`${r} is not installed for ${n}. Run pnpm install there.`);let s=t(_(o,`package.json`)),c=(e,t)=>{if(typeof e==`string`)return t==="default"?e:void 0;if(!(!e||typeof e!=`object`))return typeof e[t]==`string`?e[t]:c(e.import,t)??c(e.default,t)},l=s.exports?.[`.`],u=s.types??c(l,`types`),d=c(l,`default`)??s.main;if(!u)throw Error(`${r} declares no types, and the manifest reads its declaration files.`);if(!d)throw Error(`${r} declares no entry file for its runtime.`);let f=c(s.exports?.[`./canvasKit`],`default`);return{dir:o,pkg:s,isSelf:a,typesFile:_(o,u),entryFile:_(o,d),canvasKitFile:f?_(o,f):null}}function T(e,n,r){let i=t(_(e,`package.json`)),a=i.dependencies?.[n]??i.devDependencies?.[n];if(/^\d+\.\d+\.\d+$/.test(a??``)&&a!==r)throw Error(`${n} is pinned to ${a} in package.json but ${r} is installed. Run pnpm install first.`)}function E(e,n,r){let i=e.pkg.exports?.[`./canvas-kit/*`];if(typeof i!=`string`)throw Error(`${n} exports no ./canvas-kit/*; a product kit takes the library's components from its kit release.`);let a=_(e.dir,i.replace(`*`,`manifest.json`)),o=t(a);if(!(o?.kind===S[r]&&o.platform===r&&Array.isArray(o.components)&&Array.isArray(o.icons)))throw Error(`${a} is not a ${r} library kit release.`);return o}function D(e,t){let n=C[t];for(let{meta:r,file:i}of e)if(!r.platforms?.includes(n))throw Error(`${i}: platforms: a ${t} kit lists only components that list ${n}`)}function O(e,n){if(!n)return;let r=t(n);if(typeof r!=`object`||!r||Array.isArray(r))throw Error(`${n} must be an object from component name to role.`);for(let[t,i]of Object.entries(r)){let r=e.find(e=>e.name===t);if(!r)throw Error(`${n} names ${t}, which the kit does not have.`);if(!x.includes(i))throw Error(`${n}: ${t} has role ${JSON.stringify(i)}; a role is title or navigation.`);r.role=i}}function k(e){let n=t(e);if(!Array.isArray(n)||n.some(e=>typeof e?.name!=`string`))throw Error(`${e} must be the style key table: a list of style keys, each with a name.`);return n}function A(e){let n=t(e);if(n?.schema!==1)throw Error(`${e} has schema ${n?.schema}; this reader reads schema 1.`);if(!n.itemActions)throw Error(`${e} has no itemActions; the phone kit's action lists come from it.`);return{flags:n.styleKeys??{},itemActions:n.itemActions}}function j(e,t,n){let r=e.map(({name:e})=>e),i=r.filter(e=>typeof t[e]!=`boolean`),a=Object.keys(t).filter(e=>!r.includes(e));if(i.length>0||a.length>0)throw Error(`${n} must list exactly the style keys of the style key table, each true or false. Missing or not a boolean: ${i.join(`, `)||`none`}. Not in the table: ${a.join(`, `)||`none`}.`)}function te(e,t){return e.map(({name:e,type:n,values:r,appliesTo:i,description:a})=>({name:e,type:n,values:r,appliesTo:i,...t?{phoneSupported:t[e]}:{},description:a}))}var ne=(e,t)=>e.name<t.name?-1:+(e.name>t.name);async function M({projectRoot:t,kit:g,platform:x,entry:C,components:M,tokens:N,libraryPackage:P,rolesFile:F,rendererProtocolVersion:I,phoneRendererSupportFile:L,styleKeysFile:R}){if(!b.test(g??``))throw Error(`kit ${JSON.stringify(g)} must be 2 to 40 characters: lowercase letters, digits and hyphens, starting with a letter.`);if(!ee.includes(x))throw Error(`platform must be Web or Phone, not ${JSON.stringify(x)}.`);if(!Number.isInteger(I)||I<1)throw Error(`rendererProtocolVersion must be a positive integer, not ${JSON.stringify(I)}.`);if(C!==void 0)throw Error(`A kit lists its components with components, a glob of .meta.js files; entry is retired.`);if(typeof M!=`string`||M===``||typeof N!=`string`||N===``)throw Error(`A kit needs components, a glob of .meta.js files, and tokens, the path of its webority-theme-tokens/2 file.`);let z=y(t),B=w(z,P),V=B.isSelf;if(x===`Phone`&&!L&&!V)throw Error(`A Phone product kit needs phoneRendererSupportFile, the phone renderer's support file; only a phone library's own kit release builds without it.`);V||T(z,P,B.pkg.version);let H=L?A(L):null,U=x===`Phone`?H:null,W=R?k(R):null;W&&H&&j(W,H.flags,L);let G=V?null:E(B,P,x),K;K=V?x===`Web`?h(_(B.dir,`dist`)):p(_(B.dir,`lib`,`typescript`,`module`,`components`,`AppIcon`,`catalog.g.d.ts`)):G.icons;let q=[];V&&(q=await u({root:z,components:M,icons:K}),D(q,x),a({libraryPackage:P,exported:o({root:z,typesFile:B.typesFile}),
|
|
1
|
+
import{findPackageDir as e,readJson as t,toPosix as n}from"./files.js";import"./kitModule.js";import{checkMetaTypes as r}from"./metaCheck.js";import{NOT_DRAWN_FILE as i,checkDrawn as a,componentExports as o,readNotDrawn as s}from"./drawn.js";import{componentModuleOf as c,manifestComponent as l,readMetas as u}from"./metas.js";import{applyPhoneActions as d,phoneChromeEntries as f,phoneIcons as p}from"./phone.js";import{tokensFromV2 as m,webIcons as h}from"./tokens.js";import{existsSync as g}from"node:fs";import{join as _,relative as v,resolve as y}from"node:path";var b=/^[a-z][a-z0-9-]{1,39}$/,ee=[`Web`,`Phone`],x=[`title`,`navigation`],S={Web:`WeborityWeb`,Phone:`WeborityPhone`},C={Web:`web`,Phone:`phone`};function w(n,r){let i=_(n,`package.json`),a=g(i)&&t(i).name===r,o=a?n:e(n,r);if(!o)throw Error(`${r} is not installed for ${n}. Run pnpm install there.`);let s=t(_(o,`package.json`)),c=(e,t)=>{if(typeof e==`string`)return t==="default"?e:void 0;if(!(!e||typeof e!=`object`))return typeof e[t]==`string`?e[t]:c(e.import,t)??c(e.default,t)},l=s.exports?.[`.`],u=s.types??c(l,`types`),d=c(l,`default`)??s.main;if(!u)throw Error(`${r} declares no types, and the manifest reads its declaration files.`);if(!d)throw Error(`${r} declares no entry file for its runtime.`);let f=c(s.exports?.[`./canvasKit`],`default`);return{dir:o,pkg:s,isSelf:a,typesFile:_(o,u),entryFile:_(o,d),canvasKitFile:f?_(o,f):null}}function T(e,n,r){let i=t(_(e,`package.json`)),a=i.dependencies?.[n]??i.devDependencies?.[n];if(/^\d+\.\d+\.\d+$/.test(a??``)&&a!==r)throw Error(`${n} is pinned to ${a} in package.json but ${r} is installed. Run pnpm install first.`)}function E(e,n,r){let i=e.pkg.exports?.[`./canvas-kit/*`];if(typeof i!=`string`)throw Error(`${n} exports no ./canvas-kit/*; a product kit takes the library's components from its kit release.`);let a=_(e.dir,i.replace(`*`,`manifest.json`)),o=t(a);if(!(o?.kind===S[r]&&o.platform===r&&Array.isArray(o.components)&&Array.isArray(o.icons)))throw Error(`${a} is not a ${r} library kit release.`);return o}function D(e,t){let n=C[t];for(let{meta:r,file:i}of e)if(!r.platforms?.includes(n))throw Error(`${i}: platforms: a ${t} kit lists only components that list ${n}`)}function O(e,n){if(!n)return;let r=t(n);if(typeof r!=`object`||!r||Array.isArray(r))throw Error(`${n} must be an object from component name to role.`);for(let[t,i]of Object.entries(r)){let r=e.find(e=>e.name===t);if(!r)throw Error(`${n} names ${t}, which the kit does not have.`);if(!x.includes(i))throw Error(`${n}: ${t} has role ${JSON.stringify(i)}; a role is title or navigation.`);r.role=i}}function k(e){let n=t(e);if(!Array.isArray(n)||n.some(e=>typeof e?.name!=`string`))throw Error(`${e} must be the style key table: a list of style keys, each with a name.`);return n}function A(e){let n=t(e);if(n?.schema!==1)throw Error(`${e} has schema ${n?.schema}; this reader reads schema 1.`);if(!n.itemActions)throw Error(`${e} has no itemActions; the phone kit's action lists come from it.`);return{flags:n.styleKeys??{},itemActions:n.itemActions}}function j(e,t,n){let r=e.map(({name:e})=>e),i=r.filter(e=>typeof t[e]!=`boolean`),a=Object.keys(t).filter(e=>!r.includes(e));if(i.length>0||a.length>0)throw Error(`${n} must list exactly the style keys of the style key table, each true or false. Missing or not a boolean: ${i.join(`, `)||`none`}. Not in the table: ${a.join(`, `)||`none`}.`)}function te(e,t){return e.map(({name:e,type:n,values:r,appliesTo:i,description:a})=>({name:e,type:n,values:r,appliesTo:i,...t?{phoneSupported:t[e]}:{},description:a}))}var ne=(e,t)=>e.name<t.name?-1:+(e.name>t.name);async function M({projectRoot:t,kit:g,platform:x,entry:C,components:M,tokens:N,libraryPackage:P,rolesFile:F,rendererProtocolVersion:I,phoneRendererSupportFile:L,styleKeysFile:R}){if(!b.test(g??``))throw Error(`kit ${JSON.stringify(g)} must be 2 to 40 characters: lowercase letters, digits and hyphens, starting with a letter.`);if(!ee.includes(x))throw Error(`platform must be Web or Phone, not ${JSON.stringify(x)}.`);if(!Number.isInteger(I)||I<1)throw Error(`rendererProtocolVersion must be a positive integer, not ${JSON.stringify(I)}.`);if(C!==void 0)throw Error(`A kit lists its components with components, a glob of .meta.js files; entry is retired.`);if(typeof M!=`string`||M===``||typeof N!=`string`||N===``)throw Error(`A kit needs components, a glob of .meta.js files, and tokens, the path of its webority-theme-tokens/2 file.`);let z=y(t),B=w(z,P),V=B.isSelf;if(x===`Phone`&&!L&&!V)throw Error(`A Phone product kit needs phoneRendererSupportFile, the phone renderer's support file; only a phone library's own kit release builds without it.`);V||T(z,P,B.pkg.version);let H=L?A(L):null,U=x===`Phone`?H:null,W=R?k(R):null;W&&H&&j(W,H.flags,L);let G=V?null:E(B,P,x),K;K=V?x===`Web`?h(_(B.dir,`dist`)):p(_(B.dir,`lib`,`typescript`,`module`,`components`,`AppIcon`,`catalog.g.d.ts`)):G.icons;let q=[];V&&(q=await u({root:z,components:M,icons:K}),D(q,x),a({libraryPackage:P,exported:o({root:z,typesFile:B.typesFile}),drawnNames:q.map(({meta:e})=>({name:e.name,component:e.component??e.name})),notDrawn:s(_(B.dir,i))}),x===`Web`&&r({root:z,metas:q,componentOf:()=>B.typesFile}));let J=[],Y=new Map;if(!V){let e=G.components.map(({name:e})=>e);J=await u({root:z,components:M,knownNames:e,icons:K}),D(J,x);let t=J.map(({meta:e})=>e.name).filter(t=>e.includes(t));if(t.length>0)throw Error(`The kit names ${t.join(`, `)} as ${P} already has them; rename the product components.`);x===`Web`&&r({root:z,metas:J,componentOf:(e,t)=>c(e,t)});for(let{meta:e,file:t}of J)Y.set(e.name,{module:c(t,e.component??e.name),exportName:e.component??e.name,fixedProps:e.fixedProps})}let X=[];if(x===`Phone`){if(!B.canvasKitFile)throw Error(`${P} exports no ./canvasKit subpath; a Phone kit takes the device frame parts from it.`);X=f(B.canvasKitFile,P)}if(V&&x===`Phone`){let e=new Set(q.map(({meta:e})=>e.name)),t=X.filter(({name:t})=>e.has(t)).map(({name:e})=>e);if(t.length>0)throw Error(`${P} exports ${t.join(`, `)} from both its main entry and ./canvasKit.`)}let re=V?q.map(({meta:e})=>l(e,{platform:x,source:P})):G.components,ie=J.map(({meta:e})=>l(e,{platform:x,source:n(v(z,Y.get(e.name).module))})),Z=[...re,...V?X:[],...ie].sort(ne);U&&d(Z,U.itemActions),O(Z,F);let Q=e(z,`@webority/tokens`);if(!Q)throw Error(`@webority/tokens is not installed for ${z}. Run pnpm install there.`);let $=m(y(z,N),_(Q,`dist`,`meanings.json`),x);return{manifest:{kind:V?S[x]:`Product`,library:{name:B.pkg.name,version:B.pkg.version},rendererProtocolVersion:I,platform:x,kitModuleVersion:2,productKit:null,components:Z,tokens:$.tokens,tokenValues:$.tokenValues,icons:K,...W?{styleKeys:te(W,U?U.flags:null)}:{}},warnings:[],phoneChromeNames:X.map(({name:e})=>e),productModules:Y,metas:V?q:J}}export{w as libraryFiles,M as readManifest,A as readPhoneSupport};
|
package/dist/meta.d.ts
CHANGED
|
@@ -71,6 +71,10 @@ export interface ComponentUsage {
|
|
|
71
71
|
export interface ComponentMeta {
|
|
72
72
|
/** The catalogue name, such as AppButton. */
|
|
73
73
|
name: string;
|
|
74
|
+
/** The export this description draws, when it is not `name`: one export described once per fixed setup, such as a picker per mode. */
|
|
75
|
+
component?: string;
|
|
76
|
+
/** Props the kit sets on every placement, over any stored value; never shown in the panel. Only with `component`. */
|
|
77
|
+
fixedProps?: Readonly<Record<string, unknown>>;
|
|
74
78
|
/** The data-wui value the component renders, or null when it renders none. */
|
|
75
79
|
marker: string | null;
|
|
76
80
|
platforms: readonly ("web" | "phone")[];
|
package/dist/metaCheck.d.ts
CHANGED
|
@@ -110,8 +110,12 @@ export type PropsMismatch<P, F extends Shape, N> = {
|
|
|
110
110
|
|
|
111
111
|
// A meta with no omit list would make NonNullable<M["omit"]>[number] collapse ExtraProps to never.
|
|
112
112
|
type OmitOf<M extends ComponentMeta> = M extends { readonly omit: infer O extends readonly string[] } ? O[number] : never;
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
// The props a meta fixes are set by the kit, not the panel, so they are not extra props.
|
|
114
|
+
type FixedOf<M extends ComponentMeta> = M extends { readonly fixedProps: infer F extends Readonly<Record<string, unknown>> }
|
|
115
|
+
? keyof F & string
|
|
116
|
+
: never;
|
|
117
|
+
/** Props the component takes that the meta neither lists, omits nor fixes. */
|
|
118
|
+
export type ExtraProps<P, M extends ComponentMeta> = Exclude<DesignKeys<P>, keyof M["props"] | OmitOf<M> | FixedOf<M>>;
|
|
115
119
|
/** Props the meta lists that the component does not take. */
|
|
116
120
|
export type MissingProps<P, M extends ComponentMeta> = Exclude<keyof M["props"] & string, DesignKeys<P>>;
|
|
117
121
|
export type MismatchedProps<P, M extends ComponentMeta, N> = PropsMismatch<P, M["props"], N>;
|
package/dist/metaCheck.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{toPosix as e}from"./files.js";import{createRequire as t}from"node:module";import{mkdirSync as n,rmSync as r,writeFileSync as i}from"node:fs";import{dirname as a,join as o}from"node:path";import{fileURLToPath as s}from"node:url";import{execFileSync as c}from"node:child_process";var l=o(a(t(import.meta.url).resolve(`typescript/package.json`)),`bin`,`tsc`),u=o(a(s(import.meta.url)),`metaCheck.js`),d=/^check\.ts\((\d+),\d+\): error TS\d+: (.*)$/,f=/^(.+?)\(\d+,\d+\): error TS\d+: (.*)$/,p=[`propsNotInMeta`,`metaPropsNotOnComponent`,`propsThatDiffer`,`children`],m={propsNotInMeta:`props the component takes that the meta does not list`,metaPropsNotOnComponent:`props the meta lists that the component does not take`,propsThatDiffer:`props whose type, required or nullable flag, or nested fields differ from the component`};function h(t){let n=e(t);return/\.d\.ts$/.test(n)?n.replace(/\.d\.ts$/,``):n.replace(/\.(jsx|tsx|js|ts|mjs)$/,``)}function g(e){let t=[];for(let n of e.split(/\r?\n/)){let e=d.exec(n);if(e){t.push({line:Number(e[1]),file:null,message:e[2]});continue}let r=f.exec(n);r&&t.push({line:null,file:r[1],message:r[2]})}return t}function _(e){let t=/Type '(\{[^']*\})'/.exec(e);return t?[...t[1].matchAll(/: "([^"]+)"/g)].map(e=>e[1]):[]}function v(e){let t=new Map,n=(e,n,r,i)=>{let a=`${e} ${n}`;t.has(a)||t.set(a,{component:e,handler:n,path:r,owner:i})},r=(e,t,i)=>{if(!(typeof e!=`object`||!e)){for(let r of e.handlers??[])n(e.component,r,t,i);Array.isArray(e.children)&&e.children.forEach((e,n)=>r(e,`${t}.children[${n}]`,i))}};return e.forEach(({meta:e},t)=>{(e.examples??[]).forEach((i,a)=>{let o=`examples[${a}]`;for(let r of i.handlers??[])n(e.name,r,o,t);r({children:i.children},o,t),r(i.wrap,`${o}.wrap`,t)});for(let n of[`do`,`dont`])(e.usage?.[n]??[]).forEach((e,i)=>{(e.example??[]).forEach((e,a)=>r(e,`usage.${n}[${i}].example[${a}]`,t))})}),t}function y({root:t,metas:a,componentOf:s}){let d=o(t,`node_modules`,`.canvas-kit-check-${process.pid}`);try{n(d,{recursive:!0});let t=a.map(({meta:e,file:t})=>({component:h(s(t,e.name)),meta:h(t)})),r=[],f=new Map,y=new Map,b=(e,t=-1,n=null)=>{r.push(e);let i=r.length;t>=0&&f.set(i,t),n&&y.set(i,n)};b(`import type { ExtraProps, MissingProps, MismatchedProps, ChildrenOk, HandlerKeys } from "${e(u)}";`),b(`type N = import("react").ReactNode;`),b(`type Empty = { [key: string]: never };`),a.forEach((e,n)=>{b(`import type * as C${n} from "${t[n].component}";`,n),b(`import type { meta as M${n} } from "${t[n].meta}";`,n)});let x=e=>`{ [K in ${e}]: K }`;a.forEach(({meta:e},t)=>{let n=e.name;b(`type P${t} = import("react").ComponentProps<typeof C${t}.${
|
|
1
|
+
import{toPosix as e}from"./files.js";import{createRequire as t}from"node:module";import{mkdirSync as n,rmSync as r,writeFileSync as i}from"node:fs";import{dirname as a,join as o}from"node:path";import{fileURLToPath as s}from"node:url";import{execFileSync as c}from"node:child_process";var l=o(a(t(import.meta.url).resolve(`typescript/package.json`)),`bin`,`tsc`),u=o(a(s(import.meta.url)),`metaCheck.js`),d=/^check\.ts\((\d+),\d+\): error TS\d+: (.*)$/,f=/^(.+?)\(\d+,\d+\): error TS\d+: (.*)$/,p=[`propsNotInMeta`,`metaPropsNotOnComponent`,`propsThatDiffer`,`children`,`fixedProps`],m={propsNotInMeta:`props the component takes that the meta does not list`,metaPropsNotOnComponent:`props the meta lists that the component does not take`,propsThatDiffer:`props whose type, required or nullable flag, or nested fields differ from the component`,fixedProps:`fixed props whose value does not fit the component's prop`};function h(t){let n=e(t);return/\.d\.ts$/.test(n)?n.replace(/\.d\.ts$/,``):n.replace(/\.(jsx|tsx|js|ts|mjs)$/,``)}function g(e){let t=[];for(let n of e.split(/\r?\n/)){let e=d.exec(n);if(e){t.push({line:Number(e[1]),file:null,message:e[2]});continue}let r=f.exec(n);r&&t.push({line:null,file:r[1],message:r[2]})}return t}function _(e){let t=/Type '(\{[^']*\})'/.exec(e);return t?[...t[1].matchAll(/: "([^"]+)"/g)].map(e=>e[1]):[]}function v(e){let t=new Map,n=(e,n,r,i)=>{let a=`${e} ${n}`;t.has(a)||t.set(a,{component:e,handler:n,path:r,owner:i})},r=(e,t,i)=>{if(!(typeof e!=`object`||!e)){for(let r of e.handlers??[])n(e.component,r,t,i);Array.isArray(e.children)&&e.children.forEach((e,n)=>r(e,`${t}.children[${n}]`,i))}};return e.forEach(({meta:e},t)=>{(e.examples??[]).forEach((i,a)=>{let o=`examples[${a}]`;for(let r of i.handlers??[])n(e.name,r,o,t);r({children:i.children},o,t),r(i.wrap,`${o}.wrap`,t)});for(let n of[`do`,`dont`])(e.usage?.[n]??[]).forEach((e,i)=>{(e.example??[]).forEach((e,a)=>r(e,`usage.${n}[${i}].example[${a}]`,t))})}),t}function y({root:t,metas:a,componentOf:s}){let d=o(t,`node_modules`,`.canvas-kit-check-${process.pid}`);try{n(d,{recursive:!0});let t=a.map(({meta:e,file:t})=>({component:h(s(t,e.component??e.name)),meta:h(t)})),r=[],f=new Map,y=new Map,b=(e,t=-1,n=null)=>{r.push(e);let i=r.length;t>=0&&f.set(i,t),n&&y.set(i,n)};b(`import type { ExtraProps, MissingProps, MismatchedProps, ChildrenOk, HandlerKeys } from "${e(u)}";`),b(`type N = import("react").ReactNode;`),b(`type Empty = { [key: string]: never };`),a.forEach((e,n)=>{b(`import type * as C${n} from "${t[n].component}";`,n),b(`import type { meta as M${n} } from "${t[n].meta}";`,n)});let x=e=>`{ [K in ${e}]: K }`;a.forEach(({meta:e},t)=>{let n=e.name,r=e.component??e.name;b(`type P${t} = import("react").ComponentProps<typeof C${t}.${r}>;`,t),b(`export const ${n}__propsNotInMeta: Empty = null as unknown as ${x(`ExtraProps<P${t}, typeof M${t}>`)};`,t,`propsNotInMeta`),b(`export const ${n}__metaPropsNotOnComponent: Empty = null as unknown as ${x(`MissingProps<P${t}, typeof M${t}>`)};`,t,`metaPropsNotOnComponent`),b(`export const ${n}__propsThatDiffer: Empty = null as unknown as ${x(`MismatchedProps<P${t}, typeof M${t}, N>`)};`,t,`propsThatDiffer`),b(`export const ${n}__children: true = null as unknown as ChildrenOk<P${t}, typeof M${t}>;`,t,`children`),e.fixedProps!==void 0&&b(`export const ${n}__fixedProps: Partial<P${t}> = null as unknown as NonNullable<(typeof M${t})["fixedProps"]>;`,t,`fixedProps`)});let S=new Map(a.map(({meta:e},t)=>[e.name,t])),C=new Map,w=0;for(let{component:t,handler:n,path:i,owner:o}of v(a).values()){let s=S.get(t);s!==void 0&&(w+=1,b(`export const ${t.replace(/[^A-Za-z0-9_]/g,`_`)}__handler_${n}_${w}: Empty = null as unknown as { [K in Exclude<"${n}", HandlerKeys<P${s}>>]: K };`),C.set(r.length,{owner:o,where:`${e(a[o].file)}: ${i}`,component:t,handler:n}))}i(o(d,`check.ts`),`${r.join(`
|
|
2
2
|
`)}\n`),i(o(d,`tsconfig.json`),JSON.stringify({compilerOptions:{strict:!0,noEmit:!0,allowJs:!0,checkJs:!1,jsx:`react-jsx`,module:`esnext`,moduleResolution:`bundler`,target:`es2022`,skipLibCheck:!0,noErrorTruncation:!0,types:[]},files:[`check.ts`]},null,2));let T;try{c(process.execPath,[l,`-p`,o(d,`tsconfig.json`),`--pretty`,`false`],{cwd:d,encoding:`utf8`,stdio:`pipe`});return}catch(e){T=String(e.stdout??``)+String(e.stderr??``)}let E=new Map,D=[];for(let n of g(T)){let r=n.line===null?void 0:C.get(n.line);if(r){D.push({owner:r.owner,rank:p.length,text:`${r.where}: "${r.handler}" is not a function prop of ${r.component}`});continue}let i=n.line!==null&&f.has(n.line)?f.get(n.line):void 0,o=n.line===null?void 0:y.get(n.line);if(o&&i!==void 0){let e=`${i}:${o}`;if(E.has(e)||E.set(e,{owner:i,kind:o,names:new Set}),o!==`children`)for(let t of _(n.message))E.get(e).names.add(t);continue}let s=i??t.findIndex(e=>[n.file,n.message].some(t=>t&&(t.includes(e.component)||t.includes(e.meta)))),c=n.line===null?`${e(n.file)}: `:``;D.push({owner:s,rank:-1,text:`${s>=0?a[s].meta.name:`metaCheck`}: tsc could not read the check file: ${c}${n.message}`})}for(let{owner:e,kind:t,names:n}of E.values()){let{meta:r}=a[e],i=t===`children`?`${r.name}: acceptsChildren is ${r.acceptsChildren} but the component ${r.acceptsChildren?`does not take`:`takes`} children`:n.size>0?`${r.name}: ${m[t]}: ${[...n].sort().join(`, `)}`:`${r.name}: ${m[t]}: see the meta against the component's props`;D.push({owner:e,rank:p.indexOf(t),text:i})}throw D.length===0?Error(`metaCheck: tsc failed: ${T.split(/\r?\n/).slice(0,20).join(`
|
|
3
3
|
`)}`):(D.sort((e,t)=>e.owner-t.owner||e.rank-t.rank),Error(D.map(e=>e.text).join(`
|
|
4
4
|
`)))}finally{r(d,{recursive:!0,force:!0})}}export{l as TSC,y as checkMetaTypes,h as specifierOf};
|
package/dist/metas.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{toPosix as e}from"./files.js";import{existsSync as t,globSync as n}from"node:fs";import{resolve as
|
|
2
|
-
`))}function h(e,{platform:t,source:n}){let r=Object.keys(e.props).sort(L);return{name:e.name,marker:e.marker,acceptsChildren:e.acceptsChildren,props:r.map(t=>j(t,e.props[t])),itemsTakeAction:t===`Web`?r.filter(t=>P(e.props[t])):[],takesAction:[],source:n,usage:e.usage}}function g(n,r){let i=n.replace(/\.meta\.[jt]s$/,``);for(let n of f)if(t(i+n))return e(i+n);throw Error(`no component module for ${r} beside ${n}`)}function _(e,t,n,r,i,a){if(!R(e)){a.push([`meta`,`must be an object`]);return}let{name:s}=e;typeof s!=`string`||!o.test(s)?a.push([`name`,`"${s}" is not a catalogue name; start with a capital letter and use letters and digits`]):n.has(s)?a.push([`name`,`"${s}" is also the name in ${n.get(s)}`]):n.set(s,t);let{platforms:c}=e;Array.isArray(c)&&c.length>0&&c.every(e=>e===`web`||e===`phone`)||a.push([`platforms`,`must list web, phone or both`]),e.marker!==null&&typeof e.marker!=`string`&&a.push([`marker`,`must be a string or null`]),typeof e.acceptsChildren!=`boolean`&&a.push([`acceptsChildren`,`must be true or false`]),e.omit!==void 0&&(!Array.isArray(e.omit)||!e.omit.every(e=>typeof e==`string`))&&a.push([`omit`,`must be a list of prop names`]);let l=R(e.props)?e.props:{};if(!R(e.props))a.push([`props`,`must be an object`]);else for(let[t,n]of Object.entries(e.props))v(n,`props.${t}`,i,a);Array.isArray(e.examples)?e.examples.forEach((n,o)=>{E(n,`examples[${o}]`,e,l,t,r,i,a)}):a.push([`examples`,`must be a list`]),D(e.usage,i,a),A(e,``,a)}function v(e,t,n,r){if(!R(e)){r.push([t,`is not a prop`]);return}if(!d.includes(e.type)){r.push([`${t}.type`,`${I(e.type)} is not a prop type`]);return}if(e.type===`enum`||e.type===`enumOrNumber`?y(e,t,r):e.values!==void 0&&r.push([`${t}.values`,`only an enum or an enumOrNumber has values`]),e.fields!==void 0)if(e.type!==`object`)r.push([`${t}.fields`,`only an object has fields`]);else for(let[i,a]of Object.entries(e.fields))v(a,`${t}.fields.${i}`,n,r);if(e.itemFields!==void 0)if(e.type!==`array`)r.push([`${t}.itemFields`,`only an array has itemFields`]);else for(let[i,a]of Object.entries(e.itemFields))v(a,`${t}.itemFields.${i}`,n,r);if(B(e.description)||r.push([`${t}.description`,`is empty`]),e.required!==void 0&&typeof e.required!=`boolean`&&r.push([`${t}.required`,`must be true or false`]),e.nullable!==void 0&&typeof e.nullable!=`boolean`&&r.push([`${t}.nullable`,`must be true or false`]),e.default!==void 0)if(e.required===!0)r.push([`${t}.default`,`a required prop has no default`]);else{let i=[];b(e.default,e,t,n,i),i.length>0&&r.push([`${t}.default`,`${I(e.default)} does not fit ${e.type}`])}}function y(e,t,n){let{type:r,values:i}=e;if(!Array.isArray(i)||i.length===0){n.push([`${t}.values`,`an ${r} lists its values`]);return}let a=new Set;for(let e of i)(r===`enum`?typeof e==`string`||z(e):typeof e==`string`)?a.has(e)&&n.push([`${t}.values`,`"${e}" is listed twice`]):n.push([`${t}.values`,`${I(e)} is not allowed here`]),a.add(e)}function b(e,t,n,r,i){if(!R(t)||e===null&&(t.nullable===!0||t.type===`node`||t.type===`icon`))return;let a=Array.isArray(t.values)?t.values:[];switch(t.type){case`string`:case`url`:typeof e!=`string`&&F(e,t.type,n,i);return;case`number`:z(e)||F(e,t.type,n,i);return;case`boolean`:typeof e!=`boolean`&&F(e,t.type,n,i);return;case`stringOrNumber`:typeof e!=`string`&&!z(e)&&F(e,t.type,n,i);return;case`enum`:a.includes(e)||i.push([n,`${I(e)} is not one of ${I(a)}`]);return;case`enumOrNumber`:!z(e)&&!a.includes(e)&&i.push([n,`${I(e)} is not one of ${I(a)}`]);return;case`icon`:V(e)?C(e,n,r,i):typeof e==`string`?Array.isArray(r.icons)&&!r.icons.includes(e)&&i.push([n,`"${e}" is not an icon of the kit`]):F(e,t.type,n,i);return;case`node`:Array.isArray(e)?e.forEach((e,t)=>x(e,`${n}[${t}]`,r,i)):x(e,n,r,i);return;case`array`:Array.isArray(e)?t.itemFields!==void 0&&e.forEach((e,a)=>{R(e)?S(e,t.itemFields,`${n}[${a}]`,r,i):i.push([`${n}[${a}]`,`${I(e)} is not an object`])}):F(e,t.type,n,i);return;case`object`:R(e)?t.fields!==void 0&&S(e,t.fields,n,r,i):F(e,t.type,n,i);return;default:return}}function x(e,t,n,r){V(e)?C(e,t,n,r):typeof e!=`string`&&!z(e)&&r.push([t,`${I(e)} is not a node`])}function S(e,t,n,r,i){for(let a of Object.keys(e))Object.hasOwn(t,a)?b(e[a],t[a],`${n}.${a}`,r,i):i.push([`${n}.${a}`,`not a field`]);for(let[r,a]of Object.entries(t))R(a)&&a.required===!0&&!Object.hasOwn(e,r)&&i.push([`${n}.${r}`,`missing, the field is required`])}function C(e,t,n,r){let{component:i}=e,o=n.byName.get(i);if(!o&&!n.knownNames.has(i)&&!a.includes(i)&&r.push([`${t}.component`,`"${i}" is neither a component of the kit nor one of the HTML tags`]),o&&e.props!==void 0)if(!R(e.props))r.push([`${t}.props`,`must be an object`]);else{let a=R(o.props)?o.props:{};for(let[o,s]of Object.entries(e.props))Object.hasOwn(a,o)?b(s,a[o],`${t}.props.${o}`,n,r):r.push([`${t}.props.${o}`,`not a prop of ${i}`])}e.children!==void 0&&(o&&o.acceptsChildren===!1&&r.push([`${t}.children`,`${i} takes no children`]),T(e.children,`${t}.children`,n,r)),e.handlers!==void 0&&w(e.handlers,`${t}.handlers`,i,o,r)}function w(e,t,n,r,i){if(!Array.isArray(e)||!e.every(e=>typeof e==`string`)){i.push([t,`must be a list of handler names`]);return}if(a.includes(n)){i.push([t,`handlers need a kit component`]);return}if(e.length===0){i.push([t,`omit handlers when empty`]);return}let o=new Set;for(let a of e)l.test(a)?o.has(a)?i.push([t,`"${a}" is listed twice`]):r&&R(r.props)&&Object.hasOwn(r.props,a)&&i.push([t,`"${a}" is a data prop of ${n}, set it in props`]):i.push([t,`"${a}" is not a handler name (on<Event>)`]),o.add(a)}function T(e,t,n,r){if(typeof e!=`string`){if(!Array.isArray(e)){r.push([t,`is text or a list of text and placed elements`]);return}e.forEach((e,i)=>{typeof e!=`string`&&(V(e)?C(e,`${t}[${i}]`,n,r):r.push([`${t}[${i}]`,`is neither text nor a placed element`]))})}}function E(e,t,n,r,i,a,o,c){if(!R(e)){c.push([t,`is not an example`]);return}let{name:l}=n,{id:u}=e;if(typeof u==`string`&&(u===l||u.startsWith(`${l}.`)&&s.test(u.slice(l.length+1)))?a.has(u)?c.push([`${t}.id`,`"${u}" is also used in ${a.get(u)}`]):a.set(u,i):c.push([`${t}.id`,`"${u}" must be ${l} or ${l}.<case>`]),B(e.title)||c.push([`${t}.title`,`is empty`]),!R(e.props))c.push([`${t}.props`,`must be an object`]);else{for(let[n,i]of Object.entries(e.props))Object.hasOwn(r,n)?b(i,r[n],`${t}.props.${n}`,o,c):c.push([`${t}.props.${n}`,`not a prop of ${l}`]);for(let[n,i]of Object.entries(r))R(i)&&i.required===!0&&!Object.hasOwn(e.props,n)&&c.push([`${t}.props.${n}`,`missing, the prop is required`])}e.children!==void 0&&(n.acceptsChildren===!1&&c.push([`${t}.children`,`${l} takes no children`]),T(e.children,`${t}.children`,o,c)),e.wrap!==void 0&&(V(e.wrap)?C(e.wrap,`${t}.wrap`,o,c):c.push([`${t}.wrap`,`is not a placed element`])),e.handlers!==void 0&&w(e.handlers,`${t}.handlers`,l,n,c)}function D(e,t,n){if(!R(e)){n.push([`usage`,`must be an object`]);return}(!Array.isArray(e.when)||e.when.length===0||!e.when.every(B))&&n.push([`usage.when`,`lists nothing; write at least one line`]),Array.isArray(e.whenNot)?e.whenNot.forEach((e,r)=>O(e,`usage.whenNot[${r}]`,t,n)):n.push([`usage.whenNot`,`must be a list`]),Array.isArray(e.do)||n.push([`usage.do`,`must be a list`]),Array.isArray(e.dont)||n.push([`usage.dont`,`must be a list`]),Array.isArray(e.do)&&Array.isArray(e.dont)&&(e.do.length!==e.dont.length&&n.push([`usage`,`${e.do.length} do against ${e.dont.length} dont; they pair up one to one`]),e.do.forEach((e,r)=>k(e,`usage.do[${r}]`,t,n)),e.dont.forEach((e,r)=>k(e,`usage.dont[${r}]`,t,n))),Array.isArray(e.a11y)?e.a11y.forEach((e,t)=>{B(e)||n.push([`usage.a11y[${t}]`,`is empty`])}):n.push([`usage.a11y`,`must be a list`])}function O(e,t,n,r){if(!R(e)){r.push([t,`is not an object`]);return}B(e.text)||r.push([`${t}.text`,`is empty`]),e.instead!==void 0&&(typeof e.instead==`string`?c.test(e.instead)&&!n.byName.has(e.instead)&&!n.knownNames.has(e.instead)&&r.push([`${t}.instead`,`"${e.instead}" is not a component of the kit`]):r.push([`${t}.instead`,`must be text`]))}function k(e,t,n,r){if(!R(e)){r.push([t,`is not a practice`]);return}if(B(e.note)||r.push([`${t}.note`,`is empty`]),!Array.isArray(e.example)||e.example.length===0){r.push([`${t}.example`,`needs at least one placed element`]);return}e.example.forEach((e,i)=>{let a=`${t}.example[${i}]`;V(e)?C(e,a,n,r):r.push([a,`is not a placed element`])})}function A(e,t,n){if(typeof e==`string`)u.test(e)&&n.push([t,`contains an em or en dash; use a comma, colon or period`]);else if(Array.isArray(e))e.forEach((e,r)=>A(e,`${t}[${r}]`,n));else if(R(e))for(let[r,i]of Object.entries(e))A(i,t?`${t}.${r}`:r,n)}function j(e,t){let n={name:e,type:t.type};return(t.type===`enum`||t.type===`enumOrNumber`)&&(n.enum=N(t.values)),t.fields!==void 0&&(n.fields=M(t.fields)),t.itemFields!==void 0&&(n.itemFields=M(t.itemFields)),n.required=t.required===!0,t.nullable===!0&&(n.nullable=!0),t.description!==void 0&&(n.description=t.description),t.default!==void 0&&(n.default=t.default),n}function M(e){return Object.keys(e).sort(L).map(t=>j(t,e[t]))}function N(e){return[...e].sort((e,t)=>{let n=typeof e==`number`,r=typeof t==`number`;return n&&r?e-t:n===r?L(e,t):n?-1:1})}function P(e){return e.type===`array`&&Object.keys(e.itemFields??{}).some(e=>e===`href`||e===`to`)}function F(e,t,n,r){r.push([n,`${I(e)} is not a ${t}`])}function I(e){return JSON.stringify(e)}function L(e,t){return e<t?-1:+(e>t)}function R(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function z(e){return typeof e==`number`&&Number.isFinite(e)}function B(e){return typeof e==`string`&&e.trim()!==``}function V(e){return R(e)&&typeof e.component==`string`}export{a as HTML_TAGS,m as checkMetas,g as componentModuleOf,h as manifestComponent,p as readMetas};
|
|
1
|
+
import{toPosix as e}from"./files.js";import{existsSync as t,globSync as n}from"node:fs";import{basename as r,dirname as i,join as a,resolve as o}from"node:path";import{pathToFileURL as s}from"node:url";var c=Object.freeze([`a`,`b`,`button`,`div`,`img`,`kbd`,`li`,`p`,`span`,`strong`,`table`,`tbody`,`td`,`th`,`thead`,`tr`,`ul`]),l=/^[A-Z][A-Za-z0-9]*$/,u=/^[A-Za-z0-9][A-Za-z0-9_-]*$/,d=/^App[A-Za-z0-9]*$/,f=/^on[A-Z][A-Za-z0-9]*$/,p=/[\u2013\u2014]/,m=[`string`,`number`,`stringOrNumber`,`boolean`,`enum`,`enumOrNumber`,`url`,`icon`,`node`,`array`,`object`,`any`],h=[`.jsx`,`.tsx`,`.js`,`.ts`];async function g({root:e,components:t,knownNames:r,icons:i}){let a=n(t,{cwd:e});if(a.length===0)throw Error(`${e}: no component metadata matches ${t}`);let c=a.map(t=>o(e,t)).sort(B),l=[];for(let e of c){let t=await import(s(e).href);if(!(`meta`in t))throw Error(`${e}: exports no meta; write export const meta = defineMeta({...})`);l.push({meta:t.meta,file:e})}return _(l,{knownNames:r,icons:i}),l.sort((e,t)=>B(e.meta.name,t.meta.name))}function _(e,{knownNames:t=[],icons:n}={}){let r=new Map;for(let{meta:t}of e)V(t)&&typeof t.name==`string`&&!r.has(t.name)&&r.set(t.name,t);let i={byName:r,knownNames:new Set(t),icons:n},a=new Map,o=new Map,s=[];for(let{meta:t,file:n}of e){let e=[];b(t,n,a,o,i,e);for(let[t,r]of e)s.push(`${n}: ${t}: ${r}`)}if(s.length>0)throw Error(s.join(`
|
|
2
|
+
`))}function v(e,{platform:t,source:n}){let r=Object.keys(e.props).sort(B);return{name:e.name,marker:e.marker,acceptsChildren:e.acceptsChildren,props:r.map(t=>P(t,e.props[t])),itemsTakeAction:t===`Web`?r.filter(t=>L(e.props[t])):[],takesAction:[],source:n,...e.component===void 0?{}:{component:e.component},...e.fixedProps===void 0?{}:{fixedProps:e.fixedProps},usage:e.usage}}function y(n,o){let s=n.replace(/\.meta\.[jt]s$/,``),c=r(s)===o?s:a(i(s),o);for(let n of h)if(t(c+n))return e(c+n);throw Error(`no component module for ${o} beside ${n}`)}function b(e,t,n,r,i,a){if(!V(e)){a.push([`meta`,`must be an object`]);return}let{name:o}=e;typeof o!=`string`||!l.test(o)?a.push([`name`,`"${o}" is not a catalogue name; start with a capital letter and use letters and digits`]):n.has(o)?a.push([`name`,`"${o}" is also the name in ${n.get(o)}`]):n.set(o,t),e.component!==void 0&&(U(e.component)?e.component===o&&a.push([`component`,`"${e.component}" is the name; leave component out when the meta draws its own export`]):a.push([`component`,`must name an export as text`]));let{platforms:s}=e;Array.isArray(s)&&s.length>0&&s.every(e=>e===`web`||e===`phone`)||a.push([`platforms`,`must list web, phone or both`]),e.marker!==null&&typeof e.marker!=`string`&&a.push([`marker`,`must be a string or null`]),typeof e.acceptsChildren!=`boolean`&&a.push([`acceptsChildren`,`must be true or false`]),e.omit!==void 0&&(!Array.isArray(e.omit)||!e.omit.every(e=>typeof e==`string`))&&a.push([`omit`,`must be a list of prop names`]);let c=V(e.props)?e.props:{};if(!V(e.props))a.push([`props`,`must be an object`]);else for(let[t,n]of Object.entries(e.props))x(n,`props.${t}`,i,a);let u=new Set;if(e.fixedProps!==void 0)if(e.component===void 0&&a.push([`fixedProps`,`needs component, the export the fixed props go to`]),!V(e.fixedProps)||Object.keys(e.fixedProps).length===0)a.push([`fixedProps`,`must be an object of the props the kit sets`]);else{let t=Array.isArray(e.omit)?e.omit:[];for(let n of Object.keys(e.fixedProps))u.add(n),Object.hasOwn(c,n)?a.push([`fixedProps.${n}`,`is also a prop; a fixed prop is set by the kit, not the panel`]):t.includes(n)&&a.push([`fixedProps.${n}`,`is listed in omit; a prop is fixed or omitted, not both`])}i.fixed={name:o,keys:u},Array.isArray(e.examples)?e.examples.forEach((n,o)=>{k(n,`examples[${o}]`,e,c,t,r,i,a)}):a.push([`examples`,`must be a list`]),A(e.usage,i,a),i.fixed=null,N(e,``,a)}function x(e,t,n,r){if(!V(e)){r.push([t,`is not a prop`]);return}if(!m.includes(e.type)){r.push([`${t}.type`,`${z(e.type)} is not a prop type`]);return}if(e.type===`enum`||e.type===`enumOrNumber`?S(e,t,r):e.values!==void 0&&r.push([`${t}.values`,`only an enum or an enumOrNumber has values`]),e.fields!==void 0)if(e.type!==`object`)r.push([`${t}.fields`,`only an object has fields`]);else for(let[i,a]of Object.entries(e.fields))x(a,`${t}.fields.${i}`,n,r);if(e.itemFields!==void 0)if(e.type!==`array`)r.push([`${t}.itemFields`,`only an array has itemFields`]);else for(let[i,a]of Object.entries(e.itemFields))x(a,`${t}.itemFields.${i}`,n,r);if(U(e.description)||r.push([`${t}.description`,`is empty`]),e.required!==void 0&&typeof e.required!=`boolean`&&r.push([`${t}.required`,`must be true or false`]),e.nullable!==void 0&&typeof e.nullable!=`boolean`&&r.push([`${t}.nullable`,`must be true or false`]),e.default!==void 0)if(e.required===!0)r.push([`${t}.default`,`a required prop has no default`]);else{let i=[];C(e.default,e,t,n,i),i.length>0&&r.push([`${t}.default`,`${z(e.default)} does not fit ${e.type}`])}}function S(e,t,n){let{type:r,values:i}=e;if(!Array.isArray(i)||i.length===0){n.push([`${t}.values`,`an ${r} lists its values`]);return}let a=new Set;for(let e of i)(r===`enum`?typeof e==`string`||H(e):typeof e==`string`)?a.has(e)&&n.push([`${t}.values`,`"${e}" is listed twice`]):n.push([`${t}.values`,`${z(e)} is not allowed here`]),a.add(e)}function C(e,t,n,r,i){if(!V(t)||e===null&&(t.nullable===!0||t.type===`node`||t.type===`icon`))return;let a=Array.isArray(t.values)?t.values:[];switch(t.type){case`string`:case`url`:typeof e!=`string`&&R(e,t.type,n,i);return;case`number`:H(e)||R(e,t.type,n,i);return;case`boolean`:typeof e!=`boolean`&&R(e,t.type,n,i);return;case`stringOrNumber`:typeof e!=`string`&&!H(e)&&R(e,t.type,n,i);return;case`enum`:a.includes(e)||i.push([n,`${z(e)} is not one of ${z(a)}`]);return;case`enumOrNumber`:!H(e)&&!a.includes(e)&&i.push([n,`${z(e)} is not one of ${z(a)}`]);return;case`icon`:W(e)?E(e,n,r,i):typeof e==`string`?Array.isArray(r.icons)&&!r.icons.includes(e)&&i.push([n,`"${e}" is not an icon of the kit`]):R(e,t.type,n,i);return;case`node`:Array.isArray(e)?e.forEach((e,t)=>w(e,`${n}[${t}]`,r,i)):w(e,n,r,i);return;case`array`:Array.isArray(e)?t.itemFields!==void 0&&e.forEach((e,a)=>{V(e)?T(e,t.itemFields,`${n}[${a}]`,r,i):i.push([`${n}[${a}]`,`${z(e)} is not an object`])}):R(e,t.type,n,i);return;case`object`:V(e)?t.fields!==void 0&&T(e,t.fields,n,r,i):R(e,t.type,n,i);return;default:return}}function w(e,t,n,r){W(e)?E(e,t,n,r):typeof e!=`string`&&!H(e)&&r.push([t,`${z(e)} is not a node`])}function T(e,t,n,r,i){for(let a of Object.keys(e))Object.hasOwn(t,a)?C(e[a],t[a],`${n}.${a}`,r,i):i.push([`${n}.${a}`,`not a field`]);for(let[r,a]of Object.entries(t))V(a)&&a.required===!0&&!Object.hasOwn(e,r)&&i.push([`${n}.${r}`,`missing, the field is required`])}function E(e,t,n,r){let{component:i}=e,a=n.byName.get(i);if(!a&&!n.knownNames.has(i)&&!c.includes(i)&&r.push([`${t}.component`,`"${i}" is neither a component of the kit nor one of the HTML tags`]),a&&e.props!==void 0)if(!V(e.props))r.push([`${t}.props`,`must be an object`]);else{let o=V(a.props)?a.props:{};for(let[a,s]of Object.entries(e.props))n.fixed&&n.fixed.name===i&&n.fixed.keys.has(a)?r.push([`${t}.props.${a}`,`is a fixed prop; the kit sets it`]):Object.hasOwn(o,a)?C(s,o[a],`${t}.props.${a}`,n,r):r.push([`${t}.props.${a}`,`not a prop of ${i}`])}e.children!==void 0&&(a&&a.acceptsChildren===!1&&r.push([`${t}.children`,`${i} takes no children`]),O(e.children,`${t}.children`,n,r)),e.handlers!==void 0&&D(e.handlers,`${t}.handlers`,i,a,r)}function D(e,t,n,r,i){if(!Array.isArray(e)||!e.every(e=>typeof e==`string`)){i.push([t,`must be a list of handler names`]);return}if(c.includes(n)){i.push([t,`handlers need a kit component`]);return}if(e.length===0){i.push([t,`omit handlers when empty`]);return}let a=new Set;for(let o of e)f.test(o)?a.has(o)?i.push([t,`"${o}" is listed twice`]):r&&V(r.props)&&Object.hasOwn(r.props,o)&&i.push([t,`"${o}" is a data prop of ${n}, set it in props`]):i.push([t,`"${o}" is not a handler name (on<Event>)`]),a.add(o)}function O(e,t,n,r){if(typeof e!=`string`){if(!Array.isArray(e)){r.push([t,`is text or a list of text and placed elements`]);return}e.forEach((e,i)=>{typeof e!=`string`&&(W(e)?E(e,`${t}[${i}]`,n,r):r.push([`${t}[${i}]`,`is neither text nor a placed element`]))})}}function k(e,t,n,r,i,a,o,s){if(!V(e)){s.push([t,`is not an example`]);return}let{name:c}=n,{id:l}=e;if(typeof l==`string`&&(l===c||l.startsWith(`${c}.`)&&u.test(l.slice(c.length+1)))?a.has(l)?s.push([`${t}.id`,`"${l}" is also used in ${a.get(l)}`]):a.set(l,i):s.push([`${t}.id`,`"${l}" must be ${c} or ${c}.<case>`]),U(e.title)||s.push([`${t}.title`,`is empty`]),!V(e.props))s.push([`${t}.props`,`must be an object`]);else{for(let[n,i]of Object.entries(e.props))o.fixed&&o.fixed.keys.has(n)?s.push([`${t}.props.${n}`,`is a fixed prop; the kit sets it`]):Object.hasOwn(r,n)?C(i,r[n],`${t}.props.${n}`,o,s):s.push([`${t}.props.${n}`,`not a prop of ${c}`]);for(let[n,i]of Object.entries(r))V(i)&&i.required===!0&&!Object.hasOwn(e.props,n)&&s.push([`${t}.props.${n}`,`missing, the prop is required`])}e.children!==void 0&&(n.acceptsChildren===!1&&s.push([`${t}.children`,`${c} takes no children`]),O(e.children,`${t}.children`,o,s)),e.wrap!==void 0&&(W(e.wrap)?E(e.wrap,`${t}.wrap`,o,s):s.push([`${t}.wrap`,`is not a placed element`])),e.handlers!==void 0&&D(e.handlers,`${t}.handlers`,c,n,s)}function A(e,t,n){if(!V(e)){n.push([`usage`,`must be an object`]);return}(!Array.isArray(e.when)||e.when.length===0||!e.when.every(U))&&n.push([`usage.when`,`lists nothing; write at least one line`]),Array.isArray(e.whenNot)?e.whenNot.forEach((e,r)=>j(e,`usage.whenNot[${r}]`,t,n)):n.push([`usage.whenNot`,`must be a list`]),Array.isArray(e.do)||n.push([`usage.do`,`must be a list`]),Array.isArray(e.dont)||n.push([`usage.dont`,`must be a list`]),Array.isArray(e.do)&&Array.isArray(e.dont)&&(e.do.length!==e.dont.length&&n.push([`usage`,`${e.do.length} do against ${e.dont.length} dont; they pair up one to one`]),e.do.forEach((e,r)=>M(e,`usage.do[${r}]`,t,n)),e.dont.forEach((e,r)=>M(e,`usage.dont[${r}]`,t,n))),Array.isArray(e.a11y)?e.a11y.forEach((e,t)=>{U(e)||n.push([`usage.a11y[${t}]`,`is empty`])}):n.push([`usage.a11y`,`must be a list`])}function j(e,t,n,r){if(!V(e)){r.push([t,`is not an object`]);return}U(e.text)||r.push([`${t}.text`,`is empty`]),e.instead!==void 0&&(typeof e.instead==`string`?d.test(e.instead)&&!n.byName.has(e.instead)&&!n.knownNames.has(e.instead)&&r.push([`${t}.instead`,`"${e.instead}" is not a component of the kit`]):r.push([`${t}.instead`,`must be text`]))}function M(e,t,n,r){if(!V(e)){r.push([t,`is not a practice`]);return}if(U(e.note)||r.push([`${t}.note`,`is empty`]),!Array.isArray(e.example)||e.example.length===0){r.push([`${t}.example`,`needs at least one placed element`]);return}e.example.forEach((e,i)=>{let a=`${t}.example[${i}]`;W(e)?E(e,a,n,r):r.push([a,`is not a placed element`])})}function N(e,t,n){if(typeof e==`string`)p.test(e)&&n.push([t,`contains an em or en dash; use a comma, colon or period`]);else if(Array.isArray(e))e.forEach((e,r)=>N(e,`${t}[${r}]`,n));else if(V(e))for(let[r,i]of Object.entries(e))N(i,t?`${t}.${r}`:r,n)}function P(e,t){let n={name:e,type:t.type};return(t.type===`enum`||t.type===`enumOrNumber`)&&(n.enum=I(t.values)),t.fields!==void 0&&(n.fields=F(t.fields)),t.itemFields!==void 0&&(n.itemFields=F(t.itemFields)),n.required=t.required===!0,t.nullable===!0&&(n.nullable=!0),t.description!==void 0&&(n.description=t.description),t.default!==void 0&&(n.default=t.default),n}function F(e){return Object.keys(e).sort(B).map(t=>P(t,e[t]))}function I(e){return[...e].sort((e,t)=>{let n=typeof e==`number`,r=typeof t==`number`;return n&&r?e-t:n===r?B(e,t):n?-1:1})}function L(e){return e.type===`array`&&Object.keys(e.itemFields??{}).some(e=>e===`href`||e===`to`)}function R(e,t,n,r){r.push([n,`${z(e)} is not a ${t}`])}function z(e){return JSON.stringify(e)}function B(e,t){return e<t?-1:+(e>t)}function V(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function H(e){return typeof e==`number`&&Number.isFinite(e)}function U(e){return typeof e==`string`&&e.trim()!==``}function W(e){return V(e)&&typeof e.component==`string`}export{c as HTML_TAGS,_ as checkMetas,y as componentModuleOf,v as manifestComponent,g as readMetas};
|
package/dist/spec.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export interface CanvasSpecBox {
|
|
|
12
12
|
export interface CanvasSpecTokenValues {
|
|
13
13
|
light: string;
|
|
14
14
|
dark: string;
|
|
15
|
+
// The token reference the style key names, with its sigil: "$leading.heading", or "-$space.2" for a negative.
|
|
16
|
+
path?: string;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
export interface CanvasSpecCode {
|
package/dist/tokens.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readJson as e,readText as t}from"./files.js";import{join as n}from"node:path";var r=e=>typeof e==`object`&&!!e&&!Array.isArray(e),i=e=>typeof e==`number`&&Number.isFinite(e),a=e=>typeof e==`string`,o=[`x`,`y`,`blur`,`spread`,`color`,`elevation`],s=e=>e===null||r(e)&&Object.keys(e).every(e=>o.includes(e))&&i(e.x)&&i(e.y)&&i(e.blur)&&i(e.spread)&&a(e.color)&&(e.elevation===void 0||i(e.elevation));function c(e){return[...new Set(e)].sort((e,t)=>e<t?-1:+(e>t))}function l(e,t=e=>e){return Object.fromEntries(c(Object.keys(e)).map(n=>[n,t(e[n])]))}function u(e,t,n){if(!r(t[n]))throw Error(`${e} has no ${n} object.`);return t[n]}function d(e,t,n,r){for(let[i,a]of Object.entries(n))if(!r(a))throw Error(`${e}: ${t}.${i} is not a value the kit can draw.`)}function f(t,n,o){let f=e(t);if(f.format!==`webority-theme-tokens/2`)throw Error(`${t} has format ${JSON.stringify(f.format)}; this reader reads webority-theme-tokens/2.`);if(a(o)&&f.source?.platform!==o.toLowerCase())throw Error(`${t} is the ${f.source?.platform} token file; a ${o} kit needs the ${o.toLowerCase()} one.`);let p=r(f.colors)&&r(f.colors.light)?f.colors.light:null,m=r(f.colors)&&r(f.colors.dark)?f.colors.dark:null;if(!p||!m)throw Error(`${t} has no colors.${p?`dark`:`light`} object.`);let h=Object.keys(p).filter(e=>!Object.hasOwn(m,e)),g=Object.keys(m).filter(e=>!Object.hasOwn(p,e));if(h.length>0||g.length>0)throw Error(`${t}: the light and dark colours differ. Only in light: ${h.length>0?c(h).join(`, `):`none`}. Only in dark: ${g.length>0?c(g).join(`, `):`none`}.`);let _=c(Object.keys(p));d(t,`color`,p,a),d(t,`color`,m,a);let v=u(t,f,`space`);d(t,`space`,v,i);let y=u(t,f,`radius`);d(t,`radius`,y,i);let b=u(t,f,`shadow`);d(t,`shadow`,b,s);let x=u(t,f,`fonts`);d(t,`font`,x,e=>r(e)&&a(e.family)&&a(e.fallback));let S=u(t,f,`text`);d(t,`text`,S,e=>r(e)&&i(e.size)
|
|
1
|
+
import{readJson as e,readText as t}from"./files.js";import{join as n}from"node:path";var r=e=>typeof e==`object`&&!!e&&!Array.isArray(e),i=e=>typeof e==`number`&&Number.isFinite(e),a=e=>typeof e==`string`,o=[`x`,`y`,`blur`,`spread`,`color`,`elevation`],s=e=>e===null||r(e)&&Object.keys(e).every(e=>o.includes(e))&&i(e.x)&&i(e.y)&&i(e.blur)&&i(e.spread)&&a(e.color)&&(e.elevation===void 0||i(e.elevation));function c(e){return[...new Set(e)].sort((e,t)=>e<t?-1:+(e>t))}function l(e,t=e=>e){return Object.fromEntries(c(Object.keys(e)).map(n=>[n,t(e[n])]))}function u(e,t,n){if(!r(t[n]))throw Error(`${e} has no ${n} object.`);return t[n]}function d(e,t,n,r){for(let[i,a]of Object.entries(n))if(!r(a))throw Error(`${e}: ${t}.${i} is not a value the kit can draw.`)}function f(t,n,o){let f=e(t);if(f.format!==`webority-theme-tokens/2`)throw Error(`${t} has format ${JSON.stringify(f.format)}; this reader reads webority-theme-tokens/2.`);if(a(o)&&f.source?.platform!==o.toLowerCase())throw Error(`${t} is the ${f.source?.platform} token file; a ${o} kit needs the ${o.toLowerCase()} one.`);let p=r(f.colors)&&r(f.colors.light)?f.colors.light:null,m=r(f.colors)&&r(f.colors.dark)?f.colors.dark:null;if(!p||!m)throw Error(`${t} has no colors.${p?`dark`:`light`} object.`);let h=Object.keys(p).filter(e=>!Object.hasOwn(m,e)),g=Object.keys(m).filter(e=>!Object.hasOwn(p,e));if(h.length>0||g.length>0)throw Error(`${t}: the light and dark colours differ. Only in light: ${h.length>0?c(h).join(`, `):`none`}. Only in dark: ${g.length>0?c(g).join(`, `):`none`}.`);let _=c(Object.keys(p));d(t,`color`,p,a),d(t,`color`,m,a);let v=u(t,f,`space`);d(t,`space`,v,i);let y=u(t,f,`radius`);d(t,`radius`,y,i);let b=u(t,f,`shadow`);d(t,`shadow`,b,s);let x=u(t,f,`fonts`);d(t,`font`,x,e=>r(e)&&a(e.family)&&a(e.fallback));let S=u(t,f,`text`);d(t,`text`,S,e=>r(e)&&i(e.size));let C=u(t,u(t,f,`typography`),`leading`);d(t,`leading`,C,e=>i(e)&&e>0&&e<=4);let w=f.colorMeanings===void 0?{}:f.colorMeanings;if(!r(w))throw Error(`${t} has a colorMeanings entry that is not a description: colorMeanings`);for(let[e,n]of Object.entries(w))if(!a(n)||n===``)throw Error(`${t} has a colorMeanings entry that is not a description: ${e}`);let T=e(n);if(T.format!==`webority-meanings/1`)throw Error(`${n} has format ${JSON.stringify(T.format)}; this reader reads webority-meanings/1.`);let E={};for(let e of _){let t=w[e],r=a(t)&&t!==``?t:T.color?.[e]?.description;if(!a(r)||r===``)throw Error(`${n} has no meaning for the colour ${e}; move the @webority/tokens pin to a version that publishes one.`);E[e]=r}return{tokens:{color:_,space:c(Object.keys(v)),radius:c(Object.keys(y)),shadow:c(Object.keys(b)),font:c(Object.keys(x)),text:c(Object.keys(S)),leading:c(Object.keys(C)),colorMeanings:E},tokenValues:{color:Object.fromEntries(_.map(e=>[e,{light:p[e],dark:m[e]}])),space:l(v),radius:l(y),shadow:l(b),font:l(x,({family:e,fallback:t})=>({family:e,fallback:t})),text:l(S,({size:e})=>({size:e,weight:null})),leading:l(C)}}}function p(e){let r=n(e,`components`,`iconCatalogNames.g.js`),i=t(r),a=/`([^`]+)`\.split\(`\.`\)/.exec(i);if(!a)throw Error(`No icon name list in ${r}`);return c(a[1].split(`.`).filter(Boolean))}export{f as tokensFromV2,p as webIcons};
|
package/package.json
CHANGED