mirror of https://github.com/sveltejs/svelte
commit
f4edb381bf
@ -0,0 +1,41 @@
|
|||||||
|
import Renderer from '../Renderer';
|
||||||
|
import Block from '../Block';
|
||||||
|
import Comment from '../../nodes/Comment';
|
||||||
|
import Wrapper from './shared/Wrapper';
|
||||||
|
import { x } from 'code-red';
|
||||||
|
import { Identifier } from 'estree';
|
||||||
|
|
||||||
|
export default class CommentWrapper extends Wrapper {
|
||||||
|
node: Comment;
|
||||||
|
var: Identifier;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
renderer: Renderer,
|
||||||
|
block: Block,
|
||||||
|
parent: Wrapper,
|
||||||
|
node: Comment
|
||||||
|
) {
|
||||||
|
super(renderer, block, parent, node);
|
||||||
|
this.var = x`c` as Identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(block: Block, parent_node: Identifier, parent_nodes: Identifier) {
|
||||||
|
if (!this.renderer.options.preserveComments) return;
|
||||||
|
|
||||||
|
const string_literal = {
|
||||||
|
type: 'Literal',
|
||||||
|
value: this.node.data,
|
||||||
|
loc: {
|
||||||
|
start: this.renderer.locate(this.node.start),
|
||||||
|
end: this.renderer.locate(this.node.end)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
block.add_element(
|
||||||
|
this.var,
|
||||||
|
x`@comment(${string_literal})`,
|
||||||
|
parent_nodes && x`@claim_comment(${parent_nodes}, ${string_literal})`,
|
||||||
|
parent_node
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
// Note: Must import from the `css-tree` browser bundled distribution due to `createRequire` usage if importing from
|
||||||
|
// `css-tree` Node module directly. This allows the production build of Svelte to work correctly.
|
||||||
|
import { fork } from '../../../../../node_modules/css-tree/dist/csstree.esm.js';
|
||||||
|
|
||||||
|
import * as node from './node';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends `css-tree` for container query support by forking and adding new nodes and at-rule support for `@container`.
|
||||||
|
*
|
||||||
|
* The new nodes are located in `./node`.
|
||||||
|
*/
|
||||||
|
const cqSyntax = fork({
|
||||||
|
atrule: { // extend or override at-rule dictionary
|
||||||
|
container: {
|
||||||
|
parse: {
|
||||||
|
prelude() {
|
||||||
|
return this.createSingleNodeList(
|
||||||
|
this.ContainerQuery()
|
||||||
|
);
|
||||||
|
},
|
||||||
|
block(isStyleBlock = false) {
|
||||||
|
return this.Block(isStyleBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
node
|
||||||
|
});
|
||||||
|
|
||||||
|
export const parse = cqSyntax.parse;
|
@ -0,0 +1,48 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import { Delim } from 'css-tree/tokenizer';
|
||||||
|
|
||||||
|
export const name = 'Comparison';
|
||||||
|
export const structure = {
|
||||||
|
value: String
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parse() {
|
||||||
|
const start = this.tokenStart;
|
||||||
|
|
||||||
|
const char1 = this.consume(Delim);
|
||||||
|
|
||||||
|
// The first character in the comparison operator must match '<', '=', or '>'.
|
||||||
|
if (char1 !== '<' && char1 !== '>' && char1 !== '=') {
|
||||||
|
this.error('Malformed comparison operator');
|
||||||
|
}
|
||||||
|
|
||||||
|
let char2;
|
||||||
|
|
||||||
|
if (this.tokenType === Delim) {
|
||||||
|
char2 = this.consume(Delim);
|
||||||
|
|
||||||
|
// The second character in the comparison operator must match '='.
|
||||||
|
if (char2 !== '=') {
|
||||||
|
this.error('Malformed comparison operator');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the next token is also 'Delim' then it is malformed.
|
||||||
|
if (this.tokenType === Delim) {
|
||||||
|
this.error('Malformed comparison operator');
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = char2 ? `${char1}${char2}` : char1;
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'Comparison',
|
||||||
|
loc: this.getLocation(start, this.tokenStart),
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generate(node) {
|
||||||
|
for (let index = 0; index < node.value.length; index++) {
|
||||||
|
this.token(Delim, node.value.charAt(index));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import {
|
||||||
|
Function,
|
||||||
|
Ident,
|
||||||
|
Number,
|
||||||
|
Dimension,
|
||||||
|
RightParenthesis,
|
||||||
|
Colon,
|
||||||
|
Delim
|
||||||
|
} from 'css-tree/tokenizer';
|
||||||
|
|
||||||
|
export const name = 'ContainerFeatureStyle';
|
||||||
|
export const structure = {
|
||||||
|
name: String,
|
||||||
|
value: ['Function', 'Identifier', 'Number', 'Dimension', 'QueryCSSFunction', 'Ratio', null]
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parse() {
|
||||||
|
const start = this.tokenStart;
|
||||||
|
let value = null;
|
||||||
|
|
||||||
|
const function_name = this.consumeFunctionName();
|
||||||
|
if (function_name !== 'style') {
|
||||||
|
this.error('Unknown container style query identifier; "style" is expected');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.skipSC();
|
||||||
|
|
||||||
|
const name = this.consume(Ident);
|
||||||
|
this.skipSC();
|
||||||
|
|
||||||
|
if (this.tokenType !== RightParenthesis) {
|
||||||
|
this.eat(Colon);
|
||||||
|
this.skipSC();
|
||||||
|
|
||||||
|
switch (this.tokenType) {
|
||||||
|
case Number:
|
||||||
|
if (this.lookupNonWSType(1) === Delim) {
|
||||||
|
value = this.Ratio();
|
||||||
|
} else {
|
||||||
|
value = this.Number();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Dimension:
|
||||||
|
value = this.Dimension();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Function:
|
||||||
|
value = this.QueryCSSFunction();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Ident:
|
||||||
|
value = this.Identifier();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.error('Number, dimension, ratio, function or identifier is expected');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.skipSC();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.eat(RightParenthesis);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'ContainerFeatureStyle',
|
||||||
|
loc: this.getLocation(start, this.tokenStart),
|
||||||
|
name,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generate(node) {
|
||||||
|
this.token(Function, 'style(');
|
||||||
|
this.token(Ident, node.name);
|
||||||
|
|
||||||
|
if (node.value !== null) {
|
||||||
|
this.token(Colon, ':');
|
||||||
|
this.node(node.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.token(RightParenthesis, ')');
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import {
|
||||||
|
WhiteSpace,
|
||||||
|
Comment,
|
||||||
|
Function,
|
||||||
|
Ident,
|
||||||
|
LeftParenthesis
|
||||||
|
} from 'css-tree/tokenizer';
|
||||||
|
|
||||||
|
import { lookahead_is_range } from './lookahead_is_range';
|
||||||
|
|
||||||
|
const CONTAINER_QUERY_KEYWORDS = new Set(['none', 'and', 'not', 'or']);
|
||||||
|
|
||||||
|
export const name = 'ContainerQuery';
|
||||||
|
export const structure = {
|
||||||
|
name: 'Identifier',
|
||||||
|
children: [[
|
||||||
|
'Identifier',
|
||||||
|
'QueryFeature',
|
||||||
|
'QueryFeatureRange',
|
||||||
|
'ContainerFeatureStyle',
|
||||||
|
'WhiteSpace'
|
||||||
|
]]
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parse() {
|
||||||
|
const start = this.tokenStart;
|
||||||
|
const children = this.createList();
|
||||||
|
let child = null;
|
||||||
|
let name = null;
|
||||||
|
|
||||||
|
// Parse potential container name.
|
||||||
|
if (this.tokenType === Ident) {
|
||||||
|
const container_name = this.substring(this.tokenStart, this.tokenEnd);
|
||||||
|
|
||||||
|
// Container name doesn't match a query keyword, so assign it as container name.
|
||||||
|
if (!CONTAINER_QUERY_KEYWORDS.has(container_name.toLowerCase())) {
|
||||||
|
name = container_name;
|
||||||
|
this.eatIdent(container_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.skipSC();
|
||||||
|
|
||||||
|
scan:
|
||||||
|
while (!this.eof) {
|
||||||
|
switch (this.tokenType) {
|
||||||
|
case Comment:
|
||||||
|
case WhiteSpace:
|
||||||
|
this.next();
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case Ident:
|
||||||
|
child = this.Identifier();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Function:
|
||||||
|
child = this.ContainerFeatureStyle();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LeftParenthesis:
|
||||||
|
// Lookahead to determine if range feature.
|
||||||
|
child = lookahead_is_range.call(this) ? this.QueryFeatureRange() : this.QueryFeature();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break scan;
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child === null) {
|
||||||
|
this.error('Identifier or parenthesis is expected');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'ContainerQuery',
|
||||||
|
loc: this.getLocation(start, this.tokenStart - 1),
|
||||||
|
name,
|
||||||
|
children
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generate(node) {
|
||||||
|
if (typeof node.name === 'string') {
|
||||||
|
this.token(Ident, node.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.children(node);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
|||||||
|
export * as Comparison from './comparison';
|
||||||
|
export * as ContainerFeatureStyle from './container_feature_style';
|
||||||
|
export * as ContainerQuery from './container_query';
|
||||||
|
export * as MediaQuery from './media_query';
|
||||||
|
export * as QueryFeature from './query_feature';
|
||||||
|
export * as QueryFeatureRange from './query_feature_range';
|
||||||
|
export * as QueryCSSFunction from './query_css_function';
|
@ -0,0 +1,44 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import {
|
||||||
|
EOF,
|
||||||
|
WhiteSpace,
|
||||||
|
Delim,
|
||||||
|
RightParenthesis,
|
||||||
|
LeftCurlyBracket,
|
||||||
|
Colon
|
||||||
|
} from 'css-tree/tokenizer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks ahead to determine if query feature is a range query. This involves locating at least one delimiter and no
|
||||||
|
* colon tokens.
|
||||||
|
*
|
||||||
|
* @returns {boolean} Is potential range query.
|
||||||
|
*/
|
||||||
|
export function lookahead_is_range() {
|
||||||
|
let type;
|
||||||
|
let offset = 0;
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
let delim_found = false;
|
||||||
|
let no_colon = true;
|
||||||
|
|
||||||
|
// A range query has maximum 5 tokens when formatted as 'mf-range' /
|
||||||
|
// '<mf-value> <mf-lt> <mf-name> <mf-lt> <mf-value>'. So only look ahead maximum of 6 non-whitespace tokens.
|
||||||
|
do {
|
||||||
|
type = this.lookupNonWSType(offset++);
|
||||||
|
if (type !== WhiteSpace) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (type === Delim) {
|
||||||
|
delim_found = true;
|
||||||
|
}
|
||||||
|
if (type === Colon) {
|
||||||
|
no_colon = false;
|
||||||
|
}
|
||||||
|
if (type === LeftCurlyBracket || type === RightParenthesis) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (type !== EOF && count <= 6);
|
||||||
|
|
||||||
|
return delim_found && no_colon;
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import {
|
||||||
|
WhiteSpace,
|
||||||
|
Comment,
|
||||||
|
Ident,
|
||||||
|
LeftParenthesis
|
||||||
|
} from 'css-tree/tokenizer';
|
||||||
|
|
||||||
|
import { lookahead_is_range } from './lookahead_is_range';
|
||||||
|
|
||||||
|
export const name = 'MediaQuery';
|
||||||
|
export const structure = {
|
||||||
|
children: [[
|
||||||
|
'Identifier',
|
||||||
|
'QueryFeature',
|
||||||
|
'QueryFeatureRange',
|
||||||
|
'WhiteSpace'
|
||||||
|
]]
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parse() {
|
||||||
|
const children = this.createList();
|
||||||
|
let child = null;
|
||||||
|
|
||||||
|
this.skipSC();
|
||||||
|
|
||||||
|
scan:
|
||||||
|
while (!this.eof) {
|
||||||
|
switch (this.tokenType) {
|
||||||
|
case Comment:
|
||||||
|
case WhiteSpace:
|
||||||
|
this.next();
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case Ident:
|
||||||
|
child = this.Identifier();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LeftParenthesis:
|
||||||
|
// Lookahead to determine if range feature.
|
||||||
|
child = lookahead_is_range.call(this) ? this.QueryFeatureRange() : this.QueryFeature();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break scan;
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child === null) {
|
||||||
|
this.error('Identifier or parenthesis is expected');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'MediaQuery',
|
||||||
|
loc: this.getLocationFromList(children),
|
||||||
|
children
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generate(node) {
|
||||||
|
this.children(node);
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import {
|
||||||
|
RightParenthesis
|
||||||
|
} from 'css-tree/tokenizer';
|
||||||
|
|
||||||
|
const QUERY_CSS_FUNCTIONS = new Set(['calc', 'clamp', 'min', 'max']);
|
||||||
|
|
||||||
|
export const name = 'QueryCSSFunction';
|
||||||
|
export const structure = {
|
||||||
|
name: String,
|
||||||
|
expression: String
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parse() {
|
||||||
|
const start = this.tokenStart;
|
||||||
|
|
||||||
|
const name = this.consumeFunctionName();
|
||||||
|
|
||||||
|
if (!QUERY_CSS_FUNCTIONS.has(name)) {
|
||||||
|
this.error('Unknown query single value function; expected: "calc", "clamp", "max", min"');
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = this.Raw(this.tokenIndex, null, false);
|
||||||
|
|
||||||
|
this.eat(RightParenthesis);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'QueryCSSFunction',
|
||||||
|
loc: this.getLocation(start, this.tokenStart),
|
||||||
|
name,
|
||||||
|
expression: body.value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generate(node) {
|
||||||
|
this.token(Function, `${node.name}(`);
|
||||||
|
|
||||||
|
this.node(node.expression);
|
||||||
|
|
||||||
|
this.token(RightParenthesis, ')');
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import {
|
||||||
|
Ident,
|
||||||
|
Number,
|
||||||
|
Dimension,
|
||||||
|
Function,
|
||||||
|
LeftParenthesis,
|
||||||
|
RightParenthesis,
|
||||||
|
Colon,
|
||||||
|
Delim
|
||||||
|
} from 'css-tree/tokenizer';
|
||||||
|
|
||||||
|
export const name = 'QueryFeature';
|
||||||
|
export const structure = {
|
||||||
|
name: String,
|
||||||
|
value: ['Identifier', 'Number', 'Dimension', 'QueryCSSFunction', 'Ratio', null]
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parse() {
|
||||||
|
const start = this.tokenStart;
|
||||||
|
let value = null;
|
||||||
|
|
||||||
|
this.eat(LeftParenthesis);
|
||||||
|
this.skipSC();
|
||||||
|
|
||||||
|
const name = this.consume(Ident);
|
||||||
|
this.skipSC();
|
||||||
|
|
||||||
|
if (this.tokenType !== RightParenthesis) {
|
||||||
|
this.eat(Colon);
|
||||||
|
this.skipSC();
|
||||||
|
|
||||||
|
switch (this.tokenType) {
|
||||||
|
case Number:
|
||||||
|
if (this.lookupNonWSType(1) === Delim) {
|
||||||
|
value = this.Ratio();
|
||||||
|
} else {
|
||||||
|
value = this.Number();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Dimension:
|
||||||
|
value = this.Dimension();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Function:
|
||||||
|
value = this.QueryCSSFunction();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Ident:
|
||||||
|
value = this.Identifier();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.error('Number, dimension, ratio, function, or identifier is expected');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.skipSC();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.eat(RightParenthesis);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'QueryFeature',
|
||||||
|
loc: this.getLocation(start, this.tokenStart),
|
||||||
|
name,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generate(node) {
|
||||||
|
this.token(LeftParenthesis, '(');
|
||||||
|
this.token(Ident, node.name);
|
||||||
|
|
||||||
|
if (node.value !== null) {
|
||||||
|
this.token(Colon, ':');
|
||||||
|
this.node(node.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.token(RightParenthesis, ')');
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import {
|
||||||
|
Ident,
|
||||||
|
Number,
|
||||||
|
Delim,
|
||||||
|
Dimension,
|
||||||
|
Function,
|
||||||
|
LeftParenthesis,
|
||||||
|
RightParenthesis,
|
||||||
|
WhiteSpace
|
||||||
|
} from 'css-tree/tokenizer';
|
||||||
|
|
||||||
|
export const name = 'QueryFeatureRange';
|
||||||
|
export const structure = {
|
||||||
|
name: String,
|
||||||
|
value: ['Identifier', 'Number', 'Comparison', 'Dimension', 'QueryCSSFunction', 'Ratio', null]
|
||||||
|
};
|
||||||
|
|
||||||
|
function lookup_non_WS_type_and_value(offset, type, referenceStr) {
|
||||||
|
let current_type;
|
||||||
|
|
||||||
|
do {
|
||||||
|
current_type = this.lookupType(offset++);
|
||||||
|
if (current_type !== WhiteSpace) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (current_type !== 0); // NULL -> 0
|
||||||
|
|
||||||
|
return current_type === type ? this.lookupValue(offset - 1, referenceStr) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parse() {
|
||||||
|
const start = this.tokenStart;
|
||||||
|
const children = this.createList();
|
||||||
|
let child = null;
|
||||||
|
|
||||||
|
this.eat(LeftParenthesis);
|
||||||
|
this.skipSC();
|
||||||
|
|
||||||
|
while (!this.eof && this.tokenType !== RightParenthesis) {
|
||||||
|
switch (this.tokenType) {
|
||||||
|
case Number:
|
||||||
|
if (lookup_non_WS_type_and_value.call(this, 1, Delim, '/')) {
|
||||||
|
child = this.Ratio();
|
||||||
|
} else {
|
||||||
|
child = this.Number();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Delim:
|
||||||
|
child = this.Comparison();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Dimension:
|
||||||
|
child = this.Dimension();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Function:
|
||||||
|
child = this.QueryCSSFunction();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Ident:
|
||||||
|
child = this.Identifier();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.error('Number, dimension, comparison, ratio, function, or identifier is expected');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push(child);
|
||||||
|
|
||||||
|
this.skipSC();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.eat(RightParenthesis);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'QueryFeatureRange',
|
||||||
|
loc: this.getLocation(start, this.tokenStart),
|
||||||
|
children
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generate(node) {
|
||||||
|
this.children(node);
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
div.svelte-xyz{container:test-container / inline-size}@container (min-width: 400px){div.svelte-xyz{color:red}}@container test-container (min-width: 410px){div.svelte-xyz{color:green}}@container test-container (width < 400px){div.svelte-xyz{color:blue}}@container test-container (0 <= width < 300px){div.svelte-xyz{color:purple}}@container not (width < 400px){div.svelte-xyz{color:pink}}@container (width > 400px) and (height > 400px){div.svelte-xyz{color:lightgreen}}@container (width > 400px) or (height > 400px){div.svelte-xyz{color:lightblue}}@container (width > 400px) and (width > 800px) or (orientation: portrait){div.svelte-xyz{color:salmon}}@container style(color: blue){div.svelte-xyz{color:tan}}@container test-container (min-width: calc(400px + 1px)){div.svelte-xyz{color:green}}@container test-container (width < clamp(200px, 40%, 400px)){div.svelte-xyz{color:blue}}@container test-container (calc(400px + 1px) <= width < calc(500px + 1px)){div.svelte-xyz{color:purple}}@container style(--var: calc(400px + 1px)){div.svelte-xyz{color:sandybrown}}
|
@ -0,0 +1,87 @@
|
|||||||
|
<div>container query</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
container: test-container / inline-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Most common container query statements. */
|
||||||
|
|
||||||
|
@container (min-width: 400px) {
|
||||||
|
div {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container test-container (min-width: 410px) {
|
||||||
|
div {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container test-container (width < 400px) {
|
||||||
|
div {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container test-container (0 <= width < 300px) {
|
||||||
|
div {
|
||||||
|
color: purple;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container not (width < 400px) {
|
||||||
|
div {
|
||||||
|
color: pink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container (width > 400px) and (height > 400px) {
|
||||||
|
div {
|
||||||
|
color: lightgreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container (width > 400px) or (height > 400px) {
|
||||||
|
div {
|
||||||
|
color: lightblue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container (width > 400px) and (width > 800px) or (orientation: portrait) {
|
||||||
|
div {
|
||||||
|
color: salmon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container style(color: blue) {
|
||||||
|
div {
|
||||||
|
color: tan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container test-container (min-width: calc(400px + 1px)) {
|
||||||
|
div {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container test-container (width < clamp(200px, 40%, 400px)) {
|
||||||
|
div {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container test-container (calc(400px + 1px) <= width < calc(500px + 1px)) {
|
||||||
|
div {
|
||||||
|
color: purple;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container style(--var: calc(400px + 1px)) {
|
||||||
|
div {
|
||||||
|
color: sandybrown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1 +1 @@
|
|||||||
@media(min-width: 400px){.large-screen.svelte-xyz{display:block}}
|
@media(min-width: 400px){.large-screen.svelte-xyz{display:block}}@media(min-width: calc(400px + 1px)){.large-screen.svelte-xyz{display:block}}@media(width >= 600px){.large-screen.svelte-xyz{display:block}}@media(400px <= width <= 1000px){.large-screen.svelte-xyz{display:block}}@media(width < clamp(200px, 40%, 400px)){.large-screen.svelte-xyz{display:block}}@media(calc(400px + 1px) <= width <= calc(1000px + 1px)){.large-screen.svelte-xyz{display:block}}
|
@ -0,0 +1 @@
|
|||||||
|
<div><!-- test1 --><!-- test2 --></div>
|
@ -0,0 +1 @@
|
|||||||
|
<div><!-- test1 --></div>
|
@ -0,0 +1,20 @@
|
|||||||
|
export default {
|
||||||
|
compileOptions: {
|
||||||
|
preserveComments:true
|
||||||
|
},
|
||||||
|
snapshot(target) {
|
||||||
|
const div = target.querySelector('div');
|
||||||
|
|
||||||
|
return {
|
||||||
|
div,
|
||||||
|
comment: div.childNodes[0]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
test(assert, target, snapshot) {
|
||||||
|
const div = target.querySelector('div');
|
||||||
|
assert.equal(div, snapshot.div);
|
||||||
|
assert.equal(div.childNodes[0], snapshot.comment);
|
||||||
|
assert.equal(div.childNodes[1].nodeType, 8);
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1 @@
|
|||||||
|
<div><!-- test1 --><!-- test2 --></div>
|
@ -0,0 +1,5 @@
|
|||||||
|
export default {
|
||||||
|
options: {
|
||||||
|
preserveComments: true
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,58 @@
|
|||||||
|
/* generated by Svelte vX.Y.Z */
|
||||||
|
import {
|
||||||
|
SvelteComponent,
|
||||||
|
comment,
|
||||||
|
detach,
|
||||||
|
element,
|
||||||
|
init,
|
||||||
|
insert,
|
||||||
|
noop,
|
||||||
|
safe_not_equal,
|
||||||
|
space
|
||||||
|
} from "svelte/internal";
|
||||||
|
|
||||||
|
function create_fragment(ctx) {
|
||||||
|
let div0;
|
||||||
|
let t1;
|
||||||
|
let c;
|
||||||
|
let t2;
|
||||||
|
let div1;
|
||||||
|
|
||||||
|
return {
|
||||||
|
c() {
|
||||||
|
div0 = element("div");
|
||||||
|
div0.textContent = "content";
|
||||||
|
t1 = space();
|
||||||
|
c = comment(" comment ");
|
||||||
|
t2 = space();
|
||||||
|
div1 = element("div");
|
||||||
|
div1.textContent = "more content";
|
||||||
|
},
|
||||||
|
m(target, anchor) {
|
||||||
|
insert(target, div0, anchor);
|
||||||
|
insert(target, t1, anchor);
|
||||||
|
insert(target, c, anchor);
|
||||||
|
insert(target, t2, anchor);
|
||||||
|
insert(target, div1, anchor);
|
||||||
|
},
|
||||||
|
p: noop,
|
||||||
|
i: noop,
|
||||||
|
o: noop,
|
||||||
|
d(detaching) {
|
||||||
|
if (detaching) detach(div0);
|
||||||
|
if (detaching) detach(t1);
|
||||||
|
if (detaching) detach(c);
|
||||||
|
if (detaching) detach(t2);
|
||||||
|
if (detaching) detach(div1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class Component extends SvelteComponent {
|
||||||
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
init(this, options, null, create_fragment, safe_not_equal, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component;
|
@ -0,0 +1,3 @@
|
|||||||
|
<div>content</div>
|
||||||
|
<!-- comment -->
|
||||||
|
<div>more content</div>
|
@ -0,0 +1,10 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
html: '<div hidden />',
|
||||||
|
test({ assert, component, target }) {
|
||||||
|
component.hidden = false;
|
||||||
|
assert.htmlEqual(target.innerHTML, '<div />');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
export let hidden = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div {hidden} />
|
@ -1,11 +0,0 @@
|
|||||||
export default {
|
|
||||||
props: {
|
|
||||||
itemscope: true
|
|
||||||
},
|
|
||||||
test({ assert, target, component }) {
|
|
||||||
const div = target.querySelector('div');
|
|
||||||
assert.ok(div.itemscope);
|
|
||||||
component.itemscope = false;
|
|
||||||
assert.ok(!div.itemscope);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,5 +0,0 @@
|
|||||||
<script>
|
|
||||||
export let itemscope;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div {itemscope} />
|
|
@ -0,0 +1,4 @@
|
|||||||
|
export default {
|
||||||
|
html: '<textarea></textarea>',
|
||||||
|
ssrHtml: '<textarea>test\'"></textarea><script>alert(\'BIM\');</script></textarea>'
|
||||||
|
};
|
@ -0,0 +1 @@
|
|||||||
|
<textarea value={`test'"></textarea><script>alert('BIM');</script>`} />
|
@ -0,0 +1,25 @@
|
|||||||
|
// There is no relationship between the attribute and the dom node with regards to microdata attributes https://developer.mozilla.org/en-US/docs/Web/HTML/Microdata
|
||||||
|
export default {
|
||||||
|
html: `<div itemscope itemtype="https://schema.org/SoftwareApplication">
|
||||||
|
<span itemprop="name">Game</span> - REQUIRES
|
||||||
|
<span itemprop="operatingSystem">OS</span><br/>
|
||||||
|
<link itemprop="applicationCategory" href="https://schema.org/GameApplication"/>
|
||||||
|
|
||||||
|
<div itemprop="aggregateRating" itemscope="" itemtype="https://schema.org/AggregateRating">RATING:
|
||||||
|
<span itemprop="ratingValue">4.6</span> (
|
||||||
|
<span itemprop="ratingCount">8864</span> ratings )</div>
|
||||||
|
<div itemref="offers"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
itemprop="offers"
|
||||||
|
itemid="offers"
|
||||||
|
id="offers"
|
||||||
|
itemscope
|
||||||
|
itemtype="https://schema.org/Offer"
|
||||||
|
>
|
||||||
|
Price: $<span itemprop="price">1.00</span>
|
||||||
|
<meta itemprop="priceCurrency" content="USD"/>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
};
|
@ -0,0 +1,31 @@
|
|||||||
|
<!-- Example from https://developer.mozilla.org/en-US/docs/Web/HTML/Microdata -->
|
||||||
|
<div itemscope itemtype="https://schema.org/SoftwareApplication">
|
||||||
|
<span itemprop="name">Game</span> - REQUIRES
|
||||||
|
<span itemprop="operatingSystem">OS</span><br />
|
||||||
|
<link
|
||||||
|
itemprop="applicationCategory"
|
||||||
|
href="https://schema.org/GameApplication"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
itemprop="aggregateRating"
|
||||||
|
itemscope
|
||||||
|
itemtype="https://schema.org/AggregateRating"
|
||||||
|
>
|
||||||
|
RATING:
|
||||||
|
<span itemprop="ratingValue">4.6</span> (
|
||||||
|
<span itemprop="ratingCount">8864</span> ratings )
|
||||||
|
</div>
|
||||||
|
<div itemref="offers" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
itemprop="offers"
|
||||||
|
itemid="offers"
|
||||||
|
id="offers"
|
||||||
|
itemscope
|
||||||
|
itemtype="https://schema.org/Offer"
|
||||||
|
>
|
||||||
|
Price: $<span itemprop="price">1.00</span>
|
||||||
|
<meta itemprop="priceCurrency" content="USD" />
|
||||||
|
</div>
|
@ -0,0 +1,20 @@
|
|||||||
|
export default {
|
||||||
|
html: `
|
||||||
|
<p>4, 12, 60</p>
|
||||||
|
`,
|
||||||
|
|
||||||
|
async test({ component, target, assert }) {
|
||||||
|
component.permutation = [2, 3, 1];
|
||||||
|
await (component.promise1 = Promise.resolve({length: 1, width: 2, height: 3}));
|
||||||
|
try {
|
||||||
|
await (component.promise2 = Promise.reject({length: 97, width: 98, height: 99}));
|
||||||
|
} catch (e) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML, `
|
||||||
|
<p>2, 11, 2</p>
|
||||||
|
<p>9506, 28811, 98</p>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,27 @@
|
|||||||
|
<script>
|
||||||
|
export let promise1 = {length: 5, width: 3, height: 4};
|
||||||
|
export let promise2 = {length: 12, width: 5, height: 13};
|
||||||
|
export let permutation = [1, 2, 3];
|
||||||
|
|
||||||
|
function calculate(length, width, height) {
|
||||||
|
return {
|
||||||
|
'1-Dimensions': [length, width, height],
|
||||||
|
'2-Dimensions': [length * width, width * height, length * height],
|
||||||
|
'3-Dimensions': [length * width * height, length + width + height, length * width + width * height + length * height]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const th = 'th';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#await promise1 then { length, width, height }}
|
||||||
|
{@const { [0]: a, [1]: b, [2]: c } = permutation}
|
||||||
|
{@const { [`${a}-Dimensions`]: { [c - 1]: first }, [`${b}-Dimensions`]: { [b - 1]: second }, [`${c}-Dimensions`]: { [a - 1]: third } } = calculate(length, width, height) }
|
||||||
|
<p>{first}, {second}, {third}</p>
|
||||||
|
{/await}
|
||||||
|
|
||||||
|
{#await promise2 catch { [`leng${th}`]: l, [`wid${th}`]: w, height: h }}
|
||||||
|
{@const [a, b, c] = permutation}
|
||||||
|
{@const { [`${a}-Dimensions`]: { [c - 1]: first }, [`${b}-Dimensions`]: { [b - 1]: second }, [`${c}-Dimensions`]: { [a - 1]: third } } = calculate(l, w, h) }
|
||||||
|
<p>{first}, {second}, {third}</p>
|
||||||
|
{/await}
|
@ -0,0 +1,15 @@
|
|||||||
|
export default {
|
||||||
|
html: `
|
||||||
|
<button>6, 12, 8, 24</button>
|
||||||
|
<button>45, 35, 63, 315</button>
|
||||||
|
<button>60, 48, 80, 480</button>
|
||||||
|
`,
|
||||||
|
|
||||||
|
async test({ component, target, assert }) {
|
||||||
|
component.boxes = [{ length: 10, width: 20, height: 30 }];
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML,
|
||||||
|
'<button>200, 600, 300, 6000</button>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,44 @@
|
|||||||
|
<script>
|
||||||
|
export let boxes = [
|
||||||
|
{length: 2, width: 3, height: 4},
|
||||||
|
{length: 9, width: 5, height: 7},
|
||||||
|
{length: 10, width: 6, height: 8}
|
||||||
|
];
|
||||||
|
|
||||||
|
function calculate(length, width, height) {
|
||||||
|
return {
|
||||||
|
twoDimensions: {
|
||||||
|
bottomArea: length * width,
|
||||||
|
sideArea1: width * height,
|
||||||
|
sideArea2: length * height
|
||||||
|
},
|
||||||
|
threeDimensions: {
|
||||||
|
volume: length * width * height
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export let dimension = 'Dimensions';
|
||||||
|
function changeDimension() {
|
||||||
|
dimension = 'DIMENSIONS';
|
||||||
|
}
|
||||||
|
|
||||||
|
let area = 'Area';
|
||||||
|
let th = 'th';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#each boxes as { [`leng${th}`]: length, [`wid${th}`]: width, height }}
|
||||||
|
{@const {
|
||||||
|
[`two${dimension}`]: areas,
|
||||||
|
[`three${dimension}`]: {
|
||||||
|
volume
|
||||||
|
}
|
||||||
|
} = calculate(length, width, height)}
|
||||||
|
{@const {
|
||||||
|
i = 1,
|
||||||
|
[`bottom${area}`]: bottom,
|
||||||
|
[`side${area}${i++}`]: sideone,
|
||||||
|
[`side${area}${i++}`]: sidetwo
|
||||||
|
} = areas}
|
||||||
|
<button on:click={changeDimension}>{bottom}, {sideone}, {sidetwo}, {volume}</button>
|
||||||
|
{/each}
|
Loading…
Reference in new issue