@brillout/docpress 0.15.10 → 0.15.11

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 (51) hide show
  1. package/components/CodeSnippets/useSelectCodeLang.ts +60 -0
  2. package/components/CodeSnippets.css +78 -0
  3. package/components/CodeSnippets.tsx +50 -0
  4. package/components/Pre.css +51 -0
  5. package/components/Pre.tsx +72 -0
  6. package/components/index.ts +1 -0
  7. package/components/useMDXComponents.tsx +13 -0
  8. package/css/button.css +23 -0
  9. package/css/code.css +3 -21
  10. package/css/index.css +1 -0
  11. package/css/tooltip.css +10 -2
  12. package/dist/+config.js +1 -1
  13. package/dist/NavItemComponent.js +38 -46
  14. package/dist/components/CodeBlockTransformer.js +2 -3
  15. package/dist/components/CodeSnippets/useSelectCodeLang.d.ts +7 -0
  16. package/dist/components/CodeSnippets/useSelectCodeLang.js +50 -0
  17. package/dist/components/CodeSnippets.d.ts +11 -0
  18. package/dist/components/CodeSnippets.js +35 -0
  19. package/dist/components/Comment.js +1 -2
  20. package/dist/components/FileRemoved.js +4 -6
  21. package/dist/components/HorizontalLine.js +1 -2
  22. package/dist/components/ImportMeta.js +2 -3
  23. package/dist/components/Link.js +34 -50
  24. package/dist/components/Note.js +17 -29
  25. package/dist/components/P.js +1 -12
  26. package/dist/components/RepoLink.js +7 -9
  27. package/dist/components/index.d.ts +1 -0
  28. package/dist/components/index.js +1 -0
  29. package/dist/determineNavItemsColumnLayout.js +48 -63
  30. package/dist/parseMarkdownMini.js +5 -17
  31. package/dist/parsePageSections.js +41 -82
  32. package/dist/rehypeMetaToProps.d.ts +19 -0
  33. package/dist/rehypeMetaToProps.js +62 -0
  34. package/dist/remarkDetype.d.ts +4 -0
  35. package/dist/remarkDetype.js +146 -0
  36. package/dist/renderer/usePageContext.js +6 -7
  37. package/dist/resolvePageContext.js +103 -110
  38. package/dist/utils/Emoji/Emoji.js +13 -21
  39. package/dist/utils/assert.js +14 -16
  40. package/dist/utils/cls.js +1 -1
  41. package/dist/utils/determineSectionUrlHash.js +5 -5
  42. package/dist/utils/filter.js +2 -2
  43. package/dist/utils/getGlobalObject.js +3 -3
  44. package/dist/vite.config.js +12 -7
  45. package/index.ts +15 -5
  46. package/package.json +5 -1
  47. package/rehypeMetaToProps.ts +69 -0
  48. package/remarkDetype.ts +172 -0
  49. package/resolvePageContext.ts +19 -15
  50. package/tsconfig.json +2 -1
  51. package/vite.config.ts +9 -4
@@ -1,66 +1,26 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- var __generator = (this && this.__generator) || function (thisArg, body) {
11
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
12
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
- function verb(n) { return function (v) { return step([n, v]); }; }
14
- function step(op) {
15
- if (f) throw new TypeError("Generator is already executing.");
16
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
- if (y = 0, t) op = [op[0] & 2, t.value];
19
- switch (op[0]) {
20
- case 0: case 1: t = op; break;
21
- case 4: _.label++; return { value: op[1], done: false };
22
- case 5: _.label++; y = op[1]; op = [0]; continue;
23
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
- default:
25
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
- if (t[2]) _.ops.pop();
30
- _.trys.pop(); continue;
31
- }
32
- op = body.call(thisArg, _);
33
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
- }
36
- };
37
1
  export { parsePageSections };
38
2
  import { assert } from './utils/assert.js';
39
3
  import { determineSectionUrlHash } from './utils/determineSectionUrlHash.js';
40
4
  import os from 'os';
41
5
  function parsePageSections() {
42
- var _this = this;
43
6
  return {
44
7
  name: '@brillout/docpress:parsePageSections',
45
8
  enforce: 'pre',
46
- transform: function (code, id) { return __awaiter(_this, void 0, void 0, function () {
47
- var codeNew;
48
- return __generator(this, function (_a) {
49
- if (!id.endsWith('+Page.mdx')) {
50
- return [2 /*return*/];
51
- }
52
- codeNew = transform(code);
53
- return [2 /*return*/, codeNew];
54
- });
55
- }); },
9
+ transform: async (code, id) => {
10
+ if (!id.endsWith('+Page.mdx')) {
11
+ return;
12
+ }
13
+ const codeNew = transform(code);
14
+ return codeNew;
15
+ },
56
16
  };
57
17
  }
58
18
  function transform(code) {
59
- var pageSections = [];
60
- var isCodeBlock = false;
61
- var codeNew = code
19
+ const pageSections = [];
20
+ let isCodeBlock = false;
21
+ let codeNew = code
62
22
  .split('\n')
63
- .map(function (line) {
23
+ .map((line) => {
64
24
  // Skip code blocks, e.g.
65
25
  // ~~~md
66
26
  // # Markdown Example
@@ -78,51 +38,50 @@ function transform(code) {
78
38
  || line.startsWith('<h2')
79
39
  */
80
40
  ) {
81
- var _a = parsePageSection(line), pageSectionId = _a.pageSectionId, pageSectionLevel = _a.pageSectionLevel, pageSectionTitle = _a.pageSectionTitle, headingHtml = _a.headingHtml;
82
- pageSections.push({ pageSectionId: pageSectionId, pageSectionLevel: pageSectionLevel, pageSectionTitle: pageSectionTitle });
41
+ const { pageSectionId, pageSectionLevel, pageSectionTitle, headingHtml } = parsePageSection(line);
42
+ pageSections.push({ pageSectionId, pageSectionLevel, pageSectionTitle });
83
43
  return headingHtml;
84
44
  }
85
45
  return line;
86
46
  })
87
47
  .join('\n');
88
- var exportCode = "export const pageSectionsExport = [".concat(pageSections
89
- .map(function (pageSection) { return JSON.stringify(pageSection); })
90
- .join(', '), "];");
91
- codeNew += "\n\n".concat(exportCode, "\n");
48
+ const exportCode = `export const pageSectionsExport = [${pageSections
49
+ .map((pageSection) => JSON.stringify(pageSection))
50
+ .join(', ')}];`;
51
+ codeNew += `\n\n${exportCode}\n`;
92
52
  return codeNew;
93
53
  }
94
54
  function parsePageSection(line) {
95
- var _a;
96
- var _b = line.split(' '), lineBegin = _b[0], lineWords = _b.slice(1);
97
- assert(lineBegin.split('#').join('') === '', { line: line, lineWords: lineWords });
98
- var pageSectionLevel = lineBegin.length;
99
- var titleMdx = lineWords.join(' ');
100
- assert(!titleMdx.startsWith(' '), { line: line, lineWords: lineWords });
101
- assert(titleMdx, { line: line, lineWords: lineWords });
102
- var pageSectionTitle = titleMdx;
103
- var anchor = titleMdx;
55
+ const [lineBegin, ...lineWords] = line.split(' ');
56
+ assert(lineBegin.split('#').join('') === '', { line, lineWords });
57
+ const pageSectionLevel = lineBegin.length;
58
+ const titleMdx = lineWords.join(' ');
59
+ assert(!titleMdx.startsWith(' '), { line, lineWords });
60
+ assert(titleMdx, { line, lineWords });
61
+ let pageSectionTitle = titleMdx;
62
+ let anchor = titleMdx;
104
63
  {
105
64
  // Support custom anchor: `## Some Title{#custom-anchor}`
106
- var customAnchor = (_a = /(?<={#).*(?=})/g.exec(titleMdx)) === null || _a === void 0 ? void 0 : _a[0];
65
+ const customAnchor = /(?<={#).*(?=})/g.exec(titleMdx)?.[0];
107
66
  if (customAnchor) {
108
67
  anchor = customAnchor;
109
68
  pageSectionTitle = titleMdx.replace(/{#.*}/g, '');
110
69
  }
111
70
  }
112
- var pageSectionId = determineSectionUrlHash(anchor);
113
- var titleParsed = parseMarkdownMini(pageSectionTitle);
71
+ const pageSectionId = determineSectionUrlHash(anchor);
72
+ const titleParsed = parseMarkdownMini(pageSectionTitle);
114
73
  assert(pageSectionId === null || pageSectionId.length > 0);
115
- var headingId = pageSectionId === null ? '' : " id=\"".concat(pageSectionId, "\"");
116
- var headingHtml = "<h".concat(pageSectionLevel).concat(headingId, ">").concat(titleParsed, "</h").concat(pageSectionLevel, ">");
117
- var pageSection = { pageSectionLevel: pageSectionLevel, pageSectionTitle: pageSectionTitle, pageSectionId: pageSectionId, headingHtml: headingHtml };
74
+ const headingId = pageSectionId === null ? '' : ` id="${pageSectionId}"`;
75
+ const headingHtml = `<h${pageSectionLevel}${headingId}>${titleParsed}</h${pageSectionLevel}>`;
76
+ const pageSection = { pageSectionLevel, pageSectionTitle, pageSectionId, headingHtml };
118
77
  return pageSection;
119
78
  }
120
79
  function parseMarkdownMini(titleMarkdown) {
121
- var parts = [];
122
- var current;
123
- titleMarkdown.split('').forEach(function (letter) {
80
+ const parts = [];
81
+ let current;
82
+ titleMarkdown.split('').forEach((letter) => {
124
83
  if (letter === '`') {
125
- if ((current === null || current === void 0 ? void 0 : current.nodeType) === 'code') {
84
+ if (current?.nodeType === 'code') {
126
85
  // </code>
127
86
  parts.push(current);
128
87
  current = undefined;
@@ -145,25 +104,25 @@ function parseMarkdownMini(titleMarkdown) {
145
104
  if (current) {
146
105
  parts.push(current);
147
106
  }
148
- var titleHtml = parts
149
- .map(function (part) {
107
+ const titleHtml = parts
108
+ .map((part) => {
150
109
  if (part.nodeType === 'code') {
151
- return "<code>".concat(serializeText(part.content), "</code>");
110
+ return `<code>${serializeText(part.content)}</code>`;
152
111
  }
153
112
  else {
154
- assert(part.nodeType === 'text', { parts: parts });
113
+ assert(part.nodeType === 'text', { parts });
155
114
  return serializeText(part.content);
156
115
  }
157
116
  })
158
117
  .join('');
159
118
  return titleHtml;
160
119
  function serializeText(text) {
161
- var textEscaped = text.split("'").join("\\'");
120
+ let textEscaped = text.split("'").join("\\'");
162
121
  // https://github.com/brillout/docpress/pull/2
163
122
  if (isWindows()) {
164
123
  textEscaped = textEscaped.replace(/\r/, '');
165
124
  }
166
- return "{'".concat(textEscaped, "'}");
125
+ return `{'${textEscaped}'}`;
167
126
  }
168
127
  }
169
128
  function isWindows() {
@@ -0,0 +1,19 @@
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;
@@ -0,0 +1,62 @@
1
+ export { rehypeMetaToProps };
2
+ import { visit } from 'unist-util-visit';
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
+ function rehypeMetaToProps() {
20
+ return (tree) => {
21
+ visit(tree, 'element', (node, _index, parent) => {
22
+ if (node.tagName === 'code' && parent?.type === 'element' && parent.tagName === 'pre') {
23
+ const props = parseMetaString(node.data?.meta);
24
+ parent.properties ??= {};
25
+ parent.properties = { ...parent.properties, ...props };
26
+ }
27
+ });
28
+ };
29
+ }
30
+ /**
31
+ * Minimal parser for a metadata string into key-value pairs.
32
+ *
33
+ * Supports simple patterns: key or key="value".
34
+ *
35
+ * Keys must contain only letters, dashes, or underscores (no digits).
36
+ * Keys are converted to kebab-case. Values default to "true" if missing.
37
+ *
38
+ * Example:
39
+ * parseMetaString('foo fooBar="value"')
40
+ * => { foo: 'true', foo_bar: 'value' }
41
+ *
42
+ * @param metaString - The input metadata string.
43
+ * @returns A plain object of parsed key-value pairs.
44
+ */
45
+ function parseMetaString(metaString) {
46
+ if (!metaString)
47
+ return {};
48
+ const props = {};
49
+ const keyValuePairRE = /([a-zA-Z_-]+)(?:="([^"]*)")?(?=\s|$)/g;
50
+ for (const match of metaString.matchAll(keyValuePairRE)) {
51
+ let [_, key, value] = match;
52
+ props[kebabCase(key)] = value || 'true';
53
+ }
54
+ return props;
55
+ }
56
+ // Simple function to convert a camelCase or PascalCase string to kebab-case.
57
+ function kebabCase(str) {
58
+ return str
59
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
60
+ .replace('_', '-')
61
+ .toLowerCase();
62
+ }
@@ -0,0 +1,4 @@
1
+ export { remarkDetype };
2
+ import type { Root } from 'mdast';
3
+ import type { VFile } from '@mdx-js/mdx/internal-create-format-aware-processors';
4
+ declare function remarkDetype(): (tree: Root, file: VFile) => Promise<void>;
@@ -0,0 +1,146 @@
1
+ export { remarkDetype };
2
+ import { visit } from 'unist-util-visit';
3
+ import { assertUsage } from './utils/assert.js';
4
+ import pc from '@brillout/picocolors';
5
+ import module from 'node:module';
6
+ // Cannot use `import { transform } from 'detype'` as it results in errors,
7
+ // and the package has no default export. Using `module.createRequire` instead.
8
+ const { transform: detype } = module.createRequire(import.meta.url)('detype');
9
+ const prettierOptions = {
10
+ semi: false,
11
+ singleQuote: true,
12
+ printWidth: 100,
13
+ trailingComma: 'none',
14
+ };
15
+ function remarkDetype() {
16
+ return async function transformer(tree, file) {
17
+ const code_nodes = [];
18
+ visit(tree, 'code', (node, index, parent) => {
19
+ if (!parent || typeof index === 'undefined')
20
+ return;
21
+ // Skip if `node.lang` is not ts, tsx, vue, or yaml
22
+ if (!['ts', 'tsx', 'vue', 'yaml'].includes(node.lang || ''))
23
+ return;
24
+ // Skip if 'ts-only' meta is present
25
+ if (node.meta?.includes('ts-only'))
26
+ return;
27
+ // Collect this node for post-processing
28
+ code_nodes.push({ codeBlock: node, index, parent });
29
+ });
30
+ for (const node of code_nodes.reverse()) {
31
+ if (node.codeBlock.lang === 'yaml') {
32
+ transformYaml(node);
33
+ }
34
+ else {
35
+ await transformTsToJs(node, file);
36
+ }
37
+ }
38
+ };
39
+ }
40
+ function transformYaml(node) {
41
+ const { codeBlock, index, parent } = node;
42
+ const codeBlockContentJs = replaceFileNameSuffixes(codeBlock.value);
43
+ // Skip wrapping if the YAML code block hasn't changed
44
+ if (codeBlockContentJs === codeBlock.value)
45
+ return;
46
+ const { position, ...rest } = codeBlock;
47
+ // Create a new code node for the JS version based on the modified YAML
48
+ const yamlJsCode = {
49
+ ...rest,
50
+ value: codeBlockContentJs,
51
+ };
52
+ // Wrap both the original YAML and `yamlJsCode` with <CodeSnippets>
53
+ const yamlContainer = {
54
+ type: 'mdxJsxFlowElement',
55
+ name: 'CodeSnippets',
56
+ children: [yamlJsCode, codeBlock],
57
+ attributes: [],
58
+ };
59
+ parent.children.splice(index, 1, yamlContainer);
60
+ }
61
+ async function transformTsToJs(node, file) {
62
+ const { codeBlock, index, parent } = node;
63
+ let codeBlockContentJs = replaceFileNameSuffixes(codeBlock.value);
64
+ // Remove TypeScript from the TS/TSX/Vue code node
65
+ try {
66
+ codeBlockContentJs = await detype(codeBlockContentJs, `some-dummy-filename.${codeBlock.lang}`, {
67
+ customizeBabelConfig(config) {
68
+ // Add `onlyRemoveTypeImports: true` to the internal `@babel/preset-typescript` config
69
+ // https://github.com/cyco130/detype/blob/46ec867e9efd31d31a312a215ca169bd6bff4726/src/transform.ts#L206
70
+ assertUsage(config.presets && config.presets.length === 1, 'Unexpected Babel config presets');
71
+ config.presets = [[config.presets[0], { onlyRemoveTypeImports: true }]];
72
+ },
73
+ removeTsComments: true,
74
+ prettierOptions,
75
+ });
76
+ }
77
+ catch (error) {
78
+ // Log errors and return original content instead of throwing
79
+ console.error(pc.red(error.message));
80
+ console.error([
81
+ `Failed to transform the code block in: ${pc.bold(pc.blue(file.path))}.`,
82
+ "This likely happened due to invalid TypeScript syntax (see detype's error message above). You can either:",
83
+ '- Fix the code block syntax',
84
+ '- Set the code block language to js instead of ts',
85
+ '- Use custom meta or comments https://github.com/brillout/docpress#detype',
86
+ ].join('\n') + '\n');
87
+ return;
88
+ }
89
+ // Clean up both JS and TS code contents: correct diff comments (for js only) and apply custom magic comment replacements
90
+ codeBlockContentJs = cleanUpCode(codeBlockContentJs.trimEnd(), true);
91
+ codeBlock.value = cleanUpCode(codeBlock.value);
92
+ // No wrapping needed if JS and TS code are still identical
93
+ if (codeBlockContentJs === codeBlock.value)
94
+ return;
95
+ const { position, lang, ...rest } = codeBlock;
96
+ const jsCode = {
97
+ ...rest,
98
+ // The jsCode lang should be js|jsx|vue
99
+ lang: lang.replace('t', 'j'),
100
+ value: codeBlockContentJs,
101
+ };
102
+ // Wrap both the original `codeBlock` and `jsCode` with <CodeSnippets>
103
+ const container = {
104
+ type: 'mdxJsxFlowElement',
105
+ name: 'CodeSnippets',
106
+ children: [jsCode, codeBlock],
107
+ attributes: [],
108
+ };
109
+ parent.children.splice(index, 1, container);
110
+ }
111
+ // Replace all '.ts' extensions with '.js'
112
+ function replaceFileNameSuffixes(codeBlockValue) {
113
+ return codeBlockValue.replaceAll('.ts', '.js');
114
+ }
115
+ function cleanUpCode(code, isJsCode = false) {
116
+ if (isJsCode) {
117
+ code = correctCodeDiffComments(code);
118
+ }
119
+ return processMagicComments(code);
120
+ }
121
+ function processMagicComments(code) {
122
+ // @detype-replace DummyLayout Layout
123
+ const renameCommentRE = /^\/\/\s@detype-replace\s([^ ]+) ([^ ]+)\n/gm;
124
+ const matches = Array.from(code.matchAll(renameCommentRE));
125
+ if (matches.length) {
126
+ for (let i = matches.length - 1; i >= 0; i--) {
127
+ const match = matches[i];
128
+ const [fullMatch, renameFrom, renameTo] = match;
129
+ code = code.split(fullMatch).join('').replaceAll(renameFrom, renameTo);
130
+ }
131
+ }
132
+ code = code.replaceAll('// @detype-uncomment ', '');
133
+ return code;
134
+ }
135
+ /**
136
+ * Correct code diff comments that detype() unexpectedly reformatted (using Prettier and Babel internally)
137
+ * after removing TypeScript.
138
+ * See https://github.com/brillout/docpress/pull/47#issuecomment-3263953899
139
+ * @param code Transformed Javascript code.
140
+ * @returns The corrected code.
141
+ */
142
+ function correctCodeDiffComments(code) {
143
+ // Expected to match the code diff comments: `// [!code ++]` and `// [!code --]` started with newline and optional spaces
144
+ const codeDiffRE = /\n\s*\/\/\s\[!code.+\]/g;
145
+ return code.replaceAll(codeDiffRE, (codeDiff) => codeDiff.trimStart());
146
+ }
@@ -3,20 +3,19 @@ export { usePageContext };
3
3
  export { usePageContextLegacy };
4
4
  import React, { useContext } from 'react';
5
5
  import { getGlobalObject } from '../utils/getGlobalObject';
6
- var globalObject = getGlobalObject('usePageContext.ts', {
6
+ const globalObject = getGlobalObject('usePageContext.ts', {
7
7
  Ctx: React.createContext(undefined),
8
8
  });
9
9
  function usePageContextLegacy() {
10
- var Ctx = globalObject.Ctx;
11
- var pageContext = useContext(Ctx);
10
+ const { Ctx } = globalObject;
11
+ const pageContext = useContext(Ctx);
12
12
  return pageContext.resolved;
13
13
  }
14
14
  function usePageContext() {
15
- var pageContext = useContext(globalObject.Ctx);
15
+ const pageContext = useContext(globalObject.Ctx);
16
16
  return pageContext;
17
17
  }
18
- function PageContextProvider(_a) {
19
- var pageContext = _a.pageContext, children = _a.children;
20
- var Ctx = globalObject.Ctx;
18
+ function PageContextProvider({ pageContext, children, }) {
19
+ const { Ctx } = globalObject;
21
20
  return React.createElement(Ctx.Provider, { value: pageContext }, children);
22
21
  }