@inovus-medical/docs 0.2.0 → 0.4.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/assets/styles.css +1 -2
- package/bin/cli.js +6 -4
- package/package.json +1 -1
- package/src/build.js +10 -1
- package/src/markdown.js +13 -1
- package/src/serve.js +42 -19
package/assets/styles.css
CHANGED
|
@@ -102,8 +102,7 @@ a:hover { text-decoration: underline; }
|
|
|
102
102
|
.layout {
|
|
103
103
|
display: grid;
|
|
104
104
|
grid-template-columns: var(--sidebar-w) minmax(0, 1fr) var(--toc-w);
|
|
105
|
-
|
|
106
|
-
margin: 0 auto;
|
|
105
|
+
width: 100%;
|
|
107
106
|
}
|
|
108
107
|
.sidebar {
|
|
109
108
|
position: sticky; top: var(--header-h); align-self: start;
|
package/bin/cli.js
CHANGED
|
@@ -58,16 +58,18 @@ async function run() {
|
|
|
58
58
|
if (cmd === 'dev') {
|
|
59
59
|
const { pageCount, outPath, contentDir } = await build({ root, inDir, outDir })
|
|
60
60
|
console.log(`✓ Built ${pageCount} page(s) from ${contentDir === '.' ? 'repo root' : contentDir + '/'}`)
|
|
61
|
-
serve({ dir: outPath, port })
|
|
62
|
-
|
|
61
|
+
const { port: actual } = await serve({ dir: outPath, port })
|
|
62
|
+
const busy = actual !== port ? ` (port ${port} was busy)` : ''
|
|
63
|
+
console.log(`→ Serving http://localhost:${actual}${busy} (watching ${contentDir === '.' ? 'repo root' : contentDir + '/'} for changes)`)
|
|
63
64
|
watchAndRebuild({ root, inDir: contentDir, outDir })
|
|
64
65
|
return
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
if (cmd === 'serve') {
|
|
68
69
|
const outPath = path.join(root, outDir)
|
|
69
|
-
serve({ dir: outPath, port })
|
|
70
|
-
|
|
70
|
+
const { port: actual } = await serve({ dir: outPath, port })
|
|
71
|
+
const busy = actual !== port ? ` (port ${port} was busy)` : ''
|
|
72
|
+
console.log(`→ Serving ${outDir}/ at http://localhost:${actual}${busy}`)
|
|
71
73
|
return
|
|
72
74
|
}
|
|
73
75
|
|
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -117,7 +117,16 @@ export async function build({ root = process.cwd(), inDir, outDir = 'dist' } = {
|
|
|
117
117
|
const routeSegments = isIndex ? dirSegments : rawSegments
|
|
118
118
|
const route = toRoute(routeSegments)
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
let rendered
|
|
121
|
+
try {
|
|
122
|
+
rendered = renderer.render(content)
|
|
123
|
+
} catch (err) {
|
|
124
|
+
const rel = path.relative(contentRoot, file)
|
|
125
|
+
console.warn(`⚠ Could not fully render ${rel}: ${err.message} — falling back to plain text.`)
|
|
126
|
+
const escaped = content.replace(/[&<>]/g, (c) => ({ '&': '&', '<': '<', '>': '>' }[c]))
|
|
127
|
+
rendered = { html: `<pre>${escaped}</pre>`, headings: [], text: content.slice(0, 2000), title: null }
|
|
128
|
+
}
|
|
129
|
+
const { html, headings, text, title } = rendered
|
|
121
130
|
const pageTitle = data.title || title || (isIndex ? titleCase(dirSegments[dirSegments.length - 1] || config.title) : titleCase(leaf))
|
|
122
131
|
|
|
123
132
|
const page = {
|
package/src/markdown.js
CHANGED
|
@@ -42,7 +42,19 @@ export async function createRenderer() {
|
|
|
42
42
|
md.use(
|
|
43
43
|
await Shiki({
|
|
44
44
|
themes: { light: 'github-light', dark: 'github-dark' },
|
|
45
|
-
defaultColor: false
|
|
45
|
+
defaultColor: false,
|
|
46
|
+
// Real repos use fence languages Shiki doesn't ship (env, console, ...).
|
|
47
|
+
// Map the common ones, and fall back to plain text instead of crashing the build.
|
|
48
|
+
fallbackLanguage: 'text',
|
|
49
|
+
langAlias: {
|
|
50
|
+
env: 'ini',
|
|
51
|
+
dotenv: 'ini',
|
|
52
|
+
conf: 'ini',
|
|
53
|
+
console: 'bash',
|
|
54
|
+
shell: 'bash',
|
|
55
|
+
cmd: 'bat',
|
|
56
|
+
vue: 'html'
|
|
57
|
+
}
|
|
46
58
|
})
|
|
47
59
|
)
|
|
48
60
|
|
package/src/serve.js
CHANGED
|
@@ -40,24 +40,47 @@ async function resolveFile(dir, urlPath) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Start a static server for `dir`. If the requested port is busy, automatically tries the
|
|
45
|
+
* next ones (up to maxAttempts) instead of crashing. Resolves with the server and the
|
|
46
|
+
* actual port it bound to.
|
|
47
|
+
*/
|
|
48
|
+
export function serve({ dir, port = 8788, maxAttempts = 25 }) {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const server = http.createServer(async (req, res) => {
|
|
51
|
+
try {
|
|
52
|
+
const file = await resolveFile(dir, req.url || '/')
|
|
53
|
+
if (file) {
|
|
54
|
+
res.writeHead(200, { 'content-type': TYPES[path.extname(file)] || 'application/octet-stream' })
|
|
55
|
+
createReadStream(file).pipe(res)
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
const notFound = path.join(dir, '404.html')
|
|
59
|
+
try {
|
|
60
|
+
const body = await fs.readFile(notFound)
|
|
61
|
+
res.writeHead(404, { 'content-type': 'text/html; charset=utf-8' })
|
|
62
|
+
res.end(body)
|
|
63
|
+
} catch {
|
|
64
|
+
res.writeHead(404, { 'content-type': 'text/plain' })
|
|
65
|
+
res.end('Not found')
|
|
66
|
+
}
|
|
67
|
+
} catch (err) {
|
|
68
|
+
// A single bad request should never take down the dev server.
|
|
69
|
+
res.writeHead(500, { 'content-type': 'text/plain' })
|
|
70
|
+
res.end('Internal error: ' + err.message)
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
let attempt = 0
|
|
75
|
+
server.on('error', (err) => {
|
|
76
|
+
if (err.code === 'EADDRINUSE' && attempt < maxAttempts) {
|
|
77
|
+
attempt++
|
|
78
|
+
server.listen(port + attempt)
|
|
79
|
+
} else {
|
|
80
|
+
reject(err)
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
server.once('listening', () => resolve({ server, port: server.address().port }))
|
|
84
|
+
server.listen(port)
|
|
60
85
|
})
|
|
61
|
-
server.listen(port)
|
|
62
|
-
return server
|
|
63
86
|
}
|