@brillout/docpress 0.15.11 → 0.15.13-commit-ffe283f

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.
Files changed (45) hide show
  1. package/ExternalLinks.tsx +32 -10
  2. package/Layout.tsx +193 -160
  3. package/MenuModal/NavigationWithColumnLayout.tsx +18 -11
  4. package/MenuModal/toggleMenuModal.ts +2 -2
  5. package/MenuModal.tsx +4 -4
  6. package/NavItemComponent.tsx +15 -1
  7. package/autoScrollNav.ts +3 -3
  8. package/{components → code-blocks/components}/CodeSnippets.css +1 -5
  9. package/{components → code-blocks/components}/CodeSnippets.tsx +3 -2
  10. package/{components → code-blocks/components}/Pre.tsx +1 -3
  11. package/{components → code-blocks/hooks}/useMDXComponents.tsx +2 -2
  12. package/{components/CodeSnippets → code-blocks/hooks}/useSelectCodeLang.ts +14 -0
  13. package/{rehypeMetaToProps.ts → code-blocks/rehypeMetaToProps.ts} +2 -2
  14. package/{remarkDetype.ts → code-blocks/remarkDetype.ts} +31 -11
  15. package/code-blocks/shikiTransformerAutoLinks.ts +61 -0
  16. package/components/index.ts +0 -1
  17. package/css/index.css +0 -1
  18. package/determineNavItemsColumnLayout.spec.ts +518 -0
  19. package/determineNavItemsColumnLayout.ts +11 -10
  20. package/dist/NavItemComponent.d.ts +24 -2
  21. package/dist/code-blocks/rehypeMetaToProps.d.ts +35 -0
  22. package/dist/{rehypeMetaToProps.js → code-blocks/rehypeMetaToProps.js} +2 -2
  23. package/dist/{remarkDetype.js → code-blocks/remarkDetype.js} +25 -7
  24. package/dist/code-blocks/shikiTransformerAutoLinks.d.ts +8 -0
  25. package/dist/code-blocks/shikiTransformerAutoLinks.js +51 -0
  26. package/dist/components/index.d.ts +0 -1
  27. package/dist/components/index.js +0 -1
  28. package/dist/determineNavItemsColumnLayout.js +10 -9
  29. package/dist/types/Config.d.ts +1 -0
  30. package/dist/vite.config.js +8 -3
  31. package/docsearch/SearchLink.tsx +5 -1
  32. package/icons/coin.svg +38 -0
  33. package/icons/index.ts +2 -0
  34. package/icons/loudspeaker.svg +1 -0
  35. package/index.ts +3 -11
  36. package/package.json +3 -2
  37. package/types/Config.ts +1 -0
  38. package/vite.config.ts +8 -3
  39. package/dist/components/CodeSnippets/useSelectCodeLang.d.ts +0 -7
  40. package/dist/components/CodeSnippets/useSelectCodeLang.js +0 -50
  41. package/dist/components/CodeSnippets.d.ts +0 -11
  42. package/dist/components/CodeSnippets.js +0 -35
  43. package/dist/rehypeMetaToProps.d.ts +0 -19
  44. /package/{components → code-blocks/components}/Pre.css +0 -0
  45. /package/dist/{remarkDetype.d.ts → code-blocks/remarkDetype.d.ts} +0 -0
@@ -1,6 +1,7 @@
1
1
  export { remarkDetype };
2
2
  import { visit } from 'unist-util-visit';
3
- import { assertUsage } from './utils/assert.js';
3
+ import { assertUsage } from '../utils/assert.js';
4
+ import { parseMetaString } from './rehypeMetaToProps.js';
4
5
  import pc from '@brillout/picocolors';
5
6
  import module from 'node:module';
6
7
  // Cannot use `import { transform } from 'detype'` as it results in errors,
@@ -9,7 +10,6 @@ const { transform: detype } = module.createRequire(import.meta.url)('detype');
9
10
  const prettierOptions = {
10
11
  semi: false,
11
12
  singleQuote: true,
12
- printWidth: 100,
13
13
  trailingComma: 'none',
14
14
  };
15
15
  function remarkDetype() {
@@ -54,16 +54,23 @@ function transformYaml(node) {
54
54
  type: 'mdxJsxFlowElement',
55
55
  name: 'CodeSnippets',
56
56
  children: [yamlJsCode, codeBlock],
57
- attributes: [],
57
+ attributes: [
58
+ {
59
+ name: 'hideToggle',
60
+ type: 'mdxJsxAttribute',
61
+ },
62
+ ],
58
63
  };
59
64
  parent.children.splice(index, 1, yamlContainer);
60
65
  }
61
66
  async function transformTsToJs(node, file) {
62
67
  const { codeBlock, index, parent } = node;
63
- let codeBlockContentJs = replaceFileNameSuffixes(codeBlock.value);
68
+ const maxWidth = Number(parseMetaString(codeBlock.meta)['max-width']);
69
+ let codeBlockReplacedJs = replaceFileNameSuffixes(codeBlock.value);
70
+ let codeBlockContentJs = '';
64
71
  // Remove TypeScript from the TS/TSX/Vue code node
65
72
  try {
66
- codeBlockContentJs = await detype(codeBlockContentJs, `some-dummy-filename.${codeBlock.lang}`, {
73
+ codeBlockContentJs = await detype(codeBlockReplacedJs, `some-dummy-filename.${codeBlock.lang}`, {
67
74
  customizeBabelConfig(config) {
68
75
  // Add `onlyRemoveTypeImports: true` to the internal `@babel/preset-typescript` config
69
76
  // https://github.com/cyco130/detype/blob/46ec867e9efd31d31a312a215ca169bd6bff4726/src/transform.ts#L206
@@ -71,7 +78,10 @@ async function transformTsToJs(node, file) {
71
78
  config.presets = [[config.presets[0], { onlyRemoveTypeImports: true }]];
72
79
  },
73
80
  removeTsComments: true,
74
- prettierOptions,
81
+ prettierOptions: {
82
+ ...prettierOptions,
83
+ printWidth: maxWidth ? maxWidth : 99,
84
+ },
75
85
  });
76
86
  }
77
87
  catch (error) {
@@ -93,18 +103,26 @@ async function transformTsToJs(node, file) {
93
103
  if (codeBlockContentJs === codeBlock.value)
94
104
  return;
95
105
  const { position, lang, ...rest } = codeBlock;
106
+ const attributes = [];
96
107
  const jsCode = {
97
108
  ...rest,
98
109
  // The jsCode lang should be js|jsx|vue
99
110
  lang: lang.replace('t', 'j'),
100
111
  value: codeBlockContentJs,
101
112
  };
113
+ // Add `hideToggle` attribute (prop) to `CodeSnippets` if the only change was replacing `.ts` with `.js`
114
+ if (codeBlockReplacedJs === codeBlockContentJs) {
115
+ attributes.push({
116
+ name: 'hideToggle',
117
+ type: 'mdxJsxAttribute',
118
+ });
119
+ }
102
120
  // Wrap both the original `codeBlock` and `jsCode` with <CodeSnippets>
103
121
  const container = {
104
122
  type: 'mdxJsxFlowElement',
105
123
  name: 'CodeSnippets',
106
124
  children: [jsCode, codeBlock],
107
- attributes: [],
125
+ attributes,
108
126
  };
109
127
  parent.children.splice(index, 1, container);
110
128
  }
@@ -0,0 +1,8 @@
1
+ export { shikiTransformerAutoLinks };
2
+ import type { ShikiTransformer } from 'shiki';
3
+ /**
4
+ * A Shiki transformer that converts plain HTTPS URLs in code blocks into clickable `<a>` links.
5
+ *
6
+ * Inspired by `@jcayzac/shiki-transformer-autolinks`, but tailored for a narrower use case.
7
+ */
8
+ declare function shikiTransformerAutoLinks(): ShikiTransformer;
@@ -0,0 +1,51 @@
1
+ export { shikiTransformerAutoLinks };
2
+ const linkRE = /https:\/\/[^\s]*[^.,\s"'`]/g;
3
+ /**
4
+ * A Shiki transformer that converts plain HTTPS URLs in code blocks into clickable `<a>` links.
5
+ *
6
+ * Inspired by `@jcayzac/shiki-transformer-autolinks`, but tailored for a narrower use case.
7
+ */
8
+ function shikiTransformerAutoLinks() {
9
+ return {
10
+ name: 'docpress-shiki-autolinks',
11
+ span(span) {
12
+ if (span.children.length !== 1)
13
+ return;
14
+ let child = span.children[0];
15
+ if (child.type !== 'text')
16
+ return;
17
+ const links = [];
18
+ const matches = Array.from(child.value.matchAll(linkRE));
19
+ // Filter out URLs that contain `${...}`. e.g. `https://star-wars.brillout.com/api/films/${id}.json`.
20
+ const filtered = matches.filter(([href]) => !href.includes('${'));
21
+ if (filtered.length === 0)
22
+ return;
23
+ for (const match of filtered) {
24
+ const [href] = match;
25
+ links.unshift({ href, index: match.index });
26
+ }
27
+ const newChildren = [];
28
+ for (const { href, index } of links) {
29
+ const postIndex = index + href.length;
30
+ const postValue = child.value.slice(postIndex);
31
+ if (postValue.length > 0) {
32
+ newChildren.unshift({ type: 'text', value: postValue });
33
+ }
34
+ newChildren.unshift({
35
+ type: 'element',
36
+ tagName: 'a',
37
+ properties: { href },
38
+ children: [{ type: 'text', value: href }],
39
+ });
40
+ child = {
41
+ type: 'text',
42
+ value: child.value.slice(0, index),
43
+ };
44
+ }
45
+ if (child.value.length > 0) {
46
+ newChildren.unshift(child);
47
+ }
48
+ span.children = newChildren;
49
+ },
50
+ };
51
+ }
@@ -8,4 +8,3 @@ export * from './HorizontalLine';
8
8
  export * from './CodeBlockTransformer';
9
9
  export * from './Comment';
10
10
  export * from './FileRemoved';
11
- export * from './CodeSnippets';
@@ -8,4 +8,3 @@ export * from './HorizontalLine';
8
8
  export * from './CodeBlockTransformer';
9
9
  export * from './Comment';
10
10
  export * from './FileRemoved';
11
- export * from './CodeSnippets';
@@ -1,13 +1,13 @@
1
1
  export { determineNavItemsColumnLayout };
2
- import { assert, assertUsage } from './utils/assert';
2
+ import { assert } from './utils/assert';
3
3
  function determineNavItemsColumnLayout(navItems) {
4
4
  const columnLayouts = getColumnEntries(navItems);
5
5
  columnLayouts.forEach((columnEntries) => {
6
6
  for (let numberOfColumns = columnEntries.length; numberOfColumns >= 1; numberOfColumns--) {
7
7
  const columnMapping = determineColumnLayout(columnEntries.map((columnEntry) => columnEntry.numberOfEntries), numberOfColumns);
8
8
  columnEntries.forEach((columnEntry, i) => {
9
- columnEntry.navItemLeader.isColumnEntry ??= {};
10
- columnEntry.navItemLeader.isColumnEntry[numberOfColumns] = columnMapping[i];
9
+ columnEntry.navItemLeader.isPotentialColumn ??= {};
10
+ columnEntry.navItemLeader.isPotentialColumn[numberOfColumns] = columnMapping[i];
11
11
  });
12
12
  }
13
13
  });
@@ -49,7 +49,8 @@ function getColumnEntries(navItems) {
49
49
  isFullWidthCategory = !!navItem.menuModalFullWidth;
50
50
  if (isFullWidthCategory)
51
51
  isFullWidthCategoryBegin = true;
52
- if (isFullWidthCategoryPrevious !== undefined && isFullWidthCategoryPrevious !== isFullWidthCategory) {
52
+ if (isFullWidthCategoryPrevious !== undefined &&
53
+ (isFullWidthCategoryPrevious !== isFullWidthCategory || (isFullWidthCategory && columnEntries.length > 0))) {
53
54
  columnLayouts.push(columnEntries);
54
55
  columnEntries = [];
55
56
  }
@@ -69,11 +70,11 @@ function getColumnEntries(navItems) {
69
70
  assert(numberOfHeadings !== null);
70
71
  if (isFullWidthCategoryBegin) {
71
72
  assert(navItem.level === 1);
72
- assertUsage(navItemNext && navItemNext.level === 4,
73
- // We can lift this requirement, but it isn't trivial to implement.
74
- 'level-1 headings with menuModalFullWidth need to be followed by a level-4 heading');
75
- assert(navItemNext.numberOfHeadings);
76
- numberOfHeadings = navItemNext.numberOfHeadings;
73
+ // If followed by a level-4 heading, use its count instead
74
+ if (navItemNext && navItemNext.level === 4) {
75
+ assert(navItemNext.numberOfHeadings);
76
+ numberOfHeadings = navItemNext.numberOfHeadings;
77
+ }
77
78
  }
78
79
  columnEntries.push({ navItemLeader: navItems[i], numberOfEntries: numberOfHeadings });
79
80
  }
@@ -14,6 +14,7 @@ type Config = {
14
14
  twitter?: string;
15
15
  bluesky?: string;
16
16
  linkedin?: string;
17
+ changelog?: boolean;
17
18
  headings: HeadingDefinition[];
18
19
  headingsDetached: HeadingDetachedDefinition[];
19
20
  categories?: Category[];
@@ -5,12 +5,17 @@ import { parsePageSections } from './parsePageSections.js';
5
5
  import rehypePrettyCode from 'rehype-pretty-code';
6
6
  import remarkGfm from 'remark-gfm';
7
7
  import { transformerNotationDiff } from '@shikijs/transformers';
8
- import { remarkDetype } from './remarkDetype.js';
9
- import { rehypeMetaToProps } from './rehypeMetaToProps.js';
8
+ import { rehypeMetaToProps } from './code-blocks/rehypeMetaToProps.js';
9
+ import { remarkDetype } from './code-blocks/remarkDetype.js';
10
+ import { shikiTransformerAutoLinks } from './code-blocks/shikiTransformerAutoLinks.js';
10
11
  const root = process.cwd();
11
12
  const prettyCode = [
12
13
  rehypePrettyCode,
13
- { theme: 'github-light', keepBackground: false, transformers: [transformerNotationDiff()] },
14
+ {
15
+ theme: 'github-light',
16
+ keepBackground: false,
17
+ transformers: [transformerNotationDiff(), shikiTransformerAutoLinks()],
18
+ },
14
19
  ];
15
20
  const rehypePlugins = [prettyCode, [rehypeMetaToProps]];
16
21
  const remarkPlugins = [remarkGfm, remarkDetype];
@@ -33,7 +33,11 @@ function SearchIcon() {
33
33
  <img
34
34
  src={iconMagnifyingGlass}
35
35
  width={18}
36
- style={{ marginRight: 'var(--icon-text-padding)', position: 'relative', top: -1 }}
36
+ style={{
37
+ marginRight: 'var(--icon-text-padding)',
38
+ position: 'relative',
39
+ top: 1,
40
+ }}
37
41
  className="decolorize-7"
38
42
  />
39
43
  )
package/icons/coin.svg ADDED
@@ -0,0 +1,38 @@
1
+ <svg width="448.52" height="448.52" data-name="Layer 1" version="1.1" viewBox="0 0 448.52 448.52" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <linearGradient id="linear-gradient" x1="256" x2="256" y1="460.43" y2="11.91" gradientTransform="translate(-31.74,-11)" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#bd7f26" offset="0"/>
5
+ <stop stop-color="#e3ca75" offset="1"/>
6
+ </linearGradient>
7
+ <linearGradient id="linear-gradient-2" x1="256" x2="256" y1="449.56" y2="22.68" gradientTransform="translate(-31.74,-11)" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#e5b151" offset="0"/>
9
+ <stop stop-color="#ffd645" offset="1"/>
10
+ </linearGradient>
11
+ <linearGradient id="linear-gradient-3" x1="1902.1" x2="1902.1" y1="5236.8" y2="4882" gradientTransform="rotate(180 1063.2 2641.5)" gradientUnits="userSpaceOnUse">
12
+ <stop stop-color="#bd7f26" offset="0"/>
13
+ <stop stop-color="#fbf2ac" offset="1"/>
14
+ </linearGradient>
15
+ <linearGradient id="linear-gradient-4" x1="1902.1" x2="1902.1" y1="5228.2" y2="4890.5" gradientTransform="rotate(180 1063.2 2641.5)" gradientUnits="userSpaceOnUse">
16
+ <stop stop-color="#edb300" offset="0"/>
17
+ <stop stop-color="#be871d" offset="1"/>
18
+ </linearGradient>
19
+ <linearGradient id="linear-gradient-5" x1="256" x2="256" y1="372.53" y2="113.06" gradientTransform="translate(-31.74,-11)" gradientUnits="userSpaceOnUse">
20
+ <stop stop-color="#bd7f26" offset="0"/>
21
+ <stop stop-color="#bd7f26" offset="1"/>
22
+ </linearGradient>
23
+ <linearGradient id="linear-gradient-6" x1="256" x2="256" y1="105.52" y2="365" gradientTransform="translate(-31.74,-11)" gradientUnits="userSpaceOnUse">
24
+ <stop stop-color="#ffd645" offset="0"/>
25
+ <stop stop-color="#e5b151" offset="1"/>
26
+ </linearGradient>
27
+ </defs>
28
+ <title>dollar_coin</title>
29
+ <g fill-rule="evenodd">
30
+ <path d="m224.26 448.52c123.53 0 224.26-100.67 224.26-224.13 0-123.73-100.73-224.39-224.26-224.39s-224.26 100.66-224.26 224.39c0 123.46 100.74 224.13 224.26 224.13z" fill="url(#linear-gradient)"/>
31
+ <path d="m224.26 437.7c117.57 0 213.44-95.81 213.44-213.31 0-117.76-95.87-213.57-213.44-213.57s-213.44 95.81-213.44 213.57c0 117.5 95.88 213.31 213.44 213.31z" fill="url(#linear-gradient-2)"/>
32
+ <path d="m224.26 46.89c-97.7 0-177.37 79.62-177.37 177.27 0 97.84 79.67 177.47 177.37 177.47s177.37-79.63 177.37-177.47c0-97.65-79.67-177.27-177.37-177.27z" fill="url(#linear-gradient-3)"/>
33
+ <path d="m224.26 55.45c-93 0-168.81 75.78-168.81 168.71 0 93.14 75.81 168.91 168.81 168.91s168.81-75.77 168.81-168.91c0-92.93-75.81-168.71-168.81-168.71z" fill="url(#linear-gradient-4)"/>
34
+ <path d="m158 271.81h13.42c15.66 0 15.41 2.48 22.62 14.66 8 13.42 26.1 21.37 45.48 13.17 9.69-4.22 17.15-17.14 8.7-32.06-8-14.41-26.59-16.4-45-20.88-19.89-5-40.76-11.68-51-26.84-15.66-23.86-15.41-57.66 17.4-78.29 13.17-8.21 26.6-13.42 41.76-14.91v-14.41c0-10.69 3-10.19 12.92-10.19 4.48 0 8 0.24 9.95 1.74s2.23 4.47 2.23 9.19v13.92a62.1 62.1 0 0 1 9.44 1.49c27.34 4.72 45.23 15.41 53.43 43.24 4.23 14.17-2.73 17.15-15.65 17.15h-19.82c-12.43 0-14.66-3-17.89-14.41-1.49-4.72-3.73-8.2-7.45-10.44-15.91-9.69-43.75-1.74-42.5 19.63 1 14.17 20.62 19.38 40.76 25.6 26.1 7.7 53.69 15.16 64.62 39.76 11.68 26.6 4.47 56.42-25.1 73.32a106.88 106.88 0 0 1-39.77 12.92v14.66c0 10.69-2 11.68-11.93 11.68-10.68 0-13.17 0-13.17-11.68v-14.4a145.16 145.16 0 0 1-20.14-3c-27.09-5.71-40.76-17.64-48.21-43.74-3.98-14.4 1.24-16.88 14.9-16.88z" fill="url(#linear-gradient-5)"/>
35
+ <path d="m158 256.74h13.42c15.66 0 15.41 2.48 22.62 14.66 8 13.42 26.1 21.37 45.48 13.17 9.69-4.22 17.15-17.14 8.7-32.06-8-14.41-26.59-16.4-45-20.88-19.89-5-40.76-11.68-51-26.84-15.66-23.86-15.41-57.66 17.4-78.29 13.17-8.21 26.6-13.42 41.76-14.91v-14.41c0-10.69 3-10.19 12.92-10.19 4.48 0 8 0.24 9.95 1.74s2.23 4.47 2.23 9.19v13.92a62.1 62.1 0 0 1 9.44 1.49c27.34 4.72 45.23 15.41 53.43 43.24 4.23 14.17-2.73 17.15-15.65 17.15h-19.82c-12.43 0-14.66-3-17.89-14.41-1.49-4.72-3.73-8.2-7.45-10.44-15.91-9.69-43.75-1.74-42.5 19.63 1 14.17 20.62 19.38 40.76 25.6 26.1 7.7 53.69 15.16 64.62 39.76 11.68 26.6 4.47 56.42-25.1 73.32a106.88 106.88 0 0 1-39.77 12.92v14.66c0 10.69-2 11.68-11.93 11.68-10.68 0-13.17 0-13.17-11.68v-14.39a145.16 145.16 0 0 1-20.14-3c-27.09-5.71-40.76-17.64-48.21-43.74-3.98-14.41 1.24-16.89 14.9-16.89z" fill="#fbf2ac"/>
36
+ <path d="m158 264.27h13.42c15.66 0 15.41 2.48 22.62 14.66 8 13.42 26.1 21.37 45.48 13.17 9.74-4.21 17.15-17.1 8.74-32.1-8-14.41-26.59-16.4-45-20.88-19.89-5-40.76-11.68-51-26.84-15.66-23.86-15.41-57.66 17.4-78.29 13.17-8.21 26.6-13.42 41.76-14.91v-14.37c0-10.69 3-10.19 12.92-10.19 4.48 0 8 0.24 9.95 1.74s2.23 4.47 2.23 9.19v13.92a62.1 62.1 0 0 1 9.44 1.49c27.34 4.72 45.23 15.41 53.43 43.24 4.23 14.17-2.73 17.15-15.65 17.15h-19.86c-12.43 0-14.66-3-17.89-14.41-1.49-4.72-3.73-8.2-7.45-10.44-15.91-9.69-43.75-1.74-42.5 19.63 1 14.17 20.62 19.38 40.76 25.6 26.1 7.7 53.69 15.16 64.62 39.76 11.68 26.6 4.47 56.42-25.1 73.32a106.88 106.88 0 0 1-39.77 12.92v14.66c0 10.69-2 11.68-11.93 11.68-10.68 0-13.17 0-13.17-11.68v-14.39a145.16 145.16 0 0 1-20.14-3c-27.09-5.71-40.76-17.64-48.21-43.74-3.98-14.4 1.24-16.89 14.9-16.89z" fill="url(#linear-gradient-6)"/>
37
+ </g>
38
+ </svg>
package/icons/index.ts CHANGED
@@ -8,3 +8,5 @@ export { default as iconCompass } from './compass.svg'
8
8
  export { default as iconScroll } from './scroll.svg'
9
9
  export { default as iconGlobe } from './globe.svg'
10
10
  export { default as iconPlug } from './plug.svg'
11
+ export { default as iconLoudspeaker } from './loudspeaker.svg'
12
+ export { default as iconCoin } from './coin.svg'
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BE1931" d="M12.908 30.75c-.276 2.209-2.291 3-4.5 3s-3.776-1.791-3.5-4l1-9c.276-2.209 2.291-4 4.5-4s6.468 0 3.5 4-1 10-1 10z"/><path fill="#CCD6DD" d="M35.825 14.75c0 6.902-1.544 12.5-3.45 12.5-1.905 0-20.45-5.598-20.45-12.5 0-6.903 18.545-12.5 20.45-12.5 1.906 0 3.45 5.597 3.45 12.5z"/><ellipse fill="#66757F" cx="32.375" cy="14.75" rx="3.45" ry="12.5"/><path fill="#DD2E44" d="M17.925 21.75l-14-1c-5 0-5-12 0-12l14-1c-3 3-3 11 0 14z"/><ellipse fill="#99AAB5" cx="31.325" cy="14.75" rx="1.5" ry="4.348"/></svg>
package/index.ts CHANGED
@@ -1,16 +1,8 @@
1
1
  /**********/
2
2
  /* PUBLIC */
3
3
  /**********/
4
- export {
5
- CodeBlockTransformer,
6
- Link,
7
- RepoLink,
8
- FileAdded,
9
- FileRemoved,
10
- ImportMeta,
11
- Emoji,
12
- TypescriptOnly,
13
- } from './components'
4
+ export { CodeBlockTransformer, Link, RepoLink, FileAdded, FileRemoved, ImportMeta, Emoji } from './components'
5
+ export { TypescriptOnly } from './code-blocks/components/CodeSnippets'
14
6
  export { MenuToggle } from './Layout'
15
7
  export * from './components/Note'
16
8
  export * from './icons/index'
@@ -28,4 +20,4 @@ export { usePageContext } from './renderer/usePageContext'
28
20
  /************/
29
21
  // We provide our own `useMDXComponents()` to enable MDX component injection by setting `providerImportSource` to '@brillout/docpress'.
30
22
  // https://mdxjs.com/guides/injecting-components/
31
- export { useMDXComponents } from './components/useMDXComponents'
23
+ export { useMDXComponents } from './code-blocks/hooks/useMDXComponents'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brillout/docpress",
3
- "version": "0.15.11",
3
+ "version": "0.15.13-commit-ffe283f",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "@brillout/picocolors": "^1.0.10",
@@ -64,7 +64,8 @@
64
64
  "@types/mdast": "^4.0.4",
65
65
  "@types/node": "^22.5.5",
66
66
  "@types/react": "^18.3.8",
67
- "@types/react-dom": "^18.3.0"
67
+ "@types/react-dom": "^18.3.0",
68
+ "mdast-util-mdx-jsx": "^3.2.0"
68
69
  },
69
70
  "repository": "https://github.com/brillout/docpress",
70
71
  "license": "MIT",
package/types/Config.ts CHANGED
@@ -17,6 +17,7 @@ type Config = {
17
17
  twitter?: string
18
18
  bluesky?: string
19
19
  linkedin?: string
20
+ changelog?: boolean
20
21
 
21
22
  headings: HeadingDefinition[]
22
23
  headingsDetached: HeadingDetachedDefinition[]
package/vite.config.ts CHANGED
@@ -7,13 +7,18 @@ import { parsePageSections } from './parsePageSections.js'
7
7
  import rehypePrettyCode from 'rehype-pretty-code'
8
8
  import remarkGfm from 'remark-gfm'
9
9
  import { transformerNotationDiff } from '@shikijs/transformers'
10
- import { remarkDetype } from './remarkDetype.js'
11
- import { rehypeMetaToProps } from './rehypeMetaToProps.js'
10
+ import { rehypeMetaToProps } from './code-blocks/rehypeMetaToProps.js'
11
+ import { remarkDetype } from './code-blocks/remarkDetype.js'
12
+ import { shikiTransformerAutoLinks } from './code-blocks/shikiTransformerAutoLinks.js'
12
13
 
13
14
  const root = process.cwd()
14
15
  const prettyCode = [
15
16
  rehypePrettyCode,
16
- { theme: 'github-light', keepBackground: false, transformers: [transformerNotationDiff()] },
17
+ {
18
+ theme: 'github-light',
19
+ keepBackground: false,
20
+ transformers: [transformerNotationDiff(), shikiTransformerAutoLinks()],
21
+ },
17
22
  ]
18
23
  const rehypePlugins: any = [prettyCode, [rehypeMetaToProps]]
19
24
  const remarkPlugins = [remarkGfm, remarkDetype]
@@ -1,7 +0,0 @@
1
- export { useSelectCodeLang };
2
- declare function useSelectCodeLang(): readonly [string, (value: string) => void];
3
- declare global {
4
- interface WindowEventMap {
5
- 'code-lang-storage': CustomEvent;
6
- }
7
- }
@@ -1,50 +0,0 @@
1
- export { useSelectCodeLang };
2
- import { useState, useEffect, useCallback } from 'react';
3
- import { assertWarning } from '../../utils/assert';
4
- const storageKey = 'docpress:code-lang';
5
- const codeLangDefaultSsr = 'ts';
6
- const codeLangDefaultClient = 'js';
7
- function useSelectCodeLang() {
8
- const [codeLangSelected, setCodeLangSelected] = useState(codeLangDefaultSsr);
9
- const updateState = () => {
10
- setCodeLangSelected(getCodeLangStorage());
11
- };
12
- const updateStateOnStorageEvent = (event) => {
13
- if (event.key === storageKey)
14
- updateState();
15
- };
16
- const getCodeLangStorage = () => {
17
- try {
18
- return window.localStorage.getItem(storageKey) ?? codeLangDefaultClient;
19
- }
20
- catch (error) {
21
- console.error(error);
22
- assertWarning(false, 'Error reading from localStorage');
23
- return codeLangDefaultClient;
24
- }
25
- };
26
- const selectCodeLang = useCallback((value) => {
27
- try {
28
- window.localStorage.setItem(storageKey, value);
29
- setCodeLangSelected(value);
30
- window.dispatchEvent(new CustomEvent('code-lang-storage'));
31
- }
32
- catch (error) {
33
- console.error(error);
34
- assertWarning(false, 'Error setting localStorage');
35
- }
36
- }, []);
37
- useEffect(() => {
38
- // Initial load from localStorage
39
- updateState();
40
- // Update code lang in current tab
41
- window.addEventListener('code-lang-storage', updateState);
42
- // Update code lang if changed in another tab
43
- window.addEventListener('storage', updateStateOnStorageEvent);
44
- return () => {
45
- window.removeEventListener('code-lang-storage', updateState);
46
- window.removeEventListener('storage', updateStateOnStorageEvent);
47
- };
48
- }, []);
49
- return [codeLangSelected, selectCodeLang];
50
- }
@@ -1,11 +0,0 @@
1
- export { TypescriptOnly };
2
- export { CodeSnippets };
3
- import React from 'react';
4
- import './CodeSnippets.css';
5
- /** Only show if TypeScript is selected */
6
- declare function TypescriptOnly({ children }: {
7
- children: React.ReactNode;
8
- }): React.JSX.Element;
9
- declare function CodeSnippets({ children }: {
10
- children: React.ReactNode;
11
- }): React.JSX.Element;
@@ -1,35 +0,0 @@
1
- // Public
2
- export { TypescriptOnly };
3
- // Internal
4
- export { CodeSnippets };
5
- import React, { useEffect, useRef } from 'react';
6
- import { useSelectCodeLang } from './CodeSnippets/useSelectCodeLang';
7
- import './CodeSnippets.css';
8
- /** Only show if TypeScript is selected */
9
- function TypescriptOnly({ children }) {
10
- const [codeLangSelected] = useSelectCodeLang();
11
- return React.createElement("div", { style: { display: codeLangSelected === 'ts' ? 'block' : 'none' } }, children);
12
- }
13
- function CodeSnippets({ children }) {
14
- const [codeLangSelected, selectCodeLang] = useSelectCodeLang();
15
- const prevPositionRef = useRef(null);
16
- // Restores the scroll position of the toggle element after toggling languages.
17
- useEffect(() => {
18
- if (!prevPositionRef.current)
19
- return;
20
- const { top, el } = prevPositionRef.current;
21
- const delta = el.getBoundingClientRect().top - top;
22
- if (delta !== 0) {
23
- window.scrollBy(0, delta);
24
- }
25
- prevPositionRef.current = null;
26
- }, [codeLangSelected]);
27
- return (React.createElement("div", { className: "code-snippets" },
28
- React.createElement("input", { type: "checkbox", name: "code-lang-toggle", className: "code-lang-toggle raised", checked: codeLangSelected === 'ts', onChange: onChange, title: "Toggle language" }),
29
- children));
30
- function onChange(e) {
31
- const element = e.target;
32
- prevPositionRef.current = { top: element.getBoundingClientRect().top, el: element };
33
- selectCodeLang(element.checked ? 'ts' : 'js');
34
- }
35
- }
@@ -1,19 +0,0 @@
1
- export { rehypeMetaToProps };
2
- import type { Root } from 'hast';
3
- /**
4
- * Rehype plugin to extract metadata from `<code>` blocks in markdown
5
- * and attach them as props to the parent `<pre>` element.
6
- *
7
- * This allows using those props inside a custom `<Pre>` component.
8
- *
9
- * Example:
10
- * ~~~mdx
11
- * ```js foo="bar" hide_copy='true'
12
- * export function add(a, b) {
13
- * return a + b
14
- * }
15
- * ```
16
- * ~~~
17
- * These props are then added to the `<pre>` element
18
- */
19
- declare function rehypeMetaToProps(): (tree: Root) => void;
File without changes