@webority/canvas-kit 0.88.1 → 0.90.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 +87 -29
- package/dist/build.js +3 -3
- package/dist/cli.js +7 -5
- package/dist/drawn.js +4 -0
- package/dist/guidance.js +1 -1
- package/dist/index.js +1 -1
- package/dist/manifest.d.ts +14 -1
- package/dist/manifest.js +1 -1
- package/dist/meta.d.ts +6 -0
- package/dist/metaCheck.d.ts +19 -5
- package/dist/metaCheck.js +4 -1
- package/dist/metas.js +2 -1
- package/dist/phone.js +1 -1
- package/dist/release.js +1 -1
- package/dist/tokens.js +1 -1
- package/package.json +1 -1
- package/dist/declarations.js +0 -1
package/README.md
CHANGED
|
@@ -1,27 +1,24 @@
|
|
|
1
1
|
# @webority/canvas-kit
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Webority fleet kits (`webority-web`, `webority-phone`) are built this way by Canvas Web's `publish-fleet-kit.mjs`. A
|
|
8
|
-
product kit has an `entry` and adds its own components.
|
|
3
|
+
A kit is a Webority library plus, for a product, the product's own presentational components. Every component is
|
|
4
|
+
described by a `.meta.js` file (see Component metadata). A kit built inside its own library is a self-build: ui-react
|
|
5
|
+
builds the webority-web kit and mobile-ui the webority-phone kit this way. A product kit adds its own components to the
|
|
6
|
+
library's published kit release. The build writes an immutable release folder that Canvas stores and draws screens with.
|
|
9
7
|
|
|
10
8
|
## Build a release
|
|
11
9
|
|
|
12
10
|
```sh
|
|
13
|
-
canvas-kit build --config canvas-kit.json --out canvas-kit
|
|
14
|
-
canvas-kit build --config
|
|
11
|
+
canvas-kit build --config canvas-kit.json --out dist/canvas-kit
|
|
12
|
+
canvas-kit build --config canvas-kit.json --out canvas-kit-release --style-keys <file>
|
|
15
13
|
```
|
|
16
14
|
|
|
17
|
-
`--out` must not exist. A release folder is never overwritten
|
|
18
|
-
`<kitKey>/<version>`, and the build refuses any other folder.
|
|
15
|
+
`--out` must not exist. A release folder is never overwritten, so build into a new folder. Any folder name works.
|
|
19
16
|
|
|
20
17
|
The flags are:
|
|
21
18
|
|
|
22
19
|
| Flag | Meaning |
|
|
23
20
|
| --- | --- |
|
|
24
|
-
| `--style-keys <file>` | The style key table the renderer draws from.
|
|
21
|
+
| `--style-keys <file>` | Optional. The style key table the renderer draws from. The manifest carries `styleKeys` only when this flag is given. |
|
|
25
22
|
| `--phone-renderer-support <file>` | The phone renderer's support file: each style key's `phoneSupported` flag and the phone kit's action lists. A Phone kit needs it. |
|
|
26
23
|
|
|
27
24
|
Flag paths are relative to the working directory.
|
|
@@ -30,48 +27,107 @@ The config is a JSON object with these keys. Paths are relative to the config fi
|
|
|
30
27
|
|
|
31
28
|
| Key | Meaning |
|
|
32
29
|
| --- | --- |
|
|
33
|
-
| `kit` | The kit key, lowercase letters, digits and hyphens, 2 to 40 characters, for example `
|
|
34
|
-
| `platform` | `Web` or `Phone`.
|
|
35
|
-
| `entry` | Optional. The kit's entry module, which exports the product's components. Leave it out for a library-only kit. |
|
|
30
|
+
| `kit` | The kit key, lowercase letters, digits and hyphens, 2 to 40 characters, for example `sample-kit`. |
|
|
31
|
+
| `platform` | `Web` or `Phone`. |
|
|
36
32
|
| `libraryPackage` | The Webority library the kit is built on, for example `@webority/ui-react`. |
|
|
33
|
+
| `components` | A glob of `.meta.js` files, for example `src/components/*.meta.js`. |
|
|
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`. |
|
|
37
35
|
| `rolesFile` | Optional. A JSON object from component name to `title` or `navigation`. |
|
|
38
36
|
| `rendererProtocolVersion` | The renderer protocol number the kit is built for. |
|
|
39
37
|
|
|
40
|
-
A
|
|
38
|
+
A kit lists its components with `components`. A config that names `entry` fails the read with that message, and so does
|
|
39
|
+
a config that names any other key.
|
|
41
40
|
|
|
42
41
|
## What a release holds
|
|
43
42
|
|
|
44
|
-
The release folder
|
|
43
|
+
The release folder holds these four files:
|
|
45
44
|
|
|
46
45
|
- `kit.js`: one ES module whose default export comes from `defineKit`, with the components, the markers, the token
|
|
47
46
|
values and the manifest. React and react-dom stay bare imports, so the renderer's own React draws the kit. A Phone kit
|
|
48
47
|
also leaves react-native and react-native-svg bare; the phone renderer's import map resolves them.
|
|
49
48
|
- `kit.css`: the styles the bundle imports, or an empty file.
|
|
50
49
|
- `manifest.json`: the components with their props, sources and roles, the library's tokens and icons, and the style
|
|
51
|
-
keys each with its `phoneSupported` flag.
|
|
50
|
+
keys each with its `phoneSupported` flag when a style key table is given. Each component carries its `usage` and each
|
|
51
|
+
prop its `description` and `default`.
|
|
52
52
|
- `release.json`: the kit key as `name`, the `version`, the platform, the kit module version, the protocol version, the
|
|
53
53
|
library name and version, and the SHA-256 and byte count of each file above.
|
|
54
54
|
|
|
55
|
-
A
|
|
56
|
-
|
|
55
|
+
A release is stamped with the kit root's `package.json` version: the library's own version for a self-build, the
|
|
56
|
+
product's for a product kit.
|
|
57
|
+
|
|
58
|
+
## Component metadata
|
|
59
|
+
|
|
60
|
+
A meta module imports only `defineMeta` from `@webority/canvas-kit/meta` and exports `meta`. The fields of `meta`:
|
|
61
|
+
|
|
62
|
+
| Field | Meaning |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| `name` | The catalogue name, such as `AppButton`. Letters and digits, starting with a capital letter. |
|
|
65
|
+
| `marker` | The `data-wui` value the component renders, or `null`. |
|
|
66
|
+
| `platforms` | `web`, `phone` or both. |
|
|
67
|
+
| `acceptsChildren` | `true` or `false`. |
|
|
68
|
+
| `props` | Each prop has a `type`, one of `string`, `number`, `stringOrNumber`, `boolean`, `enum`, `enumOrNumber`, `url`, `icon`, `node`, `array`, `object` or `any`, and a `description`. An enum or enumOrNumber lists its `values`; numbers are allowed in an enum, and an enumOrNumber lists its named values only and also takes any number. Optional `default` (never on a required prop), `required`, `fields` on an object and `itemFields` on an array of objects. |
|
|
69
|
+
| `omit` | Optional. Design props deliberately not described. |
|
|
70
|
+
| `examples` | Each has an `id`, a `title`, `props`, optional `children` and optional `wrap`. The id is the name for the base example and `<name>.<case>` for the others. |
|
|
71
|
+
| `usage` | `when` lines, `whenNot` entries with `text` and optional `instead`, `do` and `dont` pairs of `note` and `example` matched by index, and `a11y` lines. |
|
|
72
|
+
|
|
73
|
+
A node in an example, a `wrap` or a practice places kit components and the HTML tags listed in `HTML_TAGS`. Event
|
|
74
|
+
handlers, `ref`, `key`, `children`, and props typed as a component are never listed.
|
|
75
|
+
|
|
76
|
+
### The type check
|
|
77
|
+
|
|
78
|
+
The build generates a `.ts` file under `node_modules/.canvas-kit-check-<pid>`, runs the TypeScript compiler on it, and
|
|
79
|
+
fails with one line per mismatch: `<Name>: props the component takes that the meta does not list: ...`, props the meta
|
|
80
|
+
lists that the component does not take, props whose type, required flag or nested fields differ, and `acceptsChildren`
|
|
81
|
+
against the component. The folder is removed afterwards. A product kit is checked the same way as the library. The check
|
|
82
|
+
covers Web metas; a phone meta is proven by mobile-ui's own type check.
|
|
83
|
+
|
|
84
|
+
### The checks on a meta
|
|
85
|
+
|
|
86
|
+
`readMetas` and `checkMetas` refuse a meta that:
|
|
87
|
+
|
|
88
|
+
- has a duplicate or malformed `name`, or an `omit` that is not a list of prop names;
|
|
89
|
+
- has empty `platforms`, a `marker` that is neither a string nor `null`, or an `acceptsChildren` that is not `true` or `false`;
|
|
90
|
+
- has a prop type not in the list above, `values` off an enum or enumOrNumber, a repeated value, or a value of the wrong kind;
|
|
91
|
+
- has `fields` off an object, `itemFields` off an array, or an empty `description`;
|
|
92
|
+
- has a `default` that does not fit its type, or a `default` on a required prop;
|
|
93
|
+
- has an example id that is not the name or `<name>.<case>`, or an id used twice across metas;
|
|
94
|
+
- has an example prop the meta does not list, a value outside the prop's type, or no value for a required prop;
|
|
95
|
+
- has `children` where `acceptsChildren` is `false`;
|
|
96
|
+
- places a node whose component is unknown;
|
|
97
|
+
- has an empty `when`, `do` and `dont` lists of different lengths, or an `instead` that names an unknown component;
|
|
98
|
+
- has an `icon` outside the kit's icons;
|
|
99
|
+
- has an em or en dash in any string.
|
|
100
|
+
|
|
101
|
+
## Guidance file
|
|
102
|
+
|
|
103
|
+
`canvas-kit guidance --config canvas-kit.json --out dist/guidance.json` writes `webority-guidance/1`:
|
|
104
|
+
`{ format, package: { name, version }, components: [{ name, usage }] }`, sorted by name, from the metas the config's
|
|
105
|
+
`components` glob lists. It reads only `components` from the config, so a package that ships guidance and no kit (for
|
|
106
|
+
example one whose components need a live service client) writes a config with `kit`, `platform`, `libraryPackage` and
|
|
107
|
+
`components` and runs only this command. Humans and agents read it instead of the showcase pages.
|
|
57
108
|
|
|
58
109
|
## Product components
|
|
59
110
|
|
|
60
|
-
A kit component is
|
|
61
|
-
|
|
62
|
-
|
|
111
|
+
A product kit component is a component module with a sibling `<Name>.meta.js`. The module is the first existing of
|
|
112
|
+
`.jsx`, `.tsx`, `.js` or `.ts` beside the meta, and exports the component under the meta's name. The kit reads the
|
|
113
|
+
library's components from the library's published kit release, so the library's `package.json` must export
|
|
114
|
+
`./canvas-kit/*`. The product meta's `marker` is the `data-wui` value its component writes, or `null`.
|
|
63
115
|
|
|
64
116
|
## Refusals
|
|
65
117
|
|
|
66
118
|
The build stops with a named fix when:
|
|
67
119
|
|
|
68
120
|
- the kit imports `react-redux`, `react-router-dom`, `axios`, or a file under `src/services`;
|
|
69
|
-
-
|
|
70
|
-
- the library installed differs from the exact version the product pins;
|
|
121
|
+
- React is not major 19, the Canvas renderer's React major;
|
|
122
|
+
- the library installed differs from the exact version the product pins (product kits only);
|
|
71
123
|
- a role names a component the kit does not have, or a role is not `title` or `navigation`;
|
|
72
|
-
- a product component takes a name the library already
|
|
73
|
-
- a
|
|
74
|
-
-
|
|
124
|
+
- a product component takes a name the library already has;
|
|
125
|
+
- a meta lists a platform other than the kit's;
|
|
126
|
+
- the config names `entry`, or lacks `components` or `tokens`;
|
|
127
|
+
- 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 meta does not match its component's typed props, or fails one of the checks on a meta;
|
|
130
|
+
- a Phone kit is built without `--phone-renderer-support`.
|
|
75
131
|
|
|
76
132
|
## Reading a release back
|
|
77
133
|
|
|
@@ -80,7 +136,8 @@ Any file changed after the build fails the check.
|
|
|
80
136
|
|
|
81
137
|
## Exports
|
|
82
138
|
|
|
83
|
-
-
|
|
139
|
+
- `.` (Node only): `kitModuleVersion`, `KIT_MODULE_EXTERNALS`, `defineKit`, `readManifest` (async), `readReleaseManifest(dir)`, `buildKitRelease`, `readConfig`, `readMetas`, `HTML_TAGS`, `checkMetaTypes`, `guidanceOf`, `writeGuidance`.
|
|
140
|
+
- `./meta`: `defineMeta` and the meta types (`ComponentMeta`, `MetaProp`, `MetaNode`, `MetaExample`, `MetaPractice`, `ComponentUsage`).
|
|
84
141
|
- `./kitModule`: the kit module contract alone.
|
|
85
142
|
- `./browser`: for the renderers, with no Node built-ins. `loadKit({ kitKey, version, baseUrl })` loads the release at `<baseUrl>/<kitKey>/<version>` and returns its kit module, for a fleet kit and a product kit alike.
|
|
86
143
|
|
|
@@ -88,4 +145,5 @@ Any file changed after the build fails the check.
|
|
|
88
145
|
|
|
89
146
|
The package builds into `dist` before publish: `pnpm run build`. Its tests run with `pnpm test`, which reads the
|
|
90
147
|
source under `src`. The tests build throwaway product folders with a stub library, so they need only the
|
|
91
|
-
package's own dependencies installed.
|
|
148
|
+
package's own dependencies installed. The stub folders hold a stub library with its metas, a stub `@webority/tokens`
|
|
149
|
+
package and two `webority-theme-tokens/2` fixtures.
|
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{
|
|
2
|
-
`)}function
|
|
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`,`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({libraryFile:e,chromeFile:t,manifest:r,libraryNames:i,chromeNames:a,productModules:o}){let s=[`import { defineKit } from ${JSON.stringify(n(b))};`],c=[...o];c.forEach(([,{module:e,exportName:t}],r)=>{s.push(`import { ${t} as product${r} } from ${JSON.stringify(n(e))};`)}),i.length>0&&s.push(`import { ${i.join(`, `)} } from ${JSON.stringify(n(e))};`),a.length>0&&s.push(`import { ${a.join(`, `)} } from ${JSON.stringify(n(t))};`);let l=[...i,...a,...c.map(([e],t)=>`${e}: product${t}`)],u=Object.fromEntries(r.components.filter(({marker:e})=>e!==null).map(({name:e,marker:t})=>[e,t]));return s.push(`export default defineKit({ components: { ${l.join(`, `)} }, markers: ${JSON.stringify(u)}, tokenValues: ${JSON.stringify(r.tokenValues)}, manifest: ${JSON.stringify(r)} });`,``),s.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,libraryFile:i,chromeFile:a,libraryNames:o,chromeNames:s,productModules:c,manifest:l}){let u=r[n],d=await p({configFile:!1,root:e,logLevel:`warn`,publicDir:!1,envDir:!1,define:x,plugins:[D(E({libraryFile:i,chromeFile:a,manifest:l,libraryNames:o,chromeNames:s,productModules:c})),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=>u.some(t=>e===t||e.startsWith(`${t}/`)),output:{inlineDynamicImports:!0}}}}),f=(Array.isArray(d)?d:[d]).flatMap(e=>e.output),m=f.find(e=>e.type===`chunk`&&e.isEntry);if(!m)throw Error(`The bundle of ${t} has no entry module.`);let h=S.exec(m.code);if(h)throw Error(`The bundle of ${t} still reads ${h[1]}, which the renderer does not define.`);let g=f.filter(e=>e.type===`chunk`&&!e.isEntry);if(g.length>0)throw Error(`The bundle of ${t} split ${g.map(e=>e.fileName).join(`, `)} out of kit.js; a kit must be one file.`);let _=f.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:m.code,styles:_}}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})=>e),{script:E,styles:D}=await k({root:m,kit:p.kit,platform:p.platform,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,8 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{buildKitRelease as e}from"./build.js";import{
|
|
2
|
+
import{buildKitRelease as e}from"./build.js";import{writeGuidance as t}from"./guidance.js";import{resolve as n}from"node:path";var r=`Usage: canvas-kit build --config <file> --out <dir> [--style-keys <file>] [--phone-renderer-support <file>]
|
|
3
|
+
canvas-kit guidance --config <file> --out <file>
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
build: builds a kit release into <dir>: kit.js, kit.css, manifest.json and release.json.
|
|
5
6
|
<dir> must not exist; a release folder is never overwritten.
|
|
6
|
-
--style-keys: the style key table the renderer draws from.
|
|
7
|
-
--phone-renderer-support: the phone renderer's support file. A Phone kit needs it.
|
|
8
|
-
|
|
7
|
+
--style-keys: the style key table the renderer draws from. Optional.
|
|
8
|
+
--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
|
+
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.`,i=new Set([`--config`,`--out`,`--style-keys`,`--phone-renderer-support`]);function a(e){if(e.length===0||e.includes(`--help`)||e.includes(`-h`))return{help:!0};let[t,...n]=e,r={};for(let e=0;e<n.length;e+=1){let t=n[e];if(!i.has(t))throw Error(`Unknown argument ${t}.`);let a=n[e+1];if(a===void 0||a.startsWith(`--`))throw Error(`${t} needs a value.`);r[t.slice(2)]=a,e+=1}return{command:t,options:r}}async function o(i){let o=a(i);if(o.help){process.stdout.write(`${r}\n`);return}if(o.command!==`build`&&o.command!==`guidance`)throw Error(`Unknown command ${o.command}. The commands are build and guidance.`);if(o.command===`guidance`){if(!o.options.config||!o.options.out)throw Error(`guidance needs --config and --out.`);if(o.options[`style-keys`]!==void 0||o.options[`phone-renderer-support`]!==void 0)throw Error(`guidance takes only --config and --out.`);let e=await t({configFile:n(o.options.config),outFile:n(o.options.out)});process.stdout.write(`Guidance for ${e.components.length} components written to ${n(o.options.out)}.\n`);return}if(!o.options.config||!o.options.out)throw Error(`build needs --config and --out.`);let s=o.options[`style-keys`],c=o.options[`phone-renderer-support`],l=await e({configFile:n(o.options.config),outDir:n(o.options.out),styleKeysFile:s===void 0?void 0:n(s),phoneRendererSupportFile:c===void 0?void 0:n(c)});for(let e of l.warnings)process.stderr.write(`warning: ${e}\n`);process.stdout.write(`Built ${l.release.name} (${l.release.platform}): ${l.manifest.components.length} components. Release written to ${l.outDir}.\n`)}o(process.argv.slice(2)).catch(e=>{process.stderr.write(`canvas-kit: ${e.message}\n`),process.exitCode=1});export{};
|
package/dist/drawn.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
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
|
+
`)}\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,metaNames:n,notDrawn:r}){let i=new Set(t),a=new Set(n),o=Object.keys(r),s=[],c=t.filter(e=>!a.has(e)&&!(e in r));c.length>0&&s.push(`${e} exports ${c.join(`, `)} with no meta. Write a meta for each, or list it in ${u} with the reason the kit does not draw it.`);let l=o.filter(e=>a.has(e));l.length>0&&s.push(`${u} lists ${l.join(`, `)}, which have a meta. A component is drawn or not drawn; remove one.`);let d=o.filter(e=>!i.has(e));d.length>0&&s.push(`${u} lists ${d.join(`, `)}, which ${e} does not export as components. Remove them.`);let f=n.filter(e=>!i.has(e));if(f.length>0&&s.push(`${f.join(`, `)} have a meta, but ${e} does not export them as components.`),s.length>0)throw Error(s.join(`
|
|
4
|
+
`))}export{u as NOT_DRAWN_FILE,p as checkDrawn,d as componentExports,f as readNotDrawn};
|
package/dist/guidance.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e,t){
|
|
1
|
+
import{findPackageDir as e,readJson as t}from"./files.js";import{readMetas as n}from"./metas.js";import{mkdirSync as r,writeFileSync as i}from"node:fs";import{dirname as a,join as o,resolve as s}from"node:path";function c(e){return typeof e==`string`&&e.length>0}function l(e,t){return e.name<t.name?-1:+(e.name>t.name)}function u(e,t){return{format:`webority-guidance/1`,package:{name:t.name,version:t.version},components:e.map(({meta:e})=>({name:e.name,usage:e.usage})).sort(l)}}function d(n,r){let i=[];for(let a of Object.keys({...r.dependencies,...r.peerDependencies})){let r=e(n,a);if(!r)continue;let s=t(o(r,`package.json`)).exports?.[`./guidance.json`];typeof s==`string`&&i.push(...t(o(r,s)).components.map(e=>e.name))}return i}async function f({configFile:e,outFile:l}){let f=t(s(e));if(typeof f!=`object`||!f||!c(f.components))throw Error(`${e} needs the key components, a glob of .meta.js files.`);let p=a(s(e)),m=o(p,`package.json`),h=t(m);if(typeof h!=`object`||!h||!c(h.name)||!c(h.version))throw Error(`${m} needs a name and a version; the guidance file is stamped with them.`);let g=u(await n({root:p,components:f.components,knownNames:d(p,h)}),{name:h.name,version:h.version});return r(a(s(l)),{recursive:!0}),i(s(l),`${JSON.stringify(g,null,2)}\n`),g}export{u as guidanceOf,f as writeGuidance};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{KIT_MODULE_EXTERNALS as e,defineKit as t,kitModuleVersion as n}from"./kitModule.js";import{
|
|
1
|
+
import{KIT_MODULE_EXTERNALS as e,defineKit as t,kitModuleVersion as n}from"./kitModule.js";import{checkMetaTypes as r}from"./metaCheck.js";import{HTML_TAGS as i,readMetas as a}from"./metas.js";import{readManifest as o}from"./manifest.js";import{readReleaseManifest as s}from"./release.js";import{buildKitRelease as c,readConfig as l}from"./build.js";import{guidanceOf as u,writeGuidance as d}from"./guidance.js";export{i as HTML_TAGS,e as KIT_MODULE_EXTERNALS,c as buildKitRelease,r as checkMetaTypes,t as defineKit,u as guidanceOf,n as kitModuleVersion,l as readConfig,o as readManifest,a as readMetas,s as readReleaseManifest,d as writeGuidance};
|
package/dist/manifest.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export interface CanvasManifestProp {
|
|
|
35
35
|
// The fields of each item of an array prop. A list whose items carry href or to takes the action on the Web.
|
|
36
36
|
itemFields?: CanvasManifestProp[];
|
|
37
37
|
required: boolean;
|
|
38
|
+
// The prop takes null as a value. Written only when it does.
|
|
39
|
+
nullable?: true;
|
|
38
40
|
description?: string;
|
|
39
41
|
// The value the component applies when the prop is left out, as JSON.
|
|
40
42
|
default?: unknown;
|
|
@@ -74,11 +76,22 @@ export interface CanvasManifestTokenValues {
|
|
|
74
76
|
color: Record<string, CanvasManifestColorValue>;
|
|
75
77
|
space: Record<string, number>;
|
|
76
78
|
radius: Record<string, number>;
|
|
77
|
-
shadow: Record<string,
|
|
79
|
+
shadow: Record<string, CanvasShadow | null>;
|
|
78
80
|
font: Record<string, CanvasManifestFontValue>;
|
|
79
81
|
text: Record<string, CanvasManifestTextValue>;
|
|
80
82
|
}
|
|
81
83
|
|
|
84
|
+
// Lengths in px at scale 1. `color` is the resolved colour with its opacity in the alpha.
|
|
85
|
+
export interface CanvasShadow {
|
|
86
|
+
x: number;
|
|
87
|
+
y: number;
|
|
88
|
+
blur: number;
|
|
89
|
+
spread: number;
|
|
90
|
+
color: string;
|
|
91
|
+
// Phone only: the Android elevation, when the token sets one.
|
|
92
|
+
elevation?: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
82
95
|
export interface CanvasManifestColorValue {
|
|
83
96
|
light: string;
|
|
84
97
|
dark: string;
|
package/dist/manifest.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{findPackageDir as e,readJson as t,
|
|
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}),metaNames:q.map(({meta:e})=>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.name),exportName:e.name})}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
|
@@ -23,6 +23,8 @@ export interface MetaProp {
|
|
|
23
23
|
/** The value the component applies when the prop is left out, as JSON. Never on a required prop. */
|
|
24
24
|
default?: unknown;
|
|
25
25
|
required?: boolean;
|
|
26
|
+
/** The component takes null for it: a value that is always sent and may be empty. Examples may then set null. */
|
|
27
|
+
nullable?: boolean;
|
|
26
28
|
description: string;
|
|
27
29
|
/** The fields of an object prop. Only on an object. */
|
|
28
30
|
fields?: Readonly<Record<string, MetaProp>>;
|
|
@@ -36,6 +38,8 @@ export interface MetaNode {
|
|
|
36
38
|
props?: Readonly<Record<string, unknown>>;
|
|
37
39
|
/** Text, or a list of placed elements and text items. */
|
|
38
40
|
children?: string | readonly (MetaNode | string)[];
|
|
41
|
+
/** Function props a renderer attaches as a no-op so the demo draws complete (a remove button, a retry action). Each must be a function prop of the component. */
|
|
42
|
+
handlers?: readonly string[];
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
export interface MetaExample {
|
|
@@ -46,6 +50,8 @@ export interface MetaExample {
|
|
|
46
50
|
children?: string | readonly (MetaNode | string)[];
|
|
47
51
|
/** An element the example is placed inside, for a component that only renders within a parent. */
|
|
48
52
|
wrap?: MetaNode;
|
|
53
|
+
/** Function props a renderer attaches as a no-op so the demo draws complete (a remove button, a retry action). Each must be a function prop of the component. */
|
|
54
|
+
handlers?: readonly string[];
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
/** One side of a do and dont pair; do[i] is shown beside dont[i]. Example props may be scalars, icons, nodes, or arrays and objects checked against the prop's itemFields or fields. */
|
package/dist/metaCheck.d.ts
CHANGED
|
@@ -25,11 +25,16 @@ type FieldKeys<P> = {
|
|
|
25
25
|
/** Every prop a design sets: the field keys, less React's children, ref and key (a nested data field may be named key). */
|
|
26
26
|
export type DesignKeys<P> = Exclude<FieldKeys<P>, "children" | "ref" | "key">;
|
|
27
27
|
|
|
28
|
+
/** Every event handler prop of the component: the names a meta's handlers list may use. */
|
|
29
|
+
export type HandlerKeys<P> = { [K in keyof P]-?: NonNullable<P[K]> extends Handler ? K : never }[keyof P] & string;
|
|
30
|
+
|
|
28
31
|
type RequiredKeys<P> = { [K in keyof P]-?: Partial<Pick<P, K>> extends Pick<P, K> ? never : K }[keyof P];
|
|
29
32
|
type ItemOf<T> = Defined<T> extends readonly (infer I)[] ? I : Defined<T> extends ReadonlySet<infer I> ? I : never;
|
|
30
33
|
|
|
34
|
+
// "any" is a meta's explicit opt-out for a value no meta type can state (a union of a File, an object and an array):
|
|
35
|
+
// Canvas passes it through unchanged, so only its presence and required flag are checked.
|
|
31
36
|
type ValueOk<T, M extends MetaProp, N> = M["type"] extends "any"
|
|
32
|
-
?
|
|
37
|
+
? true
|
|
33
38
|
: IsAny<T> extends true
|
|
34
39
|
? false
|
|
35
40
|
: M["type"] extends "enum"
|
|
@@ -72,6 +77,11 @@ type RequiredOk<P, K extends keyof P, M extends MetaProp> = Same<
|
|
|
72
77
|
M["required"] extends true ? true : false
|
|
73
78
|
>;
|
|
74
79
|
|
|
80
|
+
// ReactNode carries null itself, so a prop that takes any node (a node, or an icon given as a name or a node) is
|
|
81
|
+
// empty-able by its type, not nullable in its own right. "any" opts out: its value is passed through unchecked.
|
|
82
|
+
type OwnNull<T, N> = null extends T ? (Defined<N> extends Defined<T> ? false : true) : false;
|
|
83
|
+
type NullableOk<T, M extends MetaProp, N> = M["type"] extends "any" ? true : Same<OwnNull<T, N>, M["nullable"] extends true ? true : false>;
|
|
84
|
+
|
|
75
85
|
type NestedOk<T, M extends MetaProp, N> = M["type"] extends "object"
|
|
76
86
|
? M["fields"] extends Shape
|
|
77
87
|
? ShapeOk<Defined<T>, M["fields"], N>
|
|
@@ -85,19 +95,23 @@ type NestedOk<T, M extends MetaProp, N> = M["type"] extends "object"
|
|
|
85
95
|
type ShapeOk<T, F extends Shape, N> =
|
|
86
96
|
Same<FieldKeys<T>, keyof F & string> extends true ? ([PropsMismatch<T, F, N>] extends [never] ? true : false) : false;
|
|
87
97
|
|
|
88
|
-
/** The names of meta props whose type, required flag or nested fields differ from the component's. */
|
|
98
|
+
/** The names of meta props whose type, required or nullable flag, or nested fields differ from the component's. */
|
|
89
99
|
export type PropsMismatch<P, F extends Shape, N> = {
|
|
90
100
|
[K in keyof F & keyof P & string]: ValueOk<P[K], F[K], N> extends true
|
|
91
101
|
? RequiredOk<P, K, F[K]> extends true
|
|
92
|
-
?
|
|
93
|
-
?
|
|
102
|
+
? NullableOk<P[K], F[K], N> extends true
|
|
103
|
+
? NestedOk<P[K], F[K], N> extends true
|
|
104
|
+
? never
|
|
105
|
+
: K
|
|
94
106
|
: K
|
|
95
107
|
: K
|
|
96
108
|
: K;
|
|
97
109
|
}[keyof F & keyof P & string];
|
|
98
110
|
|
|
111
|
+
// A meta with no omit list would make NonNullable<M["omit"]>[number] collapse ExtraProps to never.
|
|
112
|
+
type OmitOf<M extends ComponentMeta> = M extends { readonly omit: infer O extends readonly string[] } ? O[number] : never;
|
|
99
113
|
/** Props the component takes that the meta neither lists nor omits. */
|
|
100
|
-
export type ExtraProps<P, M extends ComponentMeta> = Exclude<DesignKeys<P>, keyof M["props"] |
|
|
114
|
+
export type ExtraProps<P, M extends ComponentMeta> = Exclude<DesignKeys<P>, keyof M["props"] | OmitOf<M>>;
|
|
101
115
|
/** Props the meta lists that the component does not take. */
|
|
102
116
|
export type MissingProps<P, M extends ComponentMeta> = Exclude<keyof M["props"] & string, DesignKeys<P>>;
|
|
103
117
|
export type MismatchedProps<P, M extends ComponentMeta, N> = PropsMismatch<P, M["props"], N>;
|
package/dist/metaCheck.js
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
|
-
function e(e){
|
|
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}.${n}>;`,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`)});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
|
+
`)}\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
|
+
`)}`):(D.sort((e,t)=>e.owner-t.owner||e.rank-t.rank),Error(D.map(e=>e.text).join(`
|
|
4
|
+
`)))}finally{r(d,{recursive:!0,force:!0})}}export{l as TSC,y as checkMetaTypes,h as specifierOf};
|
package/dist/metas.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
import{toPosix as e}from"./files.js";import{existsSync as t,globSync as n}from"node:fs";import{resolve as r}from"node:path";import{pathToFileURL as i}from"node:url";var a=Object.freeze([`a`,`b`,`button`,`div`,`img`,`kbd`,`li`,`p`,`span`,`strong`,`table`,`tbody`,`td`,`th`,`thead`,`tr`,`ul`]),o=/^[A-Z][A-Za-z0-9]*$/,s=/^[A-Za-z0-9][A-Za-z0-9_-]*$/,c=/^App[A-Za-z0-9]*$/,l=/^on[A-Z][A-Za-z0-9]*$/,u=/[\u2013\u2014]/,d=[`string`,`number`,`stringOrNumber`,`boolean`,`enum`,`enumOrNumber`,`url`,`icon`,`node`,`array`,`object`,`any`],f=[`.jsx`,`.tsx`,`.js`,`.ts`];async function p({root:e,components:t,knownNames:a,icons:o}){let s=n(t,{cwd:e});if(s.length===0)throw Error(`${e}: no component metadata matches ${t}`);let c=s.map(t=>r(e,t)).sort(L),l=[];for(let e of c){let t=await import(i(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 m(l,{knownNames:a,icons:o}),l.sort((e,t)=>L(e.meta.name,t.meta.name))}function m(e,{knownNames:t=[],icons:n}={}){let r=new Map;for(let{meta:t}of e)R(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=[];_(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 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};
|
package/dist/phone.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readText as e}from"./files.js";import t from"@babel/parser";
|
|
1
|
+
import{readText as e}from"./files.js";import t from"@babel/parser";function n(n){return t.parse(e(n),{sourceType:`module`,plugins:[`typescript`]})}function r(e){return[...new Set(e)].sort((e,t)=>e<t?-1:+(e>t))}function i(e){return e.type===`Identifier`?e.name:e.type===`StringLiteral`?e.value:null}function a(e){let t=new Map;for(let n of e.program.body){let e=n.type===`ExportNamedDeclaration`?n.declaration:n;if(e?.type===`VariableDeclaration`)for(let n of e.declarations)n.id.type===`Identifier`&&t.set(n.id.name,n.init)}return t}function o(e,t,n){let r=t;for(let t=0;r?.type===`Identifier`;t+=1){if(t>10||!e.has(r.name))throw Error(`${r.name} in ${n} is not a constant the reader can follow.`);r=e.get(r.name)}return r}function s(e){let t=n(e).program.body.map(e=>e.type===`ExportNamedDeclaration`?e.declaration:e).find(e=>e?.type===`TSTypeAliasDeclaration`&&e.id.name===`IconName`);if(t?.typeAnnotation.type!==`TSUnionType`)throw Error(`IconName union not found in ${e}`);return r(t.typeAnnotation.types.map(t=>{if(t.type!==`TSLiteralType`||t.literal.type!==`StringLiteral`)throw Error(`IconName in ${e} has a member that is not a string literal`);return t.literal.value}))}function c(e,t,n){let r=o(e,t,n);switch(r.type){case`StringLiteral`:case`NumericLiteral`:case`BooleanLiteral`:return r.value;case`UnaryExpression`:if(r.operator===`!`&&r.argument.type===`NumericLiteral`)return!r.argument.value;break;case`ArrayExpression`:return r.elements.map(t=>c(e,t,n));case`ObjectExpression`:return Object.fromEntries(r.properties.map(t=>{if(t.type!==`ObjectProperty`||t.computed)throw Error(`phoneChromeEntries in ${n} has an object member the reader cannot follow.`);return[i(t.key),c(e,t.value,n)]}));case`MemberExpression`:if(!r.computed&&r.property.type===`Identifier`){let t=c(e,r.object,n);if(typeof t==`object`&&t&&r.property.name in t)return t[r.property.name]}break}throw Error(`phoneChromeEntries in ${n} has a ${r.type} the reader cannot read as data.`)}function l(e){return new Set(e.program.body.filter(e=>e.type===`ExportNamedDeclaration`&&e.declaration).flatMap(({declaration:e})=>e.type===`VariableDeclaration`?e.declarations.map(e=>e.id.name):[e.id?.name]))}function u(n,r){let i=t.parse(e(n),{sourceType:`module`,plugins:[`jsx`]}),o=a(i);if(!o.has(`phoneChromeEntries`))throw Error(`phoneChromeEntries is not declared in ${n}; the phone kit's frame parts come from it.`);let s=c(o,o.get(`phoneChromeEntries`),n),u=l(i);if(!Array.isArray(s)||s.length===0)throw Error(`phoneChromeEntries in ${n} must be a list of manifest entries.`);return s.map(e=>{let{name:t,marker:i,acceptsChildren:a,props:o,itemsTakeAction:s,takesAction:c,source:l}=e??{};if(typeof t!=`string`||typeof i!=`string`||typeof a!=`boolean`||!Array.isArray(o)||!Array.isArray(s)||!Array.isArray(c))throw Error(`phoneChromeEntries in ${n} has an entry that is not a manifest component: ${JSON.stringify(e)}`);if(l!==r)throw Error(`phoneChromeEntries in ${n}: ${t} names the source ${l}, not ${r}.`);if(!u.has(t))throw Error(`phoneChromeEntries in ${n} lists ${t}, which the module does not export.`);return{name:t,marker:i,acceptsChildren:a,props:o,itemsTakeAction:s,takesAction:c,source:l}})}function d(e,t){for(let[n,i]of[[`itemsTakeAction`,`array`],[`takesAction`,`object`]])for(let[a,o]of Object.entries(t[n]??{})){let t=e.find(({name:e})=>e===a);if(!t)throw Error(`phoneStyleSupport.json ${n} names ${a}, which the kit does not have.`);for(let e of o)if(t.props.find(({name:t})=>t===e)?.type!==i)throw Error(`phoneStyleSupport.json ${n} names ${a}.${e}, which is not a prop of type ${i} in the kit.`);t[n]=r([...new Set([...t[n],...o])])}}export{d as applyPhoneActions,u as phoneChromeEntries,s as phoneIcons};
|
package/dist/release.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readJson as e}from"./files.js";import{RELEASE_FILE as t,changedMessage as n,checkStampFiles as r}from"./releaseStamp.js";import{existsSync as i,mkdirSync as a,readFileSync as o,renameSync as s,rmSync as c,writeFileSync as l}from"node:fs";import{
|
|
1
|
+
import{readJson as e}from"./files.js";import{RELEASE_FILE as t,changedMessage as n,checkStampFiles as r}from"./releaseStamp.js";import{existsSync as i,mkdirSync as a,readFileSync as o,renameSync as s,rmSync as c,writeFileSync as l}from"node:fs";import{dirname as u,join as d}from"node:path";import{createHash as f}from"node:crypto";function p(e){let t=Buffer.from(e);return{sha256:f(`sha256`).update(t).digest(`hex`),bytes:t.length}}function m(e,n,r){if(i(e))throw Error(`${e} already exists. A release folder is never overwritten; choose a new folder.`);a(u(e),{recursive:!0});let o=`${e}.staging-${process.pid}-${Date.now()}`;a(o);try{for(let[e,t]of Object.entries(n))l(d(o,e),t,{flag:`wx`});l(d(o,t),`${JSON.stringify(r,null,2)}\n`,{flag:`wx`}),s(o,e)}catch(e){throw c(o,{recursive:!0,force:!0}),e}}function h(a){let s=d(a,t);if(!i(s))throw Error(`${a} has no ${t}; it is not a kit release.`);let c=e(s);r(c,a);for(let[e,t]of Object.entries(c.files)){let r=d(a,e);if(!i(r))throw Error(`${e} is missing from ${a}.`);let s=p(o(r));if(s.sha256!==t.sha256||s.bytes!==t.bytes)throw Error(n(e,a))}return{release:c,manifest:e(d(a,`manifest.json`))}}export{p as digest,h as readReleaseManifest,m as writeReleaseFolder};
|
package/dist/tokens.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readJson as e,readText as t}from"./files.js";import{
|
|
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)&&i(e.lineHeight));let C=e(n);if(C.format!==`webority-meanings/1`)throw Error(`${n} has format ${JSON.stringify(C.format)}; this reader reads webority-meanings/1.`);let w={};for(let e of _){let t=C.color?.[e]?.description;if(!a(t)||t===``)throw Error(`${n} has no meaning for the colour ${e}; move the @webority/tokens pin to a version that publishes one.`);w[e]=t}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)),colorMeanings:w},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,lineHeight:t})=>({size:e,lineHeight:t,weight:null}))}}}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
package/dist/declarations.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{readText as e}from"./files.js";import{existsSync as t}from"node:fs";import{dirname as n,join as r,resolve as i}from"node:path";import a from"@babel/parser";var o=`function`,s=8,c=2,l=120,u=[`ForwardRefExoticComponent`,`FC`,`FunctionComponent`,`ComponentType`,`MemoExoticComponent`],d=[`ReactElement`,`ReactNode`,`ReactPortal`],f=[`Array`,`ReadonlyArray`,`Set`,`ReadonlySet`],ee=/(^i|I)con$/,p=/(Href|href|Url|url)$/,m=new Map,h=new Set,g=new Set,_=[];function v(e,t){return e<t?-1:+(e>t)}function y(e){return[...new Set(e)].sort(v)}function b(e){return e.type===`Identifier`?e.name:e.type===`StringLiteral`?e.value:null}function x(e){let t=e.type===`TSImportType`?e.qualifier:e.typeName;return t?t.type===`TSQualifiedName`?t.right.name:t.name:null}function S(e){switch(e.type){case`TSDeclareFunction`:case`FunctionDeclaration`:case`TSInterfaceDeclaration`:case`TSTypeAliasDeclaration`:return[[e.id.name,e]];case`ClassDeclaration`:return e.id?[[e.id.name,e]]:[];case`VariableDeclaration`:return e.declarations.filter(e=>e.id.type===`Identifier`).map(e=>[e.id.name,e]);default:return[]}}function C(t){if(m.has(t))return m.get(t);let n=e(t),r=a.parse(n,{sourceType:`module`,plugins:[`typescript`]}),i={declarations:new Map,imports:new Map,exports:[],defaultDeclaration:null,source:n};for(let e of r.program.body)if(e.type===`ImportDeclaration`)for(let t of e.specifiers)t.type===`ImportSpecifier`&&i.imports.set(t.local.name,{source:e.source.value,imported:b(t.imported)});else if(e.type===`ExportAllDeclaration`)i.exports.push({star:!0,source:e.source.value});else if(e.type===`ExportDefaultDeclaration`)i.defaultDeclaration=e.declaration,i.exports.push({name:`default`,local:`default`});else if(e.type===`ExportNamedDeclaration`&&e.source)for(let t of e.specifiers)i.exports.push({name:t.exported.name,local:t.local.name,source:e.source.value});else{let t=e.type===`ExportNamedDeclaration`,n=t?e.declaration:e;for(let[e,r]of n?S(n):[])i.declarations.set(e,r),t&&i.exports.push({name:e,local:e});if(t)for(let t of e.specifiers)i.exports.push({name:t.exported.name,local:t.local.name})}return m.set(t,i),i}function w(e,a){if(!a.startsWith(`.`))return null;let o=i(n(e),a).replace(/\.(jsx?|tsx?)$/,``);for(let e of[`${o}.d.ts`,r(o,`index.d.ts`)])if(t(e))return e;throw Error(`Cannot resolve ${a} from ${e}`)}function T(e,t=new Set){let n=new Map;if(t.has(e))return n;t.add(e);for(let r of C(e).exports){if(r.star){let i=w(e,r.source);for(let[e,r]of i?T(i,t):[])e!=="default"&&!n.has(e)&&n.set(e,r);continue}let i=r.source===void 0?e:w(e,r.source);i&&n.set(r.name,{file:i,local:r.local})}return n}function E(e,t=new Set){let n=`${e.file}#${e.local}`;if(t.has(n))return null;t.add(n);let r=C(e.file);if(r.declarations.has(e.local))return e;let i=r.exports.find(t=>t.name===e.local&&t.source!==void 0),a=i&&w(e.file,i.source);return a?E({file:a,local:i.local},t):null}function D(e){return e.local==="default"?e:E(e)}function O(e){let t=D(e);if(!t)return null;let{declarations:n,defaultDeclaration:r}=C(t.file),i=t.local==="default"?r?.type===`Identifier`?n.get(r.name):r:n.get(t.local);return i?.type===`TSDeclareFunction`||i?.type===`FunctionDeclaration`?i:null}function te(e,t,n){let r=e.params[0];if(!r)return[];let i=(r.type===`AssignmentPattern`?r.left:r).typeAnnotation?.typeAnnotation;if(!i)return null;let a=P(i,t.file,new Map,0);if(a)return a;let o=x(i);if(i.type===`TSTypeReference`&&o?.endsWith(`Props`)&&C(t.file).declarations.has(o))throw Error(`${n}: ${o} is not an object type in ${t.file}`);return null}function k(e,t){let n=C(e),r=n.declarations.get(t);if(r)return{file:e,declared:r};let i=n.imports.get(t),a=i&&w(e,i.source);if(!a)return null;let o=E({file:a,local:i.imported});return o?{file:o.file,declared:C(o.file).declarations.get(o.local)}:null}function A(e,t,n,r,i){let a=new Map;return(e.typeParameters?.params??[]).forEach((e,o)=>{let s=t[o];s?a.set(e.name,{node:s,file:n,env:r}):e.default?a.set(e.name,{node:e.default,file:i,env:a}):a.set(e.name,{node:{type:`TSUnknownKeyword`},file:i,env:new Map})}),a}function j(e){if(!e?.expression)return null;let t=(e.typeParameters??e.typeArguments)?.params;return{type:`TSTypeReference`,typeName:e.expression,...t?{typeParameters:{params:t}}:{}}}function M(e,t,n){if(e.type===`TSImportType`){let t=e.argument?.value;return typeof t!=`string`||!t.startsWith(`.`)}let r=n?C(n).imports.get(t):null;return!!(r&&!r.source.startsWith(`.`))}function ne(e,t,n){if(!e)return null;let r=e.type===`TSUnionType`?e.types:[e],i=[];for(let e of r){if(e.type===`TSNullKeyword`||e.type===`TSUndefinedKeyword`)continue;let r=z(e,t,n);if(r.length===0||r.includes(null))return null;i.push(...r)}return i.length>0?i:null}function re(e,t,n,r){let i=e.filter(e=>e.type!==`TSNullKeyword`&&e.type!==`TSUndefinedKeyword`);if(i.length===1)return P(i[0],t,n,r);let a=[];for(let e of i){let i=P(e,t,n,r);if(!i)return null;a.push(i)}let o=[],s=new Map;for(let e of a)for(let t of e){let e=s.get(t.name);e||(e={name:t.name,count:0,requiredEverywhere:!0,branches:[]},s.set(t.name,e),o.push(t.name)),e.count+=1,e.requiredEverywhere=e.requiredEverywhere&&!t.optional,e.branches.push(...t.branches)}return o.map(e=>{let t=s.get(e);return{name:e,optional:!(t.count===a.length&&t.requiredEverywhere),branches:t.branches}})}function ie(e,t,n,r,i,a){let o=A(e,t,n,r,i),s=[],c=new Map;for(let t of e.extends??[]){let e=P(j(t),i,o,a+1);if(!e)return null;for(let t of e)c.has(t.name)||s.push(t.name),c.set(t.name,t)}let l=P({type:`TSTypeLiteral`,members:e.body.body},i,o,a);if(!l)return null;for(let e of l){let t=s.indexOf(e.name);t>=0&&s.splice(t,1),s.push(e.name),c.set(e.name,e)}return s.map(e=>c.get(e))}function N(e,t,n,r){let i=x(e),a=(e.typeParameters??e.typeArguments)?.params??[];if(i&&n.has(i)){let e=n.get(i);return P(e.node,e.file,e.env,r+1)}if(i===`RefAttributes`)return[];if([`Partial`,`Required`,`Readonly`].includes(i)&&a.length===1){let e=P(a[0],t,n,r);return e?i===`Partial`?e.map(e=>({...e,optional:!0})):i===`Required`?e.map(e=>({...e,optional:!1})):e:null}if((i===`Omit`||i===`Pick`)&&a.length===2){let e=P(a[0],t,n,r);if(!e)return null;let o=ne(a[1],t,r);if(!o)return i===`Omit`?e:null;let s=new Set(o);return i===`Omit`?e.filter(e=>!s.has(e.name)):e.filter(e=>s.has(e.name))}if(M(e,i,t))return i&&g.add(i),[];let o=k(t,i);if(!o?.declared)return null;if(o.declared.type===`TSInterfaceDeclaration`)return ie(o.declared,a,t,n,o.file,r);if(o.declared.type===`TSTypeAliasDeclaration`){let e=A(o.declared,a,t,n,o.file);return P(o.declared.typeAnnotation,o.file,e,r+1)}return null}function P(e,t,n,r){if(!e||r>=s)return null;switch(e.type){case`TSParenthesizedType`:return P(e.typeAnnotation,t,n,r);case`TSTypeLiteral`:return e.members.filter(e=>e.type===`TSPropertySignature`&&b(e.key)!==null).map(e=>({name:b(e.key),optional:e.optional===!0,branches:[{node:e.typeAnnotation?.typeAnnotation??{type:`TSAnyKeyword`},file:t,env:n}]}));case`TSIntersectionType`:{let i=[],a=new Map;for(let o of e.types){let e=P(o,t,n,r);if(!e)return null;for(let t of e)a.has(t.name)||i.push(t.name),a.set(t.name,t)}return i.map(e=>a.get(e))}case`TSUnionType`:return re(e.types,t,n,r);case`TSTypeReference`:case`TSImportType`:return N(e,t,n,r);default:return null}}function F(e,t,n){if(e===`ReactNode`||e===`ReactElement`)return{type:`node`};if(f.includes(e))return{type:`array`};if(e===`Record`)return{type:`object`};if(e===`Date`)return{type:`string`};if(e===`Function`)return o;if(e===`SlotIcon`)return{type:`node`};if(!t||n>=s)return null;let r=k(t,e);if(r?.declared?.type===`TSTypeAliasDeclaration`)return V(r.declared.typeAnnotation,r.file,n+1);if(r?.declared?.type===`TSInterfaceDeclaration`){let i=P({type:`TSTypeReference`,typeName:{type:`Identifier`,name:e}},t,_.at(-1)??new Map,n+1);return i?W(i,r.declared):null}return null}function I(e){return e.type===`TSBooleanKeyword`||e.type===`TSLiteralType`&&e.literal.type===`BooleanLiteral`}function ae(e){return e.type===`TSLiteralType`&&e.literal.type===`StringLiteral`}function oe(e){return e.type===`TSObjectKeyword`||e.type===`TSTypeLiteral`}function L(e){return e?.type===`TSQualifiedName`&&e.left.type===`Identifier`&&e.left.name===`JSX`&&e.right.name===`Element`}function se(e){return e.type===`TSTypeReference`&&[`File`,`Blob`].includes(x(e))}function R(e,t,n){let r=e.filter(e=>e.type!==`TSNullKeyword`&&e.type!==`TSUndefinedKeyword`&&!se(e)),i=e=>r.every(t=>t.type===`TSLiteralType`&&t.literal.type===e);if(r.length===0)return null;if(i(`StringLiteral`))return{type:`enum`,enum:y(r.map(e=>e.literal.value))};if(i(`BooleanLiteral`)||r.some(I)&&r.every(e=>I(e)||ae(e)||oe(e)))return{type:`boolean`};if(i(`NumericLiteral`))return{type:`number`};if(r.length===1&&r[0].type!==`TSLiteralType`)return V(r[0],t,n);let a=r.flatMap(e=>z(e,t,n));if(a.length>0&&!a.includes(null))return{type:`enum`,enum:y(a)};let s=new Set(r.map(e=>B(e,t,n)));return s.has(`node`)?{type:`node`}:s.size===2&&s.has(`string`)&&s.has(`number`)?{type:`stringOrNumber`}:s.size===1&&!s.has(null)?{type:[...s][0]}:r.every(e=>e.type!==`TSLiteralType`)&&r.map(e=>V(e,t,n)).every(e=>e&&e!==o&&[`object`,`array`].includes(e.type))?{type:`any`}:null}function z(e,t,n){if(e.type===`TSLiteralType`)return e.literal.type===`StringLiteral`?[e.literal.value]:[null];let r=V(e,t,n);return r?.type===`enum`?r.enum:[null]}function B(e,t,n){if(e.type===`TSLiteralType`){let t=e.literal.type;return t===`StringLiteral`?`string`:t===`NumericLiteral`?`number`:t===`BooleanLiteral`?`boolean`:null}let r=V(e,t,n);return r?.type===`enum`?`string`:r&&r!==o&&[`node`,`string`,`number`,`boolean`].includes(r.type)?r.type:null}function V(e,t,n=0){switch(e.type){case`TSParenthesizedType`:return V(e.typeAnnotation,t,n);case`TSAnyKeyword`:case`TSUnknownKeyword`:return{type:`any`,anyUnknown:!0};case`TSStringKeyword`:return{type:`string`};case`TSNumberKeyword`:return{type:`number`};case`TSBooleanKeyword`:return{type:`boolean`};case`TSArrayType`:return K(e.elementType,t,n);case`TSTypeLiteral`:return G(e.members,t);case`TSFunctionType`:return o;case`TSLiteralType`:return R([e],t,n);case`TSUnionType`:return R(e.types,t,n);case`TSTypeReference`:{let r=x(e),i=_.at(-1);if(r&&i?.has(r)){let e=i.get(r);_.push(e.env);try{return V(e.node,e.file,n+1)}finally{_.pop()}}return L(e.typeName)?{type:`node`}:f.includes(r)&&e.typeParameters?.params.length===1?K(e.typeParameters.params[0],t,n):F(r,t,n)}case`TSImportType`:return L(e.qualifier)?{type:`node`}:F(x(e),null,n);default:return null}}function H(e,t){return p.test(e)&&(t===`string`||t===`any`)?`url`:t}function U(e,t=e){if(h.size>=c||h.has(t))return null;h.add(t);try{return q(e)}finally{h.delete(t)}}function W(e,t=e){let n=U(e,t);return n?{type:`object`,fields:n.props,skippedFields:n.skippedProps,...n.hasHandler?{handler:!0}:{}}:{type:`object`}}function G(e,t){let n=P({type:`TSTypeLiteral`,members:e},t,_.at(-1)??new Map,0);return n?W(n):{type:`object`}}function K(e,t,n){let r=V(e,t,n);return r?.fields?{type:`array`,itemFields:r.fields,skippedFields:r.skippedFields,...r.handler?{itemHandler:!0}:{}}:{type:`array`}}function ce(e){_.push(e.env);try{return V(e.node,e.file)}finally{_.pop()}}function le(e){let t=e.branches.map(e=>J(e.node,e.file));return t.length===1?t[0]:t.join(` | `)}function q(e){let t=[],n=[],r=!1,i=!1;for(let a of e){let e=a.name;if(e===`children`){r=!0;continue}let s=a.branches.map(e=>ce(e));if(s.every(e=>e===o)){i=!0;continue}let c=a.branches[0],l;if(s.every(e=>e!==null&&JSON.stringify(e)===JSON.stringify(s[0])))l=s[0];else if(a.branches.every(e=>e.file===c.file&&e.env===c.env)){let e={type:`TSUnionType`,types:a.branches.map(e=>e.node)};_.push(c.env);try{l=V(e,c.file)}finally{_.pop()}}if(l===o){i=!0;continue}if(!l){n.push({name:e,type:le(a)});continue}let{type:u,enum:d,anyUnknown:f,fields:p,itemFields:m,skippedFields:h=[]}=l;for(let t of h)n.push({...t,name:`${e}${u===`array`?`[]`:``}.${t.name}`});t.push({name:e,type:H(e,u===`node`&&ee.test(e)?`icon`:u),...l.handler?{handler:!0}:{},...l.itemHandler?{itemHandler:!0}:{},...d?{enum:d}:{},...p?{fields:p}:{},...m?{itemFields:m}:{},required:!a.optional&&!f})}return t.sort((e,t)=>v(e.name,t.name)),{props:t,acceptsChildren:r,skippedProps:n,hasHandler:i}}function J(e,t){if(e.start===void 0)return e.type===`TSUnionType`?e.types.map(e=>J(e,t)).join(` | `):e.type;let n=t?C(t).source:null;if(!n)return e.type;let r=n.slice(e.start,e.end).replace(/\s+/g,` `);return r.length>l?`${r.slice(0,l)}...`:r}function Y(e){let t=D(e);if(!t)return null;let{declarations:n,defaultDeclaration:r}=C(t.file),i=t.local==="default"?r?.type===`Identifier`&&n.get(r.name):n.get(t.local);return i?.type===`VariableDeclarator`?{node:i,declarations:n}:null}function X(e){return[`TSTypeReference`,`TSImportType`].includes(e?.type)&&u.includes(x(e))}function Z(e){if(!e)return!1;if(e.type===`TSParenthesizedType`)return Z(e.typeAnnotation);if(e.type===`TSUnionType`){let t=e.types.filter(e=>e.type!==`TSNullKeyword`&&e.type!==`TSUndefinedKeyword`);return t.length>0&&t.every(Z)}let t=e.type===`TSImportType`?e.qualifier:e.typeName;return[`TSTypeReference`,`TSImportType`].includes(e.type)&&(L(t)||d.includes(x(e)))}function Q(e){if(!e)return null;switch(e.type){case`TSParenthesizedType`:return Q(e.typeAnnotation);case`TSTypeReference`:case`TSImportType`:return X(e)?e:null;case`TSFunctionType`:return Z(e.typeAnnotation?.typeAnnotation)?e:null;case`TSTypeLiteral`:return e.members.find(e=>e.type===`TSCallSignatureDeclaration`&&Z(e.typeAnnotation?.typeAnnotation))??null;case`TSIntersectionType`:for(let t of e.types){let e=Q(t);if(e)return e}return null;default:return null}}function $(e){let t=D(e),n=t&&C(t.file).declarations.get(t.local);if(n?.type!==`ClassDeclaration`||!n.superClass)return null;let r=n.superClass.type===`MemberExpression`?n.superClass.property:n.superClass;return r?.type===`Identifier`&&[`Component`,`PureComponent`].includes(r.name)?{node:n,file:t.file}:null}function ue(e){let t=$(e);if(!t)return null;let n=(t.node.superTypeParameters??t.node.superTypeArguments)?.params?.[0];return n?P(n,t.file,new Map,0):[]}function de(e){return Q(Y(e)?.node.id.typeAnnotation?.typeAnnotation)!==null||$(e)!==null}function fe(e,t){let n=(e.parameters??e.params??[])[0];if(!n)return[];let r=(n.type===`AssignmentPattern`?n.left:n).typeAnnotation?.typeAnnotation;return r?P(r,t,A(e,[],t,new Map,t),0):null}function pe(e){let t=Y(e);if(!t)return null;let n=D(e)?.file,r=Q(t.node.id.typeAnnotation?.typeAnnotation);if(r&&!X(r))return fe(r,n);for(;r;){if(![`TSTypeReference`,`TSImportType`].includes(r.type)||!u.includes(x(r)))return null;let e=(r.typeParameters??r.typeArguments)?.params??[];if(e.length===0)return[];if(r=e[0],![`TSTypeReference`,`TSImportType`].includes(r.type)||!u.includes(x(r)))return P(r,n,new Map,0)}return null}function me(e,{namedConsts:t=!1,kit:n=``}={}){m=new Map,h.clear(),g.clear(),_.length=0;let r=[],i=[],a=[];for(let[o,s]of T(e)){if(!/^[A-Z][A-Za-z0-9]*$/.test(o))continue;let c=O(s),l=D(s),u=c?te(c,l,o):t?pe(s)??ue(s):null;if(!u){(c||t&&de(s))&&(i.push(`Component left out, its props could not be read: ${n} ${o}`),a.push(o));continue}let d=q(u);if(d.skippedProps.length>0){let e=d.skippedProps.map(({name:e,type:t})=>`${e} (${t})`).join(`, `);i.push(`Skipped props, no manifest type: ${n} ${o}: ${e}`)}r.push({name:o,acceptsChildren:d.acceptsChildren,props:d.props,file:l?.file??e})}return r.sort((e,t)=>v(e.name,t.name)),g.size>0&&i.push(`Props inherited from outside the kit were not read: ${n} ${y(g).join(`, `)}`),{components:r,warnings:i,unreadable:y(a)}}export{me as collectComponents};
|