/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ 'use strict'; import Modes = require('vs/editor/common/modes'); import modesUtil = require('vs/editor/test/common/modesUtil'); import {htmlTokenTypes} from 'vs/languages/html/common/html'; import handlebarsTokenTypes = require('vs/languages/handlebars/common/handlebarsTokenTypes'); import {HandlebarsMode} from 'vs/languages/handlebars/common/handlebars'; import {MockModeService} from 'vs/editor/test/common/mocks/mockModeService'; import {MockTokenizingMode} from 'vs/editor/test/common/mocks/mockMode'; class HandlebarsMockModeService extends MockModeService { private _handlebarsMode: HandlebarsMode; constructor() { super(); this._handlebarsMode = null; } public setHandlebarsMode(handlebarsMode: HandlebarsMode): void { this._handlebarsMode = handlebarsMode; } isRegisteredMode(mimetypeOrModeId: string): boolean { if (mimetypeOrModeId === 'text/javascript') { return true; } if (mimetypeOrModeId === 'text/x-handlebars-template') { return true; } throw new Error('Not implemented'); } getModeId(mimetypeOrModeId: string): string { if (mimetypeOrModeId === 'text/javascript') { return 'js-mode-id'; } if (mimetypeOrModeId === 'text/x-handlebars-template') { return 'handlebars-mode-id'; } throw new Error('Not implemented'); } getMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): Modes.IMode { if (commaSeparatedMimetypesOrCommaSeparatedIds === 'js-mode-id') { return new MockTokenizingMode('mock-js'); } if (commaSeparatedMimetypesOrCommaSeparatedIds === 'handlebars-mode-id') { return this._handlebarsMode; } throw new Error('Not implemented'); } } suite('Handlebars', () => { var tokenizationSupport: Modes.ITokenizationSupport; suiteSetup(function() { let modeService = new HandlebarsMockModeService(); let mode = new HandlebarsMode( { id: 'handlebars' }, null, modeService, null, null, null ); modeService.setHandlebarsMode(mode); tokenizationSupport = Modes.TokenizationRegistry.get(mode.getId()); }); test('Just HTML', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '

handlebars!

', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_START }, { startIndex:1, type: htmlTokenTypes.getTag('h1') }, { startIndex:3, type: htmlTokenTypes.DELIM_START }, { startIndex:4, type: '' }, { startIndex:15, type: htmlTokenTypes.DELIM_END }, { startIndex:17, type: htmlTokenTypes.getTag('h1') }, { startIndex:19, type: htmlTokenTypes.DELIM_END } ]} ]); }); test('Expressions', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '

{{ title }}

', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_START }, { startIndex:1, type: htmlTokenTypes.getTag('h1') }, { startIndex:3, type: htmlTokenTypes.DELIM_START }, { startIndex:4, type: handlebarsTokenTypes.EMBED }, { startIndex:6, type: '' }, { startIndex:7, type: handlebarsTokenTypes.VARIABLE }, { startIndex:12, type: '' }, { startIndex:13, type: handlebarsTokenTypes.EMBED }, { startIndex:15, type: htmlTokenTypes.DELIM_END }, { startIndex:17, type: htmlTokenTypes.getTag('h1') }, { startIndex:19, type: htmlTokenTypes.DELIM_END } ]} ]); }); test('Expressions Sans Whitespace', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '

{{title}}

', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_START }, { startIndex:1, type: htmlTokenTypes.getTag('h1') }, { startIndex:3, type: htmlTokenTypes.DELIM_START }, { startIndex:4, type: handlebarsTokenTypes.EMBED }, { startIndex:6, type: handlebarsTokenTypes.VARIABLE }, { startIndex:11, type: handlebarsTokenTypes.EMBED }, { startIndex:13, type: htmlTokenTypes.DELIM_END }, { startIndex:15, type: htmlTokenTypes.getTag('h1') }, { startIndex:17, type: htmlTokenTypes.DELIM_END } ]} ]); }); test('Unescaped Expressions', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '

{{{ title }}}

', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_START }, { startIndex:1, type: htmlTokenTypes.getTag('h1') }, { startIndex:3, type: htmlTokenTypes.DELIM_START }, { startIndex:4, type: handlebarsTokenTypes.EMBED_UNESCAPED }, { startIndex:7, type: '' }, { startIndex:8, type: handlebarsTokenTypes.VARIABLE }, { startIndex:13, type: '' }, { startIndex:14, type: handlebarsTokenTypes.EMBED_UNESCAPED }, { startIndex:17, type: htmlTokenTypes.DELIM_END }, { startIndex:19, type: htmlTokenTypes.getTag('h1') }, { startIndex:21, type: htmlTokenTypes.DELIM_END } ]} ]); }); test('Blocks', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_START }, { startIndex:1, type: htmlTokenTypes.getTag('ul') }, { startIndex:3, type: htmlTokenTypes.DELIM_START }, { startIndex:4, type: handlebarsTokenTypes.EMBED }, { startIndex:6, type: handlebarsTokenTypes.KEYWORD }, { startIndex:11, type: '' }, { startIndex:12, type: handlebarsTokenTypes.VARIABLE }, { startIndex:17, type: handlebarsTokenTypes.EMBED }, { startIndex:19, type: htmlTokenTypes.DELIM_START }, { startIndex:20, type: htmlTokenTypes.getTag('li') }, { startIndex:22, type: htmlTokenTypes.DELIM_START }, { startIndex:23, type: handlebarsTokenTypes.EMBED }, { startIndex:25, type: handlebarsTokenTypes.VARIABLE }, { startIndex:29, type: handlebarsTokenTypes.EMBED }, { startIndex:31, type: htmlTokenTypes.DELIM_END }, { startIndex:33, type: htmlTokenTypes.getTag('li') }, { startIndex:35, type: htmlTokenTypes.DELIM_END }, { startIndex:36, type: handlebarsTokenTypes.EMBED }, { startIndex:38, type: handlebarsTokenTypes.KEYWORD }, { startIndex:43, type: handlebarsTokenTypes.EMBED }, { startIndex:45, type: htmlTokenTypes.DELIM_END }, { startIndex:47, type: htmlTokenTypes.getTag('ul') }, { startIndex:49, type: htmlTokenTypes.DELIM_END } ]} ]); }); test('Multiline', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '
', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_START }, { startIndex:1, type: htmlTokenTypes.getTag('div') }, { startIndex:4, type: htmlTokenTypes.DELIM_START } ]}, { line: '{{#if foo}}', tokens: [ { startIndex:0, type: handlebarsTokenTypes.EMBED }, { startIndex:2, type: handlebarsTokenTypes.KEYWORD }, { startIndex:5, type: '' }, { startIndex:6, type: handlebarsTokenTypes.VARIABLE }, { startIndex:9, type: handlebarsTokenTypes.EMBED } ]}, { line: '{{bar}}', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_START }, { startIndex:1, type: htmlTokenTypes.getTag('span') }, { startIndex:5, type: htmlTokenTypes.DELIM_START }, { startIndex:6, type: handlebarsTokenTypes.EMBED }, { startIndex:8, type: handlebarsTokenTypes.VARIABLE }, { startIndex:11, type: handlebarsTokenTypes.EMBED }, { startIndex:13, type: htmlTokenTypes.DELIM_END }, { startIndex:15, type: htmlTokenTypes.getTag('span') }, { startIndex:19, type: htmlTokenTypes.DELIM_END } ]}, { line: '{{/if}}', tokens: null} ]); }); test('Div end', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '
', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_END }, { startIndex:2, type: htmlTokenTypes.getTag('div') }, { startIndex:5, type: htmlTokenTypes.DELIM_END } ]} ]); }); // shamelessly stolen from the HTML test bed since Handlebars are a superset of HTML test('Embedded Content in HTML', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_START }, { startIndex:1, type: htmlTokenTypes.getTag('script') }, { startIndex:7, type: '' }, { startIndex:8, type: htmlTokenTypes.ATTRIB_NAME }, { startIndex:12, type: htmlTokenTypes.DELIM_ASSIGN }, { startIndex:13, type: htmlTokenTypes.ATTRIB_VALUE }, { startIndex:30, type: htmlTokenTypes.DELIM_START }, { startIndex:31, type: 'mock-js' }, { startIndex:41, type: htmlTokenTypes.DELIM_END }, { startIndex:43, type: htmlTokenTypes.getTag('script') }, { startIndex:49, type: htmlTokenTypes.DELIM_END } ]} ]); }); test('HTML Expressions', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_START }, { startIndex:1, type: htmlTokenTypes.getTag('script') }, { startIndex:7, type: '' }, { startIndex:8, type: htmlTokenTypes.ATTRIB_NAME }, { startIndex:12, type: htmlTokenTypes.DELIM_ASSIGN }, { startIndex:13, type: htmlTokenTypes.ATTRIB_VALUE }, { startIndex:41, type: htmlTokenTypes.DELIM_START }, { startIndex:42, type: htmlTokenTypes.DELIM_START }, { startIndex:43, type: htmlTokenTypes.getTag('h1') }, { startIndex:45, type: htmlTokenTypes.DELIM_START }, { startIndex:46, type: handlebarsTokenTypes.EMBED }, { startIndex:48, type: '' }, { startIndex:49, type: handlebarsTokenTypes.VARIABLE }, { startIndex:54, type: '' }, { startIndex:55, type: handlebarsTokenTypes.EMBED }, { startIndex:57, type: htmlTokenTypes.DELIM_END }, { startIndex:59, type: htmlTokenTypes.getTag('h1') }, { startIndex:61, type: htmlTokenTypes.DELIM_END }, { startIndex:62, type: htmlTokenTypes.DELIM_END }, { startIndex:64, type: htmlTokenTypes.getTag('script') }, { startIndex:70, type: htmlTokenTypes.DELIM_END } ]} ]); }); test('Multi-line HTML Expressions', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_END }, { startIndex:2, type: htmlTokenTypes.getTag('script') }, { startIndex:8, type: htmlTokenTypes.DELIM_END } ]} ]); }); test('HTML Nested Modes', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '{{foo}}{{bar}}', tokens: [ { startIndex:0, type: handlebarsTokenTypes.EMBED }, { startIndex:2, type: handlebarsTokenTypes.VARIABLE }, { startIndex:5, type: handlebarsTokenTypes.EMBED }, { startIndex:7, type: htmlTokenTypes.DELIM_START }, { startIndex:8, type: htmlTokenTypes.getTag('script') }, { startIndex:14, type: htmlTokenTypes.DELIM_START }, { startIndex:15, type: htmlTokenTypes.DELIM_END }, { startIndex:17, type: htmlTokenTypes.getTag('script') }, { startIndex:23, type: htmlTokenTypes.DELIM_END }, { startIndex:24, type: handlebarsTokenTypes.EMBED }, { startIndex:26, type: handlebarsTokenTypes.VARIABLE }, { startIndex:29, type: handlebarsTokenTypes.EMBED } ]} ]); }); test('else keyword', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '{{else}}', tokens: [ { startIndex:0, type: handlebarsTokenTypes.EMBED }, { startIndex:2, type: handlebarsTokenTypes.KEYWORD }, { startIndex:6, type: handlebarsTokenTypes.EMBED } ]} ]); }); test('else keyword #2', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '{{elseFoo}}', tokens: [ { startIndex:0, type: handlebarsTokenTypes.EMBED }, { startIndex:2, type: handlebarsTokenTypes.VARIABLE }, { startIndex:9, type: handlebarsTokenTypes.EMBED } ]} ]); }); test('Token inside attribute', () => { modesUtil.assertTokenization(tokenizationSupport, [{ line: '', tokens: [ { startIndex:0, type: htmlTokenTypes.DELIM_START }, { startIndex:1, type: htmlTokenTypes.getTag('a') }, { startIndex:2, type: '' }, { startIndex:3, type: htmlTokenTypes.ATTRIB_NAME }, { startIndex:7, type: htmlTokenTypes.DELIM_ASSIGN }, { startIndex:8, type: htmlTokenTypes.ATTRIB_VALUE }, { startIndex:16, type: handlebarsTokenTypes.EMBED }, { startIndex:18, type: handlebarsTokenTypes.VARIABLE }, { startIndex:27, type: handlebarsTokenTypes.EMBED }, { startIndex:29, type: htmlTokenTypes.ATTRIB_VALUE }, { startIndex:30, type: htmlTokenTypes.DELIM_START } ]} ]); }); });