blume 0.7.0 → 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/CHANGELOG.md +666 -0
- package/LICENSE +21 -0
- package/README.md +107 -0
- package/dist/cli/index.js +1852 -380
- package/dist/cli/index.js.map +98 -91
- package/dist/types/ai/component-markdown.d.ts +34 -0
- package/dist/types/components/content/youtube.d.ts +18 -0
- package/dist/types/core/base-path.d.ts +9 -0
- package/dist/types/core/config-input.d.ts +47 -2
- package/dist/types/core/config.d.ts +3 -2
- package/dist/types/core/data.d.ts +7 -0
- package/dist/types/core/i18n-ui.d.ts +526 -132
- package/dist/types/core/schema.d.ts +293 -146
- package/dist/types/index.d.ts +1 -0
- package/dist/types/openapi/references.d.ts +60 -0
- package/dist/types/seo/x-handle.d.ts +12 -0
- package/docs/01-quickstart.mdx +5 -2
- package/docs/02-deployment.mdx +8 -8
- package/docs/03-faq.mdx +46 -16
- package/docs/advanced/api-reference.mdx +1 -1
- package/docs/advanced/changelog.mdx +1 -1
- package/docs/advanced/custom-pages.mdx +1 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/configuration/ai.mdx +49 -10
- package/docs/configuration/customization.mdx +11 -0
- package/docs/configuration/export.mdx +1 -1
- package/docs/configuration/index.mdx +27 -3
- package/docs/configuration/seo.mdx +35 -5
- package/docs/content/components.mdx +2 -2
- package/docs/content/i18n.mdx +1 -1
- package/docs/content/navigation.mdx +3 -3
- package/docs/content/sources.mdx +1 -1
- package/docs/content/syntax.mdx +6 -4
- package/docs/index.mdx +2 -2
- package/docs/reference/cli.mdx +9 -7
- package/docs/reference/frontmatter.mdx +1 -1
- package/package.json +22 -4
- package/skills/blume/SKILL.md +5 -3
- package/skills/blume-update-docs/SKILL.md +3 -2
- package/src/ai/agent-readability.ts +9 -8
- package/src/ai/ask-context.ts +7 -2
- package/src/ai/ask-data.ts +3 -0
- package/src/ai/component-markdown.ts +461 -0
- package/src/ai/llms.ts +135 -26
- package/src/ai/markdown.ts +35 -6
- package/src/ai/mcp/data.ts +25 -4
- package/src/ai/mcp/discovery.ts +10 -3
- package/src/ai/mcp/server.ts +21 -7
- package/src/ai/mcp/tools.ts +1 -1
- package/src/ai/visibility.ts +74 -0
- package/src/astro/component-slots.ts +11 -1
- package/src/astro/generate.ts +77 -45
- package/src/astro/integration.ts +1 -1
- package/src/astro/markdown-negotiation.ts +1 -1
- package/src/astro/pages.ts +81 -19
- package/src/astro/templates.ts +150 -19
- package/src/blume-modules.d.ts +8 -0
- package/src/cli/commands/build.ts +120 -23
- package/src/cli/commands/check.ts +1 -1
- package/src/cli/commands/dev.ts +26 -5
- package/src/cli/commands/eject.ts +47 -19
- package/src/cli/commands/init.ts +120 -180
- package/src/cli/commands/preview.ts +4 -1
- package/src/cli/commands/validate.ts +43 -2
- package/src/cli/dev-lock.ts +8 -4
- package/src/cli/eject-scripts.ts +72 -0
- package/src/cli/env.ts +15 -5
- package/src/cli/init/questions.ts +158 -0
- package/src/cli/init/scaffold.ts +380 -0
- package/src/cli/internal-error.ts +9 -4
- package/src/cli/prepare.ts +3 -2
- package/src/components/Icon.astro +2 -1
- package/src/components/content/AccordionItem.astro +23 -4
- package/src/components/content/Badge.astro +3 -1
- package/src/components/content/Card.astro +4 -2
- package/src/components/content/Step.astro +10 -1
- package/src/components/content/Tabs.astro +15 -3
- package/src/components/content/Tile.astro +2 -1
- package/src/components/content/Tooltip.astro +3 -1
- package/src/components/content/Update.astro +9 -2
- package/src/components/content/auto-type-table.ts +7 -1
- package/src/components/content/base-href.ts +33 -0
- package/src/components/content/changelog-element.ts +9 -2
- package/src/components/content/mermaid-element.ts +7 -2
- package/src/components/islands/AskAI.astro +5 -2
- package/src/components/islands/ask-ai.tsx +86 -11
- package/src/components/islands/hooks.ts +28 -8
- package/src/components/layout/Banner.astro +10 -2
- package/src/components/layout/Breadcrumbs.astro +11 -2
- package/src/components/layout/Header.astro +13 -4
- package/src/components/layout/Logo.astro +11 -3
- package/src/components/layout/NavTree.astro +19 -5
- package/src/components/layout/PageActions.astro +25 -10
- package/src/components/layout/PageLayout.astro +85 -9
- package/src/components/layout/Pagination.astro +10 -4
- package/src/components/layout/ReferenceLayout.astro +20 -2
- package/src/components/layout/RootLayout.astro +142 -12
- package/src/components/layout/Search.astro +117 -27
- package/src/components/layout/search/algolia.ts +11 -2
- package/src/components/layout/search/endpoint.ts +11 -5
- package/src/components/layout/search/orama-cloud.ts +8 -2
- package/src/components/layout/search/types.ts +5 -1
- package/src/components/layout/search/typesense.ts +4 -1
- package/src/components/layout/toc-element.ts +1 -1
- package/src/components/openapi/ApiTagOperations.astro +2 -1
- package/src/components/openapi/Operation.astro +47 -40
- package/src/components/openapi/RequestPanel.astro +1 -1
- package/src/components/openapi/helpers.ts +71 -3
- package/src/components/openapi/panel.ts +1 -1
- package/src/core/base-path.ts +24 -0
- package/src/core/builtin-tags.ts +2 -0
- package/src/core/config-input.ts +48 -2
- package/src/core/config.ts +3 -2
- package/src/core/data.ts +4 -0
- package/src/core/frontmatter.ts +7 -0
- package/src/core/graph.ts +15 -5
- package/src/core/i18n-ui.ts +54 -0
- package/src/core/i18n.ts +16 -8
- package/src/core/last-modified.ts +13 -6
- package/src/core/links.ts +32 -8
- package/src/core/navigation.ts +29 -4
- package/src/core/package-json.ts +17 -2
- package/src/core/project-graph.ts +15 -6
- package/src/core/schema.ts +71 -2
- package/src/core/sources/assets.ts +6 -1
- package/src/core/sources/filesystem.ts +4 -0
- package/src/core/sources/mdx-remote.ts +23 -14
- package/src/core/sources/normalize.ts +152 -50
- package/src/core/sources/notion.ts +8 -8
- package/src/core/ui-packs/ar.ts +8 -0
- package/src/core/ui-packs/bg.ts +8 -0
- package/src/core/ui-packs/bn.ts +8 -0
- package/src/core/ui-packs/ca.ts +8 -0
- package/src/core/ui-packs/cs.ts +8 -0
- package/src/core/ui-packs/da.ts +8 -0
- package/src/core/ui-packs/de.ts +8 -0
- package/src/core/ui-packs/el.ts +8 -0
- package/src/core/ui-packs/es.ts +8 -0
- package/src/core/ui-packs/fa.ts +8 -0
- package/src/core/ui-packs/fi.ts +8 -0
- package/src/core/ui-packs/fr.ts +9 -1
- package/src/core/ui-packs/he.ts +8 -0
- package/src/core/ui-packs/hi.ts +8 -0
- package/src/core/ui-packs/hr.ts +8 -0
- package/src/core/ui-packs/hu.ts +8 -0
- package/src/core/ui-packs/id.ts +8 -0
- package/src/core/ui-packs/it.ts +8 -0
- package/src/core/ui-packs/ja.ts +8 -0
- package/src/core/ui-packs/ko.ts +8 -0
- package/src/core/ui-packs/nl.ts +8 -0
- package/src/core/ui-packs/no.ts +8 -0
- package/src/core/ui-packs/pl.ts +8 -0
- package/src/core/ui-packs/pt-br.ts +8 -0
- package/src/core/ui-packs/pt.ts +8 -0
- package/src/core/ui-packs/ro.ts +8 -0
- package/src/core/ui-packs/ru.ts +8 -0
- package/src/core/ui-packs/sk.ts +8 -0
- package/src/core/ui-packs/sr.ts +8 -0
- package/src/core/ui-packs/sv.ts +8 -0
- package/src/core/ui-packs/th.ts +8 -0
- package/src/core/ui-packs/tr.ts +8 -0
- package/src/core/ui-packs/uk.ts +8 -0
- package/src/core/ui-packs/vi.ts +8 -0
- package/src/core/ui-packs/zh-tw.ts +8 -0
- package/src/core/ui-packs/zh.ts +8 -0
- package/src/deploy/adapter-output.ts +18 -8
- package/src/deploy/redirects.ts +7 -2
- package/src/deploy/sitemap.ts +53 -11
- package/src/index.ts +5 -0
- package/src/markdown/base-links.ts +10 -8
- package/src/markdown/index.ts +15 -3
- package/src/markdown/inline-code.ts +7 -2
- package/src/markdown/package-commands.ts +10 -4
- package/src/og/card.ts +4 -2
- package/src/og/dimensions.ts +12 -0
- package/src/openapi/model.ts +12 -4
- package/src/openapi/parse.ts +21 -0
- package/src/openapi/references.ts +38 -8
- package/src/openapi/render-mdx.ts +62 -1
- package/src/openapi/source.ts +59 -10
- package/src/registry/eject.ts +184 -12
- package/src/registry/registry.ts +0 -3
- package/src/search/documents.ts +34 -2
- package/src/seo/jsonld.ts +20 -13
- package/src/seo/x-handle.ts +18 -0
|
@@ -90,50 +90,140 @@ const mapRoute = (
|
|
|
90
90
|
return { groups, route, segments };
|
|
91
91
|
};
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
// CommonMark allows backtick *and* tilde fences. The scanners track which
|
|
94
|
+
// delimiter opened the current fence (`null` when outside one) so a ``` line
|
|
95
|
+
// inside a ~~~ block is content, not a toggle — see `nextFenceState`.
|
|
96
|
+
const CODE_FENCE = /^(?<delimiter>```|~~~)/u;
|
|
97
|
+
|
|
98
|
+
/** The fence delimiter opening the current code block, or null outside one. */
|
|
99
|
+
type FenceState = "```" | "~~~" | null;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Advance the fenced-code state for one line: an opening fence records its
|
|
103
|
+
* delimiter, only the matching delimiter closes it, and any other line leaves
|
|
104
|
+
* the state untouched.
|
|
105
|
+
*/
|
|
106
|
+
const nextFenceState = (line: string, fence: FenceState): FenceState => {
|
|
107
|
+
const delimiter = line.trimStart().match(CODE_FENCE)?.groups?.delimiter as
|
|
108
|
+
| Exclude<FenceState, null>
|
|
109
|
+
| undefined;
|
|
110
|
+
if (delimiter === undefined) {
|
|
111
|
+
return fence;
|
|
112
|
+
}
|
|
113
|
+
if (fence === null) {
|
|
114
|
+
return delimiter;
|
|
115
|
+
}
|
|
116
|
+
return fence === delimiter ? null : fence;
|
|
117
|
+
};
|
|
94
118
|
// A closing hash sequence must be preceded by whitespace (CommonMark), so a
|
|
95
|
-
// heading like `## What is C#` keeps its trailing `#`.
|
|
96
|
-
|
|
119
|
+
// heading like `## What is C#` keeps its trailing `#`. Up to 3 leading spaces
|
|
120
|
+
// are allowed; 4+ is an indented code block.
|
|
121
|
+
const ATX_HEADING = /^ {0,3}(?<hashes>#{1,6})\s+(?<text>.+?)(?:\s+#+)?\s*$/u;
|
|
122
|
+
// A setext underline: a run of `=` (level 1) or `-` (level 2) alone on a line,
|
|
123
|
+
// up to 3 leading spaces. It only forms a heading directly under paragraph
|
|
124
|
+
// text — see `scanHeadingLine`.
|
|
125
|
+
const SETEXT_UNDERLINE = /^ {0,3}(?<marker>=+|-+)\s*$/u;
|
|
126
|
+
// Lines that end a paragraph without being one (CommonMark): blank lines are
|
|
127
|
+
// checked separately; these cover list items, blockquotes, and thematic
|
|
128
|
+
// breaks, so a `---` after any of them stays a thematic break, not an
|
|
129
|
+
// underline promoting the list/quote text to a heading.
|
|
130
|
+
const PARAGRAPH_INTERRUPT = /^ {0,3}(?:[-+*][ \t]|\d{1,9}[.)][ \t]|>)/u;
|
|
131
|
+
const THEMATIC_BREAK =
|
|
132
|
+
/^ {0,3}(?:(?:-[ \t]*){3,}|(?:\*[ \t]*){3,}|(?:_[ \t]*){3,})$/u;
|
|
133
|
+
const FRONT_MATTER_CLOSE = /^(?:-{3}|\.{3})\s*$/u;
|
|
97
134
|
|
|
98
135
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* `blume validate` stops false-flagging links like `#the-read--write-fallback`
|
|
105
|
-
* (a hand slugify collapses `--`; github-slugger keeps it) and resolves repeated
|
|
106
|
-
* headings the same way (`setup`, `setup-1`).
|
|
136
|
+
* The body lines, minus a leading front matter block. Bodies from the
|
|
137
|
+
* normalize pipeline are already frontmatter-stripped, but `extractHeadings`
|
|
138
|
+
* also runs on raw documents — where a leading `---` block (closed by `---` or
|
|
139
|
+
* `...`) is front matter, not a thematic break whose closing `---` would
|
|
140
|
+
* underline the last metadata line into a phantom setext heading.
|
|
107
141
|
*/
|
|
108
|
-
|
|
142
|
+
const linesWithoutFrontMatter = (body: string): string[] => {
|
|
143
|
+
const lines = body.split("\n");
|
|
144
|
+
if (!/^-{3}\s*$/u.test(lines[0] ?? "")) {
|
|
145
|
+
return lines;
|
|
146
|
+
}
|
|
147
|
+
const close = lines.findIndex(
|
|
148
|
+
(line, index) => index > 0 && FRONT_MATTER_CLOSE.test(line)
|
|
149
|
+
);
|
|
150
|
+
return close === -1 ? lines : lines.slice(close + 1);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/** Scanner state: the open fence plus the paragraph lines accumulated so far. */
|
|
154
|
+
interface HeadingScanState {
|
|
155
|
+
fence: FenceState;
|
|
156
|
+
/** Consecutive paragraph lines — the candidate text for a setext underline. */
|
|
157
|
+
paragraph: string[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Extract ATX and setext headings from a markdown body, skipping fenced code
|
|
162
|
+
* blocks, exactly as the renderer sees them: ATX headings may be indented up
|
|
163
|
+
* to 3 spaces, and a paragraph underlined with `=`/`-` is a level 1/2 setext
|
|
164
|
+
* heading. Each heading's anchor slug comes from a per-document
|
|
165
|
+
* `github-slugger` — the exact slugger the renderer uses
|
|
166
|
+
* (`markdown/heading-anchors`) — advanced over every heading in document
|
|
167
|
+
* order. Matching it (rather than a hand-rolled slugify) keeps the manifest's
|
|
168
|
+
* anchor ids identical to the rendered ones, so `blume validate` stops
|
|
169
|
+
* false-flagging links like `#the-read--write-fallback` (a hand slugify
|
|
170
|
+
* collapses `--`; github-slugger keeps it) and resolves repeated headings the
|
|
171
|
+
* same way (`setup`, `setup-1`).
|
|
172
|
+
*/
|
|
173
|
+
/** Scan one line for a heading, advancing the fence/paragraph state. */
|
|
109
174
|
const scanHeadingLine = (
|
|
110
175
|
line: string,
|
|
111
|
-
|
|
176
|
+
state: HeadingScanState,
|
|
112
177
|
slugger: GithubSlugger,
|
|
113
178
|
headings: Heading[]
|
|
114
|
-
):
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
|
|
179
|
+
): void => {
|
|
180
|
+
const next = nextFenceState(line, state.fence);
|
|
181
|
+
// Skip fence delimiter lines themselves and anything inside a fence. A fence
|
|
182
|
+
// also ends any open paragraph, so no underline can reach across it.
|
|
183
|
+
if (state.fence !== null || next !== null) {
|
|
184
|
+
state.fence = next;
|
|
185
|
+
state.paragraph = [];
|
|
186
|
+
return;
|
|
120
187
|
}
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
123
|
-
const depth =
|
|
124
|
-
const text = (
|
|
188
|
+
const atx = line.match(ATX_HEADING);
|
|
189
|
+
if (atx?.groups) {
|
|
190
|
+
const depth = atx.groups.hashes?.length ?? 1;
|
|
191
|
+
const text = (atx.groups.text ?? "").trim();
|
|
125
192
|
headings.push({ depth, slug: slugger.slug(text), text });
|
|
193
|
+
state.paragraph = [];
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const setext = line.match(SETEXT_UNDERLINE);
|
|
197
|
+
if (setext?.groups && state.paragraph.length > 0) {
|
|
198
|
+
// Setext wins over thematic break when it closes a paragraph (CommonMark);
|
|
199
|
+
// a multi-line paragraph renders as one heading, soft breaks as spaces.
|
|
200
|
+
const text = state.paragraph.join(" ").trim();
|
|
201
|
+
headings.push({
|
|
202
|
+
depth: setext.groups.marker?.startsWith("=") ? 1 : 2,
|
|
203
|
+
slug: slugger.slug(text),
|
|
204
|
+
text,
|
|
205
|
+
});
|
|
206
|
+
state.paragraph = [];
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (
|
|
210
|
+
line.trim() === "" ||
|
|
211
|
+
THEMATIC_BREAK.test(line) ||
|
|
212
|
+
PARAGRAPH_INTERRUPT.test(line)
|
|
213
|
+
) {
|
|
214
|
+
state.paragraph = [];
|
|
215
|
+
return;
|
|
126
216
|
}
|
|
127
|
-
|
|
217
|
+
state.paragraph.push(line.trim());
|
|
128
218
|
};
|
|
129
219
|
|
|
130
220
|
export const extractHeadings = (body: string): Heading[] => {
|
|
131
221
|
const headings: Heading[] = [];
|
|
132
222
|
const slugger = new GithubSlugger();
|
|
133
|
-
|
|
223
|
+
const state: HeadingScanState = { fence: null, paragraph: [] };
|
|
134
224
|
|
|
135
|
-
for (const line of body
|
|
136
|
-
|
|
225
|
+
for (const line of linesWithoutFrontMatter(body)) {
|
|
226
|
+
scanHeadingLine(line, state, slugger, headings);
|
|
137
227
|
}
|
|
138
228
|
|
|
139
229
|
return headings;
|
|
@@ -145,19 +235,20 @@ const INLINE_CODE = /`[^`]*`/gu;
|
|
|
145
235
|
/**
|
|
146
236
|
* Extract link targets from a markdown body for later validation, recording the
|
|
147
237
|
* 1-based line/column of each target. Skips fenced code blocks and inline code.
|
|
238
|
+
* `lineOffset` shifts every recorded line: the body is frontmatter-stripped, so
|
|
239
|
+
* diagnostics that point into the raw file must add the stripped block's height.
|
|
148
240
|
*/
|
|
149
241
|
/** Scan one line for link targets; returns the next fenced-block state. */
|
|
150
242
|
const scanLinkLine = (
|
|
151
243
|
line: string,
|
|
152
244
|
lineNumber: number,
|
|
153
|
-
|
|
245
|
+
fence: FenceState,
|
|
154
246
|
links: PageLink[]
|
|
155
|
-
):
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return inFence;
|
|
247
|
+
): FenceState => {
|
|
248
|
+
const next = nextFenceState(line, fence);
|
|
249
|
+
// Skip fence delimiter lines themselves and anything inside a fence.
|
|
250
|
+
if (fence !== null || next !== null) {
|
|
251
|
+
return next;
|
|
161
252
|
}
|
|
162
253
|
// Blank out inline code spans (`[label](/x)` shown as syntax, not a link)
|
|
163
254
|
// with same-length padding so recorded columns stay accurate.
|
|
@@ -180,17 +271,17 @@ const scanLinkLine = (
|
|
|
180
271
|
target,
|
|
181
272
|
});
|
|
182
273
|
}
|
|
183
|
-
return
|
|
274
|
+
return next;
|
|
184
275
|
};
|
|
185
276
|
|
|
186
|
-
export const extractLinks = (body: string): PageLink[] => {
|
|
277
|
+
export const extractLinks = (body: string, lineOffset = 0): PageLink[] => {
|
|
187
278
|
const links: PageLink[] = [];
|
|
188
|
-
let
|
|
189
|
-
let lineNumber =
|
|
279
|
+
let fence: FenceState = null;
|
|
280
|
+
let lineNumber = lineOffset;
|
|
190
281
|
|
|
191
282
|
for (const line of body.split("\n")) {
|
|
192
283
|
lineNumber += 1;
|
|
193
|
-
|
|
284
|
+
fence = scanLinkLine(line, lineNumber, fence, links);
|
|
194
285
|
}
|
|
195
286
|
|
|
196
287
|
return links;
|
|
@@ -212,14 +303,13 @@ const JSX_OPEN = /<(?<tag>[A-Z][A-Za-z0-9]*)/gu;
|
|
|
212
303
|
/** Scan one line for JSX component tags; returns the next fenced-block state. */
|
|
213
304
|
const scanTagLine = (
|
|
214
305
|
line: string,
|
|
215
|
-
|
|
306
|
+
fence: FenceState,
|
|
216
307
|
tags: Set<string>
|
|
217
|
-
):
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return inFence;
|
|
308
|
+
): FenceState => {
|
|
309
|
+
const next = nextFenceState(line, fence);
|
|
310
|
+
// Skip fence delimiter lines themselves and anything inside a fence.
|
|
311
|
+
if (fence !== null || next !== null) {
|
|
312
|
+
return next;
|
|
223
313
|
}
|
|
224
314
|
const clean = line.replaceAll(INLINE_CODE, "").replaceAll(DOUBLE_QUOTED, "");
|
|
225
315
|
for (const match of clean.matchAll(JSX_OPEN)) {
|
|
@@ -228,18 +318,27 @@ const scanTagLine = (
|
|
|
228
318
|
tags.add(tag);
|
|
229
319
|
}
|
|
230
320
|
}
|
|
231
|
-
return
|
|
321
|
+
return next;
|
|
232
322
|
};
|
|
233
323
|
|
|
234
324
|
export const extractComponentTags = (body: string): string[] => {
|
|
235
325
|
const tags = new Set<string>();
|
|
236
|
-
let
|
|
326
|
+
let fence: FenceState = null;
|
|
237
327
|
for (const line of body.split("\n")) {
|
|
238
|
-
|
|
328
|
+
fence = scanTagLine(line, fence, tags);
|
|
239
329
|
}
|
|
240
330
|
return [...tags];
|
|
241
331
|
};
|
|
242
332
|
|
|
333
|
+
/**
|
|
334
|
+
* Height of the frontmatter block stripped from `raw` to produce `body` (0
|
|
335
|
+
* when the raw text is unknown or nothing was stripped). Link positions are
|
|
336
|
+
* extracted from the stripped body, but diagnostics point into the raw
|
|
337
|
+
* document — recorded lines must shift by this offset to match it.
|
|
338
|
+
*/
|
|
339
|
+
const strippedLineOffset = (raw: string | undefined, body: string): number =>
|
|
340
|
+
raw ? Math.max(0, raw.split("\n").length - body.split("\n").length) : 0;
|
|
341
|
+
|
|
243
342
|
const deriveTitle = (
|
|
244
343
|
meta: PageMeta,
|
|
245
344
|
headings: Heading[],
|
|
@@ -348,7 +447,10 @@ export const normalizeEntry = (
|
|
|
348
447
|
headings,
|
|
349
448
|
id: `${ctx.source.name}:${entry.ref}`,
|
|
350
449
|
lastModified: meta.lastModified ?? entry.lastModified,
|
|
351
|
-
links: extractLinks(
|
|
450
|
+
links: extractLinks(
|
|
451
|
+
entry.body.text,
|
|
452
|
+
strippedLineOffset(entry.raw, entry.body.text)
|
|
453
|
+
),
|
|
352
454
|
meta,
|
|
353
455
|
navPath,
|
|
354
456
|
segments,
|
|
@@ -100,10 +100,9 @@ export interface NotionSourceOptions {
|
|
|
100
100
|
token?: string;
|
|
101
101
|
properties?: NotionPropertyMap;
|
|
102
102
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* workflow rather than publishing).
|
|
103
|
+
* The `Status` property is treated as a publish signal: any value other than
|
|
104
|
+
* this maps to `draft: true`. Defaults to `Published`; pages without a
|
|
105
|
+
* Status/select property are always imported as published.
|
|
107
106
|
*/
|
|
108
107
|
publishedValue?: string;
|
|
109
108
|
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
@@ -395,12 +394,13 @@ export const notionSource = (
|
|
|
395
394
|
};
|
|
396
395
|
|
|
397
396
|
const isDraft = (page: NotionPage): boolean => {
|
|
398
|
-
if (!options.publishedValue) {
|
|
399
|
-
return false;
|
|
400
|
-
}
|
|
401
397
|
const prop = page.properties[props.status ?? "Status"];
|
|
402
398
|
const status = prop?.status?.name ?? prop?.select?.name;
|
|
403
|
-
|
|
399
|
+
// A page without a Status/select property stays published; one with a
|
|
400
|
+
// status is a draft unless it matches the published value.
|
|
401
|
+
return Boolean(
|
|
402
|
+
status && status !== (options.publishedValue ?? "Published")
|
|
403
|
+
);
|
|
404
404
|
};
|
|
405
405
|
|
|
406
406
|
const orderOf = (page: NotionPage): number | undefined => {
|
package/src/core/ui-packs/ar.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const ar: UIStringsOverride = {
|
|
|
23
23
|
send: "إرسال",
|
|
24
24
|
title: "اسأل الذكاء الاصطناعي",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "إغلاق الإعلان" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "تحديثات المنتج وملاحظات الإصدارات.",
|
|
29
|
+
title: "سجل التغييرات",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "لا",
|
|
28
33
|
question: "هل كانت هذه الصفحة مفيدة؟",
|
|
@@ -30,13 +35,16 @@ export const ar: UIStringsOverride = {
|
|
|
30
35
|
yes: "نعم",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "اللغة", untranslated: "غير مترجم" },
|
|
38
|
+
nav: { breadcrumb: "مسار التنقل" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "آخر تحديث في",
|
|
35
41
|
next: "التالي",
|
|
42
|
+
pagination: "ترقيم الصفحات",
|
|
36
43
|
previous: "السابق",
|
|
37
44
|
skipToContent: "الانتقال إلى المحتوى",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "الكل",
|
|
40
48
|
button: "بحث",
|
|
41
49
|
devOnly: "البحث متاح في إصدار الإنتاج.",
|
|
42
50
|
label: "البحث في الوثائق",
|
package/src/core/ui-packs/bg.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const bg: UIStringsOverride = {
|
|
|
23
23
|
send: "Изпрати",
|
|
24
24
|
title: "Попитай ИИ",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "Затваряне на съобщението" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "Актуализации на продукта и бележки към изданията.",
|
|
29
|
+
title: "Дневник на промените",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "Не",
|
|
28
33
|
question: "Беше ли полезна тази страница?",
|
|
@@ -30,13 +35,16 @@ export const bg: UIStringsOverride = {
|
|
|
30
35
|
yes: "Да",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "Език", untranslated: "Непреведено" },
|
|
38
|
+
nav: { breadcrumb: "Навигационна пътека" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "Последна актуализация",
|
|
35
41
|
next: "Напред",
|
|
42
|
+
pagination: "Пагинация",
|
|
36
43
|
previous: "Назад",
|
|
37
44
|
skipToContent: "Към съдържанието",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "Всички",
|
|
40
48
|
button: "Търсене",
|
|
41
49
|
devOnly: "Търсенето е достъпно в производствената компилация.",
|
|
42
50
|
label: "Търсене в документацията",
|
package/src/core/ui-packs/bn.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const bn: UIStringsOverride = {
|
|
|
23
23
|
send: "পাঠান",
|
|
24
24
|
title: "AI-কে জিজ্ঞাসা করুন",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "ঘোষণা বন্ধ করুন" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "পণ্য আপডেট এবং রিলিজ নোট।",
|
|
29
|
+
title: "পরিবর্তন লগ",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "না",
|
|
28
33
|
question: "এই পৃষ্ঠাটি কি সহায়ক ছিল?",
|
|
@@ -30,13 +35,16 @@ export const bn: UIStringsOverride = {
|
|
|
30
35
|
yes: "হ্যাঁ",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "ভাষা", untranslated: "অনূদিত নয়" },
|
|
38
|
+
nav: { breadcrumb: "ব্রেডক্রাম্ব" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "সর্বশেষ আপডেট",
|
|
35
41
|
next: "পরবর্তী",
|
|
42
|
+
pagination: "পেজিনেশন",
|
|
36
43
|
previous: "পূর্ববর্তী",
|
|
37
44
|
skipToContent: "বিষয়বস্তুতে যান",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "সব",
|
|
40
48
|
button: "অনুসন্ধান",
|
|
41
49
|
devOnly: "অনুসন্ধান প্রোডাকশন বিল্ডে উপলব্ধ।",
|
|
42
50
|
label: "ডকুমেন্টেশন অনুসন্ধান করুন",
|
package/src/core/ui-packs/ca.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const ca: UIStringsOverride = {
|
|
|
23
23
|
send: "Envia",
|
|
24
24
|
title: "Pregunta a la IA",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "Tanca l'anunci" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "Actualitzacions del producte i notes de la versió.",
|
|
29
|
+
title: "Registre de canvis",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "No",
|
|
28
33
|
question: "Aquesta pàgina t'ha estat útil?",
|
|
@@ -30,13 +35,16 @@ export const ca: UIStringsOverride = {
|
|
|
30
35
|
yes: "Sí",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "Idioma", untranslated: "Sense traduir" },
|
|
38
|
+
nav: { breadcrumb: "Ruta de navegació" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "Última actualització el",
|
|
35
41
|
next: "Següent",
|
|
42
|
+
pagination: "Paginació",
|
|
36
43
|
previous: "Anterior",
|
|
37
44
|
skipToContent: "Vés al contingut",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "Tots",
|
|
40
48
|
button: "Cerca",
|
|
41
49
|
devOnly: "La cerca està disponible a la compilació de producció.",
|
|
42
50
|
label: "Cerca a la documentació",
|
package/src/core/ui-packs/cs.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const cs: UIStringsOverride = {
|
|
|
23
23
|
send: "Odeslat",
|
|
24
24
|
title: "Zeptat se AI",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "Zavřít oznámení" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "Novinky produktu a poznámky k vydání.",
|
|
29
|
+
title: "Seznam změn",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "Ne",
|
|
28
33
|
question: "Byla tato stránka užitečná?",
|
|
@@ -30,13 +35,16 @@ export const cs: UIStringsOverride = {
|
|
|
30
35
|
yes: "Ano",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "Jazyk", untranslated: "Nepřeloženo" },
|
|
38
|
+
nav: { breadcrumb: "Drobečková navigace" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "Naposledy aktualizováno",
|
|
35
41
|
next: "Další",
|
|
42
|
+
pagination: "Stránkování",
|
|
36
43
|
previous: "Předchozí",
|
|
37
44
|
skipToContent: "Přejít k obsahu",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "Vše",
|
|
40
48
|
button: "Hledat",
|
|
41
49
|
devOnly: "Vyhledávání je dostupné v produkčním buildu.",
|
|
42
50
|
label: "Prohledat dokumentaci",
|
package/src/core/ui-packs/da.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const da: UIStringsOverride = {
|
|
|
23
23
|
send: "Send",
|
|
24
24
|
title: "Spørg AI",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "Luk meddelelsen" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "Produktopdateringer og udgivelsesnoter.",
|
|
29
|
+
title: "Ændringslog",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "Nej",
|
|
28
33
|
question: "Var denne side nyttig?",
|
|
@@ -30,13 +35,16 @@ export const da: UIStringsOverride = {
|
|
|
30
35
|
yes: "Ja",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "Sprog", untranslated: "Ikke oversat" },
|
|
38
|
+
nav: { breadcrumb: "Brødkrummesti" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "Senest opdateret den",
|
|
35
41
|
next: "Næste",
|
|
42
|
+
pagination: "Paginering",
|
|
36
43
|
previous: "Forrige",
|
|
37
44
|
skipToContent: "Spring til indhold",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "Alle",
|
|
40
48
|
button: "Søg",
|
|
41
49
|
devOnly: "Søgning er tilgængelig i produktionsbygningen.",
|
|
42
50
|
label: "Søg i dokumentationen",
|
package/src/core/ui-packs/de.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const de: UIStringsOverride = {
|
|
|
23
23
|
send: "Senden",
|
|
24
24
|
title: "KI fragen",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "Ankündigung schließen" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "Produkt-Updates und Versionshinweise.",
|
|
29
|
+
title: "Änderungsprotokoll",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "Nein",
|
|
28
33
|
question: "War diese Seite hilfreich?",
|
|
@@ -30,13 +35,16 @@ export const de: UIStringsOverride = {
|
|
|
30
35
|
yes: "Ja",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "Sprache", untranslated: "Nicht übersetzt" },
|
|
38
|
+
nav: { breadcrumb: "Brotkrümelnavigation" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "Zuletzt aktualisiert am",
|
|
35
41
|
next: "Weiter",
|
|
42
|
+
pagination: "Seitennummerierung",
|
|
36
43
|
previous: "Zurück",
|
|
37
44
|
skipToContent: "Zum Inhalt springen",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "Alle",
|
|
40
48
|
button: "Suchen",
|
|
41
49
|
devOnly: "Die Suche ist im Produktions-Build verfügbar.",
|
|
42
50
|
label: "Dokumentation durchsuchen",
|
package/src/core/ui-packs/el.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const el: UIStringsOverride = {
|
|
|
23
23
|
send: "Αποστολή",
|
|
24
24
|
title: "Ρωτήστε την AI",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "Κλείσιμο ανακοίνωσης" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "Ενημερώσεις προϊόντος και σημειώσεις έκδοσης.",
|
|
29
|
+
title: "Ιστορικό αλλαγών",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "Όχι",
|
|
28
33
|
question: "Σας φάνηκε χρήσιμη αυτή η σελίδα;",
|
|
@@ -30,13 +35,16 @@ export const el: UIStringsOverride = {
|
|
|
30
35
|
yes: "Ναι",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "Γλώσσα", untranslated: "Δεν έχει μεταφραστεί" },
|
|
38
|
+
nav: { breadcrumb: "Διαδρομή πλοήγησης" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "Τελευταία ενημέρωση",
|
|
35
41
|
next: "Επόμενο",
|
|
42
|
+
pagination: "Σελιδοποίηση",
|
|
36
43
|
previous: "Προηγούμενο",
|
|
37
44
|
skipToContent: "Μετάβαση στο περιεχόμενο",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "Όλα",
|
|
40
48
|
button: "Αναζήτηση",
|
|
41
49
|
devOnly: "Η αναζήτηση είναι διαθέσιμη στην έκδοση παραγωγής.",
|
|
42
50
|
label: "Αναζήτηση στην τεκμηρίωση",
|
package/src/core/ui-packs/es.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const es: UIStringsOverride = {
|
|
|
23
23
|
send: "Enviar",
|
|
24
24
|
title: "Preguntar a la IA",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "Cerrar el anuncio" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "Novedades del producto y notas de la versión.",
|
|
29
|
+
title: "Registro de cambios",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "No",
|
|
28
33
|
question: "¿Te ha resultado útil esta página?",
|
|
@@ -30,13 +35,16 @@ export const es: UIStringsOverride = {
|
|
|
30
35
|
yes: "Sí",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "Idioma", untranslated: "Sin traducir" },
|
|
38
|
+
nav: { breadcrumb: "Ruta de navegación" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "Última actualización el",
|
|
35
41
|
next: "Siguiente",
|
|
42
|
+
pagination: "Paginación",
|
|
36
43
|
previous: "Anterior",
|
|
37
44
|
skipToContent: "Saltar al contenido",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "Todos",
|
|
40
48
|
button: "Buscar",
|
|
41
49
|
devOnly: "La búsqueda está disponible en la compilación de producción.",
|
|
42
50
|
label: "Buscar en la documentación",
|
package/src/core/ui-packs/fa.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const fa: UIStringsOverride = {
|
|
|
23
23
|
send: "ارسال",
|
|
24
24
|
title: "از هوش مصنوعی بپرسید",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "بستن اطلاعیه" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "بهروزرسانیهای محصول و یادداشتهای انتشار.",
|
|
29
|
+
title: "گزارش تغییرات",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "خیر",
|
|
28
33
|
question: "آیا این صفحه مفید بود؟",
|
|
@@ -30,13 +35,16 @@ export const fa: UIStringsOverride = {
|
|
|
30
35
|
yes: "بله",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "زبان", untranslated: "ترجمهنشده" },
|
|
38
|
+
nav: { breadcrumb: "مسیر ناوبری" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "آخرین بهروزرسانی",
|
|
35
41
|
next: "بعدی",
|
|
42
|
+
pagination: "صفحهبندی",
|
|
36
43
|
previous: "قبلی",
|
|
37
44
|
skipToContent: "پرش به محتوا",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "همه",
|
|
40
48
|
button: "جستجو",
|
|
41
49
|
devOnly: "جستجو در نسخه تولید در دسترس است.",
|
|
42
50
|
label: "جستجو در مستندات",
|
package/src/core/ui-packs/fi.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const fi: UIStringsOverride = {
|
|
|
23
23
|
send: "Lähetä",
|
|
24
24
|
title: "Kysy tekoälyltä",
|
|
25
25
|
},
|
|
26
|
+
banner: { dismiss: "Sulje ilmoitus" },
|
|
27
|
+
changelog: {
|
|
28
|
+
description: "Tuotepäivitykset ja julkaisutiedot.",
|
|
29
|
+
title: "Muutosloki",
|
|
30
|
+
},
|
|
26
31
|
feedback: {
|
|
27
32
|
no: "Ei",
|
|
28
33
|
question: "Oliko tästä sivusta apua?",
|
|
@@ -30,13 +35,16 @@ export const fi: UIStringsOverride = {
|
|
|
30
35
|
yes: "Kyllä",
|
|
31
36
|
},
|
|
32
37
|
languageSwitcher: { label: "Kieli", untranslated: "Ei käännetty" },
|
|
38
|
+
nav: { breadcrumb: "Murupolku" },
|
|
33
39
|
page: {
|
|
34
40
|
lastUpdated: "Viimeksi päivitetty",
|
|
35
41
|
next: "Seuraava",
|
|
42
|
+
pagination: "Sivutus",
|
|
36
43
|
previous: "Edellinen",
|
|
37
44
|
skipToContent: "Siirry sisältöön",
|
|
38
45
|
},
|
|
39
46
|
search: {
|
|
47
|
+
all: "Kaikki",
|
|
40
48
|
button: "Hae",
|
|
41
49
|
devOnly: "Haku on käytettävissä tuotantokäännöksessä.",
|
|
42
50
|
label: "Hae dokumentaatiosta",
|