🚫 Include innerText in error handling

pull/4291/head
himynameisdave 7 years ago
parent 9a87cc712f
commit e8804eb941
No known key found for this signature in database
GPG Key ID: CF799D9C390BE444

@ -10,6 +10,7 @@ import Class from './Class';
import Text from './Text'; import Text from './Text';
import { namespaces } from '../../utils/namespaces'; import { namespaces } from '../../utils/namespaces';
import map_children from './shared/map_children'; import map_children from './shared/map_children';
import { isBindingContenteditable, getContenteditableAttr } from '../utils/contenteditable';
import { dimensions } from '../../utils/patterns'; import { dimensions } from '../../utils/patterns';
import fuzzymatch from '../../utils/fuzzymatch'; import fuzzymatch from '../../utils/fuzzymatch';
import list from '../../utils/list'; import list from '../../utils/list';
@ -769,19 +770,15 @@ export default class Element extends Node {
}); });
} }
} else if ( } else if (
name === 'textContent' || isBindingContenteditable(binding)
name === 'innerHTML'
) { ) {
const contenteditable = this.attributes.find( const contenteditable = getContenteditableAttr(this);
(attribute: Attribute) => attribute.name === 'contenteditable'
);
if (!contenteditable) { if (!contenteditable) {
component.error(binding, { component.error(binding, {
code: 'missing-contenteditable-attribute', code: 'missing-contenteditable-attribute',
message: '\'contenteditable\' attribute is required for textContent and innerHTML two-way bindings' message: '\'contenteditable\' attribute is required for textContent/innerHTML/innerText two-way bindings'
}); });
} else if (contenteditable && !contenteditable.is_static) { } else if (!contenteditable.is_static) {
component.error(contenteditable, { component.error(contenteditable, {
code: 'dynamic-contenteditable-attribute', code: 'dynamic-contenteditable-attribute',
message: '\'contenteditable\' attribute cannot be dynamic if element uses two-way binding' message: '\'contenteditable\' attribute cannot be dynamic if element uses two-way binding'

@ -1,5 +1,5 @@
import { is_void } from '../../../utils/names'; import { is_void } from '../../../utils/names';
import isContenteditable, { isBindingContenteditable } from '../../utils/contenteditable'; import { isBindingContenteditable, isContenteditable } from '../../utils/contenteditable';
import { get_attribute_value, get_class_attribute_value } from './shared/get_attribute_value'; import { get_attribute_value, get_class_attribute_value } from './shared/get_attribute_value';
import { boolean_attributes } from './shared/boolean_attributes'; import { boolean_attributes } from './shared/boolean_attributes';
import Renderer, { RenderOptions } from '../Renderer'; import Renderer, { RenderOptions } from '../Renderer';

@ -1,11 +1,12 @@
import * as assert from 'assert'; import * as assert from 'assert';
import get_name_from_filename from './get_name_from_filename'; import get_name_from_filename from './get_name_from_filename';
import { import {
default as isContenteditable, isContenteditable,
isInputOrTextarea, isInputOrTextarea,
isAttrContentEditable, isAttrContentEditable,
hasContentEditableAttr, hasContentEditableAttr,
isBindingContenteditable, isBindingContenteditable,
getContenteditableAttr,
CONTENTEDITABLE_ATTR, CONTENTEDITABLE_ATTR,
CONTENTEDITABLE_BINDINGS, CONTENTEDITABLE_BINDINGS,
} from './contenteditable'; } from './contenteditable';
@ -99,5 +100,17 @@ describe('contenteditable', () => {
assert.equal(isBindingContenteditable(binding), false); assert.equal(isBindingContenteditable(binding), false);
}); });
}); });
describe('getContenteditableAttr', () => {
it('returns the contenteditable Attribute if it exists', () => {
const attr = { name: CONTENTEDITABLE_ATTR } as Attribute;
const node = { name: 'div', attributes: [attr] } as Element;
assert.equal(getContenteditableAttr(node), attr);
});
it('returns undefined if contenteditable attribute cannot be found', () => {
const node = { name: 'div', attributes: [] } as Element;
assert.equal(getContenteditableAttr(node), undefined);
});
});
}); });

@ -14,7 +14,7 @@ export const CONTENTEDITABLE_BINDINGS = [
/** /**
* Returns true if node is an 'input' or 'textarea' * Returns true if node is an 'input' or 'textarea'
* @param node The element to be checked * @param {Element} node The element to be checked
*/ */
export function isInputOrTextarea(node: Element): boolean { export function isInputOrTextarea(node: Element): boolean {
return node.name === 'textarea' || node.name === 'input'; return node.name === 'textarea' || node.name === 'input';
@ -22,7 +22,7 @@ export function isInputOrTextarea(node: Element): boolean {
/** /**
* Check if a given attribute is 'contenteditable' * Check if a given attribute is 'contenteditable'
* @param attribute A node.attribute * @param {Attribute} attribute A node.attribute
*/ */
export function isAttrContentEditable(attribute: Attribute): boolean { export function isAttrContentEditable(attribute: Attribute): boolean {
return attribute.name === CONTENTEDITABLE_ATTR; return attribute.name === CONTENTEDITABLE_ATTR;
@ -30,7 +30,7 @@ export function isAttrContentEditable(attribute: Attribute): boolean {
/** /**
* Check if any of a node's attributes are 'contentenditable' * Check if any of a node's attributes are 'contentenditable'
* @param node The element to be checked * @param {Element} node The element to be checked
*/ */
export function hasContentEditableAttr(node: Element): boolean { export function hasContentEditableAttr(node: Element): boolean {
return node.attributes.some(isAttrContentEditable); return node.attributes.some(isAttrContentEditable);
@ -38,17 +38,26 @@ export function hasContentEditableAttr(node: Element): boolean {
/** /**
* Returns true if node is not textarea or input, but has 'contenteditable' attribute * Returns true if node is not textarea or input, but has 'contenteditable' attribute
* @param node The element to be tested * @param {Element} node The element to be tested
*/ */
export default function isContenteditable(node: Element): boolean { export function isContenteditable(node: Element): boolean {
return !isInputOrTextarea(node) && hasContentEditableAttr(node); return !isInputOrTextarea(node) && hasContentEditableAttr(node);
} }
/** /**
* Returns true if a given bindings should be contenteditable * Returns true if a given bindings should be contenteditable
* *
* @param binding A node's binding to be checked * @param {Binding} binding A node's binding to be checked
*/ */
export function isBindingContenteditable(binding: Binding) { export function isBindingContenteditable(binding: Binding): boolean {
return CONTENTEDITABLE_BINDINGS.includes(binding.name); return CONTENTEDITABLE_BINDINGS.includes(binding.name);
} }
/**
* Returns the contenteditable attribute from the node (if it exists)
*
* @param {Element} node The element to get the attribute from
*/
export function getContenteditableAttr(node: Element): Attribute | undefined {
return node.attributes.find(isAttrContentEditable);
}

Loading…
Cancel
Save