Closes #5876. Adds single value function support to media queries and media query range syntax / MQ level 4 support. (#8430)

pull/8458/head
Michael Leahy 2 years ago committed by GitHub
parent cfe26d8d6c
commit d42ca041dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -3,12 +3,7 @@
// `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 Comparison from './node/comparison';
import * as ContainerFeature from './node/container_feature';
import * as ContainerFeatureRange from './node/container_feature_range';
import * as ContainerFeatureStyle from './node/container_feature_style';
import * as ContainerQuery from './node/container_query';
import * as QueryCSSFunction from './node/query_css_function';
import * as node from './node';
/**
* Extends `css-tree` for container query support by forking and adding new nodes and at-rule support for `@container`.
@ -30,14 +25,7 @@ const cqSyntax = fork({
}
}
},
node: { // extend node types
Comparison,
ContainerFeature,
ContainerFeatureRange,
ContainerFeatureStyle,
ContainerQuery,
QueryCSSFunction
}
node
});
export const parse = cqSyntax.parse;

@ -1,17 +1,14 @@
// @ts-nocheck
import {
EOF,
WhiteSpace,
Comment,
Delim,
Function,
Ident,
LeftParenthesis,
RightParenthesis,
LeftCurlyBracket,
Colon
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';
@ -19,48 +16,13 @@ export const structure = {
name: 'Identifier',
children: [[
'Identifier',
'ContainerFeature',
'ContainerFeatureRange',
'QueryFeature',
'QueryFeatureRange',
'ContainerFeatureStyle',
'WhiteSpace'
]]
};
/**
* 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.
*/
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;
}
export function parse() {
const start = this.tokenStart;
const children = this.createList();
@ -98,7 +60,7 @@ export function parse() {
case LeftParenthesis:
// Lookahead to determine if range feature.
child = lookahead_is_range.call(this) ? this.ContainerFeatureRange() : this.ContainerFeature();
child = lookahead_is_range.call(this) ? this.QueryFeatureRange() : this.QueryFeature();
break;
default:

@ -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);
}

@ -10,7 +10,7 @@ import {
Delim
} from 'css-tree/tokenizer';
export const name = 'ContainerFeature';
export const name = 'QueryFeature';
export const structure = {
name: String,
value: ['Identifier', 'Number', 'Dimension', 'QueryCSSFunction', 'Ratio', null]
@ -62,7 +62,7 @@ export function parse() {
this.eat(RightParenthesis);
return {
type: 'ContainerFeature',
type: 'QueryFeature',
loc: this.getLocation(start, this.tokenStart),
name,
value

@ -10,7 +10,7 @@ import {
WhiteSpace
} from 'css-tree/tokenizer';
export const name = 'ContainerFeatureRange';
export const name = 'QueryFeatureRange';
export const structure = {
name: String,
value: ['Identifier', 'Number', 'Comparison', 'Dimension', 'QueryCSSFunction', 'Ratio', null]
@ -30,6 +30,7 @@ function lookup_non_WS_type_and_value(offset, type, referenceStr) {
}
export function parse() {
const start = this.tokenStart;
const children = this.createList();
let child = null;
@ -75,8 +76,8 @@ export function parse() {
this.eat(RightParenthesis);
return {
type: 'ContainerFeatureRange',
loc: this.getLocationFromList(children),
type: 'QueryFeatureRange',
loc: this.getLocation(start, this.tokenStart),
children
};
}

@ -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}}

@ -6,4 +6,34 @@
display: block;
}
}
</style>
@media (min-width: calc(400px + 1px)) {
.large-screen {
display: block;
}
}
@media (width >= 600px) {
.large-screen {
display: block;
}
}
@media (400px <= width <= 1000px) {
.large-screen {
display: block;
}
}
@media (width < clamp(200px, 40%, 400px)) {
.large-screen {
display: block;
}
}
@media (calc(400px + 1px) <= width <= calc(1000px + 1px)) {
.large-screen {
display: block;
}
}
</style>

Loading…
Cancel
Save