@odla-ai/blog 0.0.3 → 0.0.5
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/LICENSE +21 -0
- package/README.md +15 -8
- package/llms.txt +9 -2
- package/package.json +14 -4
- package/src/markdown.js +10 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cory Ondrejka
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
# @odla-ai/blog
|
|
2
2
|
|
|
3
|
+
> ⚠️ **Early access — pre-1.0.** Agents work from bounded runbooks; humans
|
|
4
|
+
> approve credentials, production changes, releases, and merges. APIs and exact
|
|
5
|
+
> package availability can change. Review the documented guarantees and
|
|
6
|
+
> limitations; this software is MIT-licensed and provided without warranty.
|
|
7
|
+
|
|
3
8
|
Minimal-dependency, static-first blogging platform. A site is a directory of
|
|
4
9
|
markdown plus one JSON config; `build()` emits a fully static site that works on
|
|
5
|
-
GitHub Pages or Cloudflare. When [odla-db](https://
|
|
10
|
+
GitHub Pages or Cloudflare. When [odla-db](https://www.npmjs.com/package/@odla-ai/db) is
|
|
6
11
|
configured, interactive features (sign-in, comments, likes) light up as a
|
|
7
12
|
progressive layer — the static site never depends on it.
|
|
8
13
|
|
|
@@ -38,19 +43,21 @@ Pick one with `"theme": "salt"` in `blog.config.json`. Themes ship in the
|
|
|
38
43
|
design system); every built site also gets ui's class-scoped component layer
|
|
39
44
|
(`assets/odla-ui.css` — buttons, form fields, cards, …) theme-matched via the
|
|
40
45
|
theme's `ui.css` token aliases. Override any theme file by placing a
|
|
41
|
-
same-named file in your site's `theme/` directory.
|
|
42
|
-
|
|
46
|
+
same-named file in your site's `theme/` directory. Build your site with the
|
|
47
|
+
package API and preview the emitted static directory with your usual local
|
|
48
|
+
static server.
|
|
43
49
|
|
|
44
50
|
## Deploy (Cloudflare)
|
|
45
51
|
|
|
46
52
|
`build()` emits a plain static directory; serve it from a Worker assets
|
|
47
53
|
binding — `{ "assets": { "directory": "./dist-site" } }` in `wrangler.jsonc`,
|
|
48
54
|
build before every deploy. Add a `main` worker script only when you want
|
|
49
|
-
`/api/*` routes next to the static site
|
|
50
|
-
|
|
55
|
+
`/api/*` routes next to the static site; the public platform manual describes
|
|
56
|
+
how to combine the assets binding with odla-db and o11y.
|
|
51
57
|
|
|
52
58
|
## Status
|
|
53
59
|
|
|
54
|
-
Early. The build pipeline
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
Early. The build pipeline and themes work; CLI (`init`/`new`/`dev`/`check`),
|
|
61
|
+
feeds, search, deploy scaffolding, and the odla-db islands are in progress.
|
|
62
|
+
Track supported behavior in the public docs and the package's shipped
|
|
63
|
+
`llms.txt` rather than relying on internal planning files.
|
package/llms.txt
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
# @odla-ai/blog —
|
|
1
|
+
# @odla-ai/blog — LLM context
|
|
2
|
+
|
|
3
|
+
> Minimal-dependency, static-first blogging platform. Files in, site out; odla-db lights up interactivity when configured.
|
|
4
|
+
|
|
5
|
+
> EARLY ACCESS — pre-1.0. Agents work from bounded runbooks; humans approve
|
|
6
|
+
> credentials, production changes, releases, and merges. APIs and exact package
|
|
7
|
+
> availability can change. Review the documented guarantees and limitations;
|
|
8
|
+
> this software is MIT-licensed and provided without warranty.
|
|
2
9
|
|
|
3
10
|
This file ships in the npm package so an agent working in a *site* repo can
|
|
4
11
|
operate the platform from `node_modules/@odla-ai/blog/llms.txt` alone. The
|
|
@@ -172,7 +179,7 @@ to the theme's CSS (after the `ui.css` aliases). Post URLs live under
|
|
|
172
179
|
|
|
173
180
|
The output is a plain static directory — serve it from a Worker's assets
|
|
174
181
|
binding (this is what `blog init --deploy cloudflare` will generate; a
|
|
175
|
-
|
|
182
|
+
the public platform manual documents the same Worker + assets composition):
|
|
176
183
|
|
|
177
184
|
```js
|
|
178
185
|
// build-site.mjs — run before every deploy
|
package/package.json
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@odla-ai/blog",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Minimal-dependency, static-first blogging platform. Files in, site out; odla-db lights up interactivity when configured.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"homepage": "https://odla.ai/docs/packages/blog",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/cory/odla-ai.git",
|
|
11
|
+
"directory": "packages/blog"
|
|
12
|
+
},
|
|
7
13
|
"exports": {
|
|
8
14
|
".": "./src/index.js"
|
|
9
15
|
},
|
|
@@ -14,17 +20,21 @@
|
|
|
14
20
|
"config.schema.json"
|
|
15
21
|
],
|
|
16
22
|
"publishConfig": {
|
|
17
|
-
"access": "public"
|
|
23
|
+
"access": "public",
|
|
24
|
+
"provenance": false
|
|
18
25
|
},
|
|
19
26
|
"engines": {
|
|
20
27
|
"node": ">=20"
|
|
21
28
|
},
|
|
22
29
|
"scripts": {
|
|
23
30
|
"preview": "node scripts/preview.mjs",
|
|
24
|
-
"test": "node --test --test-reporter=spec"
|
|
31
|
+
"test": "node --test --test-reporter=spec",
|
|
32
|
+
"coverage": "c8 --src=src --reporter=text --reporter=html node --test",
|
|
33
|
+
"gen:llms": "node ../../scripts/gen-llms.mjs",
|
|
34
|
+
"prepublishOnly": "npm run gen:llms && npm test"
|
|
25
35
|
},
|
|
26
36
|
"dependencies": {
|
|
27
|
-
"@odla-ai/ui": "^0.
|
|
37
|
+
"@odla-ai/ui": "^0.2.2",
|
|
28
38
|
"highlight.js": "^11.11.0",
|
|
29
39
|
"marked": "^16.0.0",
|
|
30
40
|
"yaml": "^2.8.0"
|
package/src/markdown.js
CHANGED
|
@@ -31,12 +31,21 @@ export function slugify(text) {
|
|
|
31
31
|
// is synchronous, so module-level state is safe.
|
|
32
32
|
let footnoteNumbers = new Map(); // id → number, in first-reference order
|
|
33
33
|
let footnoteBodies = new Map(); // id → rendered inline HTML
|
|
34
|
+
let headingIds = new Map(); // base slug → occurrences in this document
|
|
35
|
+
|
|
36
|
+
function uniqueHeadingId(text) {
|
|
37
|
+
const base = slugify(text);
|
|
38
|
+
const count = (headingIds.get(base) ?? 0) + 1;
|
|
39
|
+
headingIds.set(base, count);
|
|
40
|
+
return count === 1 ? base : `${base}-${count}`;
|
|
41
|
+
}
|
|
34
42
|
|
|
35
43
|
const footnotes = {
|
|
36
44
|
hooks: {
|
|
37
45
|
preprocess(markdown) {
|
|
38
46
|
footnoteNumbers = new Map();
|
|
39
47
|
footnoteBodies = new Map();
|
|
48
|
+
headingIds = new Map();
|
|
40
49
|
// Number by first reference (definitions like "[^id]:" excluded).
|
|
41
50
|
for (const match of markdown.matchAll(/\[\^([^\]\s]+)\](?!:)/g)) {
|
|
42
51
|
if (!footnoteNumbers.has(match[1])) {
|
|
@@ -135,7 +144,7 @@ const marked = new Marked(
|
|
|
135
144
|
},
|
|
136
145
|
heading({ tokens, depth }) {
|
|
137
146
|
const text = this.parser.parseInline(tokens);
|
|
138
|
-
const id =
|
|
147
|
+
const id = uniqueHeadingId(text);
|
|
139
148
|
return `<h${depth} id="${id}">${text}</h${depth}>\n`;
|
|
140
149
|
},
|
|
141
150
|
},
|