@readme/markdown 15.8.0 → 15.9.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/dist/main.node.js CHANGED
@@ -19045,7 +19045,7 @@ module.exports = function () {
19045
19045
 
19046
19046
  /***/ },
19047
19047
 
19048
- /***/ 4246
19048
+ /***/ 5789
19049
19049
  (module, __webpack_exports__, __webpack_require__) {
19050
19050
 
19051
19051
  "use strict";
@@ -24743,9 +24743,9 @@ const HTMLBlock = ({ children = '', html: htmlProp, runScripts, safeMode: safeMo
24743
24743
  const safeMode = typeof safeModeRaw !== 'boolean' ? safeModeRaw === 'true' : safeModeRaw;
24744
24744
  const [cleanedHtml, exec] = extractScripts(html);
24745
24745
  (0,external_react_.useEffect)(() => {
24746
- if (typeof window !== 'undefined' && typeof runScripts === 'boolean' && runScripts)
24746
+ if (typeof window !== 'undefined' && typeof runScripts === 'boolean' && runScripts && !safeMode)
24747
24747
  exec();
24748
- }, [runScripts, exec]);
24748
+ }, [runScripts, safeMode, exec]);
24749
24749
  if (nonStringChildren) {
24750
24750
  // Fail soft: a non-string child (e.g. JSX that wasn't serialized back to a
24751
24751
  // raw string) should never throw, so render the child nodes directly
@@ -124071,6 +124071,32 @@ const mdxComponentHandlers = {
124071
124071
  [NodeTypes.htmlBlock]: htmlBlockHandler,
124072
124072
  };
124073
124073
 
124074
+ ;// ./processor/plugin/safe-mode-html-blocks.ts
124075
+
124076
+
124077
+ /**
124078
+ * Whether a tag name renders through the `HTMLBlock` component. Mirrors the
124079
+ * separator-agnostic, case-insensitive lookup in `getComponentName` and the
124080
+ * rehype-react component map, so `html-block`, `HTMLBlock`, `HtmlBlock` and
124081
+ * `htmlblock` all match.
124082
+ */
124083
+ const isHtmlBlockTag = (tagName) => toPascalCase(tagName).toLowerCase() === 'htmlblock';
124084
+ /**
124085
+ * Forces `safeMode` on every element that renders through `HTMLBlock` so it is
124086
+ * shown as escaped text instead of injected.
124087
+ *
124088
+ * Runs last, so it sees every producer of the element — `[block:html]`,
124089
+ * `<HTMLBlock>` with a template body or an `html` attribute, and a literal
124090
+ * `<html-block>` — and it is unconditional so an author-supplied
124091
+ * `safeMode="false"` can't opt out.
124092
+ */
124093
+ const enforceSafeModeHtmlBlocks = () => tree => {
124094
+ visit(tree, 'element', node => {
124095
+ if (isHtmlBlockTag(node.tagName))
124096
+ node.properties.safeMode = 'true';
124097
+ });
124098
+ };
124099
+
124074
124100
  ;// ./processor/transform/mdxish/anchor-to-jsx.ts
124075
124101
 
124076
124102
 
@@ -126378,7 +126404,7 @@ const parseApiHeaderTitle = (text) => {
126378
126404
  * Transform a magicBlock node into final MDAST nodes.
126379
126405
  */
126380
126406
  function transformMagicBlock(blockType, data, rawValue, options = {}) {
126381
- const { compatibilityMode = false, hardBreaks = true, safeMode = false } = options;
126407
+ const { compatibilityMode = false, hardBreaks = true } = options;
126382
126408
  // Handle empty data by returning placeholder nodes for known block types
126383
126409
  // This allows the editor to show appropriate placeholder UI instead of nothing
126384
126410
  if (Object.keys(data).length < 1) {
@@ -126596,7 +126622,7 @@ function transformMagicBlock(blockType, data, rawValue, options = {}) {
126596
126622
  wrapPinnedBlocks({
126597
126623
  data: {
126598
126624
  hName: 'html-block',
126599
- hProperties: { html: htmlJson.html, runScripts: compatibilityMode, safeMode },
126625
+ hProperties: { html: htmlJson.html, runScripts: compatibilityMode },
126600
126626
  },
126601
126627
  type: 'html-block',
126602
126628
  }, data),
@@ -126856,6 +126882,80 @@ const mdxishHtmlBlocks = () => tree => {
126856
126882
  };
126857
126883
  /* harmony default export */ const mdxish_html_blocks = (mdxishHtmlBlocks);
126858
126884
 
126885
+ ;// ./processor/transform/mdxish/tables/cell-width.ts
126886
+
126887
+
126888
+ // Key must follow `{` or `,` so `minWidth`/`maxWidth` don't match on their suffix
126889
+ const STYLE_OBJECT_WIDTH_REGEX = /[{,]\s*["']?width["']?\s*:\s*(?:"([^"]*)"|'([^']*)'|([^,}]+))/i;
126890
+ // First colon only, so `url(http://…)` values stay intact
126891
+ const CSS_DECLARATION_REGEX = /:(.*)/s;
126892
+ const UNITLESS_NUMBER_REGEX = /^\d+(?:\.\d+)?$/;
126893
+ // HTML reads a `width` attribute as a leading number plus optional `%`, ignoring the rest
126894
+ const HTML_DIMENSION_REGEX = /^\s*(\d+(?:\.\d+)?)\s*(%?)/;
126895
+ /** Bare numbers are pixels. A value carrying declaration separators is not a single width. */
126896
+ const normalizeWidth = (value) => {
126897
+ if (typeof value === 'number')
126898
+ return `${value}px`;
126899
+ if (typeof value !== 'string' || !value.trim())
126900
+ return null;
126901
+ const trimmed = value.trim();
126902
+ if (/[;:{}]/.test(trimmed))
126903
+ return null;
126904
+ return UNITLESS_NUMBER_REGEX.test(trimmed) ? `${trimmed}px` : trimmed;
126905
+ };
126906
+ const widthFromAttribute = (value) => {
126907
+ if (typeof value === 'number')
126908
+ return `${value}px`;
126909
+ if (typeof value !== 'string')
126910
+ return null;
126911
+ const match = HTML_DIMENSION_REGEX.exec(value);
126912
+ return match ? `${match[1]}${match[2] || 'px'}` : null;
126913
+ };
126914
+ const cssPropertyNames = (style) => style
126915
+ .split(';')
126916
+ .map(declaration => declaration.split(CSS_DECLARATION_REGEX)[0].trim().toLowerCase())
126917
+ .filter(Boolean);
126918
+ /** Handles a CSS declaration list and a style object safe mode left as a string (`{ width: "30%" }`). */
126919
+ const widthFromStyleString = (style) => {
126920
+ const trimmed = style.trim();
126921
+ if (trimmed.startsWith('{')) {
126922
+ return STYLE_OBJECT_WIDTH_REGEX.exec(trimmed)?.slice(1).find(Boolean);
126923
+ }
126924
+ return trimmed
126925
+ .split(';')
126926
+ .map(declaration => declaration.split(CSS_DECLARATION_REGEX))
126927
+ .find(([property]) => property.trim().toLowerCase() === 'width')?.[1];
126928
+ };
126929
+ /** Accepts `style={{ width }}`, `style="width: …"` and the hand-authored `width="…"`. */
126930
+ const getCellWidth = (cell) => {
126931
+ const { style, width } = getAttrs(cell);
126932
+ let styleWidth;
126933
+ if (style_object_to_css_isPlainObject(style)) {
126934
+ styleWidth = style.width;
126935
+ }
126936
+ else if (typeof style === 'string') {
126937
+ styleWidth = widthFromStyleString(style);
126938
+ }
126939
+ return normalizeWidth(styleWidth) ?? widthFromAttribute(width);
126940
+ };
126941
+ /** True when the cell's attributes state nothing but its width, which mdast can carry. */
126942
+ const hasOnlyWidthAttributes = (cell) => {
126943
+ if (cell.attributes.length === 0)
126944
+ return false;
126945
+ const { style } = getAttrs(cell);
126946
+ return cell.attributes.every(attribute => {
126947
+ if (!('name' in attribute))
126948
+ return false;
126949
+ if (attribute.name === 'width')
126950
+ return true;
126951
+ if (attribute.name !== 'style')
126952
+ return false;
126953
+ if (style_object_to_css_isPlainObject(style))
126954
+ return Object.keys(style).every(key => key === 'width');
126955
+ return typeof style === 'string' && cssPropertyNames(style).every(property => property === 'width');
126956
+ });
126957
+ };
126958
+
126859
126959
  ;// ./processor/transform/mdxish/mdxish-jsx-to-mdast.ts
126860
126960
 
126861
126961
 
@@ -126863,6 +126963,7 @@ const mdxishHtmlBlocks = () => tree => {
126863
126963
 
126864
126964
 
126865
126965
 
126966
+
126866
126967
  function toImageAlign(value) {
126867
126968
  if (value === 'left' || value === 'center' || value === 'right') {
126868
126969
  return value;
@@ -127304,10 +127405,40 @@ const wrapBareCellsInRow = (node) => {
127304
127405
  });
127305
127406
  };
127306
127407
  /**
127307
- * Converts a JSX <Table> element to an MDAST table node with alignment.
127308
- * Returns null for header-less tables since MDAST always promotes the first row to <thead>.
127408
+ * A lowercase <table> reaches here only because `mdxishTables` kept it as JSX for its
127409
+ * attributes. Widths on first-row cells are the one attribute mdast can carry; anything
127410
+ * else stays JSX so it still renders.
127411
+ */
127412
+ const lowercaseTableIsConvertible = (jsx) => {
127413
+ if (jsx.attributes.length > 0)
127414
+ return false;
127415
+ const headerCells = new Set();
127416
+ let headerRowSeen = false;
127417
+ let convertible = true;
127418
+ visit(jsx, isMDXElement, (child) => {
127419
+ if (child.name === 'tr' && !headerRowSeen) {
127420
+ headerRowSeen = true;
127421
+ visit(child, mdxish_jsx_to_mdast_isTableCell, cell => {
127422
+ headerCells.add(cell);
127423
+ });
127424
+ }
127425
+ if (child.name === null || !tableTags.has(child.name) || child.attributes.length === 0)
127426
+ return;
127427
+ if (!headerCells.has(child) || !hasOnlyWidthAttributes(child) || getCellWidth(child) === null) {
127428
+ convertible = false;
127429
+ }
127430
+ });
127431
+ return convertible;
127432
+ };
127433
+ /**
127434
+ * Converts a JSX <Table>, or a lowercase <table> carrying only widths, to an MDAST table
127435
+ * node with alignment and widths. Returns null for header-less tables since MDAST always
127436
+ * promotes the first row to <thead>.
127309
127437
  */
127310
127438
  const transformTable = (jsx) => {
127439
+ const isLowercase = jsx.name === 'table';
127440
+ if (isLowercase && !lowercaseTableIsConvertible(jsx))
127441
+ return null;
127311
127442
  wrapBareCellsInRow(jsx);
127312
127443
  let hasThead = false;
127313
127444
  visit(jsx, isMDXElement, (child) => {
@@ -127319,6 +127450,7 @@ const transformTable = (jsx) => {
127319
127450
  const { align: alignAttr } = getAttrs(jsx);
127320
127451
  const align = Array.isArray(alignAttr) ? alignAttr : null;
127321
127452
  const rows = [];
127453
+ const widths = [];
127322
127454
  visit(jsx, isMDXElement, (child) => {
127323
127455
  if (child.name !== 'thead' && child.name !== 'tbody')
127324
127456
  return;
@@ -127326,6 +127458,7 @@ const transformTable = (jsx) => {
127326
127458
  if (row.name !== 'tr')
127327
127459
  return;
127328
127460
  const cells = [];
127461
+ const isHeaderRow = rows.length === 0;
127329
127462
  visit(row, mdxish_jsx_to_mdast_isTableCell, (cell) => {
127330
127463
  const parsedChildren = unwrapSoleParagraph(cell.children);
127331
127464
  cells.push({
@@ -127333,6 +127466,8 @@ const transformTable = (jsx) => {
127333
127466
  children: parsedChildren,
127334
127467
  position: cell.position,
127335
127468
  });
127469
+ if (isHeaderRow)
127470
+ widths.push(getCellWidth(cell));
127336
127471
  });
127337
127472
  rows.push({
127338
127473
  type: 'tableRow',
@@ -127345,11 +127480,16 @@ const transformTable = (jsx) => {
127345
127480
  const alignArray = align && columnCount > 0
127346
127481
  ? align.slice(0, columnCount).concat(Array.from({ length: Math.max(0, columnCount - align.length) }, () => null))
127347
127482
  : Array.from({ length: columnCount }, () => null);
127483
+ const data = {
127484
+ ...(isLowercase && { lowercaseTable: true }),
127485
+ ...(widths.some(Boolean) && { widths }),
127486
+ };
127348
127487
  return {
127349
127488
  type: 'table',
127350
127489
  align: alignArray,
127351
127490
  position: jsx.position,
127352
127491
  children: rows,
127492
+ ...(Object.keys(data).length > 0 && { data }),
127353
127493
  };
127354
127494
  };
127355
127495
  /**
@@ -127379,6 +127519,7 @@ const COMPONENT_MAP = {
127379
127519
  figure: transformFigure,
127380
127520
  Recipe: transformRecipe,
127381
127521
  Table: transformTable,
127522
+ table: transformTable,
127382
127523
  };
127383
127524
  /**
127384
127525
  * Transform mdxJsxFlowElement nodes, magic block nodes, and HTML figure elements
@@ -127854,6 +127995,28 @@ const restoreBooleanProperties = () => tree => {
127854
127995
  };
127855
127996
 
127856
127997
 
127998
+ ;// ./processor/transform/mdxish/tables/cell-style.ts
127999
+ /** `left` is the browser default, so it's omitted. Lowercase tables get the HTML string form. */
128000
+ const cellStyle = (align, width = null, { html = false } = {}) => {
128001
+ if (html) {
128002
+ if (!width)
128003
+ return null;
128004
+ return { type: 'mdxJsxAttribute', name: 'style', value: `width: ${width}` };
128005
+ }
128006
+ const declarations = [];
128007
+ if (align && align !== 'left')
128008
+ declarations.push(`textAlign: ${JSON.stringify(align)}`);
128009
+ if (width)
128010
+ declarations.push(`width: ${JSON.stringify(width)}`);
128011
+ if (declarations.length === 0)
128012
+ return null;
128013
+ return {
128014
+ type: 'mdxJsxAttribute',
128015
+ name: 'style',
128016
+ value: { type: 'mdxJsxAttributeValueExpression', value: `{ ${declarations.join(', ')} }` },
128017
+ };
128018
+ };
128019
+
127857
128020
  ;// ./processor/transform/mdxish/tables/gfm-cell-normalization.ts
127858
128021
  /** `<br />` is the only line break a GFM pipe cell can carry, since cells are single-line. */
127859
128022
  const createLineBreak = () => ({
@@ -127892,19 +128055,8 @@ const normalizeCellChildrenForGfm = (cell) => normalizeNodes(cell.children);
127892
128055
 
127893
128056
 
127894
128057
 
128058
+
127895
128059
  const SELF_CLOSING_JSX_REGEX = /^\s*<[A-Z][^>]*\/>\s*$/;
127896
- const mdxish_tables_to_jsx_alignToStyle = (align) => {
127897
- if (!align || align === 'left')
127898
- return null;
127899
- return {
127900
- type: 'mdxJsxAttribute',
127901
- name: 'style',
127902
- value: {
127903
- type: 'mdxJsxAttributeValueExpression',
127904
- value: `{ textAlign: "${align}" }`,
127905
- },
127906
- };
127907
- };
127908
128060
  const mdxish_tables_to_jsx_isTableCell = (node) => ['tableHead', 'tableCell'].includes(node.type);
127909
128061
  const mdxish_tables_to_jsx_isLiteral = (node) => 'value' in node;
127910
128062
  /**
@@ -127960,12 +128112,17 @@ const mdxishTablesToJsx = () => tree => {
127960
128112
  gfmCells.push([cell, normalized]);
127961
128113
  return undefined;
127962
128114
  });
127963
- const stayLowercase = table.data?.lowercaseTable === true;
128115
+ const widths = table.data?.widths ?? [];
128116
+ const hasWidths = widths.some(Boolean);
128117
+ // Lowercase cells can carry a width but not an alignment, so an aligned table becomes <Table>
128118
+ const hasAlignment = table.align.some(align => align && align !== 'left');
128119
+ const stayLowercase = table.data?.lowercaseTable === true && !hasAlignment;
127964
128120
  // We transform to GFM tables if:
127965
128121
  // 1. If it doesn't contain complex elements that the syntax can't represent
127966
- // 2. The original table is not lowercase HTML <table>, because we want to
128122
+ // 2. The original table is not lowercase HTML <table>, because we want to
127967
128123
  // preserve original tables as much as possible
127968
- if (!requiresJsxTable && !stayLowercase) {
128124
+ // 3. No column has a width, which GFM can't express
128125
+ if (!requiresJsxTable && !stayLowercase && !hasWidths) {
127969
128126
  gfmCells.forEach(([cell, children]) => {
127970
128127
  cell.children = children;
127971
128128
  });
@@ -127977,7 +128134,8 @@ const mdxishTablesToJsx = () => tree => {
127977
128134
  if (!headerRow)
127978
128135
  return;
127979
128136
  visit(table, mdxish_tables_to_jsx_isTableCell, flattenBreaksToNewlines);
127980
- const styles = table.align.map(mdxish_tables_to_jsx_alignToStyle);
128137
+ const headerStyles = table.align.map((align, i) => cellStyle(align, widths[i] ?? null, { html: stayLowercase }));
128138
+ const bodyStyles = table.align.map(align => cellStyle(align, null, { html: stayLowercase }));
127981
128139
  const head = {
127982
128140
  attributes: [],
127983
128141
  type: 'mdxJsxFlowElement',
@@ -127993,7 +128151,7 @@ const mdxishTablesToJsx = () => tree => {
127993
128151
  type: 'mdxJsxFlowElement',
127994
128152
  name: 'th',
127995
128153
  children: cell.children,
127996
- ...(styles[cellIndex] && { attributes: [styles[cellIndex]] }),
128154
+ ...(headerStyles[cellIndex] && { attributes: [headerStyles[cellIndex]] }),
127997
128155
  };
127998
128156
  }),
127999
128157
  },
@@ -128013,7 +128171,7 @@ const mdxishTablesToJsx = () => tree => {
128013
128171
  type: 'mdxJsxFlowElement',
128014
128172
  name: 'td',
128015
128173
  children: cell.children,
128016
- ...(styles[cellIndex] && { attributes: [styles[cellIndex]] }),
128174
+ ...(bodyStyles[cellIndex] && { attributes: [bodyStyles[cellIndex]] }),
128017
128175
  };
128018
128176
  }),
128019
128177
  };
@@ -128299,6 +128457,7 @@ function loadComponents() {
128299
128457
 
128300
128458
 
128301
128459
 
128460
+
128302
128461
 
128303
128462
 
128304
128463
  const defaultTransformers = [
@@ -128454,7 +128613,8 @@ function mdxish(mdContent, opts = {}) {
128454
128613
  .use(rehypeMdxishComponents, {
128455
128614
  components,
128456
128615
  processMarkdown: (markdown) => mdxish(markdown, opts),
128457
- });
128616
+ })
128617
+ .use(safeMode ? enforceSafeModeHtmlBlocks : undefined); // Force safeMode on every HTMLBlock; runs last so every producer is covered
128458
128618
  const vfile = new VFile({ value: parserReadyContent });
128459
128619
  const mdast = processor.parse(parserReadyContent);
128460
128620
  const hast = processor.runSync(mdast, vfile);
@@ -129485,7 +129645,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"*":["about","acceptCharset","accessK
129485
129645
  /******/ // startup
129486
129646
  /******/ // Load entry module and return exports
129487
129647
  /******/ // This entry module used 'module' so it can't be inlined
129488
- /******/ let __webpack_exports__ = __webpack_require__(4246);
129648
+ /******/ let __webpack_exports__ = __webpack_require__(5789);
129489
129649
  /******/ module.exports = __webpack_exports__;
129490
129650
  /******/
129491
129651
  /******/ })()