As you discovered already, Nova has no concept of syntax inheritance: the parent
element is used for identifying syntax families, thus allowing use of syntax specific features.
What Nova has is the notion of syntax injection. There are two ways to achieve this, only the first of which is documented.
- Template scopes: these essentially add their contents to any scope from a syntax (including external syntaxes included in it). By “any”, I mean “any”: unless your template scopes are also valid inside things like strings, comments etc., or their parsing rules are strictly context-free (not a thing in most programming languages), you will probably get template scope highlighting where you rather wouldn’t. This is the blunt instrument of injection; Nova uses it for HTML+ERB, Smarty, and PHP-HTML.
- Override collections: you can indicate that a collection should override a collection of the same name included in the parent scope by adding the undocumented
override="true"
attribute. Include your modified scopes before the original scopes in the override collection and Björn Stronginthearm is your uncle. This is the scalpel of injection; Nova uses it for CSS, JSX, LESS, Sass, SCSS, and TSX. A good way to get a grip on the basic concept is the LESS extension. It pulls from the CSS extension and has the advantage of being far more terse than the JS based grammars.
Note that including collections from a builtin extension leaves your extension at risk of breaking on any Nova update, as Panic are entirely free to change their names. The alternative is to clone the base syntax into your extension and to update it whenever it changes in Nova; your users might experience a period of feature drift between a Nova update and an extension update, but overall, I would say this is probably the better UX.