Skip to content

typings: visitor typings for remark-stringify #426

@ChristianMurphy

Description

@ChristianMurphy

Subject of the feature

Give visitors a type safe way to depend on super types of unist node

Problem

In this example

function gap(this: unified.Processor) {
  const Compiler = this.Compiler as typeof remarkStringify.Compiler
  const visitors = Compiler.prototype.visitors
  const original = visitors.heading

  visitors.heading = heading

  function heading(this: unified.Processor, node: Node, parent?: Parent) {
    // FIXME: remove need for explicit 'as' casting
    const headingNode = node as (Node & {depth: number})
    return (
      (headingNode.depth === 2 ? '\n' : '') +
      original.apply(this, [node, parent])
    )
  }
}

const plugin: unified.Attacher = gap

to get a HeadingNode from the visitor it needs to be cast as (Node & {depth: number}).
Which reduces the type safety since any property can be added in the {} block and typescript will accept it.

Expected behaviour

header should automatically of type HeaderNode

function gap(this: unified.Processor) {
  const Compiler = this.Compiler as typeof remarkStringify.Compiler
  const visitors = Compiler.prototype.visitors
  const original = visitors.heading

  visitors.heading = heading

  function heading(this: unified.Processor, node: HeaderNode, parent?: Parent) {
    return (
      (headingNode.depth === 2 ? '\n' : '') +
      original.apply(this, [node, parent])
    )
  }
}

const plugin: unified.Attacher = gap

This should be safe, because the visitors are staticly defined ahead of time.

proto.visitors = {
root: require('./visitors/root'),
text: require('./visitors/text'),
heading: require('./visitors/heading'),
paragraph: require('./visitors/paragraph'),
blockquote: require('./visitors/blockquote'),
list: require('./visitors/list'),
listItem: require('./visitors/list-item'),
inlineCode: require('./visitors/inline-code'),
code: require('./visitors/code'),
html: require('./visitors/html'),
thematicBreak: require('./visitors/thematic-break'),
strong: require('./visitors/strong'),
emphasis: require('./visitors/emphasis'),
break: require('./visitors/break'),
delete: require('./visitors/delete'),
link: require('./visitors/link'),
linkReference: require('./visitors/link-reference'),
imageReference: require('./visitors/image-reference'),
definition: require('./visitors/definition'),
image: require('./visitors/image'),
footnote: require('./visitors/footnote'),
footnoteReference: require('./visitors/footnote-reference'),
footnoteDefinition: require('./visitors/footnote-definition'),
table: require('./visitors/table'),
tableCell: require('./visitors/table-cell')
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    👀 no/externalThis makes more sense somewhere else

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions