Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 2 additions & 69 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,8 @@
"tinyglobby": "^0.2.17",
"unified": "^11.0.5",
"unist-builder": "^4.0.0",
"unist-util-find-after": "^5.0.0",
"unist-util-position": "^5.0.0",
"unist-util-remove": "^4.0.0",
"unist-util-select": "^5.1.0",
"unist-util-visit": "^5.1.0",
"yaml": "^2.9.0"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,76 @@ describe('jsx-ast transformer', () => {
assert.equal(tree.children.includes(footnotes), false);
assert.equal(layout.children.at(-1), footnotes);
});

it('wraps tables in an overflow container and adds responsive labels', () => {
const table = {
type: 'element',
tagName: 'table',
properties: {},
children: [
{
type: 'element',
tagName: 'thead',
properties: {},
children: [
{
type: 'element',
tagName: 'tr',
properties: {},
children: [
{
type: 'element',
tagName: 'th',
properties: {},
children: [{ type: 'text', value: 'Name' }],
},
],
},
],
},
{
type: 'element',
tagName: 'tbody',
properties: {},
children: [
{
type: 'element',
tagName: 'tr',
properties: {},
children: [
{
type: 'element',
tagName: 'td',
properties: {},
children: [{ type: 'text', value: 'Alice' }],
},
],
},
],
},
],
};

const tree = {
type: 'root',
children: [table],
};

transformer()(tree);

const wrapper = tree.children[0];

assert.equal(wrapper.tagName, 'div');
assert.deepEqual(wrapper.properties.className, ['overflow-container']);

const transformedTable = wrapper.children[0];

assert.equal(transformedTable.tagName, 'table');
assert.equal(
transformedTable.children[1].children[0].children[0].properties[
'data-label'
],
'Name'
);
});
});
75 changes: 57 additions & 18 deletions src/generators/jsx-ast/utils/plugins/alerts.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ import { ALERT_MARKER, GITHUB_ALERT_TYPES } from '../../constants.mjs';
import { createJSXElement } from '../ast.mjs';

/**
* Converts a marker keyword into a human-readable title (e.g. `NOTE` -> `Note`).
* @param {string} type - The uppercase alert keyword
* Converts a marker keyword into a human-readable title.
*
* Example:
* NOTE -> Note
*
* @param {string} type
* @returns {string}
*/
const toTitle = type => type[0] + type.slice(1).toLowerCase();

Expand All @@ -17,46 +22,80 @@ const toTitle = type => type[0] + type.slice(1).toLowerCase();
*/
const transformer = tree => {
visit(tree, 'blockquote', (node, index, parent) => {
// The marker must be the leading text of the blockquote's first paragraph
const paragraph = node.children[0];
/**
* Only root-level replacements need a parent.
*/
if (!parent || index === undefined) {
return;
}

const children = node.children;
const paragraph = children[0];

/**
* GitHub alerts must start with a paragraph.
*/
if (paragraph?.type !== 'paragraph') {
return;
}

const text = paragraph.children[0];
const paragraphChildren = paragraph.children;
const firstChild = paragraphChildren[0];

if (text?.type !== 'text') {
/**
* The marker must be plain text.
*/
if (firstChild?.type !== 'text') {
return;
}

const match = text.value.match(ALERT_MARKER);
const match = ALERT_MARKER.exec(firstChild.value);

if (!match) {
return;
}

// Strip the marker (and its trailing line break) from the leading text,
// dropping the now-empty text node — and its paragraph — if nothing remains.
text.value = text.value.slice(match[0].length);
/**
* Remove the alert marker.
*
* Example:
*
* "[!NOTE]\nhello"
*
* becomes:
*
* "hello"
*/
firstChild.value = firstChild.value.slice(match[0].length);

if (text.value === '') {
paragraph.children.shift();
/**
* Remove empty nodes created by stripping the marker.
*/
if (firstChild.value === '') {
paragraphChildren.shift();
}

if (paragraph.children.length === 0) {
node.children.shift();
if (paragraphChildren.length === 0) {
children.shift();
}

/**
* Replace the blockquote with AlertBox JSX.
*/
parent.children[index] = createJSXElement(JSX_IMPORTS.AlertBox.name, {
inline: false,
children: node.children,
children,
level: GITHUB_ALERT_TYPES[match[1]],
title: toTitle(match[1]),
});

// Skip the (now detached) blockquote's children, but revisit this index so
// the new AlertBox is descended into, allowing nested alerts to transform.
/**
* Skip the detached blockquote.
*
* Returning index causes the new AlertBox at this
* position to be visited again, allowing nested
* alerts to transform.
*/
return [SKIP, index];
});
};
Expand All @@ -69,6 +108,6 @@ const transformer = tree => {
* > [!NOTE]
* > Highlights information that users should take into account.
*
* @see https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts
* @see https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-syntax#alerts
*/
export default () => transformer;
Loading
Loading