-
Notifications
You must be signed in to change notification settings - Fork 33
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
Add polyfill for <Input> and <Textarea> #75
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
'use strict'; | ||
|
||
const attributeToPropertyMap = { | ||
role: 'ariaRole', | ||
}; | ||
|
||
class AngleBracketInputPolyfill { | ||
transform(ast) { | ||
let b = this.syntax.builders; | ||
|
||
// in order to debug in https://https://astexplorer.net/#/gist/0590eb883edfcd163b183514df4cc717 | ||
// **** copy from here **** | ||
function transformAttributeValue(attributeValue) { | ||
switch (attributeValue.type) { | ||
case 'TextNode': | ||
return b.string(attributeValue.chars); | ||
case 'MustacheStatement': | ||
return b.path(attributeValue.path); | ||
} | ||
} | ||
|
||
let visitor = { | ||
ElementNode(node) { | ||
let tag = node.tag.toLowerCase(); | ||
|
||
if (tag === 'input' || tag === 'textarea') { | ||
let { attributes } = node; | ||
|
||
let props = attributes | ||
.filter(({ name }) => name.charAt(0) === '@') | ||
.map(attribute => Object.assign({}, attribute, { name: attribute.name.slice(1) })); | ||
let attrs = attributes.map(attribute => | ||
attributeToPropertyMap[attribute.name] | ||
? Object.assign({}, attribute, { name: attributeToPropertyMap[attribute.name] }) | ||
: attribute | ||
); | ||
|
||
let hash = b.hash( | ||
[...props, ...attrs].map(({ name, value, loc }) => | ||
b.pair(name, transformAttributeValue(value), loc) | ||
) | ||
); | ||
|
||
return b.mustache(b.path(tag), null, hash, false, node.loc); | ||
} | ||
}, | ||
}; | ||
// **** copy to here **** | ||
|
||
this.syntax.traverse(ast, visitor); | ||
|
||
return ast; | ||
} | ||
} | ||
|
||
module.exports = AngleBracketInputPolyfill; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { module, test } from 'qunit'; | ||
import { setupRenderingTest } from 'ember-qunit'; | ||
import { render } from '@ember/test-helpers'; | ||
import hbs from 'htmlbars-inline-precompile'; | ||
|
||
module('Integration | Component | input', function(hooks) { | ||
setupRenderingTest(hooks); | ||
|
||
test('it supports text field', async function(assert) { | ||
this.set('value', 'foo'); | ||
await render(hbs`<Input @type="text" @value={{this.value}} />`); | ||
|
||
assert.dom('input').hasAttribute('type', 'text'); | ||
assert.dom('input').hasValue('foo'); | ||
}); | ||
|
||
test('it supports different input types', async function(assert) { | ||
this.set('value', 'user@example.com'); | ||
await render(hbs`<Input @type="email" @value={{this.value}} />`); | ||
|
||
assert.dom('input').hasAttribute('type', 'email'); | ||
assert.dom('input').hasValue('user@example.com'); | ||
}); | ||
|
||
test('it supports checkbox', async function(assert) { | ||
this.set('value', true); | ||
await render(hbs`<Input @type="checkbox" @checked={{this.value}} />`); | ||
|
||
assert.dom('input').hasAttribute('type', 'checkbox'); | ||
assert.dom('input').isChecked(); | ||
}); | ||
|
||
test('it supports textarea', async function(assert) { | ||
this.set('value', 'foo bar'); | ||
await render(hbs`<Textarea @value={{this.value}} />`); | ||
|
||
assert.dom('textarea').exists(); | ||
assert.dom('textarea').hasValue('foo bar'); | ||
}); | ||
|
||
test('it passes supported properties and attributes', async function(assert) { | ||
await render( | ||
hbs`<Input | ||
@value="foo" | ||
@size="20" | ||
name="username" | ||
placeholder="Enter username" | ||
class="form-input" | ||
role="searchbox" | ||
/>` | ||
); | ||
|
||
// does not test each and every supported property / HTML attribute, as the list is rather long, and the transform | ||
// will just pass anything through, so either all work or no one does. | ||
assert.dom('input').hasAttribute('type', 'text'); | ||
assert.dom('input').hasValue('foo'); | ||
assert.dom('input').hasAttribute('name', 'username'); | ||
assert.dom('input').hasAttribute('placeholder', 'Enter username'); | ||
assert.dom('input').hasClass('form-input'); | ||
assert.dom('input').hasAttribute('role', 'searchbox'); | ||
}); | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let’s propagate the original location info in these branches (so downstream error messages can use it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems I cannot do that with
b.string()
, can I?https://github.com/glimmerjs/glimmer-vm/blob/master/packages/%40glimmer/syntax/lib/builders.ts#L564
Btw, as AST docs are quite sparse/non-existent, what does this actually do and how is this used? For error messages to print concrete line/column numbers of hbs files that break something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugg, indeed you are correct. Though I think you can create it and then add the loc:
https://github.com/glimmerjs/glimmer-vm/blob/83a0c2fdfa8f22fd353dcab32ea41c4bcacaa379/packages/%40glimmer/syntax/lib/builders.ts#L577-L581 needs to be updated to take
loc
as the last arg in the returned function.Right, when creating new AST nodes we should always attempt to propagate the original location information through to the new nodes. This helps to ensure that any error messages include the correct module name, line, and column number.