[IMP] owl-vision: syntax scripts, single quotes attributes and slot props highlight and switch below command

This commit adds the following:

- Syntax builder scripts to make syntaxes easier to read and edit
- Syntax highlight in single quote attributes
- Syntax highlight for slot props
- Basic syntax highlight for xpaths
- Added `Switch Below` command

This commit fixes the following:

- Using `Switch Besides` or `Switch Below` does not open a new panel if one was already open
- Fixed missing space in component's snippet indentation
This commit is contained in:
Bastien Fafchamps (bafa)
2023-11-02 13:33:20 +01:00
committed by Géry Debongnie
parent 398df543fe
commit 34489a2494
13 changed files with 951 additions and 261 deletions
@@ -0,0 +1,48 @@
import { createTagPattern, exportPatterns } from "./syntax_builder_utils.mjs";
import {
htmlAttributes,
owlAttributesDynamic,
owlAttributesFormattedString,
owlAttributesStatic,
propsAttributes
} from "./syntax_parts/owl_attributes.mjs";
import { xpathAttributes } from "./syntax_parts/xpath.mjs";
const componentsTags = createTagPattern("component-tags", {
match: "[A-Z][a-zA-Z0-9_]*",
name: "entity.name.type.class owl.component",
patterns: [
owlAttributesDynamic,
owlAttributesDynamic,
propsAttributes,
],
});
const htmlTags = createTagPattern("html-tags", {
match: "[a-z][a-zA-Z0-9_:.]+|[abiqsuw]",
name: "entity.name.tag.localname.xml owl.xml.tag",
patterns: [
owlAttributesFormattedString,
xpathAttributes,
owlAttributesDynamic,
owlAttributesStatic,
htmlAttributes,
],
});
const tTag = createTagPattern("t-tag", {
match: "t(?![a-zA-Z])",
name: "entity.name.tag.localname.xml owl.tag",
patterns: [
propsAttributes,
owlAttributesFormattedString,
owlAttributesDynamic,
owlAttributesStatic,
],
});
exportPatterns(
"L:text.xml -comment",
"owl.template",
[componentsTags, htmlTags, tTag]
);
@@ -0,0 +1,117 @@
import { writeFileSync } from "fs";
import { dirname, resolve } from "path";
import { fileURLToPath } from 'url';
const REPOSITORY = {};
export function exportPatterns(injectionSelector, scopeName, patterns) {
const data = {
injectionSelector: injectionSelector,
scopeName: scopeName,
patterns: [],
repository: {}
}
for (const pattern of patterns) {
data.patterns.push({ include: `#${pattern.id}` });
}
for (const id in REPOSITORY) {
const pattern = { ...REPOSITORY[id] };
delete pattern.id;
data.repository[id] = pattern;
}
const currentDir = dirname(fileURLToPath(import.meta.url));
const filePath = resolve(currentDir, "../syntaxes", `${scopeName}.json`);
writeFileSync(filePath, JSON.stringify(data, null, 4));
console.info(`Sucessfuly build ./syntaxes/${scopeName}.json`);
}
export function createPattern(id, { name, match, begin, end, contentName, beginCaptures, endCaptures, patterns }) {
const pattern = { ...arguments[1] };
if (id) {
pattern.id = id;
REPOSITORY[id] = pattern;
}
function mapCaptures(name, captures) {
if (!captures) {
return;
}
pattern[name] = {};
for (const key in captures) {
pattern[name][key] = { name: captures[key] }
}
}
mapCaptures("beginCaptures", beginCaptures);
mapCaptures("endCaptures", endCaptures);
pattern.patterns = [];
if (patterns) {
for (const childPattern of patterns) {
if (typeof childPattern === "string") {
pattern.patterns.push({ include: childPattern });
} else if (childPattern.id) {
pattern.patterns.push({ include: `#${childPattern.id}` });
} else {
pattern.patterns.push(childPattern);
}
}
}
return pattern;
}
export function createTagPattern(id, { match, name, patterns }) {
return createPattern(id, {
begin: `(</?)(${match})`,
beginCaptures: {
"1": "punctuation.definition.tag.xml owl.xml.punctuation",
"2": name,
},
end: "\\s*([/?]?>)",
endCaptures: {
"1": "punctuation.definition.tag.xml punctuation",
},
patterns,
});
}
export function createAttributePatterns(id, { match, attributeName, contentName = "", patterns = [] }) {
return createPattern(id, {
patterns: [
createPattern(undefined, {
contentName: contentName !== null ? (contentName + " string.quoted.double.xml").trim() : undefined,
begin: `(\\s*)(${match})(=)(")`,
beginCaptures: {
"2": "entity.other.attribute-name.localname.xml " + attributeName,
"4": "punctuation.definition.string.begin.xml",
},
end: `(")`,
endCaptures: {
"0": "punctuation.definition.string.end.xml",
},
patterns,
}),
createPattern(undefined, {
contentName: contentName !== null ? (contentName + " string.quoted.single.xml").trim() : undefined,
begin: `(\\s*)(${match})(=)(')`,
beginCaptures: {
"2": "entity.other.attribute-name.localname.xml " + attributeName,
"4": "punctuation.definition.string.begin.xml",
},
end: `(')`,
endCaptures: {
"0": "punctuation.definition.string.end.xml",
},
patterns,
})
]
});
}
@@ -0,0 +1,103 @@
import { createAttributePatterns, createPattern } from "../syntax_builder_utils.mjs";
export const inilineJs = [createPattern("inline-js", {
patterns: [
{
match: "\\s(=>)\\s",
captures: {
"1": {
name: "string.quoted.double.xml owl.arrow",
}
}
},
{
match: "\\b(props)\\b",
captures: {
"1": {
name: "variable.language.js owl.expression.props",
}
}
},
{
match: "\\s(and|or)\\s",
captures: {
"1": {
name: "keyword.operator.logical.js owl.logical",
}
}
},
{
include: "source.js"
}
]
})];
const formattedString = createPattern("formatted-string", {
contentName: "meta.embedded.block.javascript",
begin: `({{)`,
beginCaptures: {
"1": "owl.double-curlybrackets",
},
end: `(}})`,
endCaptures: {
"1": "owl.double-curlybrackets",
},
patterns: inilineJs
});
// -------------------------------- Attributes --------------------------------
export const htmlAttributes = createAttributePatterns("html-attributes", {
match: "[a-z]{2}[a-z_:.-]+",
attributeName: "owl.xml.attribute",
});
export const propsAttributes = createAttributePatterns("props-attributes", {
match: "[a-zA-Z]{2}[a-zA-Z_:.]*",
contentName: "meta.embedded.block.javascript",
attributeName: "owl.attribute owl.attribute.props",
patterns: inilineJs,
});
export const owlAttributesDynamic = createAttributePatterns("owl-attributes-dynamic", {
match: [
"t-if",
"t-else",
"t-elif",
"t-foreach",
"t-as",
"t-key",
"t-esc",
"t-out",
"t-props",
"t-component",
"t-set",
"t-value",
"t-portal",
"t-slot-scope",
"t-att-[a-z_:.-]+",
"t-on-[a-z_:.-]+"
].join("|"),
contentName: "meta.embedded.block.javascript",
attributeName: "owl.attribute owl.attribute.dynamic",
patterns: inilineJs,
});
export const owlAttributesStatic = createAttributePatterns("owl-attributes-static", {
match: [
"t-name",
"t-ref",
"t-set-slot",
"t-model",
"t-inherit",
"t-inherit-mode",
"t-translation"
].join("|"),
attributeName: "owl.attribute owl.attribute.static",
});
export const owlAttributesFormattedString = createAttributePatterns("owl-attributes-formatted-string", {
match: ["t-call", "t-slot", "t-attf-[a-z_:.-]+"].join("|"),
attributeName: "owl.attribute owl.attribute.formatted",
patterns: [formattedString],
});
@@ -0,0 +1,105 @@
import { createAttributePatterns, createPattern } from "../syntax_builder_utils.mjs";
const xpathPattern = [createPattern("xpath", {
patterns: [
{
begin: "\\[",
beginCaptures: {
"0": {
name: "punctuation.definition",
}
},
end: "\\]",
endCaptures: {
"0": {
name: "punctuation.definition",
}
},
patterns: [
{
begin: "'",
beginCaptures: {
"0": {
name: "punctuation.definition",
}
},
end: "'",
endCaptures: {
"0": {
name: "punctuation.definition",
}
},
contentName: "string.quoted.single",
},
{
begin: "\\\"",
beginCaptures: {
"0": {
name: "punctuation.definition",
}
},
end: "\\\"",
endCaptures: {
"0": {
name: "punctuation.definition",
}
},
contentName: "string.quoted.double",
},
{
match: "(@)([a-zA-Z0-9_:\\-]+)\\b",
captures: {
"1": {
name: "punctuation.definition",
},
"2": {
name: "entity.other.attribute-name",
}
}
},
{
match: "(\\(|\\))",
name: "meta.brace.round",
},
{
match: "[0-9]+(\\.[0-9]+)?",
name: "constant.numeric.decimal",
},
{
match: "\\b(hasclass)\\b",
captures: {
"1": {
name: "entity.name.function",
},
}
},
]
},
{
match: "/{1,2}",
name: "text",
},
{
match: "(?<!@)([A-Z][a-zA-Z]+)\\b",
captures: {
"1": {
name: "entity.name.type.class",
}
}
},
{
match: "(?<!@)([a-z][a-zA-Z0-9_:.]+|[abiqsuw])\\b",
captures: {
"1": {
name: "entity.name.tag",
}
}
},
]
})];
export const xpathAttributes = createAttributePatterns("xpath-attributes", {
match: "expr",
attributeName: "owl.xml.attribute owl.xml.attribute.xpath",
patterns: xpathPattern,
});