mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[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:
committed by
Géry Debongnie
parent
398df543fe
commit
34489a2494
@@ -4,7 +4,22 @@ All notable changes to the "owl-vision" extension will be documented in this fil
|
|||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
|
||||||
## [Unreleased] [0.0.1] - 2023-03-10
|
## [0.0.2] - 2023-2-11
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Switch Below command
|
||||||
|
- Basic syntax highlight for xpaths
|
||||||
|
- Syntax builder scripts to make syntaxes easier to read and edit
|
||||||
|
- Syntax highlight in single quote attributes
|
||||||
|
- Syntax highlight for slot props
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Added missing space in component's snippet indentation
|
||||||
|
- Using `Switch Besides` or `Switch Below` does not open a new panel if one was already open
|
||||||
|
|
||||||
|
## [0.0.1] - 2023-03-10
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
||||||
@@ -15,4 +30,3 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
- `Find Component` Command - Finds the selected component definition.
|
- `Find Component` Command - Finds the selected component definition.
|
||||||
- `Switch` Command - Finds the corresponding template or component file depending on the current file.
|
- `Switch` Command - Finds the corresponding template or component file depending on the current file.
|
||||||
- `Switch Besides` Command - Finds the corresponding template or component file depending on the current file and opens it besides.
|
- `Switch Besides` Command - Finds the corresponding template or component file depending on the current file and opens it besides.
|
||||||
- `Owl Documentation` Sidebar - A webview which allows easly searching through the owl's documentation from github
|
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ Owl Vision is an extension for the amazing [Owl framework](https://github.com/od
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
This extension also adds a small Component snippet to allow you to create beautiful components as fast as possible!
|
This extension also adds:
|
||||||
|
- A basic component snippent.
|
||||||
|
- "Go to definition" providers for component tags in xml or in inline templates.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
@@ -13,11 +15,10 @@ This extension also adds a small Component snippet to allow you to create beauti
|
|||||||
- If the cursor is on a component, finds the template of the selected component.
|
- If the cursor is on a component, finds the template of the selected component.
|
||||||
* `Owl Vision: Find Component`: Finds the selected component definition.
|
* `Owl Vision: Find Component`: Finds the selected component definition.
|
||||||
* `Owl Vision: Switch`: Finds the corresponding template or component depending on the current file.
|
* `Owl Vision: Switch`: Finds the corresponding template or component depending on the current file.
|
||||||
* `Owl Vision: Switch Besides`: Finds the corresponding template or component depending on the current file and opens it besides.
|
* `Owl Vision: Switch (Besides)`: Finds the corresponding template or component depending on the current file and opens it besides.
|
||||||
|
* `Owl Vision: Switch (Below)`: Finds the corresponding template or component depending on the current file and opens it below.
|
||||||
|
|
||||||
## Extension Settings
|
## Settings
|
||||||
|
|
||||||
This extension contributes the following settings:
|
|
||||||
|
|
||||||
* `owl-vision.include`: Glob filter for files to include while searching.
|
* `owl-vision.include`: Glob filter for files to include while searching.
|
||||||
* `owl-vision.exclude`: Glob filter for files to exclude while searching.
|
* `owl-vision.exclude`: Glob filter for files to exclude while searching.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"description": "Owl framework extension that highlights templates and ease navigation between components and templates.",
|
"description": "Owl framework extension that highlights templates and ease navigation between components and templates.",
|
||||||
"publisher": "Odoo",
|
"publisher": "Odoo",
|
||||||
"license": "LGPL-3.0-only",
|
"license": "LGPL-3.0-only",
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/odoo/owl/tree/master/tools/owl-vision"
|
"url": "https://github.com/odoo/owl/tree/master/tools/owl-vision"
|
||||||
@@ -30,7 +30,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "owl-vision.switch-besides",
|
"command": "owl-vision.switch-besides",
|
||||||
"title": "Switch Besides",
|
"title": "Switch (Besides)",
|
||||||
|
"category": "Owl Vision"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "owl-vision.switch-below",
|
||||||
|
"title": "Switch (Below)",
|
||||||
"category": "Owl Vision"
|
"category": "Owl Vision"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -74,9 +79,6 @@
|
|||||||
"embeddedLanguages": {
|
"embeddedLanguages": {
|
||||||
"meta.embedded.block.javascript": "source.js"
|
"meta.embedded.block.javascript": "source.js"
|
||||||
},
|
},
|
||||||
"tokenTypes": {
|
|
||||||
"string.quoted.double.xml": "other"
|
|
||||||
},
|
|
||||||
"injectTo": [
|
"injectTo": [
|
||||||
"text.xml"
|
"text.xml"
|
||||||
]
|
]
|
||||||
@@ -120,7 +122,8 @@
|
|||||||
"vscode:prepublish": "npm run esbuild-base -- --minify",
|
"vscode:prepublish": "npm run esbuild-base -- --minify",
|
||||||
"esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node",
|
"esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node",
|
||||||
"esbuild": "npm run esbuild-base -- --sourcemap",
|
"esbuild": "npm run esbuild-base -- --sourcemap",
|
||||||
"esbuild-watch": "npm run esbuild-base -- --sourcemap --watch"
|
"esbuild-watch": "npm run esbuild-base -- --sourcemap --watch",
|
||||||
|
"build-syntax": "node ./scripts/owl_template_syntax.mjs"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "20.2.5",
|
"@types/node": "20.2.5",
|
||||||
|
|||||||
@@ -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,
|
||||||
|
});
|
||||||
@@ -3,13 +3,13 @@
|
|||||||
"prefix": "owlcomponent",
|
"prefix": "owlcomponent",
|
||||||
"body": [
|
"body": [
|
||||||
"export class ${1:component-name} extends Component {",
|
"export class ${1:component-name} extends Component {",
|
||||||
" static template = \"${2:template-name}\";",
|
" static template = \"${2:template-name}\";",
|
||||||
" static components = {};",
|
" static components = {};",
|
||||||
" static props = {};",
|
" static props = {};",
|
||||||
"",
|
"",
|
||||||
" setup() {",
|
" setup() {",
|
||||||
"",
|
"",
|
||||||
" }",
|
" }",
|
||||||
"}",
|
"}",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { Search } from './search';
|
import { Search } from './search';
|
||||||
import { ComponentDefinitionProvider } from './definiton_providers';
|
import { ComponentDefinitionProvider } from './definiton_providers';
|
||||||
|
import { OpenDirection } from './utils';
|
||||||
|
|
||||||
export async function activate(context: vscode.ExtensionContext) {
|
export async function activate(context: vscode.ExtensionContext) {
|
||||||
const search = new Search();
|
const search = new Search();
|
||||||
|
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('owl-vision.switch', () => search.switchCommand()));
|
context.subscriptions.push(vscode.commands.registerCommand('owl-vision.switch', () => search.switch()));
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('owl-vision.switch-besides', () => search.switchCommand(true)));
|
context.subscriptions.push(vscode.commands.registerCommand('owl-vision.switch-besides', () => search.switch(OpenDirection.Besides)));
|
||||||
|
context.subscriptions.push(vscode.commands.registerCommand('owl-vision.switch-below', () => search.switch(OpenDirection.Below)));
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('owl-vision.find-component', () => search.findComponentCommand()));
|
context.subscriptions.push(vscode.commands.registerCommand('owl-vision.find-component', () => search.findComponentCommand()));
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('owl-vision.find-template', () => search.findTemplateCommand()));
|
context.subscriptions.push(vscode.commands.registerCommand('owl-vision.find-template', () => search.findTemplateCommand()));
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,12 @@
|
|||||||
|
import { GlobPattern, Location, Range, Uri, window, workspace } from 'vscode';
|
||||||
|
import { OpenDirection, getClosestMatch, getSelectedText, hideStatusMessage, showResult, showStatusMessage } from './utils';
|
||||||
import path = require('path');
|
import path = require('path');
|
||||||
import * as vscode from 'vscode';
|
|
||||||
import { getSelectedText, showStatusMessage, hideStatusMessage, getActiveCursorIndex, getClosestMatch } from './utils';
|
|
||||||
|
|
||||||
class SearchResult {
|
|
||||||
uri: vscode.Uri;
|
|
||||||
range: vscode.Range;
|
|
||||||
|
|
||||||
constructor(uri: vscode.Uri, range: vscode.Range) {
|
|
||||||
this.uri = uri;
|
|
||||||
this.range = range;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Search {
|
export class Search {
|
||||||
|
|
||||||
finderCache = new Map<string, vscode.Uri>();
|
finderCache = new Map<string, Uri>();
|
||||||
|
|
||||||
public async switchCommand(openBesides: Boolean = false) {
|
public async switch(openDirection: OpenDirection = OpenDirection.Active) {
|
||||||
if (!this.currentDocument) {
|
if (!this.currentDocument) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -24,26 +14,20 @@ export class Search {
|
|||||||
let result = undefined;
|
let result = undefined;
|
||||||
const text = this.currentDocument.getText();
|
const text = this.currentDocument.getText();
|
||||||
const isJs = this.currentDocument.fileName.endsWith(".js");
|
const isJs = this.currentDocument.fileName.endsWith(".js");
|
||||||
const isXml = this.currentDocument.fileName.endsWith(".xml");
|
const templateName = this.getTemplateName(text, isJs);
|
||||||
|
|
||||||
if (isJs) {
|
if (templateName && isJs) {
|
||||||
const templateName = this.getTemplateNameInJS(text);
|
result = await this.findTemplate(templateName);
|
||||||
if (templateName) {
|
} else if (templateName) {
|
||||||
result = await this.findTemplate(templateName);
|
result = await this.findComponentFromTemplateName(templateName);
|
||||||
}
|
|
||||||
} else if (isXml) {
|
|
||||||
const templateName = this.getTemplateNameInXML(text);
|
|
||||||
if (templateName) {
|
|
||||||
result = await this.findComponentFromTemplateName(templateName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result !== undefined) {
|
if (result !== undefined) {
|
||||||
this.showResult(result, openBesides);
|
showResult(result, openDirection);
|
||||||
} else if (isJs) {
|
} else if (isJs) {
|
||||||
vscode.window.showWarningMessage(`Could not find a template for current component`);
|
window.showWarningMessage(`Could not find a template for current component`);
|
||||||
} else if (isXml) {
|
} else {
|
||||||
vscode.window.showWarningMessage(`Could not find a component for current template`);
|
window.showWarningMessage(`Could not find a component for current template`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,9 +40,9 @@ export class Search {
|
|||||||
showStatusMessage(`Searching for component "${currentWord}"`);
|
showStatusMessage(`Searching for component "${currentWord}"`);
|
||||||
const result = await this.findComponent(currentWord);
|
const result = await this.findComponent(currentWord);
|
||||||
if (result) {
|
if (result) {
|
||||||
this.showResult(result);
|
showResult(result);
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showWarningMessage(`Could not find a component for "${currentWord}"`);
|
window.showWarningMessage(`Could not find a component for "${currentWord}"`);
|
||||||
}
|
}
|
||||||
hideStatusMessage();
|
hideStatusMessage();
|
||||||
}
|
}
|
||||||
@@ -72,14 +56,14 @@ export class Search {
|
|||||||
showStatusMessage(`Searching for template "${currentWord}"`);
|
showStatusMessage(`Searching for template "${currentWord}"`);
|
||||||
const result = await this.findTemplate(currentWord);
|
const result = await this.findTemplate(currentWord);
|
||||||
if (result) {
|
if (result) {
|
||||||
this.showResult(result);
|
showResult(result);
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showWarningMessage(`Could not find a template for "${currentWord}"`);
|
window.showWarningMessage(`Could not find a template for "${currentWord}"`);
|
||||||
}
|
}
|
||||||
hideStatusMessage();
|
hideStatusMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async findComponent(componentName: string): Promise<SearchResult | undefined> {
|
public async findComponent(componentName: string): Promise<Location | undefined> {
|
||||||
if (componentName.toLowerCase() === componentName || componentName.includes(".") || componentName.includes("-")) {
|
if (componentName.toLowerCase() === componentName || componentName.includes(".") || componentName.includes("-")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -88,7 +72,7 @@ export class Search {
|
|||||||
return await this.find(componentName, query, "js");
|
return await this.find(componentName, query, "js");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async findTemplate(templateName: string): Promise<SearchResult | undefined> {
|
public async findTemplate(templateName: string): Promise<Location | undefined> {
|
||||||
const isComponentName = templateName.match(/^[A-Z][a-zA-Z0-9_]*$/);
|
const isComponentName = templateName.match(/^[A-Z][a-zA-Z0-9_]*$/);
|
||||||
|
|
||||||
if (isComponentName) {
|
if (isComponentName) {
|
||||||
@@ -96,9 +80,8 @@ export class Search {
|
|||||||
if (!componentResult) {
|
if (!componentResult) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
const document = await vscode.workspace.openTextDocument(componentResult.uri);
|
const text = (await workspace.openTextDocument(componentResult.uri)).getText();
|
||||||
const text = document.getText();
|
const foundTemplateName = this.getTemplateName(text, true);
|
||||||
const foundTemplateName = this.getTemplateNameInJS(text);
|
|
||||||
if (foundTemplateName) {
|
if (foundTemplateName) {
|
||||||
templateName = foundTemplateName;
|
templateName = foundTemplateName;
|
||||||
} else {
|
} else {
|
||||||
@@ -111,24 +94,24 @@ export class Search {
|
|||||||
return await this.find(templateName, query, "xml");
|
return await this.find(templateName, query, "xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async findComponentFromTemplateName(templateName: string): Promise<SearchResult | undefined> {
|
private findComponentFromTemplateName(templateName: string): Promise<Location | undefined> {
|
||||||
const query = this.buildQuery(`template\\s*=\\s*["']`, templateName, `["']`);
|
const query = this.buildQuery(`template\\s*=\\s*["']`, templateName, `["']`);
|
||||||
return await this.find(templateName, query, "js");
|
return this.find(templateName, query, "js");
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTemplateNameInJS(str: string): string | undefined {
|
private getTemplateName(str: string, isJsFile: boolean): string | undefined {
|
||||||
return getClosestMatch(str, /template\s*=\s*["']([a-zA-Z0-9_\-\.]+)["']/g, +1);
|
if (isJsFile) {
|
||||||
|
return getClosestMatch(str, /template\s*=\s*["']([a-zA-Z0-9_\-\.]+)["']/g, +1);
|
||||||
|
} else {
|
||||||
|
return getClosestMatch(str, /t-name="([a-zA-Z0-9_\-\.]+)"/g);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTemplateNameInXML(str: string): string | undefined {
|
public async find(
|
||||||
return getClosestMatch(str, /t-name="([a-zA-Z0-9_\-\.]+)"/g);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async find(
|
|
||||||
name: string,
|
name: string,
|
||||||
searchQuery: string,
|
searchQuery: string,
|
||||||
fileType: "js" | "xml",
|
fileType: "js" | "xml",
|
||||||
) {
|
): Promise<Location | undefined> {
|
||||||
const key = `${name}-${fileType}`;
|
const key = `${name}-${fileType}`;
|
||||||
const cachedUri = this.finderCache.get(key);
|
const cachedUri = this.finderCache.get(key);
|
||||||
if (cachedUri) {
|
if (cachedUri) {
|
||||||
@@ -140,8 +123,8 @@ export class Search {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const include = `{${vscode.workspace.getConfiguration().get(`owl-vision.include`)}}`;
|
const include = `{${workspace.getConfiguration().get(`owl-vision.include`)}, *.${fileType}}`;
|
||||||
const exclude = `{${vscode.workspace.getConfiguration().get(`owl-vision.exclude`)}}`;
|
const exclude = `{${workspace.getConfiguration().get(`owl-vision.exclude`)}}`;
|
||||||
const files = await this.getFiles(name, include, exclude);
|
const files = await this.getFiles(name, include, exclude);
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
@@ -155,10 +138,10 @@ export class Search {
|
|||||||
|
|
||||||
private async getFiles(
|
private async getFiles(
|
||||||
searchQuery: string,
|
searchQuery: string,
|
||||||
include: vscode.GlobPattern,
|
include: GlobPattern,
|
||||||
exclude: vscode.GlobPattern,
|
exclude: GlobPattern,
|
||||||
): Promise<Array<vscode.Uri>> {
|
): Promise<Array<Uri>> {
|
||||||
const files = await vscode.workspace.findFiles(include, exclude);
|
const files = await workspace.findFiles(include, exclude);
|
||||||
const parts = searchQuery.split(".").flatMap(s => s.split(/(?=[A-Z])/)).map(s => s.toLowerCase());
|
const parts = searchQuery.split(".").flatMap(s => s.split(/(?=[A-Z])/)).map(s => s.toLowerCase());
|
||||||
const currentDir = this.currentDocument ? path.dirname(this.currentDocument.uri.path) : "";
|
const currentDir = this.currentDocument ? path.dirname(this.currentDocument.uri.path) : "";
|
||||||
|
|
||||||
@@ -182,33 +165,24 @@ export class Search {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async findInFile(
|
private async findInFile(
|
||||||
file: vscode.Uri,
|
file: Uri,
|
||||||
searchQuery: string,
|
searchQuery: string,
|
||||||
): Promise<SearchResult | undefined> {
|
): Promise<Location | undefined> {
|
||||||
const document = await vscode.workspace.openTextDocument(file);
|
const document = await workspace.openTextDocument(file);
|
||||||
const text = document.getText();
|
const text = document.getText();
|
||||||
const match = text.match(new RegExp(searchQuery));
|
const match = text.match(new RegExp(searchQuery));
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
const index = match.index || 0;
|
const index = match.index || 0;
|
||||||
return new SearchResult(file, new vscode.Range(
|
return new Location(file, new Range(
|
||||||
document.positionAt(index),
|
document.positionAt(index),
|
||||||
document.positionAt(index)
|
document.positionAt(index)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async showResult(result: SearchResult, openBesides: Boolean = false) {
|
|
||||||
const editor = await vscode.window.showTextDocument(result.uri, {
|
|
||||||
viewColumn: openBesides ? vscode.ViewColumn.Beside : vscode.ViewColumn.Active,
|
|
||||||
});
|
|
||||||
|
|
||||||
editor.revealRange(result.range);
|
|
||||||
editor.selection = new vscode.Selection(result.range.start, result.range.end);
|
|
||||||
}
|
|
||||||
|
|
||||||
private get currentDocument() {
|
private get currentDocument() {
|
||||||
return vscode.window.activeTextEditor?.document;
|
return window.activeTextEditor?.document;
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildQuery(
|
private buildQuery(
|
||||||
|
|||||||
@@ -67,3 +67,38 @@ export function getClosestMatch(str: string, regex: RegExp, lineDelta = 0): stri
|
|||||||
|
|
||||||
return closestMatch[1];
|
return closestMatch[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum OpenDirection {
|
||||||
|
Active,
|
||||||
|
Besides,
|
||||||
|
Below,
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function showResult(result: vscode.Location, openDirection: OpenDirection = OpenDirection.Active) {
|
||||||
|
let editor = undefined;
|
||||||
|
|
||||||
|
if (openDirection == OpenDirection.Active) {
|
||||||
|
editor = await vscode.window.showTextDocument(result.uri);
|
||||||
|
} else {
|
||||||
|
let targetColumn = vscode.ViewColumn.Beside;
|
||||||
|
const existingDocument = vscode.workspace.textDocuments.find(t => t.uri.path === result.uri.path);
|
||||||
|
if (existingDocument) {
|
||||||
|
const currentColumn = vscode.window.activeTextEditor?.viewColumn;
|
||||||
|
if (currentColumn == vscode.ViewColumn.One) {
|
||||||
|
targetColumn = vscode.ViewColumn.Two;
|
||||||
|
} else if (currentColumn == vscode.ViewColumn.Two) {
|
||||||
|
targetColumn = vscode.ViewColumn.One;
|
||||||
|
}
|
||||||
|
editor = await vscode.window.showTextDocument(existingDocument, { viewColumn: targetColumn });
|
||||||
|
} else {
|
||||||
|
editor = await vscode.window.showTextDocument(result.uri, { viewColumn: targetColumn });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openDirection === OpenDirection.Below) {
|
||||||
|
await vscode.commands.executeCommand('workbench.action.editorLayoutTwoRows');
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.revealRange(result.range);
|
||||||
|
editor.selection = new vscode.Selection(result.range.start, result.range.end);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"injectionSelector": "L:source.js -comment",
|
"injectionSelector": "L:source.js -comment -(string -meta.embedded)",
|
||||||
"scopeName": "owl.template.inline",
|
"scopeName": "owl.template.inline",
|
||||||
"patterns": [
|
"patterns": [
|
||||||
{
|
{
|
||||||
@@ -12,16 +12,19 @@
|
|||||||
"contentName": "meta.embedded.block.xml",
|
"contentName": "meta.embedded.block.xml",
|
||||||
"beginCaptures": {
|
"beginCaptures": {
|
||||||
"1": {
|
"1": {
|
||||||
"name": "entity.name.function.tagged-template.js owl-inline-template"
|
"name": "entity.name.function.tagged-template.js"
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"name": "punctuation.definition.string.template.begin.js string.template.js"
|
"name": "punctuation.definition.string.template.begin.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"end": "(`)",
|
"end": "(`)",
|
||||||
"endCaptures": {
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "string.js"
|
||||||
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"name": "punctuation.definition.string.template.end.js string.template.js"
|
"name": "punctuation.definition.string.template.end.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"patterns": [
|
"patterns": [
|
||||||
@@ -34,4 +37,4 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,22 +5,451 @@
|
|||||||
{
|
{
|
||||||
"include": "#component-tags"
|
"include": "#component-tags"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"include": "#html-tags"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"include": "#t-tag"
|
"include": "#t-tag"
|
||||||
},
|
|
||||||
{
|
|
||||||
"include": "#xml-tags"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"include": "#props"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"formatted-string": {
|
||||||
|
"contentName": "meta.embedded.block.javascript",
|
||||||
|
"begin": "({{)",
|
||||||
|
"beginCaptures": {
|
||||||
|
"1": {
|
||||||
|
"name": "owl.double-curlybrackets"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(}})",
|
||||||
|
"endCaptures": {
|
||||||
|
"1": {
|
||||||
|
"name": "owl.double-curlybrackets"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#inline-js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"html-attributes": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"contentName": "string.quoted.double.xml",
|
||||||
|
"begin": "(\\s*)([a-z]{2}[a-z_:.-]+)(=)(\")",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.xml.attribute"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(\")",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contentName": "string.quoted.single.xml",
|
||||||
|
"begin": "(\\s*)([a-z]{2}[a-z_:.-]+)(=)(')",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.xml.attribute"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(')",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"props-attributes": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"contentName": "meta.embedded.block.javascript string.quoted.double.xml",
|
||||||
|
"begin": "(\\s*)([a-zA-Z]{2}[a-zA-Z_:.]*)(=)(\")",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.attribute owl.attribute.props"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(\")",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#inline-js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contentName": "meta.embedded.block.javascript string.quoted.single.xml",
|
||||||
|
"begin": "(\\s*)([a-zA-Z]{2}[a-zA-Z_:.]*)(=)(')",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.attribute owl.attribute.props"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(')",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#inline-js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"owl-attributes-dynamic": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"contentName": "meta.embedded.block.javascript string.quoted.double.xml",
|
||||||
|
"begin": "(\\s*)(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_:.-]+)(=)(\")",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.attribute owl.attribute.dynamic"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(\")",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#inline-js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contentName": "meta.embedded.block.javascript string.quoted.single.xml",
|
||||||
|
"begin": "(\\s*)(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_:.-]+)(=)(')",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.attribute owl.attribute.dynamic"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(')",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#inline-js"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"owl-attributes-static": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"contentName": "string.quoted.double.xml",
|
||||||
|
"begin": "(\\s*)(t-name|t-ref|t-set-slot|t-model|t-inherit|t-inherit-mode|t-translation)(=)(\")",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.attribute owl.attribute.static"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(\")",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contentName": "string.quoted.single.xml",
|
||||||
|
"begin": "(\\s*)(t-name|t-ref|t-set-slot|t-model|t-inherit|t-inherit-mode|t-translation)(=)(')",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.attribute owl.attribute.static"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(')",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"owl-attributes-formatted-string": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"contentName": "string.quoted.double.xml",
|
||||||
|
"begin": "(\\s*)(t-call|t-slot|t-attf-[a-z_:.-]+)(=)(\")",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.attribute owl.attribute.formatted"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(\")",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#formatted-string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contentName": "string.quoted.single.xml",
|
||||||
|
"begin": "(\\s*)(t-call|t-slot|t-attf-[a-z_:.-]+)(=)(')",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.attribute owl.attribute.formatted"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(')",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#formatted-string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"xpath-attributes": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"contentName": "string.quoted.double.xml",
|
||||||
|
"begin": "(\\s*)(expr)(=)(\")",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.xml.attribute owl.xml.attribute.xpath"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(\")",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#xpath"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contentName": "string.quoted.single.xml",
|
||||||
|
"begin": "(\\s*)(expr)(=)(')",
|
||||||
|
"beginCaptures": {
|
||||||
|
"2": {
|
||||||
|
"name": "entity.other.attribute-name.localname.xml owl.xml.attribute owl.xml.attribute.xpath"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "punctuation.definition.string.begin.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(')",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.string.end.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#xpath"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"component-tags": {
|
"component-tags": {
|
||||||
"begin": "(</?)([A-Z][a-zA-Z0-9_]*)",
|
"begin": "(</?)([A-Z][a-zA-Z0-9_]*)",
|
||||||
"beginCaptures": {
|
"beginCaptures": {
|
||||||
"1": {
|
"1": {
|
||||||
"name": "punctuation.definition.tag.xml owl.punctuation"
|
"name": "punctuation.definition.tag.xml owl.xml.punctuation"
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"name": "entity.name.type.class owl.component"
|
"name": "entity.name.type.class owl.component"
|
||||||
@@ -34,45 +463,18 @@
|
|||||||
},
|
},
|
||||||
"patterns": [
|
"patterns": [
|
||||||
{
|
{
|
||||||
"include": "#qweb-directives-interpreted"
|
"include": "#owl-attributes-dynamic"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include": "#qweb-directives-string"
|
"include": "#owl-attributes-dynamic"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include": "#component-props"
|
"include": "#props-attributes"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"component-props": {
|
"html-tags": {
|
||||||
"contentName": "meta.embedded.block.javascript string.quoted.double.xml",
|
"begin": "(</?)([a-z][a-zA-Z0-9_:.]+|[abiqsuw])",
|
||||||
"begin": "(\\s*)([a-zA-Z_:.]*)(=)(\")",
|
|
||||||
"beginCaptures": {
|
|
||||||
"2": {
|
|
||||||
"name": "entity.other.attribute-name.localname.xml owl.component.props"
|
|
||||||
},
|
|
||||||
"4": {
|
|
||||||
"name": "punctuation.definition.string.begin.xml punctuation"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"end": "(\")",
|
|
||||||
"endCaptures": {
|
|
||||||
"0": {
|
|
||||||
"name": "punctuation.definition.string.end.xml punctuation"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"patterns": [
|
|
||||||
{
|
|
||||||
"include": "source.js"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "keyword.operator.logical.js",
|
|
||||||
"match": "\\s(and|or)\\s"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"xml-tags": {
|
|
||||||
"begin": "(</?)([a-z][a-zA-Z0-9_:.]*)",
|
|
||||||
"beginCaptures": {
|
"beginCaptures": {
|
||||||
"1": {
|
"1": {
|
||||||
"name": "punctuation.definition.tag.xml owl.xml.punctuation"
|
"name": "punctuation.definition.tag.xml owl.xml.punctuation"
|
||||||
@@ -84,51 +486,32 @@
|
|||||||
"end": "\\s*([/?]?>)",
|
"end": "\\s*([/?]?>)",
|
||||||
"endCaptures": {
|
"endCaptures": {
|
||||||
"1": {
|
"1": {
|
||||||
"name": "punctuation.definition.tag.xml owl.xml.punctuation"
|
"name": "punctuation.definition.tag.xml punctuation"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"patterns": [
|
"patterns": [
|
||||||
{
|
{
|
||||||
"include": "#qweb-directives-interpreted"
|
"include": "#owl-attributes-formatted-string"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include": "#qweb-directives-string"
|
"include": "#xpath-attributes"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include": "#qweb-directives-formatted-string"
|
"include": "#owl-attributes-dynamic"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include": "#xml-attributes"
|
"include": "#owl-attributes-static"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "string.quoted.double.xml",
|
"include": "#html-attributes"
|
||||||
"match": "(\")((.*)(=>)(.*))(\")"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"xml-attributes": {
|
|
||||||
"contentName": "string.quoted.double.xml owl.xml.string",
|
|
||||||
"begin": "(\\s)([a-z][a-z_:.-]+)(=)(\")",
|
|
||||||
"beginCaptures": {
|
|
||||||
"2": {
|
|
||||||
"name": "entity.other.attribute-name.localname.xml owl.xml.attribute"
|
|
||||||
},
|
|
||||||
"4": {
|
|
||||||
"name": "punctuation.definition.string.begin.xml owl.xml.punctuation"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"end": "(\")",
|
|
||||||
"endCaptures": {
|
|
||||||
"0": {
|
|
||||||
"name": "punctuation.definition.string.end.xml owl.xml.punctuation"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"t-tag": {
|
"t-tag": {
|
||||||
"begin": "(</?)(t(?![a-zA-Z]))",
|
"begin": "(</?)(t(?![a-zA-Z]))",
|
||||||
"beginCaptures": {
|
"beginCaptures": {
|
||||||
"1": {
|
"1": {
|
||||||
"name": "punctuation.definition.tag.xml owl.punctuation"
|
"name": "punctuation.definition.tag.xml owl.xml.punctuation"
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"name": "entity.name.tag.localname.xml owl.tag"
|
"name": "entity.name.tag.localname.xml owl.tag"
|
||||||
@@ -137,121 +520,23 @@
|
|||||||
"end": "\\s*([/?]?>)",
|
"end": "\\s*([/?]?>)",
|
||||||
"endCaptures": {
|
"endCaptures": {
|
||||||
"1": {
|
"1": {
|
||||||
"name": "punctuation.definition.tag.xml owl.punctuation"
|
"name": "punctuation.definition.tag.xml punctuation"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"patterns": [
|
"patterns": [
|
||||||
{
|
{
|
||||||
"include": "#qweb-directives-interpreted"
|
"include": "#props-attributes"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include": "#qweb-directives-string"
|
"include": "#owl-attributes-formatted-string"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include": "#xml-attributes"
|
"include": "#owl-attributes-dynamic"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "string.quoted.double.xml",
|
"include": "#owl-attributes-static"
|
||||||
"match": "(\")((.*)(=>)(.*))(\")"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
"qweb-directives-interpreted": {
|
|
||||||
"contentName": "meta.embedded.block.javascript string.quoted.double.xml",
|
|
||||||
"begin": "(\\s)(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-att-|t-on-)[a-z_:.-]+)(=)(\")",
|
|
||||||
"beginCaptures": {
|
|
||||||
"2": {
|
|
||||||
"name": "entity.other.attribute-name.localname.xml owl.attribute"
|
|
||||||
},
|
|
||||||
"5": {
|
|
||||||
"name": "punctuation.definition.string.begin.xml owl.punctuation owl.doublequote"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"end": "(\")",
|
|
||||||
"endCaptures": {
|
|
||||||
"0": {
|
|
||||||
"name": "punctuation.definition.string.end.xml owl.punctuation owl.doublequote"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"patterns": [
|
|
||||||
{
|
|
||||||
"include": "source.js"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "keyword.operator.logical.js",
|
|
||||||
"match": "\\s(and|or)\\s"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"qweb-directives-string": {
|
|
||||||
"contentName": "string.quoted.double.xml",
|
|
||||||
"begin": "(\\s)(t-name|t-ref|t-slot|t-set-slot|t-model|t-translation)(=)(\")",
|
|
||||||
"beginCaptures": {
|
|
||||||
"2": {
|
|
||||||
"name": "entity.other.attribute-name.localname.xml owl.attribute"
|
|
||||||
},
|
|
||||||
"5": {
|
|
||||||
"name": "punctuation.definition.string.begin.xml owl.punctuation owl.doublequote"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"end": "(\")",
|
|
||||||
"endCaptures": {
|
|
||||||
"0": {
|
|
||||||
"name": "punctuation.definition.string.end.xml owl.punctuation owl.doublequote"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"qweb-directives-formatted-string": {
|
|
||||||
"begin": "(\\s)(t-call|(t-attf-)[a-z_:.-]+)(=)(\")",
|
|
||||||
"beginCaptures": {
|
|
||||||
"2": {
|
|
||||||
"name": "entity.other.attribute-name.localname.xml owl.attribute owl.attribute.formatted"
|
|
||||||
},
|
|
||||||
"5": {
|
|
||||||
"name": "punctuation.definition.string.begin.xml owl.punctuation owl.doublequote"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"end": "(\")",
|
|
||||||
"endCaptures": {
|
|
||||||
"0": {
|
|
||||||
"name": "punctuation.definition.string.end.xml owl.punctuation owl.doublequote"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"patterns": [
|
|
||||||
{
|
|
||||||
"include": "#formatted-string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"formatted-string": {
|
|
||||||
"contentName": "meta.embedded.block.javascript string.quoted.double.xml",
|
|
||||||
"begin": "([^\"|}}]*)({{)",
|
|
||||||
"beginCaptures": {
|
|
||||||
"1": {
|
|
||||||
"name": "string.quoted.double.xml"
|
|
||||||
},
|
|
||||||
"2": {
|
|
||||||
"name": "string.quoted.double.xml owl.doublecurlybrackets"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"end": "(}})([^\"|{{]*)",
|
|
||||||
"endCaptures": {
|
|
||||||
"1": {
|
|
||||||
"name": "string.quoted.double.xml owl.doublecurlybrackets"
|
|
||||||
},
|
|
||||||
"2": {
|
|
||||||
"name": "string.quoted.double.xml"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"patterns": [
|
|
||||||
{
|
|
||||||
"include": "source.js"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"props": {
|
|
||||||
"name": "variable.language owl.expression.props",
|
|
||||||
"match": "\\b(props)\\b"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user