New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@netflix/x-element

Package Overview
Dependencies
Maintainers
0
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@netflix/x-element - npm Package Compare versions

Comparing version 2.0.0-rc.6 to 2.0.0-rc.7

2

package.json
{
"name": "@netflix/x-element",
"description": "A dead simple starting point for custom elements.",
"version": "2.0.0-rc.6",
"version": "2.0.0-rc.7",
"license": "Apache-2.0",

@@ -6,0 +6,0 @@ "repository": "github:Netflix/x-element",

@@ -72,17 +72,2 @@ import { XParser } from '../x-parser.js';

// Overwrite console warn for testing so we don’t get spammed with our own
// deprecation warnings.
const seen = new Set();
const warn = console.warn; // eslint-disable-line no-console
const localMessages = [
'Support for the <style> tag is deprecated and will be removed in future versions.',
];
console.warn = (...args) => { // eslint-disable-line no-console
if (!localMessages.includes(args[0]?.message)) {
warn(...args);
} else {
seen.add(args[0].message);
}
};
// Simple helper for asserting thrown messages.

@@ -415,12 +400,2 @@ const assertThrows = (callback, expectedMessage, options) => {

describe('errors', () => {
it('throws when attempting to interpolate within a style tag', () => {
const callback = () => html`
<style>
div { background-color: ${VALUE}; }
</style>
`;
const expectedMessage = '[#191]';
assertThrows(callback, expectedMessage, { startsWith: true });
});
it('throws when attempting non-trivial interpolation of a textarea tag (preceding space)', () => {

@@ -484,3 +459,3 @@ const callback = () => html`<textarea id="target"> ${VALUE}</textarea>`;

super();
html`<style></style>`;
html`<div></div>`;
}

@@ -1043,2 +1018,8 @@ }

it('throws for forbidden <style> tag', () => {
const callback = () => html`<style></style>`;
const expectedMessage = '[#153]';
assertThrows(callback, expectedMessage, { startsWith: true });
});
it('throws for forbidden <script> tag', () => {

@@ -1068,2 +1049,8 @@ const callback = () => html`<script></script>`;

it('throws for forbidden <svg> tag', () => {
const callback = () => html`<svg></svg>`;
const expectedMessage = '[#153]';
assertThrows(callback, expectedMessage, { startsWith: true });
});
it('throws for declarative shadow roots', () => {

@@ -1136,39 +1123,1 @@ const callback = () => html`<template shadowrootmode="open"></template>`;

});
describe('deprecated', () => {
it('parses non-interpolated style', () => {
const fragment = html`
<style>
#target {
/* the color is red */
color: rgb(255, 0, 0);
}
#target::after {
content: "\\2026"; /* This is the right syntax. The slash just needs escaping for the template literal. */
}
</style>
<div id="target">hi</div>
`;
const container = document.createElement('div');
container.append(fragment);
document.body.append(container); // Need to connect for computed styles.
assert(container.childElementCount === 2);
assert(getComputedStyle(container.querySelector('#target')).color === 'rgb(255, 0, 0)');
assert(container.querySelector('#target').textContent === 'hi');
container.remove();
});
it('validate deprecation warnings work', () => {
// eslint-disable-next-line no-shadow
const html = strings => wrapper(validator, strings);
html`
<style>/* causes console warning which we need for coverage */</style>
`;
});
});
it('confirm that deprecation warnings are still necessary', () => {
for (const message of localMessages) {
assert(seen.has(message), `Unused deprecation warning: ${message}`);
}
});

@@ -137,5 +137,5 @@ /** Base element class for creating custom elements. */

* ```js
* static template(html, { nullish }) {
* return (href) => {
* return html`<a href=${nullish(href)}>click me</a>`;
* static template(html) {
* return ({ href }) => {
* return html`<a href="${href}">click me</a>`;
* }

@@ -142,0 +142,0 @@ * }

export const render: any;
export const html: any;
export const map: any;
export const live: any;
export const unsafeHTML: any;
export const ifDefined: any;
export const nullish: any;
export const repeat: any;
//# sourceMappingURL=x-template.d.ts.map

@@ -146,5 +146,5 @@ import * as defaultTemplateEngine from './x-template.js';

* ```js
* static template(html, { nullish }) {
* return (href) => {
* return html`<a href=${nullish(href)}>click me</a>`;
* static template(html) {
* return ({ href }) => {
* return html`<a href="${href}">click me</a>`;
* }

@@ -151,0 +151,0 @@ * }

@@ -15,6 +15,2 @@ /** Strict HTML parser meant to handle interpolated HTML. */

// Simple flags to ensure we only warn once about things being deprecated.
// TODO: #237: Remove <style> tag usage.
#hasWarnedAboutStyleDeprecation = false;
// DOM introspection is expensive. Since we are creating all of the elements,

@@ -81,3 +77,3 @@ // we can cache the introspections we need behind performant lookups.

#deniedHtmlElements = new Set([
'html', 'head', 'base', 'link', 'meta', 'title', 'body', 'script',
'html', 'head', 'base', 'link', 'meta', 'title', 'style', 'body', 'script',
'noscript', 'canvas', 'acronym', 'big', 'center', 'content', 'dir', 'font',

@@ -87,3 +83,2 @@ 'frame', 'frameset', 'image', 'marquee', 'menuitem', 'nobr', 'noembed',

'tt', 'xmp', 'math', 'svg',
// TODO: #237: Remove <style> tag usage — add 'style' to this list.
]);

@@ -193,8 +188,2 @@ #allowedHtmlElements = this.#htmlElements.difference(this.#deniedHtmlElements);

// The “style” tag is deprecated and will be removed in future versions. It
// contains “non-replaceable” character data.
// https://w3c.github.io/html-reference/syntax.html#non-replaceable-character-data
// TODO: #237: Remove support for <style> tags.
#throughStyle = /.*?<\/style>/ys;
//////////////////////////////////////////////////////////////////////////////

@@ -321,5 +310,2 @@ // JS-y Escapes //////////////////////////////////////////////////////////////

['#157', 'Forbidden declarative shadow root used (e.g., `<template shadowrootmode="open">`).'],
// TODO: #237: Remove support for <style> tags completely.
['#191', 'Interpolation of <style> tags is not allowed.'],
]);

@@ -376,5 +362,2 @@

['declarative-shadow-root', '#157'],
// TODO: #237: Remove support for <style> tags completely.
['style-interpolation', '#191'],
]);

@@ -675,21 +658,2 @@

// TODO: #237: Remove support for <style> tags.
// Style contains so-called “non-replaceable” character data.
#finalizeStyle(string, path, element, childNodesIndex, nextStringIndex) {
const closeTagLength = 8; // </style>
this.#throughStyle.lastIndex = nextStringIndex;
if (this.#throughStyle.test(string)) {
const content = string.slice(nextStringIndex, this.#throughStyle.lastIndex - closeTagLength);
element.value.textContent = content;
} else {
const errorMessagesKey = this.#namedErrorsToErrorMessagesKey.get('style-interpolation');
const errorMessage = this.#errorMessages.get(errorMessagesKey);
throw new Error(`[${errorMessagesKey}] ${errorMessage}`);
}
childNodesIndex.value = path.pop();
element.value = element.value[this.#parentNode];
this.#closeTag.lastIndex = this.#throughStyle.lastIndex;
return this.#closeTag;
}
// Unbound content is just literal text in a template string that needs to

@@ -858,11 +822,2 @@ // land as text content. We replace any character references (html entities)

// TODO: #237: Remove support for <style> tags.
#styleDeprecationWarning() {
if (!this.#hasWarnedAboutStyleDeprecation) {
this.#hasWarnedAboutStyleDeprecation = true;
const error = new Error('Support for the <style> tag is deprecated and will be removed in future versions.');
this.#window.console.warn(error);
}
}
//////////////////////////////////////////////////////////////////////////////

@@ -1052,7 +1007,2 @@ // Public interface //////////////////////////////////////////////////////////

nextStringIndex = value.lastIndex;
} else if (tagName === 'style') {
// TODO: #237: Remove support for <style> tags.
this.#styleDeprecationWarning();
value = this.#finalizeStyle(string, path, element, childNodesIndex, nextStringIndex);
nextStringIndex = value.lastIndex;
} else if (

@@ -1059,0 +1009,0 @@ tagName === 'textarea' &&

@@ -42,7 +42,3 @@ import { XParser } from './x-parser.js';

// Deprecated interface.
map: TemplateEngine.#interfaceDeprecated('map', TemplateEngine.map),
live: TemplateEngine.#interfaceDeprecated('live', TemplateEngine.live),
unsafeHTML: TemplateEngine.#interfaceDeprecated('unsafeHTML', TemplateEngine.unsafeHTML),
ifDefined: TemplateEngine.#interfaceDeprecated('ifDefined', TemplateEngine.ifDefined),
nullish: TemplateEngine.#interfaceDeprecated('nullish', TemplateEngine.nullish),
repeat: TemplateEngine.#interfaceDeprecated('repeat', TemplateEngine.repeat),

@@ -109,92 +105,6 @@ });

/**
* Updater to manage an attribute which may not exist.
* In the following example, the "nullish" updater will remove the
* attribute if it's nullish. Else, it sets the key-value pair.
* ```js
* html`<a href="${nullish(obj.href)}"></div>`;
* ```
* Shim for prior "repeat" function. Use native entries array.
* @deprecated
* @param {any} value
* @returns {any}
*/
static nullish(value) {
const symbol = Object.create(null);
const updater = TemplateEngine.#nullish;
const update = { updater, value };
TemplateEngine.#symbolToUpdate.set(symbol, update);
return symbol;
}
/**
* Updater to manage a property which may change outside the template engine.
* Typically, properties are declaratively managed from state and efficient
* value checking is used (i.e., "value !== lastValue"). However, if DOM state
* is expected to change, the "live" updater can be used to essentially change
* this check to "value !== node[property]".
* ```js
* html`<input .value="${live(obj.value)}"/>`;
* ```
* @deprecated
* @param {any} value
* @returns {any}
*/
static live(value) {
const symbol = Object.create(null);
const updater = TemplateEngine.#live;
const update = { updater, value };
TemplateEngine.#symbolToUpdate.set(symbol, update);
return symbol;
}
/**
* Updater to inject trusted HTML into the DOM.
* Use with caution. The "unsafeHTML" updater allows arbitrary input to be
* parsed as HTML and injected into the DOM.
* ```js
* html`<div>${unsafeHTML(obj.trustedMarkup)}</div>`;
* ```
* @deprecated
* @param {any} value
* @returns {any}
*/
static unsafeHTML(value) {
const symbol = Object.create(null);
const updater = TemplateEngine.#unsafeHTML;
const update = { updater, value };
TemplateEngine.#symbolToUpdate.set(symbol, update);
return symbol;
}
/**
* Updater to manage a keyed array of templates (allows for DOM reuse).
* ```js
* html`
* <ul>
* ${map(items, item => item.id, item => html`<li>${item.value}</li>`)}
* </div>
* `;
* ```
* @param {any[]} items
* @param {Function} identify
* @param {Function} callback
* @returns {any}
*/
static map(items, identify, callback) {
if (!Array.isArray(items)) {
throw new Error(`Unexpected map items "${items}" provided, expected an array.`);
}
if (typeof identify !== 'function') {
throw new Error(`Unexpected map identify "${identify}" provided, expected a function.`);
}
if (typeof callback !== 'function') {
throw new Error(`Unexpected map callback "${callback}" provided, expected a function.`);
}
return items.map(item => [identify(item), callback(item)]);
}
/**
* Shim for prior "repeat" function. Use "map".
* @deprecated
* @param {any[]} items
* @param {Function} identify
* @param {Function} [callback]

@@ -230,32 +140,2 @@ * @returns {any}

// Deprecated. Will remove in future release.
static #nullish(node, name, value, lastValue) {
if (value !== lastValue) {
value === undefined || value === null
? node.removeAttribute(name)
: node.setAttribute(name, value);
}
}
// Deprecated. Will remove in future release.
static #live(node, name, value) {
if (node[name] !== value) {
node[name] = value;
}
}
// Deprecated. Will remove in future release.
static #unsafeHTML(node, startNode, value, lastValue) {
if (value !== lastValue) {
if (typeof value === 'string') {
const template = document.createElement('template');
template.innerHTML = value;
TemplateEngine.#removeBetween(startNode, node);
TemplateEngine.#insertAllBefore(node.parentNode, node, template.content.childNodes);
} else {
throw new Error(`Unexpected unsafeHTML value "${value}".`);
}
}
}
// After cloning our common fragment, we use the “lookups” to cache live

@@ -417,15 +297,6 @@ // references to DOM nodes so that we can surgically perform updates later in

const update = TemplateEngine.#symbolToUpdate.get(value);
const lastUpdate = TemplateEngine.#symbolToUpdate.get(lastValue);
if (update) {
switch (update.updater) {
case TemplateEngine.#ifDefined:
TemplateEngine.#ifDefined(node, name, update.value, lastUpdate?.value);
break;
case TemplateEngine.#nullish:
TemplateEngine.#nullish(node, name, update.value, lastUpdate?.value);
break;
default:
TemplateEngine.#throwUpdaterError(update.updater, TemplateEngine.#ATTRIBUTE);
break;
}
// If there’s an update, it _has_ to be #ifDefined at this point.
const lastUpdate = TemplateEngine.#symbolToUpdate.get(lastValue);
TemplateEngine.#ifDefined(node, name, update.value, lastUpdate?.value);
} else {

@@ -441,3 +312,3 @@ if (value !== lastValue) {

if (update) {
TemplateEngine.#throwUpdaterError(update.updater, TemplateEngine.#BOOLEAN);
TemplateEngine.#throwIfDefinedError(TemplateEngine.#BOOLEAN);
} else {

@@ -453,3 +324,3 @@ if (value !== lastValue) {

if (update) {
TemplateEngine.#throwUpdaterError(update.updater, TemplateEngine.#DEFINED);
TemplateEngine.#throwIfDefinedError(TemplateEngine.#DEFINED);
} else {

@@ -467,10 +338,3 @@ if (value !== lastValue) {

if (update) {
switch (update.updater) {
case TemplateEngine.#live:
TemplateEngine.#live(node, name, update.value);
break;
default:
TemplateEngine.#throwUpdaterError(update.updater, TemplateEngine.#PROPERTY);
break;
}
TemplateEngine.#throwIfDefinedError(TemplateEngine.#PROPERTY);
} else {

@@ -503,3 +367,3 @@ if (value !== lastValue) {

// if (category !== lastCategory && lastValue !== TemplateEngine.#UNSET) {
// // Reset content under certain conditions. E.g., `map(…)` >> `null`.
// // Reset content under certain conditions. E.g., `map` >> `null`.
// const state = TemplateEngine.#getState(node, TemplateEngine.#STATE);

@@ -559,8 +423,6 @@ // const arrayState = TemplateEngine.#getState(startNode, TemplateEngine.#ARRAY_STATE);

if (
lastValue !== TemplateEngine.#UNSET && (
introspection?.category !== lastIntrospection?.category ||
introspection?.update?.updater !== lastIntrospection?.update?.updater
)
lastValue !== TemplateEngine.#UNSET &&
introspection?.category !== lastIntrospection?.category
) {
// Reset content under certain conditions. E.g., `map(…)` >> `null`.
// Reset content under certain conditions. E.g., `map` >> `null`.
const state = TemplateEngine.#getState(node, TemplateEngine.#STATE);

@@ -573,12 +435,3 @@ const arrayState = TemplateEngine.#getState(startNode, TemplateEngine.#ARRAY_STATE);

if (introspection?.category === 'update') {
const { update } = introspection;
const lastUpdate = lastIntrospection?.update;
switch (update.updater) {
case TemplateEngine.#unsafeHTML:
TemplateEngine.#unsafeHTML(node, startNode, update.value, lastUpdate?.value);
break;
default:
TemplateEngine.#throwUpdaterError(update.updater, TemplateEngine.#CONTENT);
break;
}
TemplateEngine.#throwIfDefinedError(TemplateEngine.#CONTENT);
} else {

@@ -632,3 +485,3 @@ // Note that we always want to re-render results / lists, but because the

if (update) {
TemplateEngine.#throwUpdaterError(update.updater, TemplateEngine.#TEXT);
TemplateEngine.#throwIfDefinedError(TemplateEngine.#TEXT);
} else {

@@ -794,14 +647,4 @@ if (value !== lastValue) {

static #throwUpdaterError(updater, binding) {
switch (updater) {
// We’ll delete these updaters later.
case TemplateEngine.#live:
throw new Error(`The live update must be used on ${TemplateEngine.#getBindingText(TemplateEngine.#PROPERTY)}, not on ${TemplateEngine.#getBindingText(binding)}.`);
case TemplateEngine.#unsafeHTML:
throw new Error(`The unsafeHTML update must be used on ${TemplateEngine.#getBindingText(TemplateEngine.#CONTENT)}, not on ${TemplateEngine.#getBindingText(binding)}.`);
case TemplateEngine.#ifDefined:
throw new Error(`The ifDefined update must be used on ${TemplateEngine.#getBindingText(TemplateEngine.#ATTRIBUTE)}, not on ${TemplateEngine.#getBindingText(binding)}.`);
case TemplateEngine.#nullish:
throw new Error(`The nullish update must be used on ${TemplateEngine.#getBindingText(TemplateEngine.#ATTRIBUTE)}, not on ${TemplateEngine.#getBindingText(binding)}.`);
}
static #throwIfDefinedError(binding) {
throw new Error(`The ifDefined update must be used on ${TemplateEngine.#getBindingText(TemplateEngine.#ATTRIBUTE)}, not on ${TemplateEngine.#getBindingText(binding)}.`);
}

@@ -939,7 +782,3 @@

// Deprecated interface.
export const map = TemplateEngine.interface.map.bind(TemplateEngine);
export const live = TemplateEngine.interface.live.bind(TemplateEngine);
export const unsafeHTML = TemplateEngine.interface.unsafeHTML.bind(TemplateEngine);
export const ifDefined = TemplateEngine.interface.ifDefined.bind(TemplateEngine);
export const nullish = TemplateEngine.interface.nullish.bind(TemplateEngine);
export const repeat = TemplateEngine.interface.repeat.bind(TemplateEngine);

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc