Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: build template.json grammar from typescript source files #581

Merged
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ dist/
.vscode/settings.json
.vimrc
.nvimrc
syntaxes/out
syntaxes/test/*.js
syntaxes/test/*.map
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,16 @@
"compile:test": "tsc -b server/src/tests",
"compile:integration": "tsc -b integration",
"compile:syntaxes-test": "tsc -b syntaxes/test",
"compile:syntaxes": "tsc -b syntaxes",
"build:syntaxes": "yarn compile:syntaxes && node syntaxes/out/build.js",
"format": "scripts/format.sh",
"watch": "tsc -b -w",
"postinstall": "vscode-install && cd client && yarn && cd ../server && yarn && cd ..",
"package": "rm -rf dist && node scripts/package.js",
"test": "yarn compile:test && jasmine server/out/tests/*_spec.js",
"test:lsp": "yarn compile:integration && jasmine integration/out/lsp/*_spec.js",
"test:e2e": "yarn compile:integration && ./scripts/e2e.sh",
"test:syntaxes": "yarn compile:syntaxes-test && jasmine syntaxes/test/driver.js"
"test:syntaxes": "yarn compile:syntaxes-test && yarn build:syntaxes && jasmine syntaxes/test/driver.js"
},
"dependencies": {
"typescript": "~3.7.4"
Expand Down
7 changes: 6 additions & 1 deletion scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set -ex -o pipefail
# Clean up from last build
rm -rf client/out
rm -rf server/out
rm -rf syntaxes/out
rm -rf dist
rm -rf **/*.tsbuildinfo

Expand All @@ -17,9 +18,13 @@ cp package.json yarn.lock angular.png CHANGELOG.md README.md dist
cp client/package.json client/yarn.lock dist/client
# Copy files to server directory
cp server/package.json server/yarn.lock server/README.md dist/server
# Copy files to syntaxes directory
# Build and copy files to syntaxes directory
node syntaxes/out/build.js
mkdir dist/syntaxes
cp syntaxes/out/*.json dist/syntaxes
# TODO: Remove the next two lines once all syntaxes have been refactored to TypeScript
cp syntaxes/*.json dist/syntaxes
rm dist/syntaxes/tsconfig.json

pushd dist
yarn install --production --ignore-scripts
Expand Down
1 change: 1 addition & 0 deletions scripts/cleanup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ set -ex -o pipefail
# Clean up from last build
rm -rf client/out
rm -rf server/out
rm -rf syntaxes/out
43 changes: 43 additions & 0 deletions syntaxes/src/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import * as fs from 'fs';

import {GrammarDefinition, JsonObject} from './types';
import {template} from './template/grammar';

// Recursively transforms a TypeScript grammar definition into an object which can be processed by
// JSON.stringify to generate a valid TextMate JSON grammar definition
function processGrammar(grammar: GrammarDefinition): JsonObject {
const processedGrammar: JsonObject = {};
for (const [key, value] of Object.entries(grammar)) {
if (typeof value === 'string') {
processedGrammar[key] = value;
} else if (value instanceof RegExp) {
// Escape backslashes/quote marks and trim the demarcating `/` characters from a regex literal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, i see. nice!

processedGrammar[key] = value.toString().replace(/^\/|\/$/g, '');
} else if (value instanceof Array) {
processedGrammar[key] = value.map(processGrammar);
} else {
processedGrammar[key] = processGrammar(value);
}
}
return processedGrammar;
}

// Build a TextMate grammar JSON file from a source TypeScript object
function build(grammar: GrammarDefinition, filename: string): void {
const processedGrammar: JsonObject = processGrammar(grammar);
const grammarContent: string = JSON.stringify(processedGrammar, null, ' ') + '\n';

fs.writeFile(`syntaxes/out/${filename}.json`, grammarContent, (error) => {
if (error) throw error;
});
}

build(template, 'template');
36 changes: 36 additions & 0 deletions syntaxes/src/template/grammar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {GrammarDefinition} from '../types';

import {bindingKey} from './repository/binding-key';
import {eventBinding} from './repository/event-binding';
import {interpolation} from './repository/interpolation';
import {propertyBinding} from './repository/property-binding';
import {templateBinding} from './repository/template-binding';
import {twoWayBinding} from './repository/two-way-binding';

export const template: GrammarDefinition = {
scopeName: 'template.ng',
injectionSelector: 'L:text.html -comment',
patterns: [
{include: '#interpolation'},
{include: '#propertyBinding'},
{include: '#eventBinding'},
{include: '#twoWayBinding'},
{include: '#templateBinding'},
],
repository: {
interpolation,
propertyBinding,
eventBinding,
twoWayBinding,
templateBinding,
bindingKey,
},
};
29 changes: 29 additions & 0 deletions syntaxes/src/template/repository/binding-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {GrammarDefinition} from '../../types';

export const bindingKey: GrammarDefinition = {
patterns: [
{
match: /([\[\(]{1,2})(?:\s*)(@?[-_a-zA-Z0-9.$]*)(?:\s*)([\]\)]{1,2})/,
captures: {
1: {name: 'punctuation.definition.ng-binding-name.begin.html'},
2: {
patterns: [
{
match: /\./,
name: 'punctuation.accessor.html',
},
],
},
3: {name: 'punctuation.definition.ng-binding-name.end.html'},
},
},
],
};
32 changes: 32 additions & 0 deletions syntaxes/src/template/repository/event-binding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {GrammarDefinition} from '../../types';

export const eventBinding: GrammarDefinition = {
begin: /(\(\s*@?[-_a-zA-Z0-9.$]*\s*\))(=)(["'])/,
beginCaptures: {
1: {
name: 'entity.other.attribute-name.html entity.other.ng-binding-name.event.html',
patterns: [
{include: '#bindingKey'},
],
},
2: {name: 'punctuation.separator.key-value.html'},
3: {name: 'string.quoted.html punctuation.definition.string.begin.html'},
},
end: /\3/,
endCaptures: {
0: {name: 'string.quoted.html punctuation.definition.string.end.html'},
},
name: 'meta.ng-binding.event.html',
contentName: 'source.js',
patterns: [
{include: 'source.js'},
],
};
24 changes: 24 additions & 0 deletions syntaxes/src/template/repository/interpolation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {GrammarDefinition} from '../../types';

export const interpolation: GrammarDefinition = {
begin: /{{/,
beginCaptures: {
0: {name: 'punctuation.definition.block.ts'},
},
end: /}}/,
endCaptures: {
0: {name: 'punctuation.definition.block.ts'},
},
contentName: 'source.js',
patterns: [
{include: 'source.js'},
],
};
32 changes: 32 additions & 0 deletions syntaxes/src/template/repository/property-binding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {GrammarDefinition} from '../../types';

export const propertyBinding: GrammarDefinition = {
begin: /(\[\s*@?[-_a-zA-Z0-9.$]*\s*])(=)(["'])/,
beginCaptures: {
1: {
name: 'entity.other.attribute-name.html entity.other.ng-binding-name.property.html',
patterns: [
{include: '#bindingKey'},
],
},
2: {name: 'punctuation.separator.key-value.html'},
3: {name: 'string.quoted.html punctuation.definition.string.begin.html'},
},
end: /\3/,
endCaptures: {
0: {name: 'string.quoted.html punctuation.definition.string.end.html'},
},
name: 'meta.ng-binding.property.html',
contentName: 'source.js',
patterns: [
{include: 'source.js'},
],
};
32 changes: 32 additions & 0 deletions syntaxes/src/template/repository/template-binding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {GrammarDefinition} from '../../types';

export const templateBinding: GrammarDefinition = {
begin: /(\*[-_a-zA-Z0-9.$]*)(=)(["'])/,
beginCaptures: {
1: {
name: 'entity.other.attribute-name.html entity.other.ng-binding-name.template.html',
patterns: [
{include: '#bindingKey'},
],
},
2: {name: 'punctuation.separator.key-value.html'},
3: {name: 'string.quoted.html punctuation.definition.string.begin.html'},
},
end: /\3/,
endCaptures: {
0: {name: 'string.quoted.html punctuation.definition.string.end.html'},
},
name: 'meta.ng-binding.template.html',
contentName: 'source.js',
patterns: [
{include: 'source.js'},
],
};
32 changes: 32 additions & 0 deletions syntaxes/src/template/repository/two-way-binding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {GrammarDefinition} from '../../types';

export const twoWayBinding: GrammarDefinition = {
begin: /(\[\s*\(\s*@?[-_a-zA-Z0-9.$]*\s*\)\s*\])(=)(["'])/,
beginCaptures: {
1: {
name: 'entity.other.attribute-name.html entity.other.ng-binding-name.two-way.html',
patterns: [
{include: '#bindingKey'},
],
},
2: {name: 'punctuation.separator.key-value.html'},
3: {name: 'string.quoted.html punctuation.definition.string.begin.html'},
},
end: /\3/,
endCaptures: {
0: {name: 'string.quoted.html punctuation.definition.string.end.html'},
},
name: 'meta.ng-binding.two-way.html',
contentName: 'source.js',
patterns: [
{include: 'source.js'},
],
};
15 changes: 15 additions & 0 deletions syntaxes/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

export interface GrammarDefinition {
[key: string]: string|RegExp|GrammarDefinition|GrammarDefinition[];
}

export interface JsonObject {
[key: string]: string|JsonObject|JsonObject[];
}
Loading