@alstar/studio 0.0.0-beta.6 → 0.0.0-beta.7
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/api/block.ts +63 -15
- package/components/AdminPanel.ts +46 -24
- package/components/{fields/Blocks.ts → BlockFieldRenderer.ts} +33 -30
- package/components/BlockRenderer.ts +22 -0
- package/components/Entries.ts +3 -2
- package/components/Entry.ts +13 -15
- package/components/FieldRenderer.ts +35 -0
- package/components/Render.ts +46 -0
- package/components/{layout.ts → SiteLayout.ts} +8 -12
- package/components/fields/Markdown.ts +44 -0
- package/components/fields/Text.ts +10 -10
- package/components/fields/index.ts +2 -2
- package/index.ts +31 -28
- package/package.json +3 -3
- package/pages/entry/[id].ts +17 -0
- package/{components → pages}/index.ts +7 -4
- package/pages/settings.ts +10 -0
- package/public/{admin-panel.css → studio/admin-panel.css} +14 -1
- package/public/studio/main.css +162 -0
- package/public/studio/main.js +10 -0
- package/public/studio/markdown-editor.js +34 -0
- package/public/studio/sortable-list.js +40 -0
- package/queries/block.ts +2 -0
- package/types.ts +70 -32
- package/utils/define.ts +21 -9
- package/utils/file-based-router.ts +1 -0
- package/utils/get-or-create-row.ts +20 -7
- package/utils/startup-log.ts +2 -2
- package/bin/alstar.ts +0 -42
- package/components/Block.ts +0 -55
- package/public/main.css +0 -103
- package/public/main.js +0 -48
- /package/public/{blocks.css → studio/blocks.css} +0 -0
- /package/public/{entry.css → studio/entry.css} +0 -0
- /package/public/{favicon.svg → studio/favicon.svg} +0 -0
- /package/public/{settings.css → studio/settings.css} +0 -0
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import { db } from '@alstar/db'
|
|
2
2
|
import { query } from '../queries/index.ts'
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
BlockDefStructure,
|
|
5
|
+
BlocksFieldDefStructure,
|
|
6
|
+
FieldDefStructure,
|
|
7
|
+
} from '../types.ts'
|
|
8
|
+
|
|
9
|
+
export function getOrCreateRow(props: {
|
|
10
|
+
parentId: string | number | null
|
|
11
|
+
name: string
|
|
12
|
+
field: BlockDefStructure | BlocksFieldDefStructure | FieldDefStructure
|
|
13
|
+
sortOrder?: number
|
|
14
|
+
id?: number
|
|
15
|
+
}) {
|
|
16
|
+
const { parentId, name, field, sortOrder = 0, id } = props
|
|
17
|
+
|
|
18
|
+
if (id) {
|
|
19
|
+
return query.block({
|
|
20
|
+
id: id?.toString(),
|
|
21
|
+
})
|
|
22
|
+
}
|
|
4
23
|
|
|
5
|
-
export function getOrCreateRow(
|
|
6
|
-
parentId: string | number,
|
|
7
|
-
name: string,
|
|
8
|
-
field: Block | FieldDef,
|
|
9
|
-
sortOrder: number,
|
|
10
|
-
) {
|
|
11
24
|
const data = query.block({
|
|
12
25
|
parent_id: parentId?.toString() || null,
|
|
13
26
|
name: name,
|
package/utils/startup-log.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import packageJSON from '../package.json' with { type: 'json' }
|
|
2
2
|
|
|
3
|
-
export default () => {
|
|
3
|
+
export default ({ port }: { port: number }) => {
|
|
4
4
|
console.log('\x1b[32m%s\x1b[0m', '╭───────────────────────╮')
|
|
5
5
|
console.log('\x1b[32m%s\x1b[0m', '│ Alstar Studio │')
|
|
6
6
|
console.log('\x1b[32m%s\x1b[0m', `│ ${packageJSON.version}${' '.repeat(22 - packageJSON.version.length)}│`)
|
|
7
|
-
console.log('\x1b[32m%s\x1b[0m', `│ http://localhost:${
|
|
7
|
+
console.log('\x1b[32m%s\x1b[0m', `│ http://localhost:${port} │`)
|
|
8
8
|
console.log('\x1b[32m%s\x1b[0m', '╰───────────────────────╯')
|
|
9
9
|
}
|
package/bin/alstar.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from 'node:child_process'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
|
-
import path from 'node:path'
|
|
5
|
-
|
|
6
|
-
// process.removeAllListeners('warning')
|
|
7
|
-
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
9
|
-
|
|
10
|
-
// Dev-only auto watch (opt out with ALSTAR_NO_WATCH=true)
|
|
11
|
-
const isDev =
|
|
12
|
-
process.env.NODE_ENV !== 'production' &&
|
|
13
|
-
process.env.ALSTAR_NO_WATCH !== 'true'
|
|
14
|
-
const alreadyBootstrapped = process.env.ALSTAR_WATCH_BOOTSTRAPPED === '1'
|
|
15
|
-
|
|
16
|
-
if (isDev && !alreadyBootstrapped) {
|
|
17
|
-
// Start a watcher ON THIS FILE and mark the environment so the child won't re-spawn
|
|
18
|
-
const childProcess = spawn(
|
|
19
|
-
process.execPath,
|
|
20
|
-
['--watch', __filename, ...process.argv.slice(2)],
|
|
21
|
-
// [__filename, ...process.argv.slice(2)],
|
|
22
|
-
{
|
|
23
|
-
stdio: 'inherit',
|
|
24
|
-
env: { ...process.env, ALSTAR_WATCH_BOOTSTRAPPED: '1' },
|
|
25
|
-
},
|
|
26
|
-
)
|
|
27
|
-
// Important: exit this launcher so only the watched child keeps running
|
|
28
|
-
process.on('SIGINT', () => {
|
|
29
|
-
childProcess.kill('SIGINT')
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
process.on('SIGTERM', () => {
|
|
33
|
-
childProcess.kill('SIGTERM')
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
process.exit(0)
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// --- Your actual CLI logic below ---
|
|
41
|
-
// console.log(import.meta.dirname, path.resolve('.'))
|
|
42
|
-
// import("./main.js").then(m => m.default());
|
package/components/Block.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { html } from 'hono/html'
|
|
2
|
-
import type { Block, BlockDef, FieldDef } from '../types.ts'
|
|
3
|
-
import { type HtmlEscapedString } from 'hono/utils/html'
|
|
4
|
-
import { Field } from './fields/index.ts'
|
|
5
|
-
|
|
6
|
-
export default (props: {
|
|
7
|
-
entryId: number
|
|
8
|
-
parentId: number
|
|
9
|
-
blockStructure: BlockDef | Block | FieldDef
|
|
10
|
-
name: string
|
|
11
|
-
sortOrder?: number
|
|
12
|
-
}): HtmlEscapedString | Promise<HtmlEscapedString> => {
|
|
13
|
-
const { entryId, parentId, blockStructure, name, sortOrder = 0 } = props
|
|
14
|
-
|
|
15
|
-
if (!blockStructure) return html`<p>No block</p>`
|
|
16
|
-
|
|
17
|
-
let entries: [string, BlockDef | Block | FieldDef][] = []
|
|
18
|
-
|
|
19
|
-
const fieldTypes = ['text', 'image', 'markdown', 'slug']
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
if (fieldTypes.includes(blockStructure.type)) {
|
|
23
|
-
entries = [[name, blockStructure]]
|
|
24
|
-
} else if (blockStructure.type === 'blocks') {
|
|
25
|
-
entries = Object.entries(blockStructure.children)
|
|
26
|
-
} else if (blockStructure.fields) {
|
|
27
|
-
entries = Object.entries(blockStructure.fields)
|
|
28
|
-
} else {
|
|
29
|
-
console.log(blockStructure)
|
|
30
|
-
}
|
|
31
|
-
} catch (error) {
|
|
32
|
-
console.log(error)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return html`
|
|
36
|
-
${entries.map(([name, field]) => {
|
|
37
|
-
switch (field.type) {
|
|
38
|
-
case 'text': {
|
|
39
|
-
return Field.Text({ entryId, parentId, name, field, sortOrder })
|
|
40
|
-
}
|
|
41
|
-
case 'slug': {
|
|
42
|
-
return Field.Text({ entryId, parentId, name, field, sortOrder })
|
|
43
|
-
}
|
|
44
|
-
case 'markdown': {
|
|
45
|
-
return Field.Text({ entryId, parentId, name, field, sortOrder })
|
|
46
|
-
}
|
|
47
|
-
case 'image': {
|
|
48
|
-
return Field.Text({ entryId, parentId, name, field, sortOrder })
|
|
49
|
-
}
|
|
50
|
-
case 'blocks': {
|
|
51
|
-
return Field.Blocks({ entryId, parentId, name, field, sortOrder })
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
})}`
|
|
55
|
-
}
|
package/public/main.css
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/* @import './../node_modules/@alstar/ui/red.css'; */
|
|
2
|
-
@import 'https://esm.sh/@alstar/ui/red.css';
|
|
3
|
-
@import './admin-panel.css';
|
|
4
|
-
@import './entry.css';
|
|
5
|
-
@import './blocks.css';
|
|
6
|
-
@import './settings.css';
|
|
7
|
-
|
|
8
|
-
body {
|
|
9
|
-
min-height: 100vh;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
body {
|
|
13
|
-
padding: 0;
|
|
14
|
-
min-height: inherit;
|
|
15
|
-
|
|
16
|
-
display: grid;
|
|
17
|
-
grid-template-columns: auto 1fr;
|
|
18
|
-
align-content: baseline;
|
|
19
|
-
|
|
20
|
-
> main {
|
|
21
|
-
padding: 40px;
|
|
22
|
-
height: 100vh;
|
|
23
|
-
overflow: auto;
|
|
24
|
-
|
|
25
|
-
section {
|
|
26
|
-
max-width: 900px;
|
|
27
|
-
margin: 0 auto;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.entry > .fields > .block {
|
|
33
|
-
padding-block: var(--pico-spacing);
|
|
34
|
-
|
|
35
|
-
> header {
|
|
36
|
-
margin-block: var(--pico-block-spacing-vertical);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.block {
|
|
41
|
-
> header {
|
|
42
|
-
margin-bottom: var(--pico-spacing);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
header {
|
|
46
|
-
display: flex;
|
|
47
|
-
justify-content: space-between;
|
|
48
|
-
align-items: center;
|
|
49
|
-
|
|
50
|
-
background-color: inherit;
|
|
51
|
-
|
|
52
|
-
h6,
|
|
53
|
-
h5,
|
|
54
|
-
fieldset {
|
|
55
|
-
margin-bottom: 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
button {
|
|
59
|
-
padding: 0;
|
|
60
|
-
background-color: white;
|
|
61
|
-
|
|
62
|
-
svg {
|
|
63
|
-
padding: 8px;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
[data-sortable] {
|
|
70
|
-
> article {
|
|
71
|
-
transition: opacity 200ms;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.sortable-ghost {
|
|
75
|
-
opacity: 0.3;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/* .sortable-chosen {
|
|
79
|
-
filter: brightness(0.9)
|
|
80
|
-
} */
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
div.ink-mde {
|
|
84
|
-
border: var(--pico-border-width) solid #2a3140;
|
|
85
|
-
border-radius: var(--pico-border-radius);
|
|
86
|
-
outline: 0;
|
|
87
|
-
background-color: var(--pico-background-color);
|
|
88
|
-
box-shadow: var(--pico-box-shadow);
|
|
89
|
-
color: var(--pico-color);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.ink-mde-textarea {
|
|
93
|
-
width: 100%;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.disclamer {
|
|
97
|
-
display: flex;
|
|
98
|
-
justify-content: center;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
.text-secondary {
|
|
102
|
-
color: var(--pico-secondary);
|
|
103
|
-
}
|
package/public/main.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import barba from '@barba/core'
|
|
2
|
-
import Sortable from 'sortablejs'
|
|
3
|
-
// import { wrap } from 'ink-mde'
|
|
4
|
-
|
|
5
|
-
barba.init({
|
|
6
|
-
cacheIgnore: true,
|
|
7
|
-
views: [
|
|
8
|
-
{
|
|
9
|
-
namespace: 'default',
|
|
10
|
-
afterEnter() {
|
|
11
|
-
init()
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
],
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
function init() {
|
|
18
|
-
// sortable
|
|
19
|
-
{
|
|
20
|
-
const els = document.querySelectorAll('[data-sortable]')
|
|
21
|
-
|
|
22
|
-
els.forEach((el) => {
|
|
23
|
-
const id = el.dataset.sortable
|
|
24
|
-
|
|
25
|
-
var sortable = Sortable.create(el, {
|
|
26
|
-
delay: 0,
|
|
27
|
-
animation: 250,
|
|
28
|
-
dragClass: 'sortable-drag',
|
|
29
|
-
easing: 'ease-in-out',
|
|
30
|
-
handle: `[data-handle="${id}"]`,
|
|
31
|
-
})
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// // ink-mde
|
|
36
|
-
// {
|
|
37
|
-
// const el = document.querySelector('textarea')
|
|
38
|
-
|
|
39
|
-
// if (el) {
|
|
40
|
-
// wrap(el, {
|
|
41
|
-
// interface: {
|
|
42
|
-
// // appearance: InkValues.Appearance.Auto,
|
|
43
|
-
// attribution: false,
|
|
44
|
-
// },
|
|
45
|
-
// })
|
|
46
|
-
// }
|
|
47
|
-
// }
|
|
48
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|