Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 23 additions & 0 deletions lib/rouge/demos/gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { LinkTo } from '@ember/routing';
import { local } from 'embroider-css-modules';

import styles from './navigation-menu.css';

const NavigationMenu = <template>
<nav aria-label={{@name}} data-test-nav={{@name}}>
<ul class={{styles.list}}>
{{#each @menuItems as |menuItem|}}
<li>
<LinkTo
class={{local styles "link"}}
data-test-link={{menuItem.label}}
>
{{menuItem.label}}
</LinkTo>
</li>
{{/each}}
</ul>
</nav>
</template>;

export default NavigationMenu;
36 changes: 36 additions & 0 deletions lib/rouge/demos/gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { TOC } from '@ember/component/template-only';
import { LinkTo } from '@ember/routing';
import { local } from 'embroider-css-modules';

import styles from './navigation-menu.css';

type MenuItem = {
label: string;
route: string;
};

interface NavigationMenuSignature {
Args: {
menuItems: MenuItem[];
name?: string;
};
}

const NavigationMenu = <template>
<nav aria-label={{@name}} data-test-nav={{@name}}>
<ul class={{styles.list}}>
{{#each @menuItems as |menuItem|}}
<li>
<LinkTo
class={{local styles "link"}}
data-test-link={{menuItem.label}}
>
{{menuItem.label}}
</LinkTo>
</li>
{{/each}}
</ul>
</nav>
</template> satisfies TOC<NavigationMenuSignature>;

export default NavigationMenu;
39 changes: 39 additions & 0 deletions lib/rouge/lexers/gjs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

module Rouge
module Lexers
load_lexer 'javascript.rb'

class Gjs < Javascript
title "Template Tag (gjs)"
desc "Ember.js, JavaScript with <template> tags"
tag "gjs"
filenames "*.gjs"
mimetypes "text/x-gjs", "application/x-gjs"

def initialize(*)
super
@handlebars = Handlebars.new(options)
end

prepend :root do
rule %r/(<)(template)(>)/ do
groups Name::Tag, Keyword, Name::Tag
push :template
end
end

state :template do
rule %r((</)(template)(>)) do
groups Name::Tag, Keyword, Name::Tag
pop!
end

rule %r/.+?(?=<\/template>)/m do
delegate @handlebars
end
end
end
end
end
39 changes: 39 additions & 0 deletions lib/rouge/lexers/gts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

module Rouge
module Lexers
load_lexer 'typescript.rb'

class Gts < Typescript
title "Template Tag (gts)"
desc "Ember.js, TypeScript with <template> tags"
tag "gts"
filenames "*.gts"
mimetypes "text/x-gts", "application/x-gts"

def initialize(*)
super
@handlebars = Handlebars.new(options)
end

prepend :root do
rule %r/(<)(template)(>)/ do
groups Name::Tag, Keyword, Name::Tag
push :template
end
end

state :template do
rule %r((</)(template)(>)) do
groups Name::Tag, Keyword, Name::Tag
pop!
end

rule %r/.+?(?=<\/template>)/m do
delegate @handlebars
end
end
end
end
end
114 changes: 114 additions & 0 deletions spec/lexers/gjs_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

describe Rouge::Lexers::Gjs do
let(:subject) { Rouge::Lexers::Gjs.new }

describe 'guessing' do
include Support::Guessing

it 'guesses by filename' do
assert_guess :filename => 'app/components/ui/form.gjs'
assert_guess :filename => 'app/templates/form.gjs'
assert_guess :filename => 'tests/integration/components/ui/form-test.gjs'
end

it 'guesses by mimetype' do
assert_guess :mimetype => 'text/x-gjs'
assert_guess :mimetype => 'application/x-gjs'
end
end

describe 'lexing' do
include Support::Lexing

it 'lexes the opening <template> tag' do
assert_tokens_equal '<template>',
["Name.Tag", "<"], ["Keyword", "template"], ["Name.Tag", ">"]
end

it 'lexes the closing </template> tag' do
assert_tokens_equal '<template></template>',
["Name.Tag", "<"], ["Keyword", "template"], ["Name.Tag", "></"], ["Keyword", "template"], ["Name.Tag", ">"]
assert_tokens_equal '<template> </template>',
["Name.Tag", "<"], ["Keyword", "template"], ["Name.Tag", ">"], ["Text", " "], ["Name.Tag", "</"], ["Keyword", "template"], ["Name.Tag", ">"]
end

it 'lexes a Glimmer component' do
code = <<~FILE
import Component from '@glimmer/component';
import { t } from 'ember-intl';

export default class Hello extends Component {
<template>
<div data-test-message>
{{t "hello.message" name=@name}}
</div>
</template>
}
FILE

assert_no_errors code
end

it 'lexes a template-only component (1)' do
code = <<~FILE
import { t } from 'ember-intl';

const Hello = <template>
<div data-test-message>
{{t "hello.message" name=@name}}
</div>
</template>;

export default Hello;
FILE

assert_no_errors code
end

it 'lexes a template-only component (2)' do
code = <<~FILE
import { t } from 'ember-intl';

<template>
<div data-test-message>
{{t "hello.message" name=@name}}
</div>
</template>;
FILE

assert_no_errors code
end

it 'lexes a rendering test' do
code = <<~FILE
import { render } from '@ember/test-helpers';
import { setupIntl } from 'ember-intl/test-support';
import { setupRenderingTest } from 'ember-qunit';
import Hello from 'my-app/components/hello';
import { module, test } from 'qunit';

module('Integration | Component | hello', function (hooks) {
setupRenderingTest(hooks);
setupIntl(hooks, 'en-us');

test('it renders', async function (assert) {
await render(
<template>
<Hello @name="Zoey" />
</template>
);

assert.dom('[data-test-message]').hasText('Hello, Zoey!');
});
});
FILE

# Currently unable to assert with `assert_no_errors` because
# the `handlebars` lexer doesn't support arguments like `@name`
assert_tokens_includes code,
["Name.Tag", "<"], ["Keyword", "template"], ["Name.Tag", ">"]
end
end
end
134 changes: 134 additions & 0 deletions spec/lexers/gts_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

describe Rouge::Lexers::Gts do
let(:subject) { Rouge::Lexers::Gts.new }

describe 'guessing' do
include Support::Guessing

it 'guesses by filename' do
assert_guess :filename => 'app/components/ui/form.gts'
assert_guess :filename => 'app/templates/form.gts'
assert_guess :filename => 'tests/integration/components/ui/form-test.gts'
end

it 'guesses by mimetype' do
assert_guess :mimetype => 'text/x-gts'
assert_guess :mimetype => 'application/x-gts'
end
end

describe 'lexing' do
include Support::Lexing

it 'lexes the opening <template> tag' do
assert_tokens_equal '<template>',
["Name.Tag", "<"], ["Keyword", "template"], ["Name.Tag", ">"]
end

it 'lexes the closing </template> tag' do
assert_tokens_equal '<template></template>',
["Name.Tag", "<"], ["Keyword", "template"], ["Name.Tag", "></"], ["Keyword", "template"], ["Name.Tag", ">"]
assert_tokens_equal '<template> </template>',
["Name.Tag", "<"], ["Keyword", "template"], ["Name.Tag", ">"], ["Text", " "], ["Name.Tag", "</"], ["Keyword", "template"], ["Name.Tag", ">"]
end

it 'lexes a Glimmer component' do
code = <<~FILE
import Component from '@glimmer/component';
import { t } from 'ember-intl';

interface HelloSignature {
Args: {
name: string;
};
}

export default class Hello extends Component<HelloSignature> {
<template>
<div data-test-message>
{{t "hello.message" name=@name}}
</div>
</template>
}
FILE

assert_no_errors code
end

it 'lexes a template-only component (1)' do
code = <<~FILE
import type { TOC } from '@ember/component/template-only';
import { t } from 'ember-intl';

interface HelloSignature {
Args: {
name: string;
};
}

const Hello: TOC<HelloSignature> = <template>
<div data-test-message>
{{t "hello.message" name=@name}}
</div>
</template>;

export default Hello;
FILE

assert_no_errors code
end

it 'lexes a template-only component (2)' do
code = <<~FILE
import type { TOC } from '@ember/component/template-only';
import { t } from 'ember-intl';

interface HelloSignature {
Args: {
name: string;
};
}

<template>
<div data-test-message>
{{t "hello.message" name=@name}}
</div>
</template> satisfies TOC<HelloSignature>;
FILE

assert_no_errors code
end

it 'lexes a rendering test' do
code = <<~FILE
import { render } from '@ember/test-helpers';
import { setupIntl } from 'ember-intl/test-support';
import { setupRenderingTest } from 'ember-qunit';
import Hello from 'my-app/components/hello';
import { module, test } from 'qunit';

module('Integration | Component | hello', function (hooks) {
setupRenderingTest(hooks);
setupIntl(hooks, 'en-us');

test('it renders', async function (assert) {
await render(
<template>
<Hello @name="Zoey" />
</template>
);

assert.dom('[data-test-message]').hasText('Hello, Zoey!');
});
});
FILE

# Currently unable to assert with `assert_no_errors` because
# the `handlebars` lexer doesn't support arguments like `@name`
assert_tokens_includes code,
["Name.Tag", "<"], ["Keyword", "template"], ["Name.Tag", ">"]
end
end
end
Loading