check-rule-mate 0.5.8 → 0.5.9
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 +4 -4
- package/bin/commands/generate-docs-playground-experimental.js +639 -0
- package/bin/commands/generate-docs.js +435 -0
- package/bin/{verify-templates.js → commands/verify-templates.js} +8 -32
- package/bin/index.js +50 -0
- package/bin/utils/args.js +10 -0
- package/package.json +2 -4
- package/bin/generate-docs-playground-experimental.js +0 -637
- package/bin/generate-docs.js +0 -434
|
@@ -1,637 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* check-rule-mate — Auto Documentation Generator
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// import fs from "fs";
|
|
7
|
-
// import path from "path";
|
|
8
|
-
// import process from "process";
|
|
9
|
-
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const process = require('process');
|
|
13
|
-
let esbuild;
|
|
14
|
-
try {
|
|
15
|
-
esbuild = require('esbuild');
|
|
16
|
-
} catch {
|
|
17
|
-
console.warn(
|
|
18
|
-
'[check-rule-mate] esbuild not found. ' +
|
|
19
|
-
'Install it to enable playground generation.'
|
|
20
|
-
);
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* ---------------------------------------
|
|
25
|
-
* CLI ARGS
|
|
26
|
-
* -------------------------------------*/
|
|
27
|
-
const args = process.argv.slice(2);
|
|
28
|
-
const getArg = (flag) => {
|
|
29
|
-
const index = args.indexOf(flag);
|
|
30
|
-
return index !== -1 ? args[index + 1] : null;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const RULES_DIR = getArg('--rules');
|
|
34
|
-
const SCHEMAS_DIR = getArg('--schemas');
|
|
35
|
-
const ERRORS_DIR = getArg('--errors')
|
|
36
|
-
const OPTIONS_DIR = getArg('--options');
|
|
37
|
-
const OUTPUT = getArg('--out') || "check-rule-mate-docs.html";
|
|
38
|
-
const OUTPUT_DIR = path.dirname(OUTPUT);
|
|
39
|
-
|
|
40
|
-
const OPTIONS = OPTIONS_DIR ? JSON.parse(fs.readFileSync(OPTIONS_DIR, "utf-8")) : null;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (OPTIONS) {
|
|
44
|
-
let entryPointFile = Object.keys(OPTIONS.validators).map((key) => `var ${key} = require('${OPTIONS.validators[key]}')`).join('\n');
|
|
45
|
-
entryPointFile += `\n window.validatorHelpers = {${Object.keys(OPTIONS.validators).map((key) => `${key}: ${key}`)}}`
|
|
46
|
-
|
|
47
|
-
fs.writeFileSync(`./check-rule-mate.validators.docs.js`, entryPointFile);
|
|
48
|
-
|
|
49
|
-
esbuild.build({
|
|
50
|
-
entryPoints: ['./node_modules/check-rule-mate/src/main.js'],
|
|
51
|
-
bundle: true,
|
|
52
|
-
outfile: `${OUTPUT_DIR}/check-rule-mate.js`,
|
|
53
|
-
platform: 'browser',
|
|
54
|
-
target: 'node16',
|
|
55
|
-
format: 'iife',
|
|
56
|
-
minify: false
|
|
57
|
-
}).then(() => {
|
|
58
|
-
console.log('Build completed successfully: check-rule-mate.js');
|
|
59
|
-
|
|
60
|
-
const checkRuleMateFIle = fs.readFileSync(`${OUTPUT_DIR}/check-rule-mate.js`, 'utf-8');
|
|
61
|
-
const lines = checkRuleMateFIle.split('\n')
|
|
62
|
-
lines.shift();
|
|
63
|
-
lines.splice(lines.length - 2, 1)
|
|
64
|
-
fs.writeFileSync(`${OUTPUT_DIR}/check-rule-mate.js`, lines.join('\n'))
|
|
65
|
-
}).catch(() => process.exit(1));
|
|
66
|
-
|
|
67
|
-
esbuild.build({
|
|
68
|
-
entryPoints: [`./check-rule-mate.validators.docs.js`],
|
|
69
|
-
bundle: true,
|
|
70
|
-
outfile: `${OUTPUT_DIR}/index.js`,
|
|
71
|
-
platform: 'browser',
|
|
72
|
-
target: 'node16',
|
|
73
|
-
format: 'iife',
|
|
74
|
-
minify: false
|
|
75
|
-
}).then(() => {
|
|
76
|
-
console.log('Build completed successfully: index.js');
|
|
77
|
-
fs.rmSync('./check-rule-mate.validators.docs.js')
|
|
78
|
-
}).catch(() => process.exit(1));
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (!RULES_DIR || !SCHEMAS_DIR) {
|
|
83
|
-
console.error(`
|
|
84
|
-
Usage:
|
|
85
|
-
npx check-rule-mate-auto-docs --rules ./rules --schemas ./schemas --errors ./errors --out docs.html
|
|
86
|
-
`);
|
|
87
|
-
process.exit(1);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/* ---------------------------------------
|
|
91
|
-
* HELPERS
|
|
92
|
-
* -------------------------------------*/
|
|
93
|
-
const readJSONFiles = (dir) => {
|
|
94
|
-
return fs.readdirSync(dir)
|
|
95
|
-
.filter(f => f.endsWith(".json"))
|
|
96
|
-
.map(file => ({
|
|
97
|
-
name: file.replace(".json", ""),
|
|
98
|
-
content: JSON.parse(fs.readFileSync(path.join(dir, file), "utf-8"))
|
|
99
|
-
}));
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const rulesFiles = readJSONFiles(RULES_DIR);
|
|
103
|
-
const schemasFiles = readJSONFiles(SCHEMAS_DIR);
|
|
104
|
-
const errorsFiles = readJSONFiles(ERRORS_DIR);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
/* ---------------------------------------
|
|
108
|
-
* INDEX RELATIONSHIPS
|
|
109
|
-
* -------------------------------------*/
|
|
110
|
-
const ruleUsageMap = {};
|
|
111
|
-
const errorUsageMap = {}
|
|
112
|
-
|
|
113
|
-
schemasFiles.forEach(schemaFile => {
|
|
114
|
-
Object.entries(schemaFile.content).forEach(([field, config]) => {
|
|
115
|
-
const ruleName = config.rule.split("--")[0];
|
|
116
|
-
if (!ruleUsageMap[ruleName]) ruleUsageMap[ruleName] = [];
|
|
117
|
-
ruleUsageMap[ruleName].push({
|
|
118
|
-
schema: schemaFile.name,
|
|
119
|
-
field,
|
|
120
|
-
rule: config.rule
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
rulesFiles.forEach(rulesFile => {
|
|
126
|
-
Object.entries(rulesFile.content).forEach(([field, config]) => {
|
|
127
|
-
Object.entries(config.error).forEach(([key, value]) => {
|
|
128
|
-
const errorName = value;
|
|
129
|
-
if (!errorUsageMap[errorName]) errorUsageMap[errorName] = [];
|
|
130
|
-
errorUsageMap[errorName].push({
|
|
131
|
-
file: rulesFile.name,
|
|
132
|
-
field,
|
|
133
|
-
error: value
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
if (config?.modifier) {
|
|
137
|
-
Object.entries(config.modifier).forEach(([modifierKey, modifier]) => {
|
|
138
|
-
if (modifier?.error) {
|
|
139
|
-
Object.entries(modifier.error).forEach(([key, value]) => {
|
|
140
|
-
const errorName = value;
|
|
141
|
-
if (!errorUsageMap[errorName]) errorUsageMap[errorName] = [];
|
|
142
|
-
errorUsageMap[errorName].push({
|
|
143
|
-
file: rulesFile.name,
|
|
144
|
-
field,
|
|
145
|
-
error: value
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
/* ---------------------------------------
|
|
156
|
-
* HTML GENERATION
|
|
157
|
-
* -------------------------------------*/
|
|
158
|
-
const html = `
|
|
159
|
-
<!DOCTYPE html>
|
|
160
|
-
<html lang="en">
|
|
161
|
-
<head>
|
|
162
|
-
<meta charset="UTF-8" />
|
|
163
|
-
<title>check-rule-mate — Documentation</title>
|
|
164
|
-
<style>
|
|
165
|
-
${generateCSS()}
|
|
166
|
-
</style>
|
|
167
|
-
${OPTIONS ? `
|
|
168
|
-
<script src="./check-rule-mate.js" defer></script>
|
|
169
|
-
<script src="./index.js" defer></script>`
|
|
170
|
-
: ''}
|
|
171
|
-
</head>
|
|
172
|
-
<body>
|
|
173
|
-
|
|
174
|
-
<aside class="sidebar">
|
|
175
|
-
<input id="search" placeholder="Search..." />
|
|
176
|
-
|
|
177
|
-
<h3>Schemas</h3>
|
|
178
|
-
${schemasFiles.map(s => `
|
|
179
|
-
<a href="#schema-${s.name}">${s.name}</a>
|
|
180
|
-
`).join("")}
|
|
181
|
-
|
|
182
|
-
<h3>Rules</h3>
|
|
183
|
-
${rulesFiles.map(rf =>
|
|
184
|
-
Object.keys(rf.content).map(rule => `
|
|
185
|
-
<a href="#rule-${rule}">${rf.name} - ${rule}</a>
|
|
186
|
-
`).join("")
|
|
187
|
-
).join("")}
|
|
188
|
-
|
|
189
|
-
<h3>Errors</h3>
|
|
190
|
-
${errorsFiles.map(errorFile =>
|
|
191
|
-
Object.keys(errorFile.content).map(error => `
|
|
192
|
-
<a href="#error-${error}">${errorFile.name} - ${error}</a>
|
|
193
|
-
`).join("")
|
|
194
|
-
).join("")}
|
|
195
|
-
</aside>
|
|
196
|
-
|
|
197
|
-
<main>
|
|
198
|
-
<section>
|
|
199
|
-
<h1>check-rule-mate</h1>
|
|
200
|
-
<p class="muted">
|
|
201
|
-
Visual documentation of validation rules and schemas.
|
|
202
|
-
</p>
|
|
203
|
-
</section>
|
|
204
|
-
|
|
205
|
-
${renderSchemas(schemasFiles)}
|
|
206
|
-
${renderRules(rulesFiles, ruleUsageMap)}
|
|
207
|
-
${renderErrors(errorsFiles, errorUsageMap)}
|
|
208
|
-
</main>
|
|
209
|
-
|
|
210
|
-
<script>
|
|
211
|
-
${generateClientJS()}
|
|
212
|
-
</script>
|
|
213
|
-
|
|
214
|
-
</body>
|
|
215
|
-
</html>
|
|
216
|
-
`;
|
|
217
|
-
|
|
218
|
-
fs.writeFileSync(OUTPUT, html);
|
|
219
|
-
console.log(`✔ Documentation generated at ${OUTPUT}`);
|
|
220
|
-
|
|
221
|
-
/* ---------------------------------------
|
|
222
|
-
* RENDERERS
|
|
223
|
-
* -------------------------------------*/
|
|
224
|
-
function renderSchemas(schemas) {
|
|
225
|
-
return schemas.map(schema => `
|
|
226
|
-
<section id="schema-${schema.name}" class="card">
|
|
227
|
-
<h2>Schema: ${schema.name}</h2>
|
|
228
|
-
|
|
229
|
-
<table>
|
|
230
|
-
<thead>
|
|
231
|
-
<tr>
|
|
232
|
-
<th>Field</th>
|
|
233
|
-
<th>Rule</th>
|
|
234
|
-
<th class="text-center">Required</th>
|
|
235
|
-
<th class="text-center">Cache</th>
|
|
236
|
-
</tr>
|
|
237
|
-
</thead>
|
|
238
|
-
<tbody>
|
|
239
|
-
${Object.entries(schema.content).map(([field, cfg]) => `
|
|
240
|
-
<tr>
|
|
241
|
-
<td>${field}</td>
|
|
242
|
-
<td>
|
|
243
|
-
<a href="#rule-${cfg.rule.split("--")[0]}">
|
|
244
|
-
${cfg.rule}
|
|
245
|
-
</a>
|
|
246
|
-
</td>
|
|
247
|
-
<td class="text-center">${cfg.required ? "✔" : "optional"}</td>
|
|
248
|
-
<td class="text-center">${cfg.cache === false ? "off" : "✔"}</td>
|
|
249
|
-
</tr>
|
|
250
|
-
`).join("")}
|
|
251
|
-
</tbody>
|
|
252
|
-
</table>
|
|
253
|
-
${OPTIONS ? `
|
|
254
|
-
<details class="schema-test">
|
|
255
|
-
<summary>Schema Test (Experimental)</summary>
|
|
256
|
-
<div class="schema-test-container">
|
|
257
|
-
<form id="schema:${schema.name}" data-form="schema--${schema.name}">
|
|
258
|
-
${Object.entries(schema.content).map(([field, cfg]) => {
|
|
259
|
-
const attributesHTML = cfg.attributesHTML ? Object.keys(cfg.attributesHTML).map((key) => `${key}="${cfg?.attributesHTML[key]}"`).join(' ') : null
|
|
260
|
-
return `
|
|
261
|
-
<div style="display: flex; flex-direction: column;">
|
|
262
|
-
<label for="${field}">${field} (${cfg.rule})</label>
|
|
263
|
-
<input name="${field}" ${cfg.required ? 'required': ''} ${attributesHTML}/>
|
|
264
|
-
</div>
|
|
265
|
-
`}).join("")}
|
|
266
|
-
<div style="display: flex; flex-direction: column;">
|
|
267
|
-
<label for="check-rule-mate-validators">VALIDATORS</label>
|
|
268
|
-
<select name="check-rule-mate-validators" required>
|
|
269
|
-
${
|
|
270
|
-
OPTIONS?.validators ? Object.keys(OPTIONS.validators).map((key) => `
|
|
271
|
-
<option value=${key}>${key}</option>
|
|
272
|
-
`)
|
|
273
|
-
: ''
|
|
274
|
-
}
|
|
275
|
-
</select>
|
|
276
|
-
</div>
|
|
277
|
-
<div style="display: flex; flex-direction: column;">
|
|
278
|
-
<label for="check-rule-mate-rules">RULES</label>
|
|
279
|
-
<select name="check-rule-mate-rules" required>
|
|
280
|
-
${
|
|
281
|
-
rulesFiles ? rulesFiles.map((rulesFile) => `
|
|
282
|
-
<option value=${rulesFile.name}>${rulesFile.name}</option>
|
|
283
|
-
`)
|
|
284
|
-
: ''
|
|
285
|
-
}
|
|
286
|
-
</select>
|
|
287
|
-
</div>
|
|
288
|
-
<button type="submit">Validate Schema</button>
|
|
289
|
-
</form>
|
|
290
|
-
<div class="schema-test-result">
|
|
291
|
-
<span>Result:</span>
|
|
292
|
-
<textarea id="textarea-schema-${schema.name}" readonly></textarea>
|
|
293
|
-
</div>
|
|
294
|
-
</div>
|
|
295
|
-
</details>
|
|
296
|
-
` : ''}
|
|
297
|
-
</section>
|
|
298
|
-
`).join("");
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
function renderRules(rulesFiles, usageMap) {
|
|
302
|
-
return rulesFiles.map(file =>
|
|
303
|
-
Object.entries(file.content).map(([ruleName, rule]) => `
|
|
304
|
-
<section id="rule-${ruleName}" class="card">
|
|
305
|
-
<h2>Rule: ${ruleName} (${file.name})</h2>
|
|
306
|
-
${rule?.docs?.description ?
|
|
307
|
-
`<p>${rule.docs.description}</p>`
|
|
308
|
-
: ''}
|
|
309
|
-
|
|
310
|
-
<h3>Validation Flow</h3>
|
|
311
|
-
<div class="flow">
|
|
312
|
-
${rule.validate.map(v => `
|
|
313
|
-
<div class="flow-step">${v}</div>
|
|
314
|
-
<div class="flow-arrow">→</div>
|
|
315
|
-
`).join("")}
|
|
316
|
-
<div class="flow-step success">valid</div>
|
|
317
|
-
</div>
|
|
318
|
-
|
|
319
|
-
<h3>Error Codes</h3>
|
|
320
|
-
${renderRulesErrors(rule.error)}
|
|
321
|
-
|
|
322
|
-
${rule.modifier ? `
|
|
323
|
-
<h3>Modifiers</h3>
|
|
324
|
-
${Object.entries(rule.modifier).map(([mod, modRule]) => `
|
|
325
|
-
<div class="modifier">
|
|
326
|
-
<span class="tag modifier">${mod}</span>
|
|
327
|
-
${modRule?.docs?.description ? `<p>${modRule.docs.description}</p>` : ''}
|
|
328
|
-
|
|
329
|
-
<div class="flow">
|
|
330
|
-
${modRule.validate.map(v => `
|
|
331
|
-
<div class="flow-step">${v}</div>
|
|
332
|
-
<div class="flow-arrow">→</div>
|
|
333
|
-
`).join("")}
|
|
334
|
-
<div class="flow-step success">valid</div>
|
|
335
|
-
</div>
|
|
336
|
-
|
|
337
|
-
<h4>Error Codes</h4>
|
|
338
|
-
${renderRulesErrors(modRule.error)}
|
|
339
|
-
</div>
|
|
340
|
-
`).join("")}
|
|
341
|
-
` : ""}
|
|
342
|
-
|
|
343
|
-
<h3>Used by Schemas</h3>
|
|
344
|
-
<ul>
|
|
345
|
-
${(usageMap[ruleName] || []).map(u =>
|
|
346
|
-
`<li>${u.schema} → <strong>${u.field}</strong> (${u.rule})</li>`
|
|
347
|
-
).join("") || "<li>Not used</li>"}
|
|
348
|
-
</ul>
|
|
349
|
-
|
|
350
|
-
${rule?.docs?.notes ?
|
|
351
|
-
`
|
|
352
|
-
<h3>Notes</h3>
|
|
353
|
-
<div class="rule-notes">${rule?.docs?.notes}</div>
|
|
354
|
-
`
|
|
355
|
-
: ''}
|
|
356
|
-
</section>
|
|
357
|
-
`).join("")
|
|
358
|
-
).join("");
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function renderRulesErrors(errors = {}) {
|
|
362
|
-
return `
|
|
363
|
-
<ul>
|
|
364
|
-
${Object.entries(errors).map(([k, v]) =>
|
|
365
|
-
`<li><a href="#error-${v.split('.')[0]}" class="tag error">${k}</a> ${v}</li>`
|
|
366
|
-
).join("")}
|
|
367
|
-
</ul>
|
|
368
|
-
`;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
function renderErrors(errorFiles, usageMap) {
|
|
372
|
-
return errorFiles.map(file =>
|
|
373
|
-
Object.entries(file.content).map(([errorName, errors]) => `
|
|
374
|
-
<section id="error-${errorName}" class="card">
|
|
375
|
-
<h2>Error: ${errorName} (${file.name})</h2>
|
|
376
|
-
<ul>
|
|
377
|
-
${Object.entries(errors).map(([key, value]) => `
|
|
378
|
-
<li><span class="tag error">${key}</span> ${value} </li>
|
|
379
|
-
`).join('')}
|
|
380
|
-
</ul>
|
|
381
|
-
|
|
382
|
-
<h3>Used by Rules</h3>
|
|
383
|
-
<ul>
|
|
384
|
-
${Object.entries(errors).map(([key, value]) => `
|
|
385
|
-
${(usageMap[`${errorName}.${key}`] || []).map(u =>
|
|
386
|
-
`<li>${u.file} → <strong>${u.field}</strong> (${u.error})</li>`
|
|
387
|
-
).join("") || "<li>Not used</li>"}
|
|
388
|
-
`).join('')}
|
|
389
|
-
</ul>
|
|
390
|
-
</section>
|
|
391
|
-
`).join('')).join('');
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
/* ---------------------------------------
|
|
395
|
-
* CSS
|
|
396
|
-
* -------------------------------------*/
|
|
397
|
-
function generateCSS() {
|
|
398
|
-
return `
|
|
399
|
-
body {
|
|
400
|
-
margin: 0;
|
|
401
|
-
font-family: Inter, system-ui, sans-serif;
|
|
402
|
-
display: grid;
|
|
403
|
-
grid-template-columns: 280px 1fr;
|
|
404
|
-
background: #0f172a;
|
|
405
|
-
color: #e5e7eb;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.sidebar {
|
|
409
|
-
padding: 16px;
|
|
410
|
-
background: #020617;
|
|
411
|
-
overflow-y: auto;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
.sidebar input {
|
|
415
|
-
width: 100%;
|
|
416
|
-
padding: 8px;
|
|
417
|
-
border-radius: 6px;
|
|
418
|
-
border: none;
|
|
419
|
-
margin-bottom: 16px;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
.sidebar a {
|
|
423
|
-
display: block;
|
|
424
|
-
padding: 6px 10px;
|
|
425
|
-
color: #e5e7eb;
|
|
426
|
-
text-decoration: none;
|
|
427
|
-
border-radius: 6px;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
.sidebar a:hover {
|
|
431
|
-
background: rgba(56,189,248,0.2);
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
a {
|
|
435
|
-
color: #e5e7eb;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
main {
|
|
439
|
-
padding: 32px;
|
|
440
|
-
overflow-y: auto;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
.card {
|
|
444
|
-
background: #020617;
|
|
445
|
-
border-radius: 12px;
|
|
446
|
-
padding: 24px;
|
|
447
|
-
margin-bottom: 32px;
|
|
448
|
-
border: 1px solid rgba(255,255,255,0.05);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
.flow {
|
|
452
|
-
display: flex;
|
|
453
|
-
align-items: center;
|
|
454
|
-
gap: 12px;
|
|
455
|
-
flex-wrap: wrap;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
.flow-step {
|
|
459
|
-
padding: 10px 14px;
|
|
460
|
-
border-radius: 8px;
|
|
461
|
-
background: rgba(56,189,248,0.15);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
.flow-arrow {
|
|
465
|
-
opacity: 0.5;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
.success {
|
|
469
|
-
background: rgba(34,197,94,0.2);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
.tag {
|
|
473
|
-
padding: 4px 8px;
|
|
474
|
-
border-radius: 999px;
|
|
475
|
-
font-size: 14px;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
.tag.error {
|
|
479
|
-
display: inline-block;
|
|
480
|
-
margin-bottom: 8px;
|
|
481
|
-
background: rgba(239,68,68,0.2);
|
|
482
|
-
text-decoration: none;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
.tag.modifier {
|
|
486
|
-
display: inline-block;
|
|
487
|
-
font-size: 16px;
|
|
488
|
-
margin-bottom: 8px;
|
|
489
|
-
font-weight: 600;
|
|
490
|
-
background: rgba(167,139,250,0.2);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
table {
|
|
494
|
-
width: 100%;
|
|
495
|
-
border-collapse: collapse;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
td, th {
|
|
499
|
-
padding: 8px;
|
|
500
|
-
border-bottom: 1px solid rgba(255,255,255,0.05);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
th {
|
|
504
|
-
text-align: left;
|
|
505
|
-
border-bottom: 1px solid #f4f4f4;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
.rule-notes {
|
|
509
|
-
padding: 16px;
|
|
510
|
-
color: black;
|
|
511
|
-
background: #f4f4f4;
|
|
512
|
-
border-radius: 12px;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
.text-center {
|
|
516
|
-
text-align: center;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
.schema-test {
|
|
520
|
-
margin-top: 32px;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
.schema-test-container {
|
|
524
|
-
display: flex;
|
|
525
|
-
width: 100%;
|
|
526
|
-
margin: 32px 0 24px 0;
|
|
527
|
-
gap: 40px;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
.schema-test-container > * {
|
|
531
|
-
width: 100%;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
.schema-test-result span {
|
|
535
|
-
display: block;
|
|
536
|
-
font-size: 20px;
|
|
537
|
-
font-weight: 600;
|
|
538
|
-
margin-bottom: 16px;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
.schema-test-result textarea {
|
|
542
|
-
width: 100%;
|
|
543
|
-
height: 80%;
|
|
544
|
-
color: #f4f4f4;
|
|
545
|
-
background-color: #111111;
|
|
546
|
-
border: none;
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
button {
|
|
550
|
-
cursor: pointer;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
form button[type="submit"] {
|
|
554
|
-
width: 100%;
|
|
555
|
-
padding: 16px 24px;
|
|
556
|
-
min-width: 120px;
|
|
557
|
-
min-height: 48px;
|
|
558
|
-
margin-top: 16px;
|
|
559
|
-
font-size: 16px;
|
|
560
|
-
font-weight: 600;
|
|
561
|
-
color: #444444;
|
|
562
|
-
background-color: #eede91;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
label {
|
|
566
|
-
margin-bottom: 4px;
|
|
567
|
-
font-size: 16px;
|
|
568
|
-
color: #e5e7eb;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
.schema-test input,
|
|
572
|
-
.schema-test select {
|
|
573
|
-
min-height: 28px;
|
|
574
|
-
padding: 4px 8px 4px 8px;
|
|
575
|
-
margin-bottom: 16px;
|
|
576
|
-
font-size: 16px;
|
|
577
|
-
color: #e5e7eb;
|
|
578
|
-
background-color: transparent;
|
|
579
|
-
border: none;
|
|
580
|
-
border-bottom: 1px solid white;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
.schema-test select option {
|
|
584
|
-
background-color: #020617;
|
|
585
|
-
color: #e5e7eb;
|
|
586
|
-
}
|
|
587
|
-
`;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/* ---------------------------------------
|
|
591
|
-
* CLIENT JS
|
|
592
|
-
* -------------------------------------*/
|
|
593
|
-
function generateClientJS() {
|
|
594
|
-
return `
|
|
595
|
-
const search = document.getElementById("search");
|
|
596
|
-
search.addEventListener("input", e => {
|
|
597
|
-
const value = e.target.value.toLowerCase();
|
|
598
|
-
document.querySelectorAll("section.card").forEach(card => {
|
|
599
|
-
card.style.display = card.innerText.toLowerCase().includes(value)
|
|
600
|
-
? ""
|
|
601
|
-
: "none";
|
|
602
|
-
});
|
|
603
|
-
});
|
|
604
|
-
|
|
605
|
-
${OPTIONS ? `
|
|
606
|
-
setTimeout(() => {
|
|
607
|
-
const rulesFiles = ${JSON.stringify(rulesFiles)}
|
|
608
|
-
const schemasFiles = ${JSON.stringify(schemasFiles)}
|
|
609
|
-
|
|
610
|
-
const formElements = document.querySelectorAll('form[data-form]');
|
|
611
|
-
formElements.forEach((formElement) => {
|
|
612
|
-
formElement.addEventListener('submit', async (e) => {
|
|
613
|
-
e.preventDefault();
|
|
614
|
-
const inputElements = formElement.querySelectorAll('input, select');
|
|
615
|
-
const formName = formElement.dataset.form.split('--')[1];
|
|
616
|
-
const formData = {};
|
|
617
|
-
inputElements.forEach((inputElement) => {
|
|
618
|
-
formData[inputElement.name] = inputElement.value;
|
|
619
|
-
})
|
|
620
|
-
|
|
621
|
-
const validatorHelper = window.validatorHelpers[formData["check-rule-mate-validators"]][formData["check-rule-mate-validators"]];
|
|
622
|
-
|
|
623
|
-
const rules = rulesFiles.filter((rulesFile) => rulesFile.name === formData["check-rule-mate-rules"])[0].content;
|
|
624
|
-
const schema = schemasFiles.filter((schemaFile) => schemaFile.name === formName)[0].content;
|
|
625
|
-
|
|
626
|
-
const validator = createValidator(formData, {validationHelpers: validatorHelper, rules: rules, schema: schema, options: { propertiesMustMatch: false, abortEarly: false, cache: true}});
|
|
627
|
-
const result = await validator.validate();
|
|
628
|
-
console.log(formName, result);
|
|
629
|
-
|
|
630
|
-
const textAreaElement = document.querySelector('#textarea-schema-'+formName);
|
|
631
|
-
textAreaElement.value = JSON.stringify(result);
|
|
632
|
-
});
|
|
633
|
-
});
|
|
634
|
-
}, 1000);
|
|
635
|
-
`: ''}
|
|
636
|
-
`;
|
|
637
|
-
}
|