Skip to content

Commit b7bd0da

Browse files
authored
feat: allow extenstion from another preset
1 parent d688108 commit b7bd0da

File tree

5 files changed

+87
-26
lines changed

5 files changed

+87
-26
lines changed

assets/wds.png

10.7 KB
Loading

assets/wds.svg

Lines changed: 10 additions & 0 deletions
Loading

editor.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
<div class="editor">
1111
<div id="editor" class="editor__content"></div>
1212
<div class="editor__toolbar">
13-
<div class="logger flex-grow" id="output"></div>
1413
<input type="checkbox" data-action="autosave" />
1514
<button class="btn btn-primary" data-action="save">Save</button>
1615
<button class="btn btn-secondary" data-action="compile">Compile</button>
1716
</div>
17+
<div class="logger flex-grow" id="output"></div>
1818
</div>
1919
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.30.1/min/vs/loader.js"></script>
2020

@@ -41,6 +41,7 @@
4141
const editor = monaco.editor.create(document.getElementById("editor"), {
4242
value: source.ok ? await source.text() : "",
4343
language: "yaml",
44+
automaticLayout: true,
4445
});
4546

4647
const save = () =>

server/index.mjs

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,20 @@ async function savePreset(args, request, response) {
5353
const input = await readStream(request);
5454
const name = sanitise(args[0]);
5555

56-
if (name && input) {
56+
try {
57+
if (!(name && input)) {
58+
throw new Error("Missing name or input.\nPOST /update/:name");
59+
}
60+
61+
Yaml.parse(input);
5762
const inputPath = join(CWD, "systems", name + ".yml");
5863
await ensureFolder(dirname(inputPath));
5964
await writeFile(inputPath, input, "utf-8");
60-
console.log("Updated " + name);
61-
response.end(input);
62-
} else {
65+
response.end("OK");
66+
} catch (error) {
67+
console.log('Failed to update' + name, error);
6368
response.writeHead(400);
64-
response.end("Missing name or input.\nPOST /update/:name");
69+
response.end(String(error));
6570
}
6671
}
6772

@@ -91,15 +96,15 @@ async function getPreset(args, response) {
9196

9297
async function compilePreset(args, response) {
9398
const name = sanitise(args[0]);
94-
const path = join(CWD, "systems", name + ".yml");
99+
const preset = await loadPreset(name);
95100

96-
if (!existsSync(path)) {
101+
if (!preset) {
97102
return notFound(response);
98103
}
99104

100-
console.log("Generating " + name + " from " + path);
101-
const input = await readFile(path, "utf-8");
102-
const json = Yaml.parse(input);
105+
const start = Date.now();
106+
console.log("Generating " + name);
107+
const json = await loadChain(preset);
103108
const output = await generatePreset(json, response);
104109

105110
if (output.error) {
@@ -110,7 +115,6 @@ async function compilePreset(args, response) {
110115
}
111116

112117
const { config, definitions, map, css } = output;
113-
// TODO sanitize name
114118
const basePath = join(CWD, "presets", name);
115119
await writeFile(basePath + ".conf.cjs", config);
116120
await writeFile(basePath + ".mjs", definitions);
@@ -147,10 +151,51 @@ async function generate(request, response) {
147151
}
148152
}
149153

154+
/**
155+
* @param {String} name
156+
* @returns {Promise<object|null>} preset
157+
*/
158+
async function loadPreset(name) {
159+
const path = join(CWD, "systems", name + ".yml");
160+
161+
if (!existsSync(path)) {
162+
return null;
163+
}
164+
165+
const input = await readFile(path, "utf-8");
166+
return Yaml.parse(input);
167+
}
168+
169+
/**
170+
* @param {object} preset
171+
* @returns {Promise<object>} preset chain
172+
*/
173+
async function loadChain(preset) {
174+
if (!preset.extend) {
175+
return preset;
176+
}
177+
178+
const next = await loadPreset(preset.extend);
179+
preset.preset = [next, ...(preset.preset || [])].filter(Boolean);
180+
181+
if (next?.extend) {
182+
await loadChain(next);
183+
}
184+
185+
return preset;
186+
}
187+
188+
/**
189+
* @param {String} input
190+
*/
150191
function sanitise(input) {
151192
return String(input).replace(/[.]{2,}/g, ".");
152193
}
153194

195+
/**
196+
* @param {Object} input
197+
* @returns {Promise<String>}
198+
*/
154199
function readStream(input) {
155200
return new Promise((resolve) => {
156201
const chunks = [];

server/presets.mjs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,22 @@ import { defaultPlugins, allPlugins } from './constants.mjs';
77
const commentSeparator = '//';
88
const definitionSeparator = ':';
99

10-
const transformPlugins = (list) => list.flatMap(next => {
11-
if (next.endsWith('*')) {
12-
const stem = next.slice(0, -1);
13-
return allPlugins.filter(p => p.startsWith(stem));
14-
}
15-
16-
return next;
17-
});
10+
const transformPlugins = (list) =>
11+
!Array.isArray(list) ?
12+
[] :
13+
list.flatMap(next => {
14+
if (next.endsWith('*')) {
15+
const stem = next.slice(0, -1);
16+
return allPlugins.filter(p => p.startsWith(stem));
17+
}
18+
19+
return next;
20+
});
1821

1922
function transformText(input) {
20-
if (!input) return undefined;
23+
if (!input) {
24+
return undefined;
25+
}
2126

2227
const source =
2328
typeof input === 'string'
@@ -39,15 +44,14 @@ function transformText(input) {
3944
}
4045

4146
function parseDefinitions(definitions) {
42-
const { sizes, colors, spacing, devices, radius } = definitions;
47+
const { sizes, colors, spacing, devices } = definitions;
4348

4449
return {
4550
...definitions,
4651
sizes: transformText(sizes),
4752
colors: transformText(colors),
4853
spacing: transformText(spacing),
4954
devices: transformText(devices),
50-
borderRadius: transformText(radius),
5155
};
5256
}
5357

@@ -114,17 +118,19 @@ ${componentDefinitions}
114118
}
115119

116120
export function generateConfig(definitions) {
117-
const { borderRadius, colors, devices, spacing, plugins, extend = {} } = definitions;
121+
const { borderRadius, colors, devices, spacing, plugins, preset, variants = {}, theme = {} } = definitions;
118122

119123
return {
124+
...(Array.isArray(preset) && { preset: preset.map(generateConfig) } || {}),
120125
corePlugins: transformPlugins(plugins || defaultPlugins),
121126
theme: {
122127
screens: generateScreens(devices),
123128
colors: generateColors(colors),
124129
borderRadius,
125130
spacing,
126-
extend,
131+
...theme,
127132
},
133+
variants
128134
};
129135
}
130136

@@ -144,7 +150,6 @@ export async function generatePreset(definitions) {
144150
return {
145151
error: null,
146152
css: output.css,
147-
map: output.map?.toString() || '',
148153
config,
149154
definitions: json,
150155
};

0 commit comments

Comments
 (0)