specra 0.2.64 → 0.2.66

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.
@@ -5,6 +5,7 @@
5
5
  import type { SpecraConfig } from '../../config.types.js';
6
6
  import Icon from './Icon.svelte';
7
7
  import { sortSidebarItems, sortSidebarGroups } from '../../sidebar-utils.js';
8
+ import { renderInlineCode } from '../../inline.js';
8
9
 
9
10
  interface DocItem {
10
11
  title: string;
@@ -302,7 +303,7 @@
302
303
  {#if group.icon}
303
304
  <Icon icon={group.icon} size={16} className="shrink-0" />
304
305
  {/if}
305
- {group.label}
306
+ {@html renderInlineCode(group.label)}
306
307
  </a>
307
308
 
308
309
  {#if hasContent && group.collapsible && config.navigation?.collapsibleSidebar}
@@ -342,7 +343,7 @@
342
343
  {#if item.doc.meta?.icon}
343
344
  <Icon icon={item.doc.meta.icon} size={16} className="shrink-0" />
344
345
  {/if}
345
- {item.doc.title}
346
+ {@html renderInlineCode(item.doc.title)}
346
347
  {#if item.doc.meta?.isProtected}
347
348
  <Lock size={14} class="shrink-0 text-muted-foreground ml-auto" />
348
349
  {/if}
@@ -369,7 +370,7 @@
369
370
  {#if doc.meta?.icon}
370
371
  <Icon icon={doc.meta.icon} size={16} className="shrink-0" />
371
372
  {/if}
372
- {doc.title}
373
+ {@html renderInlineCode(doc.title)}
373
374
  {#if doc.meta?.isProtected}
374
375
  <Lock size={14} class="shrink-0 text-muted-foreground ml-auto" />
375
376
  {/if}
@@ -2,6 +2,7 @@
2
2
  import { browser } from '$app/environment';
3
3
  import type { SpecraConfig } from '../../config.types.js';
4
4
  import type { TOCItem } from '../../toc.js';
5
+ import { renderInlineCode } from '../../inline.js';
5
6
 
6
7
  interface Props {
7
8
  items: TOCItem[];
@@ -84,7 +85,7 @@
84
85
  ? 'text-primary font-medium'
85
86
  : 'text-foreground hover:bg-accent/50'}"
86
87
  >
87
- {item.title}
88
+ {@html renderInlineCode(item.title)}
88
89
  </a>
89
90
  {/each}
90
91
  </nav>
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export type * from './api.types.js';
12
12
  export type { ApiParam, ApiHeader, ApiResponse as SpecraApiResponse, ApiEndpointSpec, SpecraApiSpec } from './api-parser.types.js';
13
13
  export * from './utils.js';
14
14
  export * from './links.js';
15
+ export * from './inline.js';
15
16
  export * from './sidebar-utils.js';
16
17
  export * from './category.js';
17
18
  export * from './redirects.js';
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ export * from './parsers/index.js';
16
16
  // Utilities
17
17
  export * from './utils.js';
18
18
  export * from './links.js';
19
+ export * from './inline.js';
19
20
  export * from './sidebar-utils.js';
20
21
  export * from './category.js';
21
22
  export * from './redirects.js';
@@ -0,0 +1 @@
1
+ export declare function renderInlineCode(text: string): string;
package/dist/inline.js ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Render a plain label string that may contain inline-code markdown
3
+ * (backtick-delimited spans) into safe HTML, turning `` `code` `` into
4
+ * `<code>code</code>`. Used for TOC entries and sidebar labels, which come from
5
+ * headings / frontmatter titles as raw text - without this they show the literal
6
+ * backticks instead of formatted code.
7
+ *
8
+ * Everything is HTML-escaped (both the surrounding text and the code content),
9
+ * so the result is safe to use with `{@html}`. Only inline code is handled; no
10
+ * other markdown is interpreted.
11
+ */
12
+ function escapeHtml(s) {
13
+ return s
14
+ .replace(/&/g, '&amp;')
15
+ .replace(/</g, '&lt;')
16
+ .replace(/>/g, '&gt;');
17
+ }
18
+ export function renderInlineCode(text) {
19
+ if (!text)
20
+ return '';
21
+ let out = '';
22
+ let last = 0;
23
+ const re = /`([^`]+)`/g;
24
+ let m;
25
+ while ((m = re.exec(text)) !== null) {
26
+ out += escapeHtml(text.slice(last, m.index));
27
+ out += `<code>${escapeHtml(m[1])}</code>`;
28
+ last = m.index + m[0].length;
29
+ }
30
+ out += escapeHtml(text.slice(last));
31
+ return out;
32
+ }
package/dist/mdx.js CHANGED
@@ -1078,11 +1078,15 @@ function dedentComponentChildren(markdown) {
1078
1078
  minIndent = indent;
1079
1079
  }
1080
1080
  if (minIndent > 0 && minIndent !== Infinity) {
1081
- // Dedent non-code-fence lines by the common indent.
1082
- // Code fence lines are left as-is to preserve their content.
1083
- const dedented = lines.map((line, i) => {
1084
- if (codeFenceLines.has(i))
1085
- return line;
1081
+ // Dedent every non-empty line by the common indent, including code-fence
1082
+ // lines and their content. Code lines are excluded from the min-indent
1083
+ // *calculation* above (so a column-0 code line doesn't pin minIndent to 0),
1084
+ // but they must still be dedented here: leaving an indented fence at its
1085
+ // original column (e.g. 4 spaces) turns it into a CommonMark *indented*
1086
+ // code block (fences allow <=3 spaces of indent), which renders the raw
1087
+ // ```lang fence literally. The Math.min cap strips only the shared wrapper
1088
+ // indent, never a line's meaningful internal indentation.
1089
+ const dedented = lines.map((line) => {
1086
1090
  if (line.trim().length === 0)
1087
1091
  return line;
1088
1092
  return line.slice(Math.min(minIndent, line.match(/^(\s*)/)?.[1].length ?? 0));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specra",
3
- "version": "0.2.64",
3
+ "version": "0.2.66",
4
4
  "description": "A modern documentation library for SvelteKit with built-in versioning, API reference generation, full-text search, and MDX support",
5
5
  "svelte": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",