Repository navigation
feat: Add basic support for Marko 6 and 5 - #1914
Conversation
webpro
left a comment
There was a problem hiding this comment.
Thanks for the pull request! Would be cool to add Marko plugin. I do have a note.
| @@ -1,5 +1,5 @@ | |||
| --- | |||
| title: Plugins (177) | |||
| title: Plugins (179) | |||
There was a problem hiding this comment.
Please undo changes in this file, we can auto-generate separately (and they're always re-generated for website deploy).
There was a problem hiding this comment.
Great! Removed.
| /^[ \t]*(export\s+(?:type\s+)?(?:\*(?:\s+as\s+[$\w]+)?|\{[^}]*\})\s+from\s+(["'])([^"'\r\n]+)\2)[ \t]*;?/gm; | ||
| const conciseStyleMatcher = /^[ \t]*style(?:\.([\w.-]+))?[^\n{]*\{([\s\S]*?)^[ \t]*\}/gm; | ||
| const htmlTagMatcher = /<([a-z][\w.-]*)(?=[\s/|>])/g; | ||
| const conciseTagMatcher = /^[ \t]*([a-z][\w.-]*)(?=[ \t/|]|--|$)/gm; |
There was a problem hiding this comment.
The import/export/dynamic-import matchers reimplement what oxc-parser does out of the box. How about this: instead of reconstructing statements with regexes, the compiler could reduce the source to parseable JS (and let the parser do its job):
- Strip comments and style blocks (still compiling styles separately as it does now), lines starting with
<, andimport ... from "<tag>"lines. - Neutralize the Marko-only syntax so a hard error can't land before the imports:
server/client/static/$prefixes, the anonymousclass {(give it a name), and theexportmodifier on local declarations (export interface Inputmust not surface as an unused export). - Return the synthetic imports (marko, taglib dependencies, compiled styles) followed by the remainder verbatim. Synthetic lines go first: a parse error in markup leftovers truncates the module record from that point on, so the leftovers must come last.
No parsing in the compiler: the pipeline picks up static, dynamic and type imports and re-exports in any shape, quoted attribute values are inert to the tokenizer, and dynamic imports inside the class block get picked up too.
To me this feels sturdier and easier to maintain. Even though Marko syntax might change, using regexes for what oxc-parser does better feels a bit cumbersome.
WDYT?
There was a problem hiding this comment.
Agreed this feels cumbersome! I like your suggested approach. Will tinker with that and follow up soon.
There was a problem hiding this comment.
Okay, refactored to have a tag dependency pass, a style pass, then a stage where I sanitize the .marko template so parseable JS is fed into oxc-parser.
I've added regex's to account for different marko syntax things like class {}.
webpro
left a comment
There was a problem hiding this comment.
Thanks for the updates! Almost good to go.
Optional: a fixture with a marko.json that has neither exports nor tags-dir would pin the taglib-imports fallback ("conservatively considered used") behavior.
| ]; | ||
|
|
||
| const tagProduction = tagFilePatterns.map(pattern => `**/{${tagDiscoveryDirs.join(',')}}/${pattern}`); | ||
| export const production = tagProduction; |
There was a problem hiding this comment.
| export const production = tagProduction; | |
| const production = tagProduction; |
It's in the default plugin export obj.
| Local tag templates and their conventionally associated component and style files in \`components\` | ||
| (Marko 5) or \`tags\` (Marko 6) are conservatively treated as production entries. Knip does not | ||
| report unused auto-discovered local tags inside those directories. Modern Marko 5 | ||
| \`marko-tag.json\` entry points and compiler hooks are also resolved.`; |
There was a problem hiding this comment.
Please remove docs and note entirely. They look like implementation details, not documenting surprising behavior with answers / workarounds users need to know about.
There was a problem hiding this comment.
Removed the docs. I should have cross-validated with other plugins here, my bad!
| const compiler = createCompiler(); | ||
|
|
||
| export default compiler; |
There was a problem hiding this comment.
| const compiler = createCompiler(); | |
| export default compiler; |
|
π This pull request is included in v6.31.0. See Release 6.31.0 for release notes. Using Knip in a commercial project? Please consider becoming a sponsor. |
|
Thanks again, Casey β nice one. |
Adds a marko plugin to knip to analyze dependencies in
.markofiles.Marko has an auto tag discovery feature which allows authors to use custom tags without explicitly importing them. To support this, this plugin will look for Marko in the dependencies then look for
marko.jsonfiles for each project dependency in node_modules. It will then find tag names in the locations specified in marko.json and check that at least one of the tag names is used in the project.The
marko.jsonparsing is intentionally limited. It only looks atexportsandtags-dirbecause other mechanisms liketaglib-importswill be deprecated. If a Marko dependency exposes tags with a deprecated property, the plugin will categorize the dependency as used without searching for usages in the project code.This plugin also naively covers marko's "concise syntax" since it's not widely used. A follow up PR could add stronger concise syntax support, if the community needs it. https://markojs.com/docs/reference/concise-syntax
Additional Changes
plugins.mdas well as marko.AI Disclosure
I authored the PR description in my own words and reviewed the code manually, but did use a model to implement the plugin and fixtures.