livemark 0.28.2 → 0.28.3
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/build/actions/config/load.js +16 -15
- package/build/actions/config/load.unit.js +13 -1
- package/build/commands/start.js +31 -8
- package/build/content-collections.js +2 -2
- package/build/helpers/local-imports.d.ts +2 -0
- package/build/helpers/local-imports.js +20 -0
- package/build/helpers/local-imports.unit.d.ts +1 -0
- package/build/helpers/local-imports.unit.js +25 -0
- package/build/helpers/toc.d.ts +1 -1
- package/build/helpers/toc.js +29 -31
- package/build/helpers/toc.unit.js +23 -1
- package/build/models/config.d.ts +2 -0
- package/build/models/config.js +2 -1
- package/build/plugins/vite-livemark.js +72 -6
- package/package.json +1 -1
- package/skills/livemark-configuration/SKILL.md +1 -1
- package/source/actions/config/load.ts +15 -6
- package/source/actions/config/load.unit.ts +17 -0
- package/source/commands/start.ts +24 -0
- package/source/content-collections.ts +1 -1
- package/source/helpers/local-imports.ts +19 -0
- package/source/helpers/local-imports.unit.ts +36 -0
- package/source/helpers/toc.ts +29 -29
- package/source/helpers/toc.unit.ts +27 -0
- package/source/models/config.ts +1 -0
- package/source/plugins/vite-livemark.ts +72 -6
- package/source/styles/markdown.css +5 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { cpSync, existsSync, rmSync, statSync } from "node:fs"
|
|
2
|
-
import { join, sep } from "node:path"
|
|
3
|
-
import type { ConfigEnv, Plugin, UserConfig as ViteUserConfig } from "vite"
|
|
1
|
+
import { cpSync, existsSync, readFileSync, rmSync, statSync } from "node:fs"
|
|
2
|
+
import { dirname, join, sep } from "node:path"
|
|
3
|
+
import type { ConfigEnv, Plugin, UserConfig as ViteUserConfig, ViteDevServer } from "vite"
|
|
4
4
|
import { mergeConfig } from "vite"
|
|
5
5
|
import packageJson from "../../package.json" with { type: "json" }
|
|
6
6
|
import { buildTarget } from "../actions/target/build.ts"
|
|
7
|
+
import { collectLocalImports } from "../helpers/local-imports.ts"
|
|
7
8
|
import { renderInlineMarkdown } from "../helpers/render-inline-markdown.ts"
|
|
8
9
|
import { excludeTailwindSources } from "../helpers/tailwind-sources.ts"
|
|
9
10
|
import { resolveTargetExport } from "../helpers/target-export.ts"
|
|
@@ -17,6 +18,13 @@ export interface LivemarkOptions {
|
|
|
17
18
|
|
|
18
19
|
const SOURCE_DIR = join(import.meta.dirname, "..")
|
|
19
20
|
const IS_INSTALLED = SOURCE_DIR.includes(`${sep}node_modules${sep}`)
|
|
21
|
+
const LOCKFILES = [
|
|
22
|
+
"pnpm-lock.yaml",
|
|
23
|
+
"package-lock.json",
|
|
24
|
+
"yarn.lock",
|
|
25
|
+
"bun.lock",
|
|
26
|
+
"bun.lockb",
|
|
27
|
+
]
|
|
20
28
|
|
|
21
29
|
/** Single virtual module exposing livemark's runtime values to consumer
|
|
22
30
|
* override files via named exports:
|
|
@@ -102,18 +110,29 @@ export function livemark(opts: LivemarkOptions): Plugin {
|
|
|
102
110
|
].join("\n")
|
|
103
111
|
},
|
|
104
112
|
configureServer(server) {
|
|
113
|
+
// Vite restarts only for its own config's imports; the project config's
|
|
114
|
+
// imports and, in livemark's own dev, the content-collections config's
|
|
115
|
+
// imports need it too. A restart rebuilds the target, so no sync is lost.
|
|
116
|
+
const restartFiles = new Set([
|
|
117
|
+
opts.config.configPath,
|
|
118
|
+
...opts.config.configDependencies,
|
|
119
|
+
...(IS_INSTALLED
|
|
120
|
+
? []
|
|
121
|
+
: collectLocalImports(join(SOURCE_DIR, "content-collections.ts"))),
|
|
122
|
+
])
|
|
105
123
|
// Vite watches only its root (the target); the files the target is
|
|
106
124
|
// copied from join its watcher here. `.livemark/` always exists
|
|
107
125
|
// because the target lives inside it.
|
|
108
|
-
server.watcher.add([
|
|
109
|
-
if (
|
|
126
|
+
server.watcher.add([...restartFiles, overridesRoot])
|
|
127
|
+
if (IS_INSTALLED) watchInstalledVersion(server, opts.config.root)
|
|
128
|
+
else server.watcher.add(SOURCE_DIR)
|
|
110
129
|
server.watcher.on("change", file => onChange(file, "change"))
|
|
111
130
|
server.watcher.on("add", file => onChange(file, "add"))
|
|
112
131
|
server.watcher.on("unlink", file => onChange(file, "unlink"))
|
|
113
132
|
server.watcher.on("unlinkDir", file => onChange(file, "unlink"))
|
|
114
133
|
|
|
115
134
|
function onChange(file: string, kind: "change" | "add" | "unlink") {
|
|
116
|
-
if (file
|
|
135
|
+
if (restartFiles.has(file)) {
|
|
117
136
|
server.restart()
|
|
118
137
|
return
|
|
119
138
|
}
|
|
@@ -196,6 +215,53 @@ function syncSource(
|
|
|
196
215
|
if (existsSync(source)) cpSync(source, dest, { recursive: true, force: true })
|
|
197
216
|
}
|
|
198
217
|
|
|
218
|
+
// A running server keeps the livemark it started with: an in-process restart cannot
|
|
219
|
+
// reload the package's own modules, so an upgrade is reported instead.
|
|
220
|
+
function watchInstalledVersion(server: ViteDevServer, root: string) {
|
|
221
|
+
const packageDir = findInstalledPackageDir(root)
|
|
222
|
+
if (!packageDir) return
|
|
223
|
+
// Vite's watcher ignores node_modules, so the lockfile is what signals an install.
|
|
224
|
+
const projectDir = dirname(dirname(packageDir))
|
|
225
|
+
const manifest = join(packageDir, "package.json")
|
|
226
|
+
const watched = LOCKFILES.map(name => join(projectDir, name))
|
|
227
|
+
server.watcher.add(watched)
|
|
228
|
+
let timer: NodeJS.Timeout | undefined
|
|
229
|
+
server.watcher.on("all", (_, file) => {
|
|
230
|
+
if (!watched.includes(file)) return
|
|
231
|
+
clearTimeout(timer)
|
|
232
|
+
// Let the package manager finish relinking after it writes the lockfile.
|
|
233
|
+
timer = setTimeout(reportUpgrade, 1000)
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
function reportUpgrade() {
|
|
237
|
+
const version = readPackageVersion(manifest)
|
|
238
|
+
if (!version || version === packageJson.version) return
|
|
239
|
+
server.config.logger.warn(
|
|
240
|
+
`livemark ${packageJson.version} → ${version} installed; restart the dev server to use it`,
|
|
241
|
+
{ timestamp: true },
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function findInstalledPackageDir(root: string) {
|
|
247
|
+
for (let dir = root; ; dir = dirname(dir)) {
|
|
248
|
+
const packageDir = join(dir, "node_modules", packageJson.name)
|
|
249
|
+
if (existsSync(packageDir)) return packageDir
|
|
250
|
+
if (dirname(dir) === dir) return undefined
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function readPackageVersion(manifest: string) {
|
|
255
|
+
try {
|
|
256
|
+
const parsed: unknown = JSON.parse(readFileSync(manifest, "utf8"))
|
|
257
|
+
return isObject(parsed) && typeof parsed.version === "string"
|
|
258
|
+
? parsed.version
|
|
259
|
+
: undefined
|
|
260
|
+
} catch {
|
|
261
|
+
return undefined
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
199
265
|
/** Resolve livemark.config.ts's `vite` field — either a config object
|
|
200
266
|
* or a function `(env) => config` (matching Vite's own `defineConfig`).
|
|
201
267
|
* Schema stores it as `unknown`; typing for the consumer's editor
|