Proposed exports #16
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
For Nota, I have implemented a new syntax as a Markdown extension using the interface in @lezer-parser/markdown: https://github.com/nota-lang/nota/blob/markdown/packages/nota-syntax/lib/parse.ts
Everything worked quite well -- great job on the flexible API design! But I ran into a few cases where I needed functionality that's currently private to
markdown.ts. I'd like to show what those cases are, and in turn propose they be exported.Typeshould be exported fromindex.ts: I needTypein order to post-process the Markdown AST. However, althoughTypeis exported frommarkdown.ts, it's not accessible through the module root. My bundler can't seem to resolveimport "@lezer/markdown/dist/markdown"so it's not easy for me to import it from the file directly.BlockResultshould be exported: this type appears in a public interface (BlockParser.parse), so it would be nice to name it directly.InlineContextconstructor should be exported: similar to the problems described in #6, I had issues dealing with relative vs. global indexes inside block parsers. My solution was to just construct anInlineContextfor a given line, use absolute indexes everywhere, and then let the context methods handle the translation to relative indexes for me. But this strategy requires access to theInlineContextconstructor, which isn't exported.If you're ok with any of these, let me know and I will put up a pull request.
Since
Typeonly covers a part of the node types in an extended parser, and the library provides separate vocabulary for defining node types, I intentionally kept that enum out of the public interface. You can construct something like it, for a specific parser, by iterating throughparser.nodeSet.typesand building up an object. Or, if you want to refer to node types statically, use their names. Does that help?It's
boolean | null, which is only a few characters more than the name. What is gained by exporting this?There's a bunch of other internal stuff that would probably have to be exposed for this (such as
resolveMarkers) and I'm not sure I want to complicate the public interface for this rather specific use. What kind of block are you defining here, and where do the problems with relative/absolute indices come from?I can just do this if you want to keep
Typeprivate. I already do this to extract the numeric type ids for my Markdown extension.IMO it's just a bit of a surprising type, since I would normally expect this to be an enum with names for each case. The type name conveys that it's very specific to the block parsing context. Not a huge deal though.
In my use case at least, I was able to stick to the current public interface with the exception of the constructor.
For example, I have a composite block that has a "header" on the first line followed by indented blocks. Such as:
Then I have code like this that needs to parse through the header line, which involves many lookups to
line.text. I try to only use absolute positions everywhere to be consistent and avoid confusion. However theLinestructure does not expose methods to lookup substrings or characters based on absolute positions (exactly the issue in #6).An alternative here would be a method like
Line.toInlineContext(cx: BlockContext): InlineContextthat abstracts the details of the constructor.The code you linked seems to have already moved in the meantime.
In any case, I can see the use for an abstraction to help here, but simply exporting the
InlineContextconstructor feels dodgy—that does a bunch of things that don't make sense for a task like this. Maybe we should split off a superclass ofInlineContextthat just does the position-offsetting and element-building, and export that instead? Not too sure about the name, though. MaybeInputWindowor something.I actually would also like to see the
Typeenum exported. When dealing with the syntax tree, I find that I frequently am checking if a certain node is a certain type. Although yes I can clearly donode.type.name === 'StrongEmphasis', I think it would be much nicer from a dev perspective to be able to donode.type.name === MarkdownType.StrongEmphasis.In general, I find enums much better to use in this case, as they are a better guarantee of forwards compatibility and they improve discoverability. Although of course I can just make my own version of the enum, this enum would become outdated if a new node type was ever added to
lezer-parser/markdown. Although this is highly unlikely in this particular case (as the Markdown spec is fairly stable at this point), recreating an enum from a library is quite code-smelly. I'm also not sure I understand the reticence – what is lost by making this an export from the lib? Sure, the enum is not "complete" in an extended parser, but I can make it complete with: