@penpair/marwes-ui 0.2.0 → 0.3.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/dist/build-kit.js +24 -6
- package/dist/commands.d.ts +4 -0
- package/dist/commands.js +500 -94
- package/dist/components.js +375 -74
- package/dist/config.js +53 -16
- package/dist/index.js +21 -3
- package/dist/marwes.js +45 -12
- package/dist/mode-trial.js +325 -75
- package/dist/ownership.js +162 -37
- package/dist/penpot.js +447 -114
- package/dist/reconciliation.js +112 -37
- package/dist/resolved-values.d.ts +3 -8
- package/dist/resolved-values.js +99 -103
- package/dist/snapshot-file.js +255 -50
- package/dist/theme-input.js +12 -4
- package/dist/theme-lint.js +113 -27
- package/dist/tokens.d.ts +1 -1
- package/dist/tokens.js +207 -52
- package/package.json +2 -2
package/dist/config.js
CHANGED
|
@@ -5,55 +5,90 @@ export const defaultSnapshotPath = "design/marwes-tokens.snapshot.json";
|
|
|
5
5
|
export class MarwesConfigError extends Error {
|
|
6
6
|
}
|
|
7
7
|
const relative = (value, label) => {
|
|
8
|
-
if (typeof value !== "string" ||
|
|
8
|
+
if (typeof value !== "string" ||
|
|
9
|
+
value.length === 0 ||
|
|
10
|
+
path.isAbsolute(value) ||
|
|
11
|
+
value.split(/[\\/]/).includes("..")) {
|
|
9
12
|
throw new MarwesConfigError(`penpair.config.json: marwes.${label} must be a relative path that stays inside the project`);
|
|
13
|
+
}
|
|
10
14
|
return value;
|
|
11
15
|
};
|
|
12
16
|
function themeReference(value, label) {
|
|
13
|
-
if (value === undefined)
|
|
17
|
+
if (value === undefined) {
|
|
14
18
|
return undefined;
|
|
19
|
+
}
|
|
15
20
|
const v = value;
|
|
16
|
-
if (typeof value !== "object" ||
|
|
21
|
+
if (typeof value !== "object" ||
|
|
22
|
+
value === null ||
|
|
23
|
+
typeof v.export !== "string" ||
|
|
24
|
+
v.export.length === 0) {
|
|
17
25
|
throw new MarwesConfigError(`penpair.config.json: marwes.themes.${label} must be {"module": "<file>", "export": "<name>"}`);
|
|
18
|
-
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
module: relative(v.module, `themes.${label}.module`),
|
|
29
|
+
export: v.export,
|
|
30
|
+
};
|
|
19
31
|
}
|
|
20
32
|
const capitalise = (text) => text.charAt(0).toUpperCase() + text.slice(1);
|
|
21
33
|
export function readMarwesSettings(rawConfig, instance) {
|
|
22
34
|
const block = rawConfig.marwes;
|
|
23
35
|
const v = (typeof block === "object" && block !== null ? block : {});
|
|
24
|
-
if (block !== undefined && (typeof block !== "object" || block === null))
|
|
36
|
+
if (block !== undefined && (typeof block !== "object" || block === null)) {
|
|
25
37
|
throw new MarwesConfigError('penpair.config.json: "marwes" must be an object');
|
|
38
|
+
}
|
|
26
39
|
const themes = (typeof v.themes === "object" && v.themes !== null ? v.themes : {});
|
|
27
40
|
const name = v.name === undefined ? capitalise(instance) : String(v.name);
|
|
28
|
-
if (!/^[A-Za-z][A-Za-z0-9 _-]{0,40}$/.test(name))
|
|
41
|
+
if (!/^[A-Za-z][A-Za-z0-9 _-]{0,40}$/.test(name)) {
|
|
29
42
|
throw new MarwesConfigError("penpair.config.json: marwes.name must be a short name (letters, digits, spaces, hyphens)");
|
|
43
|
+
}
|
|
30
44
|
return {
|
|
31
45
|
name,
|
|
32
46
|
extras: readExtras(v.extras),
|
|
33
47
|
themeLint: readThemeLint(v.themeLint),
|
|
34
48
|
project: v.project === undefined ? "." : relative(v.project, "project"),
|
|
35
|
-
themes: {
|
|
49
|
+
themes: {
|
|
50
|
+
light: themeReference(themes.light, "light"),
|
|
51
|
+
dark: themeReference(themes.dark, "dark"),
|
|
52
|
+
},
|
|
36
53
|
snapshot: v.snapshot === undefined ? defaultSnapshotPath : relative(v.snapshot, "snapshot"),
|
|
37
54
|
};
|
|
38
55
|
}
|
|
39
56
|
function readExtras(value) {
|
|
40
|
-
if (value === undefined)
|
|
57
|
+
if (value === undefined) {
|
|
41
58
|
return [];
|
|
42
|
-
|
|
59
|
+
}
|
|
60
|
+
if (!Array.isArray(value) || value.length > 50) {
|
|
43
61
|
throw new MarwesConfigError("marwes.extras must be an array of at most 50 sets");
|
|
62
|
+
}
|
|
44
63
|
const names = new Set();
|
|
45
64
|
let count = 0;
|
|
46
|
-
return value.map(raw => {
|
|
47
|
-
if (!raw ||
|
|
65
|
+
return value.map((raw) => {
|
|
66
|
+
if (!raw ||
|
|
67
|
+
typeof raw !== "object" ||
|
|
68
|
+
Array.isArray(raw) ||
|
|
69
|
+
Object.keys(raw).some((key) => ![
|
|
70
|
+
"name",
|
|
71
|
+
"tokens",
|
|
72
|
+
].includes(key))) {
|
|
48
73
|
throw new MarwesConfigError("Invalid project extra set");
|
|
74
|
+
}
|
|
49
75
|
const set = raw;
|
|
50
|
-
if (typeof set.name !== "string" ||
|
|
76
|
+
if (typeof set.name !== "string" ||
|
|
77
|
+
!set.name.trim() ||
|
|
78
|
+
set.name.length > 200 ||
|
|
79
|
+
/[\x00-\x1f]/.test(set.name) ||
|
|
80
|
+
names.has(set.name) ||
|
|
81
|
+
!Array.isArray(set.tokens)) {
|
|
51
82
|
throw new MarwesConfigError("Invalid or duplicate project extra set");
|
|
83
|
+
}
|
|
52
84
|
names.add(set.name);
|
|
53
85
|
const tokens = new Set();
|
|
54
|
-
return {
|
|
55
|
-
|
|
86
|
+
return {
|
|
87
|
+
name: set.name,
|
|
88
|
+
tokens: set.tokens.map((rawToken) => {
|
|
89
|
+
if (++count > 10000) {
|
|
56
90
|
throw new MarwesConfigError("Project extras exceed 10000 tokens");
|
|
91
|
+
}
|
|
57
92
|
let token;
|
|
58
93
|
try {
|
|
59
94
|
token = validateEditableToken(rawToken);
|
|
@@ -61,10 +96,12 @@ function readExtras(value) {
|
|
|
61
96
|
catch (error) {
|
|
62
97
|
throw new MarwesConfigError("marwes.extras: " + String(error));
|
|
63
98
|
}
|
|
64
|
-
if (tokens.has(token.name))
|
|
99
|
+
if (tokens.has(token.name)) {
|
|
65
100
|
throw new MarwesConfigError("Duplicate project extra token: " + token.name);
|
|
101
|
+
}
|
|
66
102
|
tokens.add(token.name);
|
|
67
103
|
return token;
|
|
68
|
-
})
|
|
104
|
+
}),
|
|
105
|
+
};
|
|
69
106
|
});
|
|
70
107
|
}
|
package/dist/index.js
CHANGED
|
@@ -3,10 +3,28 @@ import { marwesKit } from "./build-kit.js";
|
|
|
3
3
|
import { checkSnapshotFor } from "./commands.js";
|
|
4
4
|
import { marwesCommand } from "./commands.js";
|
|
5
5
|
/** The adapter penpair loads when `@penpair/marwes-ui` is listed under "adapters" in penpair.config.json. */
|
|
6
|
-
export default defineAdapter({
|
|
6
|
+
export default defineAdapter({
|
|
7
|
+
name: "@penpair/marwes-ui",
|
|
8
|
+
commands: [
|
|
9
|
+
marwesCommand,
|
|
10
|
+
],
|
|
11
|
+
kits: [
|
|
12
|
+
marwesKit,
|
|
13
|
+
],
|
|
14
|
+
async status(context) {
|
|
7
15
|
const check = await checkSnapshotFor(context.root, context.rawConfig, context.config.instance);
|
|
8
|
-
return [
|
|
9
|
-
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
id: "library-tokens",
|
|
19
|
+
label: "Token snapshot",
|
|
20
|
+
state: check.current ? "ok" : "warning",
|
|
21
|
+
detail: check.current
|
|
22
|
+
? "Declarations match installed library/theme; live tokens not inspected"
|
|
23
|
+
: "Missing/stale snapshot or mixed library versions",
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
},
|
|
27
|
+
});
|
|
10
28
|
export * from "./commands.js";
|
|
11
29
|
export * from "./config.js";
|
|
12
30
|
export * from "./marwes.js";
|
package/dist/marwes.js
CHANGED
|
@@ -4,13 +4,20 @@ import path from "node:path";
|
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
export class MarwesError extends Error {
|
|
6
6
|
}
|
|
7
|
-
const familyNames = [
|
|
7
|
+
const familyNames = [
|
|
8
|
+
"react",
|
|
9
|
+
"vue",
|
|
10
|
+
"svelte",
|
|
11
|
+
"core",
|
|
12
|
+
"presets",
|
|
13
|
+
];
|
|
8
14
|
function packageDirectory(entry) {
|
|
9
15
|
let directory = path.dirname(entry);
|
|
10
16
|
while (!existsSync(path.join(directory, "package.json"))) {
|
|
11
17
|
const parent = path.dirname(directory);
|
|
12
|
-
if (parent === directory)
|
|
18
|
+
if (parent === directory) {
|
|
13
19
|
throw new MarwesError(`no package.json above ${entry}`);
|
|
20
|
+
}
|
|
14
21
|
directory = parent;
|
|
15
22
|
}
|
|
16
23
|
return directory;
|
|
@@ -24,7 +31,11 @@ export async function loadInstalledMarwes(projectDirectory) {
|
|
|
24
31
|
const fromProject = createRequire(path.join(projectDirectory, "package.json"));
|
|
25
32
|
let componentEntry;
|
|
26
33
|
let componentPackage = "";
|
|
27
|
-
for (const candidate of [
|
|
34
|
+
for (const candidate of [
|
|
35
|
+
"react",
|
|
36
|
+
"vue",
|
|
37
|
+
"svelte",
|
|
38
|
+
]) {
|
|
28
39
|
try {
|
|
29
40
|
componentEntry = fromProject.resolve(`@marwes-ui/${candidate}`);
|
|
30
41
|
componentPackage = candidate;
|
|
@@ -34,8 +45,9 @@ export async function loadInstalledMarwes(projectDirectory) {
|
|
|
34
45
|
// try the next framework
|
|
35
46
|
}
|
|
36
47
|
}
|
|
37
|
-
if (!componentEntry)
|
|
48
|
+
if (!componentEntry) {
|
|
38
49
|
throw new MarwesError(`No @marwes-ui/react, vue or svelte is installed for ${projectDirectory}. Set "marwes.project" in penpair.config.json to the folder of the package that uses Marwes.`);
|
|
50
|
+
}
|
|
39
51
|
const fromComponent = createRequire(componentEntry);
|
|
40
52
|
let coreEntry;
|
|
41
53
|
try {
|
|
@@ -44,11 +56,14 @@ export async function loadInstalledMarwes(projectDirectory) {
|
|
|
44
56
|
catch {
|
|
45
57
|
throw new MarwesError(`@marwes-ui/${componentPackage} is installed but its @marwes-ui/core cannot be found; reinstall the dependencies.`);
|
|
46
58
|
}
|
|
47
|
-
const versions = {
|
|
59
|
+
const versions = {
|
|
60
|
+
[componentPackage]: versionOf(packageDirectory(componentEntry)),
|
|
61
|
+
};
|
|
48
62
|
versions.core = versionOf(packageDirectory(coreEntry));
|
|
49
63
|
for (const name of familyNames) {
|
|
50
|
-
if (versions[name])
|
|
64
|
+
if (versions[name]) {
|
|
51
65
|
continue;
|
|
66
|
+
}
|
|
52
67
|
try {
|
|
53
68
|
versions[name] = versionOf(packageDirectory(fromComponent.resolve(`@marwes-ui/${name}`)));
|
|
54
69
|
}
|
|
@@ -57,16 +72,34 @@ export async function loadInstalledMarwes(projectDirectory) {
|
|
|
57
72
|
}
|
|
58
73
|
}
|
|
59
74
|
const namespace = (await import(pathToFileURL(coreEntry).href));
|
|
60
|
-
const core = typeof namespace.resolveThemeInput === "function"
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
const core = typeof namespace.resolveThemeInput === "function"
|
|
76
|
+
? namespace
|
|
77
|
+
: namespace.default;
|
|
78
|
+
for (const name of [
|
|
79
|
+
"resolveThemeInput",
|
|
80
|
+
"themeToCSSVars",
|
|
81
|
+
]) {
|
|
82
|
+
if (typeof core?.[name] !== "function") {
|
|
63
83
|
throw new MarwesError(`@marwes-ui/core ${versions.core} does not export ${name}; this adapter needs a Marwes that does. Update @penpair/marwes-ui or check the Marwes version.`);
|
|
64
|
-
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!core.mwThemeVars?.spacing) {
|
|
65
87
|
throw new MarwesError(`@marwes-ui/core ${versions.core} does not export mwThemeVars.spacing; this adapter needs a Marwes that does.`);
|
|
66
|
-
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
core,
|
|
91
|
+
version: versions.core,
|
|
92
|
+
versions,
|
|
93
|
+
};
|
|
67
94
|
}
|
|
68
95
|
/** Marwes releases core, presets and the framework packages together; a mix means a half-finished upgrade. */
|
|
69
96
|
export function familyProblems(installed) {
|
|
70
97
|
const distinct = new Set(Object.values(installed.versions));
|
|
71
|
-
return distinct.size > 1
|
|
98
|
+
return distinct.size > 1
|
|
99
|
+
? [
|
|
100
|
+
`the installed Marwes packages are at different versions (${Object.entries(installed.versions)
|
|
101
|
+
.map(([name, version]) => `${name} ${version}`)
|
|
102
|
+
.join(", ")}); Marwes releases them together, so finish the upgrade`,
|
|
103
|
+
]
|
|
104
|
+
: [];
|
|
72
105
|
}
|