@c4a/context-cli 0.7.64 → 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);
@@ -88233,6 +88300,12 @@ ${readerContentStyles(".vp-doc")}
88233
88300
  .context-sources li + li { margin-top: 6px; }
88234
88301
  .context-sources a { color: inherit; text-decoration: none; border-bottom: 1px solid transparent; }
88235
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; }
88236
88309
  /* Section landing pages: two cards per row, one on narrow screens. */
88237
88310
  .context-section-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-top: 24px; }
88238
88311
  .vp-doc .context-section-card { min-width: 0; padding: 18px 20px; border: 1px solid var(--vp-c-divider); border-radius: 12px;
@@ -90080,13 +90153,15 @@ async function writePackageSite(input) {
90080
90153
  const pageFrontmatter = (page, content3, titles) => {
90081
90154
  const original = sourceContent.get(page.package_path);
90082
90155
  const sources = siteArticleSources(original?.article, registry2, repositoryRemote);
90156
+ const sourceLinks = siteSourceLinks(original?.article, registry2, repositoryRemote);
90083
90157
  const timestamp = parseKnowledgeFrontmatter(original?.content ?? content3).timestamp;
90084
90158
  const updated = typeof timestamp === "string" && Number.isFinite(Date.parse(timestamp)) ? new Date(timestamp).toISOString() : null;
90085
90159
  return `---
90086
90160
  title: ${JSON.stringify(page.title)}
90087
90161
  ${titles ? `contextTitles: ${JSON.stringify(titles)}
90088
90162
  ` : ""}` + `contextSources: ${JSON.stringify(sources)}
90089
- contextUpdated: ${JSON.stringify(updated)}
90163
+ ` + `${Object.keys(sourceLinks).length ? `contextSourceLinks: ${JSON.stringify(sourceLinks)}
90164
+ ` : ""}contextUpdated: ${JSON.stringify(updated)}
90090
90165
  ---
90091
90166
  `;
90092
90167
  };