Skip to content

Conversation

@agoose77
Copy link
Contributor

@agoose77 agoose77 commented Dec 10, 2025

Closes #2582, as a part of #2563.

How mdast is typed

mdast@^3 is defined in text on the GitHub Repo, and in TypeScript in @types/mdast via Definitely Typed.

The type system is designed to be extensible through the use of mapping types, e.g.

type BlockContent = BlockContentMap[keyof BlockContentMap];

interface BlockContentMap {
  paragraph: Paragraph;
  ...
}

The reason for this approach over directly specifying type BlockContent = Paragraph | ... is that this type set is open to extension. Third-party code can extend the members of BlockContentMap by using declaration merging via module augmentation: https://www.typescriptlang.org/docs/handbook/declaration-merging.html

What this means for myst

Presently, we use two type families in MyST:

  • myst-spec-ext, which defines our effective spec (rather than our published one)
  • myst-common, which defines our GenericParent and GenericNode workarounds

As mystmd has been developed, we've worked around type problems with type casts, and our types are fragile. The goal with this PR is to set the foundations for us to be stricter with these types. I suspect future PRs will have to chip away at removing GenericParent altogether.

@changeset-bot
Copy link

changeset-bot bot commented Dec 10, 2025

⚠️ No Changeset found

Latest commit: ee7d2b6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions github-actions bot added the enhancement New feature or request label Dec 10, 2025
@agoose77 agoose77 changed the title Feat add myst spec Add myst-spec as TypeScript types Dec 10, 2025
Comment on lines +186 to 208
export function mergeTextNodes(node: Content): Content {
const children = nodeHasChildren(node)
? node.children.reduce((c, n) => {
if (n?.type !== 'text') {
c.push(mergeTextNodes(n));
return c;
}
const last = c[c.length - 1];
if (last?.type !== 'text') {
c.push(n);
return c;
}
if (n.position?.end) {
if (!last.position) last.position = {} as Required<Node>['position'];
last.position.end = n.position.end;
}
if (!last.value) last.value = '';
if (n.value) last.value += n.value;
return c;
}, [] as Content[])
: [];
if (children) (node as Parent).children = children;
return node;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this should actually be generic, e.g.

export function mergeTextNodes<T extends Nodes>(node: T): T {

although that won't be a lower bound

records: SearchRecord[];
};

export type * from 'myst-spec';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For compatibility.

enumerator: string;
}

/// Types //////////////////////////////
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First we define the custom MyST types.

}
type Visibility = 'show' | 'hide' | 'remove';

declare module 'mdast' {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we define the customisations to the mdast types

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Convert myst-spec to use mdast@3

2 participants