@luzzle/web.tools 0.0.69
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 +28 -0
- package/dist/src/browser.d.ts +1 -0
- package/dist/src/browser.js +2 -0
- package/dist/src/browser.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +19 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/assets/command.d.ts +30 -0
- package/dist/src/commands/assets/command.js +41 -0
- package/dist/src/commands/assets/command.js.map +1 -0
- package/dist/src/commands/assets/index.d.ts +4 -0
- package/dist/src/commands/assets/index.js +79 -0
- package/dist/src/commands/assets/index.js.map +1 -0
- package/dist/src/commands/assets/index.test.d.ts +1 -0
- package/dist/src/commands/assets/index.test.js +419 -0
- package/dist/src/commands/assets/index.test.js.map +1 -0
- package/dist/src/commands/assets/variants.d.ts +8 -0
- package/dist/src/commands/assets/variants.js +23 -0
- package/dist/src/commands/assets/variants.js.map +1 -0
- package/dist/src/commands/assets/variants.test.d.ts +1 -0
- package/dist/src/commands/assets/variants.test.js +48 -0
- package/dist/src/commands/assets/variants.test.js.map +1 -0
- package/dist/src/commands/config/command.d.ts +2 -0
- package/dist/src/commands/config/command.js +42 -0
- package/dist/src/commands/config/command.js.map +1 -0
- package/dist/src/commands/config/index.d.ts +3 -0
- package/dist/src/commands/config/index.js +37 -0
- package/dist/src/commands/config/index.js.map +1 -0
- package/dist/src/commands/config/index.test.d.ts +1 -0
- package/dist/src/commands/config/index.test.js +93 -0
- package/dist/src/commands/config/index.test.js.map +1 -0
- package/dist/src/commands/opengraph/browser.d.ts +3 -0
- package/dist/src/commands/opengraph/browser.js +23 -0
- package/dist/src/commands/opengraph/browser.js.map +1 -0
- package/dist/src/commands/opengraph/browser.test.d.ts +1 -0
- package/dist/src/commands/opengraph/browser.test.js +30 -0
- package/dist/src/commands/opengraph/browser.test.js.map +1 -0
- package/dist/src/commands/opengraph/command.d.ts +30 -0
- package/dist/src/commands/opengraph/command.js +41 -0
- package/dist/src/commands/opengraph/command.js.map +1 -0
- package/dist/src/commands/opengraph/command.test.d.ts +1 -0
- package/dist/src/commands/opengraph/command.test.js +68 -0
- package/dist/src/commands/opengraph/command.test.js.map +1 -0
- package/dist/src/commands/opengraph/html.d.ts +4 -0
- package/dist/src/commands/opengraph/html.js +47 -0
- package/dist/src/commands/opengraph/html.js.map +1 -0
- package/dist/src/commands/opengraph/html.test.d.ts +1 -0
- package/dist/src/commands/opengraph/html.test.js +79 -0
- package/dist/src/commands/opengraph/html.test.js.map +1 -0
- package/dist/src/commands/opengraph/index.d.ts +4 -0
- package/dist/src/commands/opengraph/index.js +47 -0
- package/dist/src/commands/opengraph/index.js.map +1 -0
- package/dist/src/commands/opengraph/index.test.d.ts +1 -0
- package/dist/src/commands/opengraph/index.test.js +162 -0
- package/dist/src/commands/opengraph/index.test.js.map +1 -0
- package/dist/src/commands/opengraph/png.d.ts +3 -0
- package/dist/src/commands/opengraph/png.js +26 -0
- package/dist/src/commands/opengraph/png.js.map +1 -0
- package/dist/src/commands/opengraph/png.test.d.ts +1 -0
- package/dist/src/commands/opengraph/png.test.js +50 -0
- package/dist/src/commands/opengraph/png.test.js.map +1 -0
- package/dist/src/commands/opengraph/svelte.d.ts +7 -0
- package/dist/src/commands/opengraph/svelte.js +77 -0
- package/dist/src/commands/opengraph/svelte.js.map +1 -0
- package/dist/src/commands/opengraph/svelte.test.d.ts +1 -0
- package/dist/src/commands/opengraph/svelte.test.js +189 -0
- package/dist/src/commands/opengraph/svelte.test.js.map +1 -0
- package/dist/src/commands/opengraph/utils.d.ts +8 -0
- package/dist/src/commands/opengraph/utils.js +136 -0
- package/dist/src/commands/opengraph/utils.js.map +1 -0
- package/dist/src/commands/opengraph/utils.test.d.ts +1 -0
- package/dist/src/commands/opengraph/utils.test.js +215 -0
- package/dist/src/commands/opengraph/utils.test.js.map +1 -0
- package/dist/src/commands/sqlite/command.d.ts +8 -0
- package/dist/src/commands/sqlite/command.js +16 -0
- package/dist/src/commands/sqlite/command.js.map +1 -0
- package/dist/src/commands/sqlite/command.test.d.ts +1 -0
- package/dist/src/commands/sqlite/command.test.js +42 -0
- package/dist/src/commands/sqlite/command.test.js.map +1 -0
- package/dist/src/commands/sqlite/database.d.ts +9 -0
- package/dist/src/commands/sqlite/database.js +174 -0
- package/dist/src/commands/sqlite/database.js.map +1 -0
- package/dist/src/commands/sqlite/database.mock.d.ts +24 -0
- package/dist/src/commands/sqlite/database.mock.js +58 -0
- package/dist/src/commands/sqlite/database.mock.js.map +1 -0
- package/dist/src/commands/sqlite/database.test.d.ts +1 -0
- package/dist/src/commands/sqlite/database.test.js +211 -0
- package/dist/src/commands/sqlite/database.test.js.map +1 -0
- package/dist/src/commands/sqlite/index.d.ts +1 -0
- package/dist/src/commands/sqlite/index.js +26 -0
- package/dist/src/commands/sqlite/index.js.map +1 -0
- package/dist/src/commands/sqlite/index.test.d.ts +1 -0
- package/dist/src/commands/sqlite/index.test.js +48 -0
- package/dist/src/commands/sqlite/index.test.js.map +1 -0
- package/dist/src/commands/theme/command.d.ts +13 -0
- package/dist/src/commands/theme/command.js +21 -0
- package/dist/src/commands/theme/command.js.map +1 -0
- package/dist/src/commands/theme/command.test.d.ts +1 -0
- package/dist/src/commands/theme/command.test.js +40 -0
- package/dist/src/commands/theme/command.test.js.map +1 -0
- package/dist/src/commands/theme/index.d.ts +1 -0
- package/dist/src/commands/theme/index.js +9 -0
- package/dist/src/commands/theme/index.js.map +1 -0
- package/dist/src/commands/theme/index.test.d.ts +1 -0
- package/dist/src/commands/theme/index.test.js +46 -0
- package/dist/src/commands/theme/index.test.js.map +1 -0
- package/dist/src/commands/theme/theme.d.ts +4 -0
- package/dist/src/commands/theme/theme.js +76 -0
- package/dist/src/commands/theme/theme.js.map +1 -0
- package/dist/src/commands/theme/theme.test.d.ts +1 -0
- package/dist/src/commands/theme/theme.test.js +54 -0
- package/dist/src/commands/theme/theme.test.js.map +1 -0
- package/dist/src/lib/browser.d.ts +55 -0
- package/dist/src/lib/browser.js +52 -0
- package/dist/src/lib/browser.js.map +1 -0
- package/dist/src/lib/browser.test.d.ts +1 -0
- package/dist/src/lib/browser.test.js +67 -0
- package/dist/src/lib/browser.test.js.map +1 -0
- package/dist/src/lib/config/config.d.ts +9 -0
- package/dist/src/lib/config/config.js +56 -0
- package/dist/src/lib/config/config.js.map +1 -0
- package/dist/src/lib/config/config.test.d.ts +1 -0
- package/dist/src/lib/config/config.test.js +71 -0
- package/dist/src/lib/config/config.test.js.map +1 -0
- package/dist/src/lib/config/config.test.ts +88 -0
- package/dist/src/lib/config/config.ts +74 -0
- package/dist/src/lib/config/defaults.json +145 -0
- package/dist/src/lib/config/defaults.yaml +151 -0
- package/dist/src/lib/config/schema.d.ts +172 -0
- package/dist/src/lib/config/schema.js +8 -0
- package/dist/src/lib/config/schema.js.map +1 -0
- package/dist/src/lib/config/schema.json +663 -0
- package/dist/src/lib/config/schema.ts +294 -0
- package/dist/src/lib/config/user-error.config.yaml +2 -0
- package/dist/src/lib/config/user.config.yaml +2 -0
- package/dist/src/lib/deep-merge.d.ts +1 -0
- package/dist/src/lib/deep-merge.js +27 -0
- package/dist/src/lib/deep-merge.js.map +1 -0
- package/dist/src/lib/deep-merge.test.d.ts +1 -0
- package/dist/src/lib/deep-merge.test.js +29 -0
- package/dist/src/lib/deep-merge.test.js.map +1 -0
- package/dist/src/lib/lastRun.d.ts +4 -0
- package/dist/src/lib/lastRun.js +23 -0
- package/dist/src/lib/lastRun.js.map +1 -0
- package/dist/src/lib/lastRun.test.d.ts +1 -0
- package/dist/src/lib/lastRun.test.js +47 -0
- package/dist/src/lib/lastRun.test.js.map +1 -0
- package/dist/src/lib/vibrant.d.ts +21 -0
- package/dist/src/lib/vibrant.js +78 -0
- package/dist/src/lib/vibrant.js.map +1 -0
- package/dist/src/lib/vibrant.test.d.ts +1 -0
- package/dist/src/lib/vibrant.test.js +164 -0
- package/dist/src/lib/vibrant.test.js.map +1 -0
- package/dist/src/sdk.d.ts +4 -0
- package/dist/src/sdk.js +4 -0
- package/dist/src/sdk.js.map +1 -0
- package/dist/src/types.d.ts +2 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { loadConfig, getConfigValue, setConfigValue } from './config.js';
|
|
3
|
+
describe('lib/config/config', () => {
|
|
4
|
+
test('should validate default config against schema', async () => {
|
|
5
|
+
try {
|
|
6
|
+
const config = loadConfig();
|
|
7
|
+
expect(config).toBeDefined();
|
|
8
|
+
}
|
|
9
|
+
catch (e) {
|
|
10
|
+
if (e) {
|
|
11
|
+
expect(e).toBeUndefined();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
test('should load a user config', () => {
|
|
16
|
+
const config = loadConfig(`${import.meta.dirname}/user.config.yaml`);
|
|
17
|
+
expect(config).toBeDefined();
|
|
18
|
+
});
|
|
19
|
+
test('should load a user config', () => {
|
|
20
|
+
const config = loadConfig(`${import.meta.dirname}/not.user.config.yaml`);
|
|
21
|
+
expect(config).toBeDefined();
|
|
22
|
+
});
|
|
23
|
+
test('should throw an error if config validation fails with user config', () => {
|
|
24
|
+
expect(() => loadConfig(`${import.meta.dirname}/user-error.config.yaml`)).toThrow('Configuration validation failed');
|
|
25
|
+
});
|
|
26
|
+
describe('getConfigValue', () => {
|
|
27
|
+
test('should return the correct value for a given path', () => {
|
|
28
|
+
const config = {
|
|
29
|
+
a: {
|
|
30
|
+
b: {
|
|
31
|
+
c: 'value'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const value = getConfigValue(config, 'a.b.c');
|
|
36
|
+
expect(value).toBe('value');
|
|
37
|
+
});
|
|
38
|
+
test('should return undefined for a non-existent path', () => {
|
|
39
|
+
const config = {
|
|
40
|
+
a: {
|
|
41
|
+
b: {
|
|
42
|
+
c: 'value'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const value = getConfigValue(config, 'a.b.d');
|
|
47
|
+
expect(value).toBeUndefined();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('setConfigValue', () => {
|
|
51
|
+
test('should correctly set a value at a given path', () => {
|
|
52
|
+
const config = {
|
|
53
|
+
a: {
|
|
54
|
+
b: {
|
|
55
|
+
c: 'value'
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
setConfigValue(config, 'a.b.c', 'new-value');
|
|
60
|
+
expect(config.a.b.c).toBe('new-value');
|
|
61
|
+
});
|
|
62
|
+
test('should create intermediate objects if they don\'t exist', () => {
|
|
63
|
+
const config = {
|
|
64
|
+
a: {}
|
|
65
|
+
};
|
|
66
|
+
setConfigValue(config, 'a.b.c', 'value');
|
|
67
|
+
expect(config.a.b.c).toBe('value');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../../../src/lib/config/config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import { loadConfig, getConfigValue, setConfigValue, Config } from './config.js'
|
|
3
|
+
|
|
4
|
+
interface TestConfig extends Config {
|
|
5
|
+
a: {
|
|
6
|
+
b: {
|
|
7
|
+
c: string
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
describe('lib/config/config', () => {
|
|
13
|
+
test('should validate default config against schema', async () => {
|
|
14
|
+
try {
|
|
15
|
+
const config = loadConfig()
|
|
16
|
+
expect(config).toBeDefined()
|
|
17
|
+
} catch (e) {
|
|
18
|
+
if (e) {
|
|
19
|
+
expect(e).toBeUndefined()
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('should load a user config', () => {
|
|
25
|
+
const config = loadConfig(`${import.meta.dirname}/user.config.yaml`)
|
|
26
|
+
expect(config).toBeDefined()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('should load a user config', () => {
|
|
30
|
+
const config = loadConfig(`${import.meta.dirname}/not.user.config.yaml`)
|
|
31
|
+
expect(config).toBeDefined()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('should throw an error if config validation fails with user config', () => {
|
|
35
|
+
expect(() => loadConfig(`${import.meta.dirname}/user-error.config.yaml`)).toThrow(
|
|
36
|
+
'Configuration validation failed'
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
describe('getConfigValue', () => {
|
|
41
|
+
test('should return the correct value for a given path', () => {
|
|
42
|
+
const config = {
|
|
43
|
+
a: {
|
|
44
|
+
b: {
|
|
45
|
+
c: 'value'
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} as unknown as TestConfig
|
|
49
|
+
const value = getConfigValue(config, 'a.b.c')
|
|
50
|
+
expect(value).toBe('value')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('should return undefined for a non-existent path', () => {
|
|
54
|
+
const config = {
|
|
55
|
+
a: {
|
|
56
|
+
b: {
|
|
57
|
+
c: 'value'
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} as unknown as TestConfig
|
|
61
|
+
const value = getConfigValue(config, 'a.b.d')
|
|
62
|
+
expect(value).toBeUndefined()
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
describe('setConfigValue', () => {
|
|
67
|
+
test('should correctly set a value at a given path', () => {
|
|
68
|
+
const config = {
|
|
69
|
+
a: {
|
|
70
|
+
b: {
|
|
71
|
+
c: 'value'
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} as unknown as TestConfig
|
|
75
|
+
setConfigValue(config, 'a.b.c', 'new-value')
|
|
76
|
+
expect(config.a.b.c).toBe('new-value')
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('should create intermediate objects if they don\'t exist', () => {
|
|
80
|
+
const config = {
|
|
81
|
+
a: {}
|
|
82
|
+
} as unknown as TestConfig
|
|
83
|
+
setConfigValue(config, 'a.b.c', 'value')
|
|
84
|
+
expect(config.a.b.c).toBe('value')
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'fs'
|
|
2
|
+
import { parse as yamlParse } from 'yaml'
|
|
3
|
+
import { Ajv } from 'ajv'
|
|
4
|
+
import { deepMerge } from '../deep-merge.js'
|
|
5
|
+
import { type Schema as Config } from './schema.js'
|
|
6
|
+
import defaults from './defaults.json' with { type: 'json' }
|
|
7
|
+
import schemaJson from './schema.json' with { type: 'json' }
|
|
8
|
+
|
|
9
|
+
export type ConfigPublic = {
|
|
10
|
+
url: Pick<Config['url'], 'app' | 'luzzle_assets' | 'app_assets'>
|
|
11
|
+
text: Config['text']
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function loadConfig(userConfigPath?: string): Config {
|
|
15
|
+
const schema = schemaJson
|
|
16
|
+
const config = defaults as Config
|
|
17
|
+
const ajv = new Ajv()
|
|
18
|
+
const validate = ajv.compile(schema)
|
|
19
|
+
|
|
20
|
+
config.paths.config = userConfigPath
|
|
21
|
+
|
|
22
|
+
if (userConfigPath) {
|
|
23
|
+
if (existsSync(userConfigPath)) {
|
|
24
|
+
const userConfig = yamlParse(readFileSync(userConfigPath, 'utf8')) as Partial<Config>
|
|
25
|
+
const mergedConfig = deepMerge(config, userConfig) as Config
|
|
26
|
+
|
|
27
|
+
if (!validate(mergedConfig)) {
|
|
28
|
+
throw new Error(`Configuration validation failed: ${ajv.errorsText(validate.errors)}`)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return mergedConfig
|
|
32
|
+
} else {
|
|
33
|
+
/* v8 ignore start */
|
|
34
|
+
console.warn(`User config file not found at: ${userConfigPath}`)
|
|
35
|
+
/* v8 ignore stop */
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* v8 ignore start */
|
|
40
|
+
if (!validate(config)) {
|
|
41
|
+
throw new Error(`Configuration validation failed: ${ajv.errorsText(validate.errors)}`)
|
|
42
|
+
}
|
|
43
|
+
/* v8 ignore stop */
|
|
44
|
+
|
|
45
|
+
return config
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getConfigValue(obj: Config, path: string): unknown {
|
|
49
|
+
return path.split('.').reduce(
|
|
50
|
+
(acc, key) => {
|
|
51
|
+
if (acc && typeof acc === 'object' && key in acc) {
|
|
52
|
+
return acc[key] as Record<string, unknown>
|
|
53
|
+
}
|
|
54
|
+
return undefined
|
|
55
|
+
},
|
|
56
|
+
obj as unknown as undefined | Record<string, unknown>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function setConfigValue(obj: Config, path: string, value: unknown): void {
|
|
61
|
+
const keys = path.split('.')
|
|
62
|
+
const lastKey = keys.pop()!
|
|
63
|
+
let current: Record<string, unknown> = obj as unknown as Record<string, unknown>
|
|
64
|
+
|
|
65
|
+
for (const key of keys) {
|
|
66
|
+
if (typeof current[key] !== 'object' || current[key] === null) {
|
|
67
|
+
current[key] = {}
|
|
68
|
+
}
|
|
69
|
+
current = current[key] as Record<string, unknown>
|
|
70
|
+
}
|
|
71
|
+
current[lastKey] = value
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { loadConfig, getConfigValue, setConfigValue, type Config }
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
{
|
|
2
|
+
"url": {
|
|
3
|
+
"app": "",
|
|
4
|
+
"app_assets": "",
|
|
5
|
+
"luzzle_assets": "",
|
|
6
|
+
"editor": "http://editor.localhost"
|
|
7
|
+
},
|
|
8
|
+
"text": {
|
|
9
|
+
"title": "Luzzle Explorer",
|
|
10
|
+
"description": "A Luzzle Explorer instance"
|
|
11
|
+
},
|
|
12
|
+
"paths": {
|
|
13
|
+
"database": "./data/luzzle.sqlite"
|
|
14
|
+
},
|
|
15
|
+
"pieces": [],
|
|
16
|
+
"theme": {
|
|
17
|
+
"globals": {
|
|
18
|
+
"shadow-raised": "0px 3px 1px -2px rgba(251 241 199 / 20%), 0px 2px 2px 0px rgba(251 241 199 / 14%), 0px 1px 5px 0px rgba(0 0 0 / 12%)",
|
|
19
|
+
"font-sans-name": "\"Noto Sans\"",
|
|
20
|
+
"font-mono-name": "\"monaco, monospace\"",
|
|
21
|
+
"font-sans-url": "\"/fonts/noto-sans.woff2\"",
|
|
22
|
+
"font-sans-weight": "300 600",
|
|
23
|
+
"font-size-xxs": "0.7rem",
|
|
24
|
+
"font-size-xs": "0.825rem",
|
|
25
|
+
"font-size-small": "1rem",
|
|
26
|
+
"font-size-normal": "1.25rem",
|
|
27
|
+
"font-size-medium": "1.5rem",
|
|
28
|
+
"font-size-large": "1.75rem",
|
|
29
|
+
"font-size-xl": "2rem",
|
|
30
|
+
"font-size-xxl": "2.25rem",
|
|
31
|
+
"font-size-mobile-responsive-factor": 0.8,
|
|
32
|
+
"font-size-root": 22,
|
|
33
|
+
"font-weight-light": 300,
|
|
34
|
+
"font-weight-normal": 400,
|
|
35
|
+
"font-weight-medium": 500,
|
|
36
|
+
"font-weight-semibold": 550,
|
|
37
|
+
"font-weight-bold": 600,
|
|
38
|
+
"radius-none": "0",
|
|
39
|
+
"radius-small": "0.25rem",
|
|
40
|
+
"radius-medium": "0.375rem",
|
|
41
|
+
"radius-large": "0.5rem",
|
|
42
|
+
"radius-xl": "0.75rem",
|
|
43
|
+
"radius-x2l": "1rem",
|
|
44
|
+
"radius-x3l": "1.5rem",
|
|
45
|
+
"radius-x4l": "2.5rem",
|
|
46
|
+
"radius-full": "9999px",
|
|
47
|
+
"breakpoint-phone": 640,
|
|
48
|
+
"breakpoint-tablet": 768,
|
|
49
|
+
"breakpoint-laptop": 1024,
|
|
50
|
+
"breakpoint-desktop": 1280,
|
|
51
|
+
"space-1": "0.25rem",
|
|
52
|
+
"space-2": "0.5rem",
|
|
53
|
+
"space-3": "0.75rem",
|
|
54
|
+
"space-4": "1rem",
|
|
55
|
+
"space-5": "1.25rem",
|
|
56
|
+
"space-6": "1.5rem",
|
|
57
|
+
"space-7": "1.75rem",
|
|
58
|
+
"space-8": "2rem",
|
|
59
|
+
"space-9": "2.25rem",
|
|
60
|
+
"space-10": "2.5rem",
|
|
61
|
+
"space-0-5": "0.125rem",
|
|
62
|
+
"space-1-5": "0.375rem",
|
|
63
|
+
"space-2-5": "0.625rem",
|
|
64
|
+
"space-3-5": "0.875rem"
|
|
65
|
+
},
|
|
66
|
+
"dark": {
|
|
67
|
+
"color-primary": "#3b82f6",
|
|
68
|
+
"color-on-primary": "#ffffff",
|
|
69
|
+
"color-primary-container": "#0d6efd",
|
|
70
|
+
"color-on-primary-container": "#cfe2ff",
|
|
71
|
+
"color-secondary": "#adb5bd",
|
|
72
|
+
"color-on-secondary": "#212529",
|
|
73
|
+
"color-secondary-container": "#495057",
|
|
74
|
+
"color-on-secondary-container": "#d3d3d4",
|
|
75
|
+
"color-tertiary": "#adb5bd",
|
|
76
|
+
"color-on-tertiary": "#212529",
|
|
77
|
+
"color-tertiary-container": "#495057",
|
|
78
|
+
"color-on-tertiary-container": "#d3d3d4",
|
|
79
|
+
"color-error": "#f87171",
|
|
80
|
+
"color-on-error": "#4f0b0b",
|
|
81
|
+
"color-error-container": "#dc3545",
|
|
82
|
+
"color-on-error-container": "#f8d7da",
|
|
83
|
+
"color-surface": "#121212",
|
|
84
|
+
"color-surface-dim": "#1f1f1f",
|
|
85
|
+
"color-surface-bright": "#333333",
|
|
86
|
+
"color-surface-inverse": "#e9ecef",
|
|
87
|
+
"color-on-surface": "#e9ecef",
|
|
88
|
+
"color-on-surface-variant": "#adb5bd",
|
|
89
|
+
"color-on-surface-inverse": "#121212",
|
|
90
|
+
"color-surface-container-lowest": "#1f1f1f",
|
|
91
|
+
"color-surface-container-low": "#333333",
|
|
92
|
+
"color-surface-container": "#4f4f4f",
|
|
93
|
+
"color-surface-container-high": "#666666",
|
|
94
|
+
"color-surface-container-highest": "#7f7f7f",
|
|
95
|
+
"color-shadow": "hsla(0, 0%, 0%, 0.5)",
|
|
96
|
+
"color-outline": "#6c757d",
|
|
97
|
+
"color-outline-variant": "#495057"
|
|
98
|
+
},
|
|
99
|
+
"light": {
|
|
100
|
+
"color-primary": "#0d6efd",
|
|
101
|
+
"color-on-primary": "#ffffff",
|
|
102
|
+
"color-primary-container": "#cfe2ff",
|
|
103
|
+
"color-on-primary-container": "#084298",
|
|
104
|
+
"color-secondary": "#6c757d",
|
|
105
|
+
"color-on-secondary": "#ffffff",
|
|
106
|
+
"color-secondary-container": "#d3d3d4",
|
|
107
|
+
"color-on-secondary-container": "#41464b",
|
|
108
|
+
"color-tertiary": "#6c757d",
|
|
109
|
+
"color-on-tertiary": "#ffffff",
|
|
110
|
+
"color-tertiary-container": "#d3d3d4",
|
|
111
|
+
"color-on-tertiary-container": "#41464b",
|
|
112
|
+
"color-error": "#dc3545",
|
|
113
|
+
"color-on-error": "#ffffff",
|
|
114
|
+
"color-error-container": "#f8d7da",
|
|
115
|
+
"color-on-error-container": "#842029",
|
|
116
|
+
"color-surface": "#f8f9fa",
|
|
117
|
+
"color-surface-dim": "#e9ecef",
|
|
118
|
+
"color-surface-bright": "#ffffff",
|
|
119
|
+
"color-surface-inverse": "#212529",
|
|
120
|
+
"color-on-surface": "#212529",
|
|
121
|
+
"color-on-surface-variant": "#495057",
|
|
122
|
+
"color-on-surface-inverse": "#f8f9fa",
|
|
123
|
+
"color-surface-container-lowest": "#ffffff",
|
|
124
|
+
"color-surface-container-low": "#e9ecef",
|
|
125
|
+
"color-surface-container": "#dee2e6",
|
|
126
|
+
"color-surface-container-high": "#ced4da",
|
|
127
|
+
"color-surface-container-highest": "#adb5bd",
|
|
128
|
+
"color-shadow": "hsla(0, 0%, 0%, 0.15)",
|
|
129
|
+
"color-outline": "#6c757d",
|
|
130
|
+
"color-outline-variant": "#ced4da"
|
|
131
|
+
},
|
|
132
|
+
"markdown": {
|
|
133
|
+
"code": {
|
|
134
|
+
"light": "github-light",
|
|
135
|
+
"dark": "github-dark"
|
|
136
|
+
},
|
|
137
|
+
"sidenote": {
|
|
138
|
+
"sidenote-callout-before-content": "\"[ \"",
|
|
139
|
+
"sidenote-callout-after-content": "\" ]\"",
|
|
140
|
+
"sidenote-citation-before-content": "\"\"",
|
|
141
|
+
"sidenote-citation-after-content": "\":\""
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Default configuration for Luzzle Web Explorer.
|
|
2
|
+
# These values can be overridden by a user-provided config.yaml
|
|
3
|
+
# or by environment variables.
|
|
4
|
+
|
|
5
|
+
# Defines the key URLs required for the application to function correctly.
|
|
6
|
+
url:
|
|
7
|
+
# The primary, public-facing URL of this Luzzle Explorer instance.
|
|
8
|
+
app: ''
|
|
9
|
+
|
|
10
|
+
# The base URL for _app assets hosted on a separate CDN or file server.
|
|
11
|
+
app_assets: ''
|
|
12
|
+
|
|
13
|
+
# The base URL for assets hosted on a separate CDN or file server.
|
|
14
|
+
luzzle_assets: ''
|
|
15
|
+
|
|
16
|
+
# The URL for the Luzzle Editor instance, used for edit links.
|
|
17
|
+
editor: 'http://editor.localhost'
|
|
18
|
+
|
|
19
|
+
# general app text strings
|
|
20
|
+
text:
|
|
21
|
+
title: 'Luzzle Explorer'
|
|
22
|
+
description: 'A Luzzle Explorer instance'
|
|
23
|
+
|
|
24
|
+
paths:
|
|
25
|
+
# The connection URL for the database.
|
|
26
|
+
database: './data/luzzle.sqlite'
|
|
27
|
+
|
|
28
|
+
pieces: []
|
|
29
|
+
|
|
30
|
+
theme:
|
|
31
|
+
globals:
|
|
32
|
+
shadow-raised: '0px 3px 1px -2px rgba(251 241 199 / 20%), 0px 2px 2px 0px rgba(251 241 199 / 14%), 0px 1px 5px 0px rgba(0 0 0 / 12%)'
|
|
33
|
+
font-sans-name: '"Noto Sans"'
|
|
34
|
+
font-mono-name: '"monaco, monospace"'
|
|
35
|
+
font-sans-url: '"/fonts/noto-sans.woff2"'
|
|
36
|
+
font-sans-weight: '300 600'
|
|
37
|
+
font-size-xxs: '0.7rem'
|
|
38
|
+
font-size-xs: '0.825rem'
|
|
39
|
+
font-size-small: '1rem'
|
|
40
|
+
font-size-normal: '1.25rem'
|
|
41
|
+
font-size-medium: '1.5rem'
|
|
42
|
+
font-size-large: '1.75rem'
|
|
43
|
+
font-size-xl: '2rem'
|
|
44
|
+
font-size-xxl: '2.25rem'
|
|
45
|
+
font-size-mobile-responsive-factor: 0.8
|
|
46
|
+
font-size-root: 22
|
|
47
|
+
font-weight-light: 300
|
|
48
|
+
font-weight-normal: 400
|
|
49
|
+
font-weight-medium: 500
|
|
50
|
+
font-weight-semibold: 550
|
|
51
|
+
font-weight-bold: 600
|
|
52
|
+
radius-none: '0'
|
|
53
|
+
radius-small: '0.25rem'
|
|
54
|
+
radius-medium: '0.375rem'
|
|
55
|
+
radius-large: '0.5rem'
|
|
56
|
+
radius-xl: '0.75rem'
|
|
57
|
+
radius-x2l: '1rem'
|
|
58
|
+
radius-x3l: '1.5rem'
|
|
59
|
+
radius-x4l: '2.5rem'
|
|
60
|
+
radius-full: '9999px'
|
|
61
|
+
breakpoint-phone: 640
|
|
62
|
+
breakpoint-tablet: 768
|
|
63
|
+
breakpoint-laptop: 1024
|
|
64
|
+
breakpoint-desktop: 1280
|
|
65
|
+
space-1: '0.25rem'
|
|
66
|
+
space-2: '0.5rem'
|
|
67
|
+
space-3: '0.75rem'
|
|
68
|
+
space-4: '1rem'
|
|
69
|
+
space-5: '1.25rem'
|
|
70
|
+
space-6: '1.5rem'
|
|
71
|
+
space-7: '1.75rem'
|
|
72
|
+
space-8: '2rem'
|
|
73
|
+
space-9: '2.25rem'
|
|
74
|
+
space-10: '2.5rem'
|
|
75
|
+
space-0-5: '0.125rem'
|
|
76
|
+
space-1-5: '0.375rem'
|
|
77
|
+
space-2-5: '0.625rem'
|
|
78
|
+
space-3-5: '0.875rem'
|
|
79
|
+
dark:
|
|
80
|
+
color-primary: '#3b82f6'
|
|
81
|
+
color-on-primary: '#ffffff'
|
|
82
|
+
color-primary-container: '#0d6efd'
|
|
83
|
+
color-on-primary-container: '#cfe2ff'
|
|
84
|
+
color-secondary: '#adb5bd'
|
|
85
|
+
color-on-secondary: '#212529'
|
|
86
|
+
color-secondary-container: '#495057'
|
|
87
|
+
color-on-secondary-container: '#d3d3d4'
|
|
88
|
+
color-tertiary: '#adb5bd'
|
|
89
|
+
color-on-tertiary: '#212529'
|
|
90
|
+
color-tertiary-container: '#495057'
|
|
91
|
+
color-on-tertiary-container: '#d3d3d4'
|
|
92
|
+
color-error: '#f87171'
|
|
93
|
+
color-on-error: '#4f0b0b'
|
|
94
|
+
color-error-container: '#dc3545'
|
|
95
|
+
color-on-error-container: '#f8d7da'
|
|
96
|
+
color-surface: '#121212'
|
|
97
|
+
color-surface-dim: '#1f1f1f'
|
|
98
|
+
color-surface-bright: '#333333'
|
|
99
|
+
color-surface-inverse: '#e9ecef'
|
|
100
|
+
color-on-surface: '#e9ecef'
|
|
101
|
+
color-on-surface-variant: '#adb5bd'
|
|
102
|
+
color-on-surface-inverse: '#121212'
|
|
103
|
+
color-surface-container-lowest: '#1f1f1f'
|
|
104
|
+
color-surface-container-low: '#333333'
|
|
105
|
+
color-surface-container: '#4f4f4f'
|
|
106
|
+
color-surface-container-high: '#666666'
|
|
107
|
+
color-surface-container-highest: '#7f7f7f'
|
|
108
|
+
color-shadow: 'hsla(0, 0%, 0%, 0.5)'
|
|
109
|
+
color-outline: '#6c757d'
|
|
110
|
+
color-outline-variant: '#495057'
|
|
111
|
+
light:
|
|
112
|
+
color-primary: '#0d6efd'
|
|
113
|
+
color-on-primary: '#ffffff'
|
|
114
|
+
color-primary-container: '#cfe2ff'
|
|
115
|
+
color-on-primary-container: '#084298'
|
|
116
|
+
color-secondary: '#6c757d'
|
|
117
|
+
color-on-secondary: '#ffffff'
|
|
118
|
+
color-secondary-container: '#d3d3d4'
|
|
119
|
+
color-on-secondary-container: '#41464b'
|
|
120
|
+
color-tertiary: '#6c757d'
|
|
121
|
+
color-on-tertiary: '#ffffff'
|
|
122
|
+
color-tertiary-container: '#d3d3d4'
|
|
123
|
+
color-on-tertiary-container: '#41464b'
|
|
124
|
+
color-error: '#dc3545'
|
|
125
|
+
color-on-error: '#ffffff'
|
|
126
|
+
color-error-container: '#f8d7da'
|
|
127
|
+
color-on-error-container: '#842029'
|
|
128
|
+
color-surface: '#f8f9fa'
|
|
129
|
+
color-surface-dim: '#e9ecef'
|
|
130
|
+
color-surface-bright: '#ffffff'
|
|
131
|
+
color-surface-inverse: '#212529'
|
|
132
|
+
color-on-surface: '#212529'
|
|
133
|
+
color-on-surface-variant: '#495057'
|
|
134
|
+
color-on-surface-inverse: '#f8f9fa'
|
|
135
|
+
color-surface-container-lowest: '#ffffff'
|
|
136
|
+
color-surface-container-low: '#e9ecef'
|
|
137
|
+
color-surface-container: '#dee2e6'
|
|
138
|
+
color-surface-container-high: '#ced4da'
|
|
139
|
+
color-surface-container-highest: '#adb5bd'
|
|
140
|
+
color-shadow: 'hsla(0, 0%, 0%, 0.15)'
|
|
141
|
+
color-outline: '#6c757d'
|
|
142
|
+
color-outline-variant: '#ced4da'
|
|
143
|
+
markdown:
|
|
144
|
+
code:
|
|
145
|
+
light: 'github-light'
|
|
146
|
+
dark: 'github-dark'
|
|
147
|
+
sidenote:
|
|
148
|
+
sidenote-callout-before-content: '"[ "'
|
|
149
|
+
sidenote-callout-after-content: '" ]"'
|
|
150
|
+
sidenote-citation-before-content: '""'
|
|
151
|
+
sidenote-citation-after-content: '":"'
|