@ape-egg/codecane 0.0.0-stage → 1.0.0
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 +151 -2
- package/core/build.js +63 -0
- package/core/check.js +37 -0
- package/core/checks.js +94 -0
- package/core/cli.js +87 -0
- package/core/data.js +64 -0
- package/core/diff.js +43 -0
- package/core/index.js +10 -0
- package/core/modules.js +17 -0
- package/core/patch.js +115 -0
- package/core/rebase.js +80 -0
- package/core/serve.js +170 -0
- package/core/stack.js +199 -0
- package/core/steps.js +102 -0
- package/package.json +31 -4
- package/ui/codecane.css +534 -0
- package/ui/components/Changes.html +25 -0
- package/ui/components/Stage.html +40 -0
- package/ui/components/Story.html +85 -0
- package/ui/components/Timeline.html +25 -0
- package/ui/index.html +20 -0
- package/ui/mounted.js +73 -0
- package/ui/stylecheat.css +8473 -0
- package/ui/viewer.js +294 -0
- package/workflow.md +81 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<header @[fold] stylecheat dark away="@[fullscreen && !returning]">
|
|
2
|
+
<a href="/" aria-current="@[root ? 'page' : 'false']"><strong>@[name]</strong></a>
|
|
3
|
+
<ol style="grid-template-rows: @[rows]">
|
|
4
|
+
<!-- each cells as cell (cell.key) -->
|
|
5
|
+
<li style="grid-area: @[cell.lane + 1] / @[cell.depth + 1] / span @[cell.span]" @[cell.shown]>
|
|
6
|
+
<!-- if cell.follows -->
|
|
7
|
+
<arrow>→</arrow>
|
|
8
|
+
<!-- /if -->
|
|
9
|
+
<a href="/@[cell.address]" onclick="codecane.pick(event, '@[cell.id]', @[cell.lane], @[cell.span])" aria-current="@[page.id === cell.id ? 'step' : 'false']" kind="@[steps[cell.id].kind ?? '']" @[cell.lit]>
|
|
10
|
+
<!-- if steps[cell.id].kind -->
|
|
11
|
+
<join aria-hidden="true">Y</join>
|
|
12
|
+
<!-- /if -->
|
|
13
|
+
<!-- if steps[cell.id].kind !== 'seam' -->
|
|
14
|
+
@[steps[cell.id].title]
|
|
15
|
+
<!-- /if -->
|
|
16
|
+
</a>
|
|
17
|
+
<!-- if cell.forks -->
|
|
18
|
+
<button fork title="@[cell.forks] timelines fork after @[steps[cell.id].title]" aria-expanded="@[fold && through === cell.id ? 'true' : 'false']" onclick="codecane.fold('@[cell.id]')"><split aria-hidden="true">Y</split>@[cell.forks]</button>
|
|
19
|
+
<!-- /if -->
|
|
20
|
+
</li>
|
|
21
|
+
<!-- /each -->
|
|
22
|
+
</ol>
|
|
23
|
+
<logotext-codecane><a href="https://codecane.korte.kim" target="_blank">code<span>cane</span></a><version>v@[version]</version></logotext-codecane>
|
|
24
|
+
<button onclick="codecane.expand()" aria-label="Fullscreen" tertiary sm><icon fullscreen></icon></button>
|
|
25
|
+
</header>
|
package/ui/index.html
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>codecane</title>
|
|
7
|
+
<link rel="stylesheet" href="/node_modules/@ape-egg/codie/codie.css">
|
|
8
|
+
<link rel="stylesheet" href="/codecane/ui/stylecheat.css">
|
|
9
|
+
<link rel="stylesheet" href="/codecane/ui/codecane.css">
|
|
10
|
+
<script type="module" src="/codecane/ui/viewer.js"></script>
|
|
11
|
+
</head>
|
|
12
|
+
<body vibe-fouc>
|
|
13
|
+
<component src="/codecane/ui/components/Timeline.html"></component>
|
|
14
|
+
<workspace fullscreen="@[fullscreen]" away="@[fullscreen && !returning]">
|
|
15
|
+
<component src="/codecane/ui/components/Story.html"></component>
|
|
16
|
+
<component src="/codecane/ui/components/Stage.html"></component>
|
|
17
|
+
<component src="/codecane/ui/components/Changes.html"></component>
|
|
18
|
+
</workspace>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
package/ui/mounted.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const blobs = {}
|
|
2
|
+
const sources = {}
|
|
3
|
+
const blob = (text, type, path) => {
|
|
4
|
+
const url = blobs[`${path}\n${text}`] ??= URL.createObjectURL(new Blob([text], { type }))
|
|
5
|
+
sources[url] = path
|
|
6
|
+
return url
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const moduleLinks = /((?:from|import)\s*\(?\s*)(['"])(\.{1,2}\/[^'"]+)\2/g
|
|
10
|
+
const styleLinks = /((?:url\(|@import\s+(?!url\())\s*)(['"]?)([^'")\s;]+)\2/g
|
|
11
|
+
|
|
12
|
+
const reporter = `{
|
|
13
|
+
let failed = false
|
|
14
|
+
const fail = failure => {
|
|
15
|
+
failed = true
|
|
16
|
+
parent.postMessage({ codecane: 'failed', ...failure }, origin)
|
|
17
|
+
}
|
|
18
|
+
addEventListener('error', event => fail(event instanceof ErrorEvent
|
|
19
|
+
? { message: String(event.error ?? event.message), source: event.filename, line: event.lineno }
|
|
20
|
+
: { message: 'Could not load ' + (event.target.src ?? event.target.href), source: '' }), true)
|
|
21
|
+
addEventListener('unhandledrejection', ({ reason }) => fail({ message: String(reason), source: '' }))
|
|
22
|
+
addEventListener('load', () => failed || parent.postMessage({ codecane: 'ran' }, origin))
|
|
23
|
+
}`
|
|
24
|
+
|
|
25
|
+
export const pathOf = (page, url) => sources[url] ?? (url.startsWith(page.base) ? url.split(/[?#]/)[0].slice(page.base.length) : url)
|
|
26
|
+
|
|
27
|
+
const sheets = (page, drafts, text) => {
|
|
28
|
+
const address = path => new URL(path, page.base).href
|
|
29
|
+
const has = path => page.files.some(file => file.path === path)
|
|
30
|
+
const styles = {}
|
|
31
|
+
const styled = path => styles[path] ??= (async () => {
|
|
32
|
+
const css = drafts[path] ?? await text(path)
|
|
33
|
+
const targets = Object.fromEntries(await Promise.all([...css.matchAll(styleLinks)].map(async ([, , , link]) => {
|
|
34
|
+
const target = new URL(link, address(path)).href
|
|
35
|
+
return [link, pathOf(page, target).endsWith('.css') && has(pathOf(page, target)) ? await styled(pathOf(page, target)) : target]
|
|
36
|
+
})))
|
|
37
|
+
return blob(css.replace(styleLinks, (_, lead, quote, link) => `${lead}${quote}${targets[link]}${quote}`), 'text/css', path)
|
|
38
|
+
})()
|
|
39
|
+
return { address, has, styled }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const restyled = (page, drafts, text) => {
|
|
43
|
+
const { has, styled } = sheets(page, drafts, text)
|
|
44
|
+
return async href => has(pathOf(page, href)) ? styled(pathOf(page, href)) : href
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const mounted = async (page, drafts, text) => {
|
|
48
|
+
const { address, has, styled } = sheets(page, drafts, text)
|
|
49
|
+
|
|
50
|
+
const modules = Object.fromEntries(Object.keys(drafts).filter(path => path.endsWith('.js')).map(path => [
|
|
51
|
+
address(path),
|
|
52
|
+
blob(drafts[path].replace(moduleLinks, (_, lead, quote, link) => `${lead}${quote}${new URL(link, address(path))}${quote}`), 'text/javascript', path),
|
|
53
|
+
]))
|
|
54
|
+
|
|
55
|
+
const doc = new DOMParser().parseFromString(drafts['index.html'] ?? await text('index.html'), 'text/html')
|
|
56
|
+
const report = Object.assign(doc.createElement('script'), { textContent: reporter })
|
|
57
|
+
const base = Object.assign(doc.createElement('base'), { href: page.base })
|
|
58
|
+
const map = doc.querySelector('script[type="importmap"]') ?? Object.assign(doc.createElement('script'), { type: 'importmap', textContent: '{}' })
|
|
59
|
+
const { imports, ...rest } = JSON.parse(map.textContent)
|
|
60
|
+
map.textContent = JSON.stringify({ ...rest, imports: { ...imports, ...modules } })
|
|
61
|
+
doc.head.prepend(report, base, map)
|
|
62
|
+
|
|
63
|
+
await Promise.all([...doc.querySelectorAll('link[rel="stylesheet"][href]')].map(async link => {
|
|
64
|
+
const path = pathOf(page, new URL(link.getAttribute('href'), page.base).href)
|
|
65
|
+
if (has(path)) link.setAttribute('href', await styled(path))
|
|
66
|
+
}))
|
|
67
|
+
doc.querySelectorAll('script[type="module"][src]').forEach(script => {
|
|
68
|
+
const target = new URL(script.getAttribute('src'), page.base).href
|
|
69
|
+
script.setAttribute('src', modules[target] ?? target)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
return blob(`<!doctype html>\n${doc.documentElement.outerHTML}`, 'text/html', 'index.html')
|
|
73
|
+
}
|