kempo 4.2.18 → 4.2.20
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/app-public/CATCH.page.html +15 -0
- package/app-public/kempo-global.global.html +0 -6
- package/dist/admin/accounts/groups/[name]/index.page.html +112 -2
- package/dist/admin/accounts/groups/index.page.html +87 -2
- package/dist/admin/accounts/permissions/index.page.html +84 -2
- package/dist/admin/accounts/users/[id]/index.page.html +117 -3
- package/dist/admin/accounts/users/index.page.html +116 -2
- package/dist/admin/components/tableControls/InstallExtension.js +2 -2
- package/dist/admin/components/tableControls/InstallExtension.js.map +1 -1
- package/dist/admin/components/tableControls/UninstallExtension.js +2 -2
- package/dist/admin/components/tableControls/UninstallExtension.js.map +1 -1
- package/dist/admin/content/fragments/edit/index.page.html +8 -1
- package/dist/admin/content/fragments/index.page.html +87 -2
- package/dist/admin/content/globals/edit/index.page.html +8 -1
- package/dist/admin/content/globals/index.page.html +102 -7
- package/dist/admin/content/pages/edit/index.page.html +8 -1
- package/dist/admin/content/pages/index.page.html +224 -27
- package/dist/admin/content/templates/edit/index.page.html +8 -1
- package/dist/admin/content/templates/index.page.html +116 -2
- package/dist/admin/default.template.html +20 -1
- package/dist/admin/extensions/index.page.html +59 -2
- package/dist/admin/icons/extension_add.svg +1 -0
- package/dist/admin/icons/extension_remove.svg +1 -0
- package/dist/admin/index.page.html +5 -1
- package/dist/admin/nav.fragment.html +84 -2
- package/dist/admin/settings/[owner]/[name]/index.page.html +110 -4
- package/dist/admin/settings/index.page.html +87 -2
- package/dist/kempo/api/fragments/DELETE.js +1 -1
- package/dist/kempo/api/fragments/DELETE.js.map +1 -1
- package/dist/kempo/api/fragments/GET.js +1 -1
- package/dist/kempo/api/fragments/GET.js.map +1 -1
- package/dist/kempo/api/fragments/POST.js +1 -1
- package/dist/kempo/api/fragments/POST.js.map +1 -1
- package/dist/kempo/api/fragments/disable/PUT.js +1 -1
- package/dist/kempo/api/fragments/disable/PUT.js.map +1 -1
- package/dist/kempo/api/fragments/enable/PUT.js +1 -1
- package/dist/kempo/api/fragments/enable/PUT.js.map +1 -1
- package/dist/kempo/api/fragments/file/GET.js +1 -1
- package/dist/kempo/api/fragments/file/GET.js.map +1 -1
- package/dist/kempo/api/fragments/file/PATCH.js +1 -1
- package/dist/kempo/api/fragments/file/PATCH.js.map +1 -1
- package/dist/kempo/api/fragments/file/PUT.js +1 -1
- package/dist/kempo/api/fragments/file/PUT.js.map +1 -1
- package/dist/kempo/api/fragments/lock/PUT.js +1 -1
- package/dist/kempo/api/fragments/lock/PUT.js.map +1 -1
- package/dist/kempo/api/globals/DELETE.js +1 -1
- package/dist/kempo/api/globals/DELETE.js.map +1 -1
- package/dist/kempo/api/globals/GET.js +1 -1
- package/dist/kempo/api/globals/GET.js.map +1 -1
- package/dist/kempo/api/globals/POST.js +1 -1
- package/dist/kempo/api/globals/POST.js.map +1 -1
- package/dist/kempo/api/globals/disable/PUT.js +1 -1
- package/dist/kempo/api/globals/disable/PUT.js.map +1 -1
- package/dist/kempo/api/globals/enable/PUT.js +1 -1
- package/dist/kempo/api/globals/enable/PUT.js.map +1 -1
- package/dist/kempo/api/globals/entry/GET.js +1 -1
- package/dist/kempo/api/globals/entry/GET.js.map +1 -1
- package/dist/kempo/api/globals/entry/PUT.js +1 -1
- package/dist/kempo/api/globals/entry/PUT.js.map +1 -1
- package/dist/kempo/api/globals/lock/PUT.js +1 -1
- package/dist/kempo/api/globals/lock/PUT.js.map +1 -1
- package/dist/kempo/api/pages/DELETE.js +1 -1
- package/dist/kempo/api/pages/DELETE.js.map +1 -1
- package/dist/kempo/api/pages/GET.js +1 -1
- package/dist/kempo/api/pages/GET.js.map +1 -1
- package/dist/kempo/api/pages/POST.js +1 -1
- package/dist/kempo/api/pages/POST.js.map +1 -1
- package/dist/kempo/api/pages/directories/GET.js +1 -1
- package/dist/kempo/api/pages/directories/GET.js.map +1 -1
- package/dist/kempo/api/pages/disable/PUT.js +1 -1
- package/dist/kempo/api/pages/disable/PUT.js.map +1 -1
- package/dist/kempo/api/pages/enable/PUT.js +1 -1
- package/dist/kempo/api/pages/enable/PUT.js.map +1 -1
- package/dist/kempo/api/pages/file/GET.js +1 -1
- package/dist/kempo/api/pages/file/GET.js.map +1 -1
- package/dist/kempo/api/pages/file/PATCH.js +1 -1
- package/dist/kempo/api/pages/file/PATCH.js.map +1 -1
- package/dist/kempo/api/pages/file/PUT.js +1 -1
- package/dist/kempo/api/pages/file/PUT.js.map +1 -1
- package/dist/kempo/api/pages/lock/PUT.js +1 -1
- package/dist/kempo/api/pages/lock/PUT.js.map +1 -1
- package/dist/kempo/api/pages/rescan/POST.js +2 -0
- package/dist/kempo/api/pages/rescan/POST.js.map +1 -0
- package/dist/kempo/api/pages/search/GET.js +1 -1
- package/dist/kempo/api/pages/search/GET.js.map +1 -1
- package/dist/kempo/api/pages/templates/GET.js +1 -1
- package/dist/kempo/api/pages/templates/GET.js.map +1 -1
- package/dist/kempo/api/templates/DELETE.js +1 -1
- package/dist/kempo/api/templates/DELETE.js.map +1 -1
- package/dist/kempo/api/templates/GET.js +1 -1
- package/dist/kempo/api/templates/GET.js.map +1 -1
- package/dist/kempo/api/templates/POST.js +1 -1
- package/dist/kempo/api/templates/POST.js.map +1 -1
- package/dist/kempo/api/templates/disable/PUT.js +1 -1
- package/dist/kempo/api/templates/disable/PUT.js.map +1 -1
- package/dist/kempo/api/templates/enable/PUT.js +1 -1
- package/dist/kempo/api/templates/enable/PUT.js.map +1 -1
- package/dist/kempo/api/templates/file/GET.js +1 -1
- package/dist/kempo/api/templates/file/GET.js.map +1 -1
- package/dist/kempo/api/templates/file/PATCH.js +1 -1
- package/dist/kempo/api/templates/file/PATCH.js.map +1 -1
- package/dist/kempo/api/templates/file/PUT.js +1 -1
- package/dist/kempo/api/templates/file/PUT.js.map +1 -1
- package/dist/kempo/api/templates/lock/PUT.js +1 -1
- package/dist/kempo/api/templates/lock/PUT.js.map +1 -1
- package/dist/kempo/icons/browse.svg +1 -0
- package/dist/kempo/icons/cards_stack.svg +1 -0
- package/dist/kempo/icons/content.svg +1 -0
- package/dist/kempo/icons/deployed_code_update.svg +1 -0
- package/dist/kempo/icons/docs.svg +1 -0
- package/dist/kempo/icons/drive_file_move.svg +1 -0
- package/dist/kempo/icons/extension.svg +1 -0
- package/dist/kempo/icons/globe.svg +1 -0
- package/dist/kempo/icons/group.svg +1 -0
- package/dist/kempo/icons/lock.svg +1 -0
- package/dist/kempo/icons/lock_add.svg +1 -0
- package/dist/kempo/icons/manage-accounts.svg +1 -0
- package/dist/kempo/icons/person.svg +1 -0
- package/dist/kempo/icons/person_add.svg +1 -0
- package/dist/kempo/icons/preview.svg +1 -0
- package/dist/kempo/icons/save.svg +1 -0
- package/dist/kempo/icons/timer_off.svg +1 -0
- package/dist/kempo/icons/visibility.svg +1 -0
- package/dist/kempo/sdk.js +1 -1
- package/dist/kempo/sdk.js.map +1 -1
- package/middleware/kempo.js +50 -1
- package/package.json +3 -3
- package/server/utils/fragments/listFragments.js +10 -1
- package/server/utils/hooks/triggerHook.js +7 -12
- package/server/utils/pages/listPages.js +57 -7
- package/app-public/kempo-global.global-disabled.html +0 -0
- package/app-public/new-page.page.html +0 -17
- package/app-public/test.page.html +0 -21
- package/dist/kempo/icons/format_indent_decrease.svg +0 -1
- package/dist/kempo/icons/format_indent_increase.svg +0 -1
- package/dist/kempo/icons/format_quote.svg +0 -1
- package/dist/kempo/icons/redo.svg +0 -1
- package/dist/kempo/icons/subscript.svg +0 -1
- package/dist/kempo/icons/superscript.svg +0 -1
- package/dist/kempo/icons/undo.svg +0 -1
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kempo",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A fullstack CMS framework for creating websites with user authentication",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"dev": "node dev.
|
|
7
|
+
"dev": "node scripts/dev.js",
|
|
8
8
|
"build": "node scripts/build.js",
|
|
9
9
|
"db:generate": "drizzle-kit generate",
|
|
10
10
|
"db:migrate": "drizzle-kit migrate",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"kempo": "^4.2.16",
|
|
50
50
|
"kempo-server": "^3.1.0",
|
|
51
51
|
"kempo-testing-framework": "^1.4.6",
|
|
52
|
-
"kempo-ui": "^0.4.
|
|
52
|
+
"kempo-ui": "^0.4.17",
|
|
53
53
|
"lexical": "^0.42.0",
|
|
54
54
|
"monaco-editor": "^0.55.1",
|
|
55
55
|
"postgres": "^3.4.7",
|
|
@@ -3,6 +3,14 @@ import { relative } from 'path';
|
|
|
3
3
|
import scanDir from '../fs/scanDir.js';
|
|
4
4
|
import parseFrontmatter from '../fs/parseFrontmatter.js';
|
|
5
5
|
|
|
6
|
+
const parseLocations = content => {
|
|
7
|
+
const locations = [];
|
|
8
|
+
const regex = /<location\s[^/]*?name="([^"]+)"[^/]*?\/>/g;
|
|
9
|
+
let match;
|
|
10
|
+
while((match = regex.exec(content)) !== null) locations.push(match[1]);
|
|
11
|
+
return locations;
|
|
12
|
+
};
|
|
13
|
+
|
|
6
14
|
export default async ({ rootDir }) => {
|
|
7
15
|
if(!rootDir){
|
|
8
16
|
return [{ code: 400, msg: 'Root directory is required' }, null];
|
|
@@ -24,7 +32,8 @@ export default async ({ rootDir }) => {
|
|
|
24
32
|
disabled: isDisabled,
|
|
25
33
|
author: meta.author || '',
|
|
26
34
|
createdAt: meta.created || '',
|
|
27
|
-
updatedAt: meta.updated || ''
|
|
35
|
+
updatedAt: meta.updated || '',
|
|
36
|
+
locations: parseLocations(content)
|
|
28
37
|
};
|
|
29
38
|
});
|
|
30
39
|
|
|
@@ -1,28 +1,21 @@
|
|
|
1
1
|
import db from '../../db/index.js';
|
|
2
2
|
import { hook } from '../../db/schema.js';
|
|
3
3
|
import { eq } from 'drizzle-orm';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { pathToFileURL } from 'url';
|
|
6
6
|
|
|
7
7
|
const handlerCache = new Map();
|
|
8
8
|
|
|
9
9
|
export const clearHandlerCache = () => handlerCache.clear();
|
|
10
10
|
|
|
11
|
-
const requireFromProject = createRequire(join(process.cwd(), 'package.json'));
|
|
12
|
-
|
|
13
11
|
const resolveHandler = (owner, callback) => {
|
|
14
12
|
if(callback.startsWith('./') || callback.startsWith('../')){
|
|
15
|
-
|
|
16
|
-
const pkgPath = requireFromProject.resolve(`${owner}/package.json`);
|
|
17
|
-
return join(dirname(pkgPath), callback);
|
|
18
|
-
} catch {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
13
|
+
return join(process.cwd(), 'node_modules', owner, callback);
|
|
21
14
|
}
|
|
22
15
|
return callback;
|
|
23
16
|
};
|
|
24
17
|
|
|
25
|
-
export default async (event, data = {}) => {
|
|
18
|
+
export default async (event, data = {}, { bail = false } = {}) => {
|
|
26
19
|
if(!event){
|
|
27
20
|
return [{ code: 400, msg: 'Event is required' }, null];
|
|
28
21
|
}
|
|
@@ -38,7 +31,7 @@ export default async (event, data = {}) => {
|
|
|
38
31
|
let handler = handlerCache.get(handlerPath);
|
|
39
32
|
if(!handler){
|
|
40
33
|
try {
|
|
41
|
-
const mod = await import(handlerPath);
|
|
34
|
+
const mod = await import(pathToFileURL(handlerPath).href);
|
|
42
35
|
handler = mod.default || mod;
|
|
43
36
|
handlerCache.set(handlerPath, handler);
|
|
44
37
|
} catch {
|
|
@@ -50,12 +43,14 @@ export default async (event, data = {}) => {
|
|
|
50
43
|
const result = await handler(data);
|
|
51
44
|
results.push({ hookId: h.id, owner: h.owner, result });
|
|
52
45
|
} catch(err) {
|
|
46
|
+
if(bail) throw err;
|
|
53
47
|
results.push({ hookId: h.id, owner: h.owner, error: err.message });
|
|
54
48
|
}
|
|
55
49
|
}
|
|
56
50
|
|
|
57
51
|
return [null, { results }];
|
|
58
52
|
} catch(error) {
|
|
53
|
+
if(bail) throw error;
|
|
59
54
|
return [{ code: 500, msg: 'Failed to trigger hooks' }, null];
|
|
60
55
|
}
|
|
61
56
|
};
|
|
@@ -2,14 +2,17 @@ import { readFile } from 'fs/promises';
|
|
|
2
2
|
import { relative } from 'path';
|
|
3
3
|
import scanDir from '../fs/scanDir.js';
|
|
4
4
|
import parseFrontmatter from '../fs/parseFrontmatter.js';
|
|
5
|
+
import getSetting from '../settings/getSetting.js';
|
|
5
6
|
|
|
6
|
-
const RESERVED_KEYS = new Set(['owner', 'name', 'author', 'created', 'updated', 'locked', 'title', 'description']);
|
|
7
|
+
const RESERVED_KEYS = new Set(['owner', 'name', 'author', 'created', 'updated', 'locked', 'hidden', 'title', 'description']);
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
/*
|
|
10
|
+
In-memory cache keyed by rootDir.
|
|
11
|
+
TTL is read from the 'system:pages:cacheTtl' setting (milliseconds, default 60000).
|
|
12
|
+
*/
|
|
13
|
+
const cache = new Map();
|
|
12
14
|
|
|
15
|
+
const scan = async (rootDir) => {
|
|
13
16
|
const pages = await scanDir(rootDir, rootDir, async (fullPath, entry, root) => {
|
|
14
17
|
const isDisabled = entry.name.endsWith('.page-disabled.html');
|
|
15
18
|
if(entry.isDirectory() || (!entry.name.endsWith('.page.html') && !isDisabled)) return null;
|
|
@@ -32,6 +35,7 @@ export default async ({ rootDir, owner }) => {
|
|
|
32
35
|
title: meta.title || '',
|
|
33
36
|
owner: meta.owner || 'custom',
|
|
34
37
|
locked: meta.locked === 'true',
|
|
38
|
+
hidden: meta.hidden === 'true',
|
|
35
39
|
disabled: isDisabled,
|
|
36
40
|
author: meta.author || '',
|
|
37
41
|
description: meta.description || '',
|
|
@@ -41,8 +45,54 @@ export default async ({ rootDir, owner }) => {
|
|
|
41
45
|
};
|
|
42
46
|
});
|
|
43
47
|
|
|
44
|
-
const
|
|
48
|
+
const scannedAt = Date.now();
|
|
49
|
+
cache.set(rootDir, { pages, scannedAt });
|
|
50
|
+
return scannedAt;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default async ({ rootDir, owner, forceRescan = false, showHidden = true, offset = 0, limit = 0 }) => {
|
|
54
|
+
if(!rootDir){
|
|
55
|
+
return [{ code: 400, msg: 'Root directory is required' }, null];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const [, cacheTtl] = await getSetting('system', 'pages:cacheTtl', 60000);
|
|
59
|
+
const cached = cache.get(rootDir);
|
|
60
|
+
|
|
61
|
+
if(!forceRescan && cached && (Date.now() - cached.scannedAt < cacheTtl)){
|
|
62
|
+
return [null, buildResult(cached.pages, cached.scannedAt, { owner, showHidden, offset, limit })];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const scannedAt = await scan(rootDir);
|
|
66
|
+
const { pages } = cache.get(rootDir);
|
|
67
|
+
return [null, buildResult(pages, scannedAt, { owner, showHidden, offset, limit })];
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const buildResult = (allPages, scannedAt, { owner, showHidden, offset, limit }) => {
|
|
71
|
+
let filtered = showHidden ? allPages : allPages.filter(p => !p.hidden);
|
|
72
|
+
|
|
73
|
+
if(owner === 'extension'){
|
|
74
|
+
filtered = filtered.filter(p => p.owner !== 'custom' && p.owner !== 'system');
|
|
75
|
+
} else if(owner){
|
|
76
|
+
filtered = filtered.filter(p => p.owner === owner);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
filtered = filtered.slice().sort((a, b) => {
|
|
80
|
+
const aPath = a.file.replace(/\.page(-disabled)?\.html$/, '');
|
|
81
|
+
const bPath = b.file.replace(/\.page(-disabled)?\.html$/, '');
|
|
82
|
+
const aDir = aPath.includes('/') ? aPath.split('/').slice(0, -1).join('/') : '';
|
|
83
|
+
const bDir = bPath.includes('/') ? bPath.split('/').slice(0, -1).join('/') : '';
|
|
84
|
+
if(aPath === 'index' || aPath === '') return -1;
|
|
85
|
+
if(bPath === 'index' || bPath === '') return 1;
|
|
86
|
+
if(aDir !== bDir){
|
|
87
|
+
if(!aDir) return -1;
|
|
88
|
+
if(!bDir) return 1;
|
|
89
|
+
return aDir.localeCompare(bDir);
|
|
90
|
+
}
|
|
91
|
+
return aPath.localeCompare(bPath);
|
|
92
|
+
});
|
|
45
93
|
|
|
46
|
-
|
|
94
|
+
const total = filtered.length;
|
|
95
|
+
const pages = limit > 0 ? filtered.slice(offset, offset + limit) : filtered.slice(offset);
|
|
96
|
+
return { pages, total, scannedAt };
|
|
47
97
|
};
|
|
48
98
|
|
|
File without changes
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
owner: custom
|
|
3
|
-
name: new page
|
|
4
|
-
author:
|
|
5
|
-
created: 2026-04-16T06:21:26.074Z
|
|
6
|
-
updated: 2026-04-19T20:54:05.204Z
|
|
7
|
-
title: new page
|
|
8
|
-
description:
|
|
9
|
-
-->
|
|
10
|
-
<page template="split" title="new page">
|
|
11
|
-
<content>
|
|
12
|
-
<h1>New Page</h1>
|
|
13
|
-
</content>
|
|
14
|
-
<content location="left">
|
|
15
|
-
<p>Left</p>
|
|
16
|
-
</content>
|
|
17
|
-
</page>
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
owner: custom
|
|
3
|
-
name: test
|
|
4
|
-
author: Dustin
|
|
5
|
-
created: 2026-04-11T06:13:14.666Z
|
|
6
|
-
updated: 2026-04-16T21:13:12.153Z
|
|
7
|
-
title: test
|
|
8
|
-
description:
|
|
9
|
-
locked: true
|
|
10
|
-
-->
|
|
11
|
-
<page template="split" title="test">
|
|
12
|
-
<content location="left">
|
|
13
|
-
<p>Left Side MEnu</p>
|
|
14
|
-
</content>
|
|
15
|
-
<content>
|
|
16
|
-
<h1>Test</h1>
|
|
17
|
-
</content>
|
|
18
|
-
<content location="scripts">
|
|
19
|
-
<p><br></p>
|
|
20
|
-
</content>
|
|
21
|
-
</page>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M120-120v-80h720v80H120Zm320-160v-80h400v80H440Zm0-160v-80h400v80H440Zm0-160v-80h400v80H440ZM120-760v-80h720v80H120Zm160 440L120-480l160-160v320Z"/></svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M120-120v-80h720v80H120Zm320-160v-80h400v80H440Zm0-160v-80h400v80H440Zm0-160v-80h400v80H440ZM120-760v-80h720v80H120Zm0 440v-320l160 160-160 160Z"/></svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="m228-240 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T458-480L320-240h-92Zm360 0 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T818-480L680-240h-92ZM362.5-517.5Q380-535 380-560t-17.5-42.5Q345-620 320-620t-42.5 17.5Q260-585 260-560t17.5 42.5Q295-500 320-500t42.5-17.5Zm360 0Q740-535 740-560t-17.5-42.5Q705-620 680-620t-42.5 17.5Q620-585 620-560t17.5 42.5Q655-500 680-500t42.5-17.5ZM680-560Zm-360 0Z"/></svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M396-200q-97 0-166.5-63T160-420q0-94 69.5-157T396-640h252L544-744l56-56 200 200-200 200-56-56 104-104H396q-63 0-109.5 40T240-420q0 60 46.5 100T396-280h284v80H396Z"/></svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M760-160v-80q0-17 11.5-28.5T800-280h80v-40H760v-40h120q17 0 28.5 11.5T920-320v40q0 17-11.5 28.5T880-240h-80v40h120v40H760Zm-525-80 185-291-172-269h106l124 200h4l123-200h107L539-531l186 291H618L482-457h-4L342-240H235Z"/></svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M760-600v-80q0-17 11.5-28.5T800-720h80v-40H760v-40h120q17 0 28.5 11.5T920-760v40q0 17-11.5 28.5T880-680h-80v40h120v40H760ZM235-160l185-291-172-269h106l124 200h4l123-200h107L539-451l186 291H618L482-377h-4L342-160H235Z"/></svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M280-200v-80h284q63 0 109.5-40T720-420q0-60-46.5-100T564-560H312l104 104-56 56-200-200 200-200 56 56-104 104h252q97 0 166.5 63T800-420q0 94-69.5 157T564-200H280Z"/></svg>
|