@c4a/context-cli 0.7.60 → 0.7.62

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/cli.js CHANGED
@@ -86607,6 +86607,9 @@ var init_packageBuildReceipt = __esm(() => {
86607
86607
  // src/project/knowledgeMapCoverage.ts
86608
86608
  import { readFile as readFile55 } from "node:fs/promises";
86609
86609
  import { join as join66 } from "node:path";
86610
+ function packageMenuTargets(packages) {
86611
+ return new Set(packages.flatMap((pkg) => pkg.kind === "package.kb" ? (pkg.site?.more ?? []).flatMap((item) => item.target ? [item.target.artifact_ref] : []) : []));
86612
+ }
86610
86613
  function knowledgeMapArticleTargets(files) {
86611
86614
  return files.flatMap((file) => {
86612
86615
  const meta = parseKnowledgeFrontmatter(file.content);
@@ -86677,6 +86680,7 @@ var init_knowledgeMapCoverage = __esm(() => {
86677
86680
  var exports_knowledgeMap = {};
86678
86681
  __export(exports_knowledgeMap, {
86679
86682
  readKnowledgeMap: () => readKnowledgeMap,
86683
+ projectMenuTargets: () => projectMenuTargets,
86680
86684
  inspectKnowledgeMap: () => inspectKnowledgeMap,
86681
86685
  applyKnowledgeMapUpdate: () => applyKnowledgeMapUpdate,
86682
86686
  acceptStructureDecision: () => acceptStructureDecision,
@@ -86697,6 +86701,12 @@ async function readKnowledgeMap(root) {
86697
86701
  const content3 = await optionalText(root, KNOWLEDGE_MAP_PATH);
86698
86702
  return content3 === undefined ? undefined : validateKnowledgeMap(import_yaml39.parse(content3));
86699
86703
  }
86704
+ async function projectMenuTargets(root) {
86705
+ const { isContextProjectRoot: isContextProjectRoot2, loadContextProjectModule: loadContextProjectModule2 } = await Promise.resolve().then(() => (init_workspace(), exports_workspace));
86706
+ if (!isContextProjectRoot2(root))
86707
+ return new Set;
86708
+ return packageMenuTargets((await loadContextProjectModule2(root)).project.packages);
86709
+ }
86700
86710
  async function inspectKnowledgeMap(root) {
86701
86711
  const current2 = await readKnowledgeMap(root);
86702
86712
  return {
@@ -86728,7 +86738,8 @@ async function acceptStructureDecision(input) {
86728
86738
  const next = input.knowledge_map === undefined ? current2 : updateKnowledgeMap(current2, input.knowledge_map);
86729
86739
  if (input.article_targets !== undefined) {
86730
86740
  const known = [...await approvedKnowledgeMapTargets(input.projectRoot), ...input.article_targets];
86731
- assertKnowledgeMapCoverage(next, known, { known, require_update: true, has_update: input.knowledge_map !== undefined, revision: input.revision, current_revision: current2?.revision ?? null });
86741
+ const menu = await projectMenuTargets(input.projectRoot);
86742
+ assertKnowledgeMapCoverage(next, known.filter((target) => !menu.has(target.artifact_ref)), { known, require_update: true, has_update: input.knowledge_map !== undefined, revision: input.revision, current_revision: current2?.revision ?? null });
86732
86743
  }
86733
86744
  const writes = [{ path: input.decisionPath, content: canonicalIndexerJson({ revision: input.revision, decision: "approved" }) }];
86734
86745
  if (input.knowledge_map !== undefined)
@@ -86762,7 +86773,8 @@ async function applyKnowledgeMapUpdate(projectRoot, update) {
86762
86773
  title: candidate.review.title,
86763
86774
  section_keys: candidate.indexer_candidate.sections.map((section) => section.section_key)
86764
86775
  }));
86765
- assertKnowledgeMapCoverage(next, approved, { known: [...approved, ...planned, ...accepted], current_revision: current2?.revision ?? null });
86776
+ const menu = await projectMenuTargets(projectRoot);
86777
+ assertKnowledgeMapCoverage(next, approved.filter((target) => !menu.has(target.artifact_ref)), { known: [...approved, ...planned, ...accepted], current_revision: current2?.revision ?? null });
86766
86778
  const content3 = import_yaml39.stringify(next);
86767
86779
  const previous2 = await optionalText(projectRoot, KNOWLEDGE_MAP_PATH);
86768
86780
  await runDurableMultiFileTransaction({
@@ -86820,7 +86832,8 @@ function packageKnowledgeMapTargets(pkg, files) {
86820
86832
  return targets;
86821
86833
  }
86822
86834
  async function writePackageKnowledgeMap(input) {
86823
- assertKnowledgeMapCoverage(input.structure, knowledgeMapArticleTargets(input.selected));
86835
+ const menu = packageMenuTargets([input.pkg]);
86836
+ assertKnowledgeMapCoverage(input.structure, knowledgeMapArticleTargets(input.selected).filter((target) => !menu.has(target.artifact_ref)));
86824
86837
  if (input.structure === undefined || input.pkg.kind !== "package.kb")
86825
86838
  return [];
86826
86839
  const projected = projectKnowledgeMap(input.structure, packageKnowledgeMapTargets(input.pkg, input.selected));
@@ -87128,14 +87141,57 @@ function createDiagramViewer(load) {
87128
87141
  actorBkg: color3("surface", dark ? "#202735" : "#f5f8ff"),
87129
87142
  actorTextColor: color3("text", dark ? "#e2e4ed" : "#161e2e"),
87130
87143
  signalColor: color3("muted-text", dark ? "#9faec5" : "#66758d"),
87131
- signalTextColor: color3("text", dark ? "#e2e4ed" : "#161e2e")
87144
+ signalTextColor: color3("text", dark ? "#e2e4ed" : "#161e2e"),
87145
+ titleColor: color3("muted-text", dark ? "#9faec5" : "#66758d")
87132
87146
  },
87133
- flowchart: { useMaxWidth: false, nodeSpacing: 36, rankSpacing: 58, padding: 16, curve: "linear", wrappingWidth: 220, htmlLabels: false },
87147
+ themeCSS: ".edgeLabel rect{opacity:1}.edgeLabel text{font-size:13px}",
87148
+ flowchart: { useMaxWidth: false, nodeSpacing: 36, rankSpacing: 58, padding: 16, curve: "linear", wrappingWidth: 220, htmlLabels: false, subGraphTitleMargin: { top: 10, bottom: 6 } },
87134
87149
  sequence: { useMaxWidth: false, diagramMarginX: 24, diagramMarginY: 20, actorMargin: 48, messageMargin: 38, wrap: true },
87135
87150
  state: { useMaxWidth: false },
87136
87151
  er: { useMaxWidth: false }
87137
87152
  };
87138
87153
  }
87154
+ function centerEdgeLabels(svg) {
87155
+ if (svg.dataset.labelsCentered || !svg.getClientRects().length)
87156
+ return;
87157
+ svg.dataset.labelsCentered = "true";
87158
+ for (const label2 of svg.querySelectorAll(".edgeLabel > .label[data-id]")) {
87159
+ const box = label2.querySelector("rect.background");
87160
+ const text7 = label2.querySelector("text");
87161
+ const path2 = svg.querySelector(`path[data-id="${CSS.escape(label2.getAttribute("data-id"))}"]`);
87162
+ const toLabel = label2.getCTM();
87163
+ const toPath = path2?.getCTM();
87164
+ const glyphs = text7?.getBBox();
87165
+ if (!box || !path2 || !toLabel || !toPath || !glyphs?.width)
87166
+ continue;
87167
+ box.setAttribute("x", String(glyphs.x - 4));
87168
+ box.setAttribute("y", String(glyphs.y - 1));
87169
+ box.setAttribute("width", String(glyphs.width + 8));
87170
+ box.setAttribute("height", String(glyphs.height + 2));
87171
+ const center = new DOMPoint(box.x.baseVal.value + box.width.baseVal.value / 2, box.y.baseVal.value + box.height.baseVal.value / 2);
87172
+ const local = center.matrixTransform(toLabel).matrixTransform(toPath.inverse());
87173
+ const length = path2.getTotalLength();
87174
+ let best = 0;
87175
+ let distance = Infinity;
87176
+ const probe = (at2) => {
87177
+ const point3 = path2.getPointAtLength(at2);
87178
+ const d = (point3.x - local.x) ** 2 + (point3.y - local.y) ** 2;
87179
+ if (d < distance) {
87180
+ distance = d;
87181
+ best = at2;
87182
+ }
87183
+ };
87184
+ for (let step = 0;step <= 64; step++)
87185
+ probe(length * step / 64);
87186
+ for (let span = length / 64;span > 0.25; span /= 2) {
87187
+ const at2 = best;
87188
+ probe(Math.max(0, at2 - span));
87189
+ probe(Math.min(length, at2 + span));
87190
+ }
87191
+ const target = path2.getPointAtLength(best).matrixTransform(toPath).matrixTransform(toLabel.inverse());
87192
+ label2.setAttribute("transform", `${label2.getAttribute("transform") ?? ""} translate(${target.x - center.x} ${target.y - center.y})`);
87193
+ }
87194
+ }
87139
87195
  function prune() {
87140
87196
  for (const [node3, state] of states)
87141
87197
  if (!node3.isConnected) {
@@ -87214,6 +87270,7 @@ function createDiagramViewer(load) {
87214
87270
  const svg = canvas.querySelector("svg");
87215
87271
  if (!svg || !state.width)
87216
87272
  return;
87273
+ centerEdgeLabels(svg);
87217
87274
  if (state.fit)
87218
87275
  state.scale = Math.min(1, Math.max(0.1, (viewport.clientWidth - 32) / state.width));
87219
87276
  svg.style.width = `${state.width * state.scale}px`;
@@ -87373,6 +87430,7 @@ function createDiagramViewer(load) {
87373
87430
  const element = canvas.querySelector("svg");
87374
87431
  if (!element)
87375
87432
  throw new Error("Missing SVG");
87433
+ centerEdgeLabels(element);
87376
87434
  state.width = element.viewBox.baseVal.width || element.getBoundingClientRect().width || 640;
87377
87435
  element.setAttribute("role", "img");
87378
87436
  if (!element.hasAttribute("aria-label") && !element.hasAttribute("aria-labelledby"))
@@ -87437,10 +87495,10 @@ var init_diagramStyles = __esm(() => {
87437
87495
  .context-diagram-percent{font-size:11px;color:var(--diagram-muted);min-width:34px;text-align:center}
87438
87496
  .context-diagram-viewport{overflow:auto;max-height:620px;min-height:60px;overscroll-behavior:contain;cursor:grab}
87439
87497
  .context-diagram-viewport:active{cursor:grabbing}.context-diagram-canvas{padding:16px;width:max-content;min-width:100%;box-sizing:border-box}
87440
- .context-diagram-canvas svg{display:block;margin:auto;height:auto;max-width:none}.context-diagram-status{padding:12px 16px;font-size:13px;color:var(--diagram-muted)}
87498
+ .context-diagram-canvas svg{display:block;margin:auto;height:auto;max-width:none}.context-diagram-canvas foreignObject p{margin:0;line-height:inherit}.context-diagram-status{padding:12px 16px;font-size:13px;color:var(--diagram-muted)}
87441
87499
  .context-diagram-expanded{position:fixed!important;inset:16px!important;z-index:10000!important;margin:0!important;display:flex;flex-direction:column;box-shadow:0 0 0 100vmax #10182788}
87442
87500
  .context-diagram-expanded .context-diagram-viewport{flex:1;max-height:none}.context-diagram-expanded .context-diagram-tools{flex-shrink:0}
87443
- .vp-doc div.language-mermaid.context-rendered{background:transparent;border:0}
87501
+ .vp-doc div.language-mermaid.context-rendered,div.language-mermaid.context-rendered{background:transparent;border:0;border-radius:0;padding:0;box-shadow:none}
87444
87502
  .context-rendered>pre,.context-rendered>.copy,.context-rendered>.lang{display:none!important}.context-diagram-shell [hidden]{display:none!important}
87445
87503
  .context-diagram-left,.context-diagram-right{display:flex;align-items:center;flex-wrap:wrap;gap:6px}.context-diagram-right{margin-left:auto}
87446
87504
  .context-diagram-tools{opacity:0;pointer-events:none;transition:opacity .15s}.context-diagram-shell:hover .context-diagram-tools,.context-diagram-shell:focus-within .context-diagram-tools{opacity:1;pointer-events:auto}
@@ -87809,6 +87867,12 @@ export default {
87809
87867
  extensions.knowledge === undefined ? siteMap() : extensions.knowledge && custom('knowledge'),
87810
87868
  extensions.resources === undefined ? resources() : extensions.resources && custom('resources')],
87811
87869
  'home-features-after': () => extensions.footer === undefined ? poweredBy() : extensions.footer && custom('footer'),
87870
+ 'not-found': () => h('div', { class: 'context-not-found' }, [
87871
+ h('p', { class: 'context-not-found-code' }, '404'),
87872
+ h('h1', both('页面不存在', 'Page not found')),
87873
+ h('p', both('链接可能已失效,或页面已被移动。', 'The link may be broken, or the page has moved.')),
87874
+ h('a', { class: 'context-not-found-home', href: data.site.value.base }, both('返回首页', 'Back to home')),
87875
+ ]),
87812
87876
  'doc-after': () => history.value ? h('section', { class: 'context-history-cards' },
87813
87877
  history.value.length ? history.value.map((entry, index) =>
87814
87878
  h('details', { class: 'context-history-card', open: index < 3, key: entry.version }, [
@@ -87859,7 +87923,7 @@ export default {
87859
87923
  },
87860
87924
  };
87861
87925
  // History belongs between the page heading and footer metadata.
87862
- return () => h(DefaultTheme.Layout, { class: inHome.value ? 'context-home' :
87926
+ return () => h(DefaultTheme.Layout, { class: inHome.value ? 'context-home' : data.page.value.isNotFound ? 'context-missing' :
87863
87927
  inLlms.value || inHistory.value ? 'context-empty-sidebar' : undefined }, { ...slots, 'doc-after': undefined,
87864
87928
  'doc-footer-before': () => [slots['doc-after'](), slots['doc-footer-before']()] });
87865
87929
  }
@@ -88066,13 +88130,20 @@ ${readerContentStyles(".vp-doc")}
88066
88130
  .context-home-powered { width: var(--context-content); margin: 24px auto 0; padding: 22px 0 30px; border-top: 1px solid var(--vp-c-divider);
88067
88131
  color: var(--vp-c-text-2); font-size: 11px; text-align: right; }
88068
88132
  .context-home-powered a { color: inherit; }
88133
+ /* 404: centred in the space below the top bar, in the reader language */
88134
+ .context-not-found { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: calc(100vh - var(--vp-nav-height)); padding: 48px 24px 96px; text-align: center; }
88135
+ .context-not-found-code { margin: 0; font: 600 72px/1 var(--vp-font-family-mono); letter-spacing: -.04em; color: var(--vp-c-text-1); }
88136
+ .context-not-found h1 { margin: 20px 0 0; font-size: 20px; font-weight: 600; line-height: 1.4; color: var(--vp-c-text-1); }
88137
+ .context-not-found h1 + p { max-width: 28rem; margin: 8px 0 0; font-size: 14px; line-height: 1.7; color: var(--vp-c-text-2); }
88138
+ .context-not-found-home { margin-top: 28px; padding: 0 18px; border: 1px solid var(--vp-c-divider); border-radius: 999px; font-size: 14px; font-weight: 500; line-height: 38px; color: var(--vp-c-text-1) !important; text-decoration: none !important; transition: border-color .2s; }
88139
+ .context-not-found-home:hover { border-color: var(--vp-c-text-3); }
88069
88140
  @keyframes context-home-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
88070
88141
  @media (min-width: 960px) {
88071
88142
  /* The sidebar background reaches the screen edge; its first-level labels line up with the top-bar title. */
88072
88143
  .VPSidebar { top: var(--vp-nav-height) !important; left: 0 !important; width: calc(var(--vp-sidebar-width) + var(--context-edge) - 26px) !important;
88073
88144
  padding: 12px 0 48px calc(var(--context-edge) - 26px) !important; }
88074
88145
  .VPSidebar .curtain { display: none; }
88075
- .VPContent.has-sidebar, .Layout:not(.context-home) .VPContent:not(.is-home) { padding-left: calc(var(--vp-sidebar-width) + var(--context-edge) - 26px) !important;
88146
+ .VPContent.has-sidebar, .Layout:not(.context-home):not(.context-missing) .VPContent:not(.is-home) { padding-left: calc(var(--vp-sidebar-width) + var(--context-edge) - 26px) !important;
88076
88147
  padding-right: calc(var(--context-edge) - var(--context-gutter)) !important; }
88077
88148
  .context-home .VPContent { padding-left: 0 !important; padding-right: 0 !important; }
88078
88149
  .VPDoc { padding: 44px 36px 80px !important; }
@@ -89867,6 +89938,22 @@ ${tail}`));
89867
89938
  });
89868
89939
  });
89869
89940
  }
89941
+ function siteHomeHero(options, input) {
89942
+ const chinese = input.tag.toLowerCase().startsWith("zh");
89943
+ const locale = input.tag === input.primary ? undefined : options.locales?.[input.tag];
89944
+ const own5 = locale?.home;
89945
+ const featured = (own5?.resources ?? options.home?.resources ?? []).filter((resource) => resource.featured && resource.href);
89946
+ return {
89947
+ name: own5?.title ?? locale?.title ?? options.home?.title ?? options.title ?? input.packageName,
89948
+ text: own5?.slogan ?? options.home?.slogan ?? (chinese ? "从知识地图开始探索" : "Explore from the knowledge map"),
89949
+ tagline: own5?.description ?? locale?.description ?? options.home?.description ?? options.description ?? "",
89950
+ actions: own5?.actions ?? options.home?.actions ?? [
89951
+ { theme: "brand", text: chinese ? "浏览知识" : "Browse knowledge", link: input.firstSection },
89952
+ ...featured.map((resource) => ({ theme: "alt", text: resource.title, link: resource.href })),
89953
+ { theme: "alt", text: "LLM Docs", link: "/llms/index.html" }
89954
+ ]
89955
+ };
89956
+ }
89870
89957
  async function writePackageSite(input) {
89871
89958
  if (input.pkg.kind !== "package.kb" || !input.pkg.site)
89872
89959
  return;
@@ -90022,7 +90109,8 @@ ${localized.body}`);
90022
90109
  }
90023
90110
  };
90024
90111
  await writeFile23(join75(configRoot, "config.mjs"), `const contextLocaleMarker = ${JSON.stringify(readers.translated ? marker : null)};
90025
- ` + `export default { ...${JSON.stringify(config)}, markdown: { ${siteMarkdownConfig} } };
90112
+ ` + `export default { ...${JSON.stringify(config)}, markdown: { ${siteMarkdownConfig} },
90113
+ ` + ` transformHtml: html => html.replace(/<script id="check-dark-mode">[\\s\\S]*?<\\/script>/u, "") };
90026
90114
  `);
90027
90115
  const menu = (lines, entries2, level, tag) => entries2.forEach((entry) => {
90028
90116
  const title = mdLabel(localizer.entryTitle(tag, entry));
@@ -90040,24 +90128,8 @@ ${localized.body}`);
90040
90128
  }));
90041
90129
  }
90042
90130
  const firstSection = sections[0]?.href ?? "/llms/index.html";
90043
- const heroFor = (tag) => {
90044
- const chinese = tag.toLowerCase().startsWith("zh");
90045
- const locale = tag === readers.primary ? undefined : options.locales?.[tag];
90046
- const home = locale ? locale.home : options.home;
90047
- const featured = (home?.resources ?? options.home?.resources ?? []).filter((resource) => resource.featured && resource.href);
90048
- return {
90049
- name: (locale ? locale.home?.title ?? locale.title : options.home?.title) ?? options.title ?? pkg.name,
90050
- text: home?.slogan ?? (chinese ? "从知识地图开始探索" : "Explore from the knowledge map"),
90051
- tagline: (locale ? locale.home?.description ?? locale.description : options.home?.description ?? options.description) ?? "",
90052
- actions: home?.actions ?? [
90053
- { theme: "brand", text: chinese ? "浏览知识" : "Browse knowledge", link: firstSection },
90054
- ...featured.map((resource) => ({ theme: "alt", text: resource.title, link: resource.href })),
90055
- { theme: "alt", text: "LLM Docs", link: "/llms/index.html" }
90056
- ]
90057
- };
90058
- };
90059
90131
  const heroTags = readers.translated ? readers.tags : [readers.primary];
90060
- const heroes = new Map(heroTags.map((tag) => [tag, heroFor(tag)]));
90132
+ const heroes = new Map(heroTags.map((tag) => [tag, siteHomeHero(options, { tag, primary: readers.primary, packageName: pkg.name, firstSection })]));
90061
90133
  const hero = {
90062
90134
  name: localizedHtml(heroTags, (tag) => heroes.get(tag).name),
90063
90135
  text: localizedHtml(heroTags, (tag) => heroes.get(tag).text),
@@ -90176,7 +90248,7 @@ var init_packageSite2 = __esm(() => {
90176
90248
  init_packageSiteExtensions();
90177
90249
  init_packageDistributionMetadata();
90178
90250
  init_packageSiteLocales();
90179
- PACKAGE_SITE_VERSION = `vitepress-site-v48-reader-locales:${createHash22("sha256").update(JSON.stringify([siteThemeVariables.toString(), siteMarkdownConfig, siteThemeCss, siteThemeScript, siteThemeLabels("zh"), siteThemeLabels("en")])).digest("hex")}`;
90251
+ PACKAGE_SITE_VERSION = `vitepress-site-v49-appearance-home-fallback:${createHash22("sha256").update(JSON.stringify([siteThemeVariables.toString(), siteMarkdownConfig, siteThemeCss, siteThemeScript, siteThemeLabels("zh"), siteThemeLabels("en")])).digest("hex")}`;
90180
90252
  require2 = createRequire6(import.meta.url);
90181
90253
  });
90182
90254
 
@@ -108893,7 +108965,8 @@ async function writeReviewHtml(input) {
108893
108965
  }
108894
108966
  await writeFile28(outPath, renderReviewHtml(model, diagramScript), "utf8");
108895
108967
  await saveReviewReportScope(input.projectRoot, reviewScope, candidates, model.baselineHash);
108896
- const unplaced = model.pages.filter((page) => page.candidate_id && !model.nodes.some((node3) => node3.page === page.id && node3.parent !== "review-unplaced" && !node3.removed)).map((page) => ({ article_id: page.id, candidate_id: page.candidate_id, path: page.path, title: page.title }));
108968
+ const menu = await projectMenuTargets(input.projectRoot);
108969
+ const unplaced = model.pages.filter((page) => page.candidate_id && !menu.has(page.id) && !model.nodes.some((node3) => node3.page === page.id && node3.parent !== "review-unplaced" && !node3.removed)).map((page) => ({ article_id: page.id, candidate_id: page.candidate_id, path: page.path, title: page.title }));
108897
108970
  return {
108898
108971
  navigation: {
108899
108972
  current_revision: (await readKnowledgeMap(input.projectRoot))?.revision ?? null,