@c4a/context-cli 0.7.63 → 0.7.65

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
@@ -87071,6 +87071,50 @@ function siteArticleSources(article, registry2, repositoryRemote) {
87071
87071
  }
87072
87072
  return [...new Map(sources.map((source2) => [JSON.stringify(source2), source2])).values()];
87073
87073
  }
87074
+ function siteSourceLinks(article, registry2, repositoryRemote) {
87075
+ const candidates = new Map;
87076
+ const names = new Map;
87077
+ const add = (map2, key, url) => map2.set(key, (map2.get(key) ?? new Set).add(url));
87078
+ for (const reference2 of article?.sections.flatMap((section) => section.references) ?? []) {
87079
+ const ref2 = reference2.source_ref;
87080
+ const local = parseRepoContentRef(ref2);
87081
+ const repo = local ? undefined : registry2.repos.find((entry) => ref2 === `repo:${entry.id}` || ref2 === `repo:${entry.name}`);
87082
+ const prefix = repo?.subpath?.replace(/^\/+|\/+$/gu, "") ?? "";
87083
+ const base = repo && repoUrl(repo.remote);
87084
+ const target = (path3, directory) => local ? local.worktree ? undefined : repoContentWebUrl(repositoryRemote, local.commit, path3, directory) : base ? `${base}/${directory ? "tree" : "blob"}/${encodeURIComponent(repo.ref)}/${encodedPath(path3)}` : undefined;
87085
+ const path2 = reference2.locator.path;
87086
+ const parts = path2.split("/");
87087
+ if (!local && !repo || path2.startsWith("/") || parts.some((part) => !part || part === "." || part === ".."))
87088
+ continue;
87089
+ for (const written of new Set([path2, prefix ? `${prefix}/${path2}` : path2])) {
87090
+ const segments = written.split("/");
87091
+ for (let depth = segments.length;depth >= 1; depth--) {
87092
+ const spelled = segments.slice(0, depth).join("/");
87093
+ const full = prefix && !written.startsWith(`${prefix}/`) ? `${prefix}/${spelled}` : spelled;
87094
+ const directory = depth < segments.length;
87095
+ const url = target(local ? spelled : full, directory);
87096
+ if (!url)
87097
+ break;
87098
+ if (!directory)
87099
+ add(candidates, spelled, url);
87100
+ else if (depth >= 2) {
87101
+ add(candidates, spelled, url);
87102
+ add(candidates, `${spelled}/`, url);
87103
+ }
87104
+ const name3 = segments[depth - 1];
87105
+ if (directory && /[._-]/u.test(name3))
87106
+ add(names, name3, url);
87107
+ }
87108
+ }
87109
+ }
87110
+ const links = {};
87111
+ for (const map2 of [names, candidates]) {
87112
+ for (const [key, urls] of map2)
87113
+ if (urls.size === 1)
87114
+ links[key] = [...urls][0];
87115
+ }
87116
+ return links;
87117
+ }
87074
87118
  var encodedPath = (value) => value.split("/").map(encodeURIComponent).join("/");
87075
87119
  var init_packageSiteSources = __esm(() => {
87076
87120
  init_src2();
@@ -87593,6 +87637,29 @@ var init_packageSiteTheme = __esm(() => {
87593
87637
  const render = md.renderer.rules[name];
87594
87638
  if (render) md.renderer.rules[name] = (...args) => render(...args).replace(/\{/g, '&#123;');
87595
87639
  }
87640
+ // The compiler lists contextSourceLinks only from the page's recorded references.
87641
+ // Headings stay unlinked because their text also feeds the outline links.
87642
+ md.core.ruler.push('context_source_links', state => {
87643
+ const links = state.env.frontmatter && state.env.frontmatter.contextSourceLinks;
87644
+ if (!links || typeof links !== 'object') return;
87645
+ state.tokens.forEach((block, position) => {
87646
+ if (block.type !== 'inline' || !block.children || state.tokens[position - 1]?.type === 'heading_open') return;
87647
+ const children = [];
87648
+ let depth = 0;
87649
+ for (const token of block.children) {
87650
+ if (token.type === 'link_open') depth++;
87651
+ if (token.type === 'link_close') depth--;
87652
+ const href = token.type === 'code_inline' && depth === 0 && Object.hasOwn(links, token.content) ? links[token.content] : null;
87653
+ if (typeof href !== 'string' || !/^https?:\/\//.test(href)) { children.push(token); continue; }
87654
+ const open = new state.Token('html_inline', '', 0);
87655
+ open.content = '<a class="context-source-link" href="' + md.utils.escapeHtml(href) + '" target="_blank" rel="noopener noreferrer">';
87656
+ const close = new state.Token('html_inline', '', 0);
87657
+ close.content = '</a>';
87658
+ children.push(open, token, close);
87659
+ }
87660
+ block.children = children;
87661
+ });
87662
+ });
87596
87663
  md.block.ruler.before('paragraph', 'context_anchor', (state, line, end, silent) => {
87597
87664
  const raw = state.src.slice(state.bMarks[line] + state.tShift[line], state.eMarks[line]);
87598
87665
  const match = /^<a id="(section-[a-zA-Z0-9_%.-]+)"><\/a>$/.exec(raw);
@@ -87750,8 +87817,11 @@ export default {
87750
87817
  tags.map(tag => h('span', { 'data-context-locales': tag, lang: next(tag) }, shortLabel(next(tag))))),
87751
87818
  ]);
87752
87819
  };
87820
+ // Origin links become absolute URLs, which VitePress never marks active.
87753
87821
  const navLink = item => ({ text: item.text,
87754
- ...(item.origin ? { link: mounted.value ? window.location.origin + item.link : item.link, target: '_self', noIcon: true } : { link: item.link }) });
87822
+ ...(item.origin ? { link: mounted.value ? window.location.origin + item.link : item.link, target: '_self', noIcon: true,
87823
+ activeMatch: [item.link, item.link + 'index.html'].includes(route.path) ||
87824
+ (inHome.value && item.link === data.site.value.base) ? '^' : '(?!)' } : { link: item.link }) });
87755
87825
  const href = value => value.startsWith('/') ? data.site.value.base + value.slice(1) : value;
87756
87826
  const external = value => /^https?:\/\//.test(value) || value.startsWith('mailto:');
87757
87827
  const copyCommand = async value => {
@@ -87871,7 +87941,7 @@ export default {
87871
87941
  ...data.theme.value.contextUiLabels?.[chinese.value ? 'zh' : 'en'],
87872
87942
  sidebar: outsideSections.value ? [] : active.value?.items || [],
87873
87943
  nav: [...userNav('start'), ...sections.value.map(section => ({ text: section.label, link: section.href,
87874
- activeMatch: !outsideSections.value && section.key === selected.value ? '^' : '(?!)' })),
87944
+ activeMatch: !inHome.value && !outsideSections.value && section.key === selected.value ? '^' : '(?!)' })),
87875
87945
  ...userNav('end'),
87876
87946
  { text: bothHtml('更多', 'More'), items: [
87877
87947
  ...(data.theme.value.contextMore || []).map(navLink),
@@ -87969,14 +88039,20 @@ export default {
87969
88039
  `;
87970
88040
  siteThemeCss = `
87971
88041
  .context-business-floating { position: fixed; right: max(20px, env(safe-area-inset-right)); bottom: max(20px, env(safe-area-inset-bottom)); z-index: 30; max-width: calc(100vw - 40px); }
87972
- .context-history-cards { display: grid; gap: 16px; margin: 24px 0; }
87973
- .context-history-card { border: 1px solid var(--vp-c-divider); border-radius: 12px; background: var(--vp-c-bg-soft); }
87974
- .context-history-card summary { display: flex; align-items: baseline; flex-wrap: wrap; gap: 12px; padding: 20px; cursor: pointer; }
88042
+ .context-history-cards { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; margin: 24px 0; }
88043
+ .context-history-card { min-width: 0; border: 1px solid var(--vp-c-divider); border-radius: 12px; background: var(--vp-c-bg-soft); }
88044
+ .context-history-card summary { display: flex; align-items: baseline; gap: 12px; padding: 20px; cursor: pointer; }
87975
88045
  .context-history-card summary::before { content: '▸'; }
87976
88046
  .context-history-card[open] summary::before { content: '▾'; }
87977
88047
  .context-history-card summary strong { color: var(--vp-c-brand-1); font-size: 13px; }
87978
- .context-history-title { font-size: 16px; font-weight: 600; overflow-wrap: anywhere; }
87979
- .context-history-attribution { margin-left: auto; font-size: 13px; color: var(--vp-c-text-2); }
88048
+ .context-history-card summary strong, .context-history-card summary::before { flex-shrink: 0; }
88049
+ .context-history-title { flex: 1; min-width: 0; font-size: 16px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
88050
+ .context-history-card[open] .context-history-title { white-space: normal; overflow-wrap: anywhere; }
88051
+ .context-history-attribution { flex-shrink: 0; margin-left: auto; font-size: 13px; color: var(--vp-c-text-2); white-space: nowrap; }
88052
+ @media (max-width: 639px) {
88053
+ .context-history-card summary { flex-wrap: wrap; }
88054
+ .context-history-attribution { flex-basis: 100%; text-align: right; }
88055
+ }
87980
88056
  .context-history-body { padding: 0 24px 20px; font-size: 13px; line-height: 1.8; overflow-wrap: anywhere; }
87981
88057
  .context-history-body ul { list-style: disc; padding-left: 20px; }
87982
88058
  .context-history-meta { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--vp-c-divider); color: var(--vp-c-text-2); }
@@ -88224,6 +88300,12 @@ ${readerContentStyles(".vp-doc")}
88224
88300
  .context-sources li + li { margin-top: 6px; }
88225
88301
  .context-sources a { color: inherit; text-decoration: none; border-bottom: 1px solid transparent; }
88226
88302
  .context-sources a:hover { color: var(--vp-c-brand-1); border-color: currentColor; }
88303
+ .vp-doc a.context-source-link { font-weight: inherit; border-bottom: 0; }
88304
+ .vp-doc a.context-source-link::before { content: ""; display: inline-block; width: .85em; height: .85em; margin-right: .25em; vertical-align: -.1em; background: currentColor; opacity: .55; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71'/%3E%3Cpath d='M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71'/%3E%3Cpath d='M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71'/%3E%3C/svg%3E") center / contain no-repeat; transition: opacity .15s; }
88305
+ .vp-doc a.context-source-link > code { border-bottom: 1px dotted color-mix(in srgb, var(--vp-c-text-1) 55%, transparent); transition: color .15s, border-color .15s; }
88306
+ .vp-doc td a.context-source-link { white-space: nowrap; }
88307
+ .vp-doc a.context-source-link:hover::before { opacity: 1; }
88308
+ .vp-doc a.context-source-link:hover > code { color: var(--vp-c-brand-1); border-bottom-style: solid; border-bottom-color: currentColor; }
88227
88309
  /* Section landing pages: two cards per row, one on narrow screens. */
88228
88310
  .context-section-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-top: 24px; }
88229
88311
  .vp-doc .context-section-card { min-width: 0; padding: 18px 20px; border: 1px solid var(--vp-c-divider); border-radius: 12px;
@@ -89697,7 +89779,7 @@ function restoreOriginNavLinks(html, base, links) {
89697
89779
  const link = href === undefined ? undefined : prefixedHref.get(href);
89698
89780
  if (link === undefined)
89699
89781
  return tag;
89700
- return tag.replace(` href="${href}"`, ` href="${link}"`).replace(/\sclass="([^"]*)"/u, (_, classes) => ` class="${classes.split(/\s+/u).filter((name3) => name3 !== "active").join(" ")}"`);
89782
+ return tag.replace(` href="${href}"`, ` href="${link}"`);
89701
89783
  });
89702
89784
  }
89703
89785
  function translatedMarkdown(content3, from, pages, resources) {
@@ -90071,13 +90153,15 @@ async function writePackageSite(input) {
90071
90153
  const pageFrontmatter = (page, content3, titles) => {
90072
90154
  const original = sourceContent.get(page.package_path);
90073
90155
  const sources = siteArticleSources(original?.article, registry2, repositoryRemote);
90156
+ const sourceLinks = siteSourceLinks(original?.article, registry2, repositoryRemote);
90074
90157
  const timestamp = parseKnowledgeFrontmatter(original?.content ?? content3).timestamp;
90075
90158
  const updated = typeof timestamp === "string" && Number.isFinite(Date.parse(timestamp)) ? new Date(timestamp).toISOString() : null;
90076
90159
  return `---
90077
90160
  title: ${JSON.stringify(page.title)}
90078
90161
  ${titles ? `contextTitles: ${JSON.stringify(titles)}
90079
90162
  ` : ""}` + `contextSources: ${JSON.stringify(sources)}
90080
- contextUpdated: ${JSON.stringify(updated)}
90163
+ ` + `${Object.keys(sourceLinks).length ? `contextSourceLinks: ${JSON.stringify(sourceLinks)}
90164
+ ` : ""}contextUpdated: ${JSON.stringify(updated)}
90081
90165
  ---
90082
90166
  `;
90083
90167
  };