@readme/markdown 15.2.1 → 15.4.0
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/README.md +1 -0
- package/components/TailwindStyle/index.tsx +5 -2
- package/dist/components/TailwindStyle/index.d.ts +3 -1
- package/dist/lib/mdxish.d.ts +9 -0
- package/dist/main.js +73 -34
- package/dist/main.node.js +73 -34
- package/dist/main.node.js.map +1 -1
- package/dist/processor/transform/mdxish/magic-blocks/patterns.d.ts +3 -0
- package/dist/processor/transform/mdxish/magic-blocks/types.d.ts +1 -0
- package/dist/render-fixture.node.js +73 -34
- package/dist/render-fixture.node.js.map +1 -1
- package/dist/utils/common-html-words.d.ts +9 -2
- package/dist/utils/tailwind-compiler.d.ts +13 -1
- package/package.json +2 -1
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
export declare const HTML_TAG_RE: RegExp;
|
|
3
3
|
/** Matches an HTML element from its opening tag to the matching closing tag. */
|
|
4
4
|
export declare const HTML_ELEMENT_BLOCK_RE: RegExp;
|
|
5
|
+
export declare const NEWLINE_RE: RegExp;
|
|
5
6
|
/** Matches a newline with surrounding horizontal whitespace. */
|
|
6
7
|
export declare const NEWLINE_WITH_WHITESPACE_RE: RegExp;
|
|
8
|
+
/** Matches a run of two or more newlines (a blank line) with surrounding horizontal whitespace. */
|
|
9
|
+
export declare const BLANK_LINE_RE: RegExp;
|
|
7
10
|
/** Matches a closing block-level tag followed by non-tag text or by a newline then non-blank content. */
|
|
8
11
|
export declare const CLOSE_BLOCK_TAG_BOUNDARY_RE: RegExp;
|
|
9
12
|
/** Strips HTML open/close tags. Used to detect non-tag inner text content. */
|
|
@@ -92693,7 +92693,7 @@ async function loadStylesheet(id, base) {
|
|
|
92693
92693
|
async function loadModule() {
|
|
92694
92694
|
throw new Error('The browser build does not support plugins or config files.');
|
|
92695
92695
|
}
|
|
92696
|
-
async function createCompiler({ darkModeDataAttribute }) {
|
|
92696
|
+
async function createCompiler({ darkModeDataAttribute, darkModeRootSelector, }) {
|
|
92697
92697
|
let css = `
|
|
92698
92698
|
@layer theme, base, components, utilities;
|
|
92699
92699
|
|
|
@@ -92701,9 +92701,12 @@ async function createCompiler({ darkModeDataAttribute }) {
|
|
|
92701
92701
|
@import "tailwindcss/utilities.css" layer(utilities);
|
|
92702
92702
|
`;
|
|
92703
92703
|
if (darkModeDataAttribute) {
|
|
92704
|
+
// Anchors `dark:` to `darkModeRootSelector`'s own attribute instead of any ancestor's,
|
|
92705
|
+
// when supplied — see the `darkModeRootSelector` param doc below for why there's no default.
|
|
92706
|
+
const root = darkModeRootSelector || '';
|
|
92704
92707
|
css += `
|
|
92705
92708
|
|
|
92706
|
-
@custom-variant dark (&:where([${darkModeDataAttribute}=dark], [${darkModeDataAttribute}=dark] *));`;
|
|
92709
|
+
@custom-variant dark (&:where(${root}[${darkModeDataAttribute}=dark], ${root}[${darkModeDataAttribute}=dark] *));`;
|
|
92707
92710
|
}
|
|
92708
92711
|
return Hu(css, {
|
|
92709
92712
|
base: '/',
|
|
@@ -92711,8 +92714,8 @@ async function createCompiler({ darkModeDataAttribute }) {
|
|
|
92711
92714
|
loadModule,
|
|
92712
92715
|
});
|
|
92713
92716
|
}
|
|
92714
|
-
async function tailwindCompiler(classes, { prefix, darkModeDataAttribute }) {
|
|
92715
|
-
const compiler = await createCompiler({ darkModeDataAttribute });
|
|
92717
|
+
async function tailwindCompiler(classes, { prefix, darkModeDataAttribute, darkModeRootSelector, }) {
|
|
92718
|
+
const compiler = await createCompiler({ darkModeDataAttribute, darkModeRootSelector });
|
|
92716
92719
|
const css = compiler.build(Array.from(classes));
|
|
92717
92720
|
return lib_postcss([postcss_prefix_selector_default()({ prefix })]).process(css, { from: undefined });
|
|
92718
92721
|
}
|
|
@@ -92727,7 +92730,7 @@ const traverse = (node, callback) => {
|
|
|
92727
92730
|
traverse(child, callback);
|
|
92728
92731
|
});
|
|
92729
92732
|
};
|
|
92730
|
-
const TailwindStyle = ({ children, darkModeDataAttribute }) => {
|
|
92733
|
+
const TailwindStyle = ({ children, darkModeDataAttribute, darkModeRootSelector }) => {
|
|
92731
92734
|
const [stylesheet, setStylesheet] = (0,external_react_.useState)('');
|
|
92732
92735
|
const classesSet = (0,external_react_.useRef)(new Set());
|
|
92733
92736
|
const ref = (0,external_react_.useRef)(null);
|
|
@@ -92751,6 +92754,7 @@ const TailwindStyle = ({ children, darkModeDataAttribute }) => {
|
|
|
92751
92754
|
const sheet = await tailwindCompiler(classes, {
|
|
92752
92755
|
prefix: `.${tailwindPrefix}`,
|
|
92753
92756
|
darkModeDataAttribute,
|
|
92757
|
+
darkModeRootSelector,
|
|
92754
92758
|
});
|
|
92755
92759
|
/* @note: don't insert an empty stylesheet */
|
|
92756
92760
|
if (sheet.css.match(/^@layer utilities;/m))
|
|
@@ -92758,7 +92762,7 @@ const TailwindStyle = ({ children, darkModeDataAttribute }) => {
|
|
|
92758
92762
|
setStylesheet(sheet.css);
|
|
92759
92763
|
};
|
|
92760
92764
|
run();
|
|
92761
|
-
}, [classes, darkModeDataAttribute]);
|
|
92765
|
+
}, [classes, darkModeDataAttribute, darkModeRootSelector]);
|
|
92762
92766
|
/*
|
|
92763
92767
|
* @note: execute once on load
|
|
92764
92768
|
*/
|
|
@@ -95928,6 +95932,7 @@ var allCSS2RNProps = __webpack_unused_export__ = flatten([allProps, CSS2RNProps]
|
|
|
95928
95932
|
|
|
95929
95933
|
|
|
95930
95934
|
|
|
95935
|
+
|
|
95931
95936
|
/**
|
|
95932
95937
|
* Extract word boundaries from camelCase strings (e.g., "borderWidth" -> ["border", "width"])
|
|
95933
95938
|
*/
|
|
@@ -96007,10 +96012,43 @@ const CUSTOM_PROP_BOUNDARIES = [
|
|
|
96007
96012
|
*/
|
|
96008
96013
|
const RUNTIME_COMPONENT_TAGS = new Set(['Variable', 'variable', 'html-block', 'rdme-pin']);
|
|
96009
96014
|
/**
|
|
96010
|
-
*
|
|
96011
|
-
*
|
|
96015
|
+
* Elements that are not actually standard HTML tags, or those that we intentionally
|
|
96016
|
+
* don't want to treat as one & is mute to check with. These include:
|
|
96017
|
+
* - SVG/MathML descendants
|
|
96018
|
+
* - Namespaced foreign content
|
|
96019
|
+
* - `image`, which the HTML tree builder rewrites to `img`
|
|
96020
|
+
* Most of these are bundled in parse5's `TAG_NAMES` set, but we can also add a few more.
|
|
96012
96021
|
*/
|
|
96013
|
-
const
|
|
96022
|
+
const NON_STANDARD_TAGS = new Set([
|
|
96023
|
+
'annotation-xml',
|
|
96024
|
+
'desc',
|
|
96025
|
+
'foreignObject',
|
|
96026
|
+
'image',
|
|
96027
|
+
'malignmark',
|
|
96028
|
+
'mglyph',
|
|
96029
|
+
'mi',
|
|
96030
|
+
'mn',
|
|
96031
|
+
'mo',
|
|
96032
|
+
'ms',
|
|
96033
|
+
'mtext',
|
|
96034
|
+
]);
|
|
96035
|
+
/**
|
|
96036
|
+
* Standard HTML tags list.
|
|
96037
|
+
* A use case of this is to differentiate custom components tag vs standard HTML tags.
|
|
96038
|
+
*
|
|
96039
|
+
* Unioned from:
|
|
96040
|
+
* - `html-tags`: All modern spec HTML elements
|
|
96041
|
+
* - parse5's `TAG_NAMES`: Elements the HTML tree-construction algorithm has to special-case
|
|
96042
|
+
* This includes obsolete tags that are still rendered by browsers.
|
|
96043
|
+
* - NON_STANDARD_TAGS: We've had to filter because currently parse5's `TAG_NAMES` set over-enumerates
|
|
96044
|
+
* tags that are not actually standard HTML tags. It also allows custom tags to be filtered out.
|
|
96045
|
+
*/
|
|
96046
|
+
const STANDARD_HTML_TAGS = new Set([
|
|
96047
|
+
...html_tags_namespaceObject,
|
|
96048
|
+
...Object.values(TAG_NAMES),
|
|
96049
|
+
'acronym', // Obselete tag not included either of the above sources. Add here if we have missed any.
|
|
96050
|
+
'blink',
|
|
96051
|
+
].filter(tag => !NON_STANDARD_TAGS.has(tag)));
|
|
96014
96052
|
/**
|
|
96015
96053
|
* Table structural tags. Blank lines inside these carry deliberate meaning for
|
|
96016
96054
|
* `mdxishTables` (e.g. splitting cell content into paragraphs, or deciding
|
|
@@ -125298,8 +125336,11 @@ function rehypeStringify(options) {
|
|
|
125298
125336
|
const HTML_TAG_RE = /<\/?([a-zA-Z][a-zA-Z0-9-]*)((?:[^>"']*(?:"[^"]*"|'[^']*'))*[^>"']*)>/g;
|
|
125299
125337
|
/** Matches an HTML element from its opening tag to the matching closing tag. */
|
|
125300
125338
|
const HTML_ELEMENT_BLOCK_RE = /<([a-zA-Z][a-zA-Z0-9-]*)[\s>][\s\S]*?<\/\1>/g;
|
|
125339
|
+
const NEWLINE_RE = /\n/g;
|
|
125301
125340
|
/** Matches a newline with surrounding horizontal whitespace. */
|
|
125302
125341
|
const NEWLINE_WITH_WHITESPACE_RE = /[^\S\n]*\n[^\S\n]*/g;
|
|
125342
|
+
/** Matches a run of two or more newlines (a blank line) with surrounding horizontal whitespace. */
|
|
125343
|
+
const BLANK_LINE_RE = /[^\S\n]*\n(?:[^\S\n]*\n)+[^\S\n]*/g;
|
|
125303
125344
|
/** Matches a closing block-level tag followed by non-tag text or by a newline then non-blank content. */
|
|
125304
125345
|
const CLOSE_BLOCK_TAG_BOUNDARY_RE = /<\/([a-zA-Z][a-zA-Z0-9-]*)>\s*(?:(?!<)(\S)|\n([^\n]))/g;
|
|
125305
125346
|
/** Strips HTML open/close tags. Used to detect non-tag inner text content. */
|
|
@@ -125369,7 +125410,6 @@ const EMPTY_CODE_PLACEHOLDER = {
|
|
|
125369
125410
|
|
|
125370
125411
|
|
|
125371
125412
|
|
|
125372
|
-
|
|
125373
125413
|
/**
|
|
125374
125414
|
* Wraps a node in a "pinned" container if sidebar: true is set.
|
|
125375
125415
|
*/
|
|
@@ -125404,16 +125444,13 @@ const textToBlock = (text) => [{ children: textToInline(text), type: 'paragraph'
|
|
|
125404
125444
|
*/
|
|
125405
125445
|
const ensureLeadingBreaks = (text) => text.replace(/^\n+/, match => '<br>'.repeat(match.length));
|
|
125406
125446
|
/** Preprocesses magic block body content before parsing. */
|
|
125407
|
-
const preprocessBody = (text) =>
|
|
125408
|
-
return ensureLeadingBreaks(text);
|
|
125409
|
-
};
|
|
125447
|
+
const preprocessBody = (text, hardBreaks) => (hardBreaks ? ensureLeadingBreaks(text) : text);
|
|
125410
125448
|
const bodyExtensions = mdxishExtensions(FEATURES.magicBlockBody);
|
|
125411
125449
|
/** Markdown parser */
|
|
125412
125450
|
const contentParser = unified()
|
|
125413
125451
|
.data('micromarkExtensions', bodyExtensions.micromarkExtensions)
|
|
125414
125452
|
.data('fromMarkdownExtensions', bodyExtensions.fromMarkdownExtensions)
|
|
125415
125453
|
.use(remarkParse)
|
|
125416
|
-
.use(hard_breaks)
|
|
125417
125454
|
.use(remarkGfm)
|
|
125418
125455
|
.use(normalize_malformed_md_syntax);
|
|
125419
125456
|
/**
|
|
@@ -125510,17 +125547,21 @@ const processMarkdownInHtmlString = (html) => {
|
|
|
125510
125547
|
/**
|
|
125511
125548
|
* Separate a closing block-level tag from the content that follows it.
|
|
125512
125549
|
*
|
|
125513
|
-
*
|
|
125514
|
-
*
|
|
125515
|
-
* the following content as markdown.
|
|
125550
|
+
* A blank line (\n\n) is appended so CommonMark ends the HTML block and parses the
|
|
125551
|
+
* following content as markdown; with hard breaks each \n also becomes a <br> to keep its spacing.
|
|
125516
125552
|
*/
|
|
125517
|
-
const separateBlockTagFromContent = (match, tag, inlineChar, nextLineChar) => {
|
|
125553
|
+
const separateBlockTagFromContent = (hardBreaks, match, tag, inlineChar, nextLineChar) => {
|
|
125518
125554
|
if (!BLOCK_LEVEL_TAGS.has(tag.toLowerCase()))
|
|
125519
125555
|
return match;
|
|
125520
|
-
const newlineCount = (match.match(
|
|
125556
|
+
const newlineCount = hardBreaks ? (match.match(NEWLINE_RE) ?? []).length : 0;
|
|
125521
125557
|
const breaks = '<br>'.repeat(newlineCount);
|
|
125522
125558
|
return `</${tag}>${breaks}\n\n${inlineChar || nextLineChar}`;
|
|
125523
125559
|
};
|
|
125560
|
+
/**
|
|
125561
|
+
* Newlines inside an HTML block become <br> so CommonMark doesn't end the block on a blank
|
|
125562
|
+
* line. Without hard breaks only blank lines break, but they still have to be replaced.
|
|
125563
|
+
*/
|
|
125564
|
+
const collapseHtmlBlockNewlines = (html, hardBreaks) => html.replace(hardBreaks ? NEWLINE_WITH_WHITESPACE_RE : BLANK_LINE_RE, '<br>');
|
|
125524
125565
|
/** Escape a leading (possibly indented) `-`/`*`/`+` so cells don't become bullet lists. */
|
|
125525
125566
|
const escapeLeadingListMarkers = (text) => text.replace(/^([ \t]*)([-*+])(?=[ \t]|$)/gm, '$1\\$2');
|
|
125526
125567
|
/**
|
|
@@ -125528,15 +125569,13 @@ const escapeLeadingListMarkers = (text) => text.replace(/^([ \t]*)([-*+])(?=[ \t
|
|
|
125528
125569
|
* so `<ul><li>_text_</li></ul>` won't convert underscores to emphasis.
|
|
125529
125570
|
* We parse first, then visit html nodes and process their text content.
|
|
125530
125571
|
*/
|
|
125531
|
-
const parseTableCell = (text) => {
|
|
125572
|
+
const parseTableCell = (text, hardBreaks) => {
|
|
125532
125573
|
if (!text.trim())
|
|
125533
125574
|
return [{ type: 'text', value: '' }];
|
|
125534
|
-
// Convert \n (and surrounding whitespace) to <br> inside HTML blocks so
|
|
125535
|
-
// CommonMark doesn't split them on blank lines.
|
|
125536
125575
|
const escaped = processBackslashEscapes(text);
|
|
125537
125576
|
const normalized = escaped
|
|
125538
|
-
.replace(HTML_ELEMENT_BLOCK_RE, match => match
|
|
125539
|
-
.replace(CLOSE_BLOCK_TAG_BOUNDARY_RE, separateBlockTagFromContent);
|
|
125577
|
+
.replace(HTML_ELEMENT_BLOCK_RE, match => collapseHtmlBlockNewlines(match, hardBreaks))
|
|
125578
|
+
.replace(CLOSE_BLOCK_TAG_BOUNDARY_RE, (match, tag, inlineChar, nextLineChar) => separateBlockTagFromContent(hardBreaks, match, tag, inlineChar, nextLineChar));
|
|
125540
125579
|
const processed = escapeLeadingListMarkers(normalized);
|
|
125541
125580
|
const tree = contentParser.runSync(contentParser.parse(processed));
|
|
125542
125581
|
// Process markdown inside HTML blocks that have non-tag inner text (e.g. `<div>**x**`
|
|
@@ -125585,7 +125624,7 @@ const parseApiHeaderTitle = (text) => {
|
|
|
125585
125624
|
* Transform a magicBlock node into final MDAST nodes.
|
|
125586
125625
|
*/
|
|
125587
125626
|
function transformMagicBlock(blockType, data, rawValue, options = {}) {
|
|
125588
|
-
const { compatibilityMode = false, safeMode = false } = options;
|
|
125627
|
+
const { compatibilityMode = false, hardBreaks = true, safeMode = false } = options;
|
|
125589
125628
|
// Handle empty data by returning placeholder nodes for known block types
|
|
125590
125629
|
// This allows the editor to show appropriate placeholder UI instead of nothing
|
|
125591
125630
|
if (Object.keys(data).length < 1) {
|
|
@@ -125724,7 +125763,7 @@ function transformMagicBlock(blockType, data, rawValue, options = {}) {
|
|
|
125724
125763
|
});
|
|
125725
125764
|
}
|
|
125726
125765
|
if (hasBody) {
|
|
125727
|
-
const bodyBlocks = parseBlock(preprocessBody(calloutJson.body || ''));
|
|
125766
|
+
const bodyBlocks = parseBlock(preprocessBody(calloutJson.body || '', hardBreaks));
|
|
125728
125767
|
children.push(...bodyBlocks);
|
|
125729
125768
|
}
|
|
125730
125769
|
const calloutElement = {
|
|
@@ -125756,12 +125795,12 @@ function transformMagicBlock(blockType, data, rawValue, options = {}) {
|
|
|
125756
125795
|
mapped[rowIndex][colIndex] = v;
|
|
125757
125796
|
return mapped;
|
|
125758
125797
|
}, []);
|
|
125759
|
-
const tokenizeCell = compatibilityMode
|
|
125760
|
-
? textToBlock
|
|
125761
|
-
: parseTableCell;
|
|
125798
|
+
const tokenizeCell = compatibilityMode ? textToBlock : (text) => parseTableCell(text, hardBreaks);
|
|
125762
125799
|
const tableChildren = Array.from({ length: rows + 1 }, (_, y) => ({
|
|
125763
125800
|
children: Array.from({ length: cols }, (__, x) => ({
|
|
125764
|
-
children: sparseData[y]?.[x]
|
|
125801
|
+
children: sparseData[y]?.[x]
|
|
125802
|
+
? tokenizeCell(preprocessBody(sparseData[y][x], hardBreaks))
|
|
125803
|
+
: [{ type: 'text', value: '' }],
|
|
125765
125804
|
type: y === 0 ? 'tableHead' : 'tableCell',
|
|
125766
125805
|
})),
|
|
125767
125806
|
type: 'tableRow',
|
|
@@ -127618,7 +127657,7 @@ function preprocessContent(content, opts) {
|
|
|
127618
127657
|
return processSnakeCaseComponent(result, { knownComponents });
|
|
127619
127658
|
}
|
|
127620
127659
|
function mdxishAstProcessor(mdContent, opts = {}) {
|
|
127621
|
-
const { components: userComponents = {}, newEditorTypes = false, safeMode = false, useTailwind } = opts;
|
|
127660
|
+
const { components: userComponents = {}, hardBreaks: enableHardBreaks = true, newEditorTypes = false, safeMode = false, useTailwind, } = opts;
|
|
127622
127661
|
const components = {
|
|
127623
127662
|
...loadComponents(),
|
|
127624
127663
|
...userComponents,
|
|
@@ -127647,7 +127686,7 @@ function mdxishAstProcessor(mdContent, opts = {}) {
|
|
|
127647
127686
|
// The next few transformers must appear after mdxishMdxComponentBlocks
|
|
127648
127687
|
// so nodes produced by the inline re-parse of component bodies
|
|
127649
127688
|
// (e.g. code/image/embed inside <Tabs>) get visited too
|
|
127650
|
-
.use(magic_block_transformer)
|
|
127689
|
+
.use(magic_block_transformer, { hardBreaks: enableHardBreaks })
|
|
127651
127690
|
.use(transform_images, { isMdxish: true })
|
|
127652
127691
|
.use(defaultTransformers)
|
|
127653
127692
|
.use(newEditorTypes ? inline_mdx_blocks : undefined) // Merge inline html components (e.g. <Anchor>) into MDAST nodes
|
|
@@ -127704,7 +127743,7 @@ function mdxishMdastToMd(mdast) {
|
|
|
127704
127743
|
* @see .claude/context/MDXish/Processor Overview.md
|
|
127705
127744
|
*/
|
|
127706
127745
|
function mdxish(mdContent, opts = {}) {
|
|
127707
|
-
const { components: userComponents = {}, safeMode = false, variables } = opts;
|
|
127746
|
+
const { components: userComponents = {}, hardBreaks: enableHardBreaks = true, safeMode = false, variables } = opts;
|
|
127708
127747
|
const components = {
|
|
127709
127748
|
...loadComponents(),
|
|
127710
127749
|
...userComponents,
|
|
@@ -127716,7 +127755,7 @@ function mdxish(mdContent, opts = {}) {
|
|
|
127716
127755
|
const { processor, parserReadyContent } = mdxishAstProcessor(contentWithoutComments, opts);
|
|
127717
127756
|
processor
|
|
127718
127757
|
.use(safeMode ? undefined : evaluate_exports) // Evaluate `export const/function` and stash scope on file.data.mdxishScope
|
|
127719
|
-
.use(hard_breaks) // Must precede evaluateExpressions to avoid splitting the \n in an evaluated template literal into a <br> node
|
|
127758
|
+
.use(enableHardBreaks ? hard_breaks : undefined) // Must precede evaluateExpressions to avoid splitting the \n in an evaluated template literal into a <br> node
|
|
127720
127759
|
.use(safeMode ? undefined : evaluate_expressions) // Evaluate self-contained MDX expressions (e.g. `{1+1}`)
|
|
127721
127760
|
.use(safeMode ? undefined : evaluate_style_block_expressions) // Evaluate `<style>{`...`}</style>` template literals into plain CSS
|
|
127722
127761
|
.use(variables_code, { variables }) // Resolve <<...>> and {user.*} inside code and inline code nodes
|