Suppose an internal report tool accepts a small rule file containing allow, deny, quoted labels, and comments. Coloring those different parts helps an author inspect the file. It does not establish whether a rule is allowed by the business system or whether a quoted destination exists.
Register the rules before creating the model
In a configured Monaco application:
const ruleLanguage = 'report-rules';
const languageRegistration = monaco.languages.register({
id: ruleLanguage
});
const tokenRegistration = monaco.languages.setMonarchTokensProvider(
ruleLanguage,
{
tokenizer: {
root: [
[/#.*$/, 'comment'],
[/"[^"\n]*"/, 'string'],
[/\b(?:allow|deny)\b/, 'keyword'],
[/\b\d+\b/, 'number'],
[/[a-zA-Z_][\w-]*/, 'identifier']
]
}
}
);
const model = monaco.editor.createModel(
'allow "quarterly report" # reviewer rule\ndeny 17',
ruleLanguage
);
Attach this model to the intended editor using the application's existing source setup. The Monaco integration guide covers the editor container and model lifetime.
The sample language is invented for this explanation. Its string rule accepts a pair of double quotes on one line; it does not support escaped quotes, multiline strings, or a complete grammar. If the real file format supports those features, write and test appropriate states before using this tokenizer with production files.
Keep rule order and boundaries intentional
Monarch evaluates rules within the active state. Here a comment beginning at # consumes the rest of the line, while the earlier quoted-string match keeps a # inside a matched string as string content. Keyword boundaries prevent allowed from being treated as the keyword allow followed by unrelated letters.
Token names such as keyword and string let a theme choose their presentation. A theme can make two token categories look similar, so inspect actual tokens when diagnosing rules instead of judging only the colors on your monitor. The Monarch language interface describes the tokenizer configuration.
For a small inspection check:
const tokenLines = monaco.editor.tokenize(
'allow "quarterly report" # reviewer rule',
ruleLanguage
);
console.log(tokenLines);
The tokenize API returns tokens by line. Expect distinct keyword, string, and comment classifications for this fixture. Exact token-type strings may include language-specific suffixes, so inspect the returned categories rather than assuming a particular display color.
Add semantic features only when the application supplies them
A tokenizer cannot tell whether deny 17 refers to a known rule. Use the application's parser or validator to decide that, then publish appropriate validation markers. For accepted names and insertion ranges, implement a completion provider separately.
Also keep rendering separate. This rule file is source data, and the editor should not execute it merely because it recognizes a keyword. Read model.getValue() at the application's intended save action and validate through the actual rule service.
Retain registration until its consumers close
Register the language once for the owning feature, rather than once per keystroke or component render. Keep the returned disposables and release them when no remaining editor needs that feature. Dispose separately owned models and editors under their own lifetime rules.
Before finishing, inspect a comment, a quoted label containing #, the identifier allowed, and an unfinished quote. Confirm the source remains unchanged after tokenization. Then reopen the saved rule file with the intended language ID and verify that both its characters and its token interpretation match the file the author reviewed.