Merge branch 'master' into dev-root
This commit is contained in:
commit
f05c13722b
|
@ -315,6 +315,15 @@
|
|||
"message": "Enable",
|
||||
"description": "Label for the button to enable a style"
|
||||
},
|
||||
"excludeStyleByDomainLabel": {
|
||||
"message": "Exclude the current domain"
|
||||
},
|
||||
"excludeStyleByUrlLabel": {
|
||||
"message": "Exclude the current URL"
|
||||
},
|
||||
"excludeStyleByUrlRedundant": {
|
||||
"message": "The current URL is the domain page"
|
||||
},
|
||||
"exportLabel": {
|
||||
"message": "Export",
|
||||
"description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)"
|
||||
|
@ -1026,6 +1035,10 @@
|
|||
"message": "Stylus failed to parse usercss:",
|
||||
"description": "The error message to show when stylus failed to parse usercss"
|
||||
},
|
||||
"popupAutoResort": {
|
||||
"message": "Resort styles in popup after toggling",
|
||||
"description": "Label for the checkbox controlling popup resorting."
|
||||
},
|
||||
"popupBorders": {
|
||||
"message": "Add white borders on the sides"
|
||||
},
|
||||
|
@ -1044,6 +1057,10 @@
|
|||
"message": "Shift-click or right-click opens manager with styles applicable for current site",
|
||||
"description": "Tooltip for the 'Manage' button in the popup."
|
||||
},
|
||||
"popupMenuButtonTooltip": {
|
||||
"message": "Action menu",
|
||||
"description": "Tooltip for menu button in popup."
|
||||
},
|
||||
"popupOpenEditInWindow": {
|
||||
"message": "Open editor in a new window",
|
||||
"description": "Label for the checkbox controlling 'edit' action behavior in the popup."
|
||||
|
@ -1056,10 +1073,6 @@
|
|||
"message": "Styles before commands",
|
||||
"description": "Label for the checkbox controlling section order in the popup."
|
||||
},
|
||||
"popupAutoResort": {
|
||||
"message": "Resort styles in popup after toggling",
|
||||
"description": "Label for the checkbox controlling popup resorting."
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Number of styles active for the current site",
|
||||
"description": "Label for the checkbox controlling toolbar badge text."
|
||||
|
|
|
@ -22,6 +22,11 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, {
|
|||
styleExists: styleManager.styleExists,
|
||||
toggleStyle: styleManager.toggleStyle,
|
||||
|
||||
addInclusion: styleManager.addInclusion,
|
||||
removeInclusion: styleManager.removeInclusion,
|
||||
addExclusion: styleManager.addExclusion,
|
||||
removeExclusion: styleManager.removeExclusion,
|
||||
|
||||
getTabUrlPrefix() {
|
||||
return this.sender.tab.url.match(/^([\w-]+:\/+[^/#]+)/)[1];
|
||||
},
|
||||
|
@ -42,9 +47,11 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, {
|
|||
// Chrome 49 doesn't report own extension pages in webNavigation apparently
|
||||
// so we do a force update which doesn't use the cache.
|
||||
if (CHROME && CHROME < 2661 && this.sender.tab.url.startsWith(URLS.ownOrigin)) {
|
||||
return updateIconBadgeForce(this.sender.tab.id, count);
|
||||
updateIconBadgeForce(this.sender.tab.id, count);
|
||||
} else {
|
||||
updateIconBadge(this.sender.tab.id, count);
|
||||
}
|
||||
return updateIconBadge(this.sender.tab.id, count);
|
||||
return true;
|
||||
},
|
||||
|
||||
// exposed for stuff that requires followup sendMessage() like popup::openSettings
|
||||
|
@ -79,8 +86,8 @@ if (FIREFOX) {
|
|||
// FF applies page CSP even to content scripts, https://bugzil.la/1267027
|
||||
navigatorUtil.onCommitted(webNavUsercssInstallerFF, {
|
||||
url: [
|
||||
{hostSuffix: '.githubusercontent.com', urlSuffix: '.user.css'},
|
||||
{hostSuffix: '.githubusercontent.com', urlSuffix: '.user.styl'},
|
||||
{pathSuffix: '.user.css'},
|
||||
{pathSuffix: '.user.styl'},
|
||||
]
|
||||
});
|
||||
// FF misses some about:blank iframes so we inject our content script explicitly
|
||||
|
|
|
@ -57,10 +57,13 @@ const styleManager = (() => {
|
|||
importStyle,
|
||||
importMany,
|
||||
toggleStyle,
|
||||
setStyleExclusions,
|
||||
getAllStyles, // used by import-export
|
||||
getStylesByUrl, // used by popup
|
||||
styleExists,
|
||||
addExclusion,
|
||||
removeExclusion,
|
||||
addInclusion,
|
||||
removeInclusion
|
||||
});
|
||||
|
||||
function handleLivePreviewConnections() {
|
||||
|
@ -92,6 +95,11 @@ const styleManager = (() => {
|
|||
});
|
||||
}
|
||||
|
||||
function escapeRegExp(text) {
|
||||
// https://github.com/lodash/lodash/blob/0843bd46ef805dd03c0c8d804630804f3ba0ca3c/lodash.js#L152
|
||||
return text.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&');
|
||||
}
|
||||
|
||||
function get(id, noCode = false) {
|
||||
const data = styles.get(id).data;
|
||||
return noCode ? getStyleWithNoCode(data) : data;
|
||||
|
@ -177,14 +185,51 @@ const styleManager = (() => {
|
|||
} else {
|
||||
data = Object.assign(createNewStyle(), data);
|
||||
}
|
||||
data.updateDate = Date.now();
|
||||
return saveStyle(data)
|
||||
.then(newData => handleSave(newData, 'editSave'));
|
||||
}
|
||||
|
||||
function setStyleExclusions(id, exclusions) {
|
||||
const data = Object.assign({}, styles.get(id).data, {exclusions});
|
||||
function addIncludeExclude(id, rule, type) {
|
||||
const data = Object.assign({}, styles.get(id).data);
|
||||
if (!data[type]) {
|
||||
data[type] = [];
|
||||
}
|
||||
if (data[type].includes(rule)) {
|
||||
throw new Error('The rule already exists');
|
||||
}
|
||||
data[type] = data[type].concat([rule]);
|
||||
return saveStyle(data)
|
||||
.then(newData => handleSave(newData, 'exclusions'));
|
||||
.then(newData => handleSave(newData, 'styleSettings'));
|
||||
}
|
||||
|
||||
function removeIncludeExclude(id, rule, type) {
|
||||
const data = Object.assign({}, styles.get(id).data);
|
||||
if (!data[type]) {
|
||||
return;
|
||||
}
|
||||
if (!data[type].includes(rule)) {
|
||||
return;
|
||||
}
|
||||
data[type] = data[type].filter(r => r !== rule);
|
||||
return saveStyle(data)
|
||||
.then(newData => handleSave(newData, 'styleSettings'));
|
||||
}
|
||||
|
||||
function addExclusion(id, rule) {
|
||||
return addIncludeExclude(id, rule, 'exclusions');
|
||||
}
|
||||
|
||||
function removeExclusion(id, rule) {
|
||||
return removeIncludeExclude(id, rule, 'exclusions');
|
||||
}
|
||||
|
||||
function addInclusion(id, rule) {
|
||||
return addIncludeExclude(id, rule, 'inclusions');
|
||||
}
|
||||
|
||||
function removeInclusion(id, rule) {
|
||||
return removeIncludeExclude(id, rule, 'inclusions');
|
||||
}
|
||||
|
||||
function deleteStyle(id) {
|
||||
|
@ -478,14 +523,7 @@ const styleManager = (() => {
|
|||
}
|
||||
|
||||
function buildGlob(text) {
|
||||
const prefix = text[0] === '^' ? '' : '\\b';
|
||||
const suffix = text[text.length - 1] === '$' ? '' : '\\b';
|
||||
return `${prefix}${escape(text)}${suffix}`;
|
||||
|
||||
function escape(text) {
|
||||
// FIXME: using .* everywhere is slow
|
||||
return text.replace(/[.*]/g, m => m === '.' ? '\\.' : '.*');
|
||||
}
|
||||
return '^' + escapeRegExp(text).replace(/\\\\\\\*|\\\*/g, m => m.length > 2 ? m : '.*') + '$';
|
||||
}
|
||||
|
||||
function getDomain(url) {
|
||||
|
|
|
@ -304,7 +304,7 @@ const APPLY = (() => {
|
|||
method: 'invokeAPI',
|
||||
name: 'updateIconBadge',
|
||||
args: [styleInjector.list.length]
|
||||
}).catch(msg.ignoreError);
|
||||
}).catch(console.error);
|
||||
}
|
||||
|
||||
function rootReady() {
|
||||
|
|
|
@ -157,10 +157,18 @@
|
|||
'text-align-all': true,
|
||||
|
||||
'contain': true,
|
||||
'mask-image': true,
|
||||
'mix-blend-mode': true,
|
||||
'rotate': true,
|
||||
'isolation': true,
|
||||
'zoom': true,
|
||||
|
||||
// https://www.w3.org/TR/css-round-display-1/
|
||||
'border-boundary': true,
|
||||
'shape': true,
|
||||
'shape-inside': true,
|
||||
'viewport-fit': true,
|
||||
|
||||
// nonstandard https://compat.spec.whatwg.org/
|
||||
'box-reflect': true,
|
||||
'text-fill-color': true,
|
||||
|
@ -171,6 +179,7 @@
|
|||
});
|
||||
Object.assign(CodeMirror.mimeModes['text/css'].valueKeywords, {
|
||||
'isolate': true,
|
||||
'rect': true,
|
||||
'recto': true,
|
||||
'verso': true,
|
||||
});
|
||||
|
|
|
@ -197,6 +197,7 @@ function createSectionsEditor({style, onTitleChanged}) {
|
|||
dirty.modify('enabled', style.enabled, newValue);
|
||||
style.enabled = newValue;
|
||||
enabledEl.checked = newValue;
|
||||
updateLivePreview();
|
||||
}
|
||||
|
||||
function nextEditor(cm, cycle = true) {
|
||||
|
@ -565,6 +566,7 @@ function createSectionsEditor({style, onTitleChanged}) {
|
|||
$('#heading').textContent = t('editStyleHeading');
|
||||
}
|
||||
livePreview.show(Boolean(style.id));
|
||||
updateLivePreview();
|
||||
});
|
||||
|
||||
function reinit() {
|
||||
|
|
|
@ -307,9 +307,9 @@
|
|||
|
||||
// set updateUrl
|
||||
const checker = $('.set-update-url input[type=checkbox]');
|
||||
// prefer the installation URL unless drag'n'dropped on the manage page
|
||||
// only use the installation URL if not specified in usercss
|
||||
const installationUrl = (params.get('updateUrl') || '').replace(/^blob.+/, '');
|
||||
const updateUrl = new URL(installationUrl || style.updateUrl || DUMMY_URL);
|
||||
const updateUrl = new URL(style.updateUrl || installationUrl || DUMMY_URL);
|
||||
if (dup && dup.updateUrl === updateUrl.href) {
|
||||
checker.checked = true;
|
||||
// there is no way to "unset" updateUrl, you can only overwrite it.
|
||||
|
@ -335,7 +335,7 @@
|
|||
|
||||
// live reload
|
||||
const setLiveReload = $('.live-reload input[type=checkbox]');
|
||||
if (updateUrl.protocol !== 'file:') {
|
||||
if (!installationUrl || !installationUrl.startsWith('file:')) {
|
||||
setLiveReload.parentNode.remove();
|
||||
} else {
|
||||
setLiveReload.addEventListener('change', () => {
|
||||
|
|
|
@ -7,7 +7,7 @@ const usercss = (() => {
|
|||
author: undefined,
|
||||
description: undefined,
|
||||
homepageURL: 'url',
|
||||
// updateURL: 'updateUrl',
|
||||
updateURL: 'updateUrl',
|
||||
name: undefined,
|
||||
};
|
||||
const RX_META = /\/\*!?\s*==userstyle==[\s\S]*?==\/userstyle==\s*\*\//i;
|
||||
|
|
70
popup.html
70
popup.html
|
@ -24,25 +24,55 @@
|
|||
|
||||
<template data-id="style">
|
||||
<div class="entry">
|
||||
<div class="main-controls">
|
||||
<label class="style-name">
|
||||
<input class="checker" type="checkbox">
|
||||
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||
</label>
|
||||
<div class="entry-content">
|
||||
<div class="main-controls">
|
||||
<label class="style-name">
|
||||
<input class="checker" type="checkbox">
|
||||
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||
</label>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="#" class="configure" i18n-title="configureStyle" tabindex="0">
|
||||
<svg class="svg-icon config"><use xlink:href="#svg-icon-config"></use></svg>
|
||||
</a>
|
||||
<a class="style-edit-link" href="edit.html?id=" i18n-title="editStyleLabel" tabindex="0">
|
||||
<svg class="svg-icon edit" viewBox="0 0 14 16">
|
||||
<path fill-rule="evenodd" d="M0 12v3h3l8-8-3-3-8 8zm3 2H1v-2h1v1h1v1zm10.3-9.3L12 6 9 3l1.3-1.3a.996.996 0 0 1 1.41 0l1.59 1.59c.39.39.39 1.02 0 1.41z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="#" class="menu-button" i18n-title="popupMenuButtonTooltip" tabindex="0">
|
||||
<svg class="svg-icon menu-button-icon" viewBox="0 0 3 16">
|
||||
<path fill-rule="evenodd" d="M0 2.5a1.5 1.5 0 1 0 3 0 1.5 1.5 0 0 0-3 0zm0 5a1.5 1.5 0 1 0 3 0 1.5 1.5 0 0 0-3 0zM1.5 14a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="#" class="configure" i18n-title="configureStyle" tabindex="0">
|
||||
<svg class="svg-icon config"><use xlink:href="#svg-icon-config"></use></svg>
|
||||
</a>
|
||||
<a class="style-edit-link" href="edit.html?id=" i18n-title="editStyleLabel" tabindex="0">
|
||||
<svg class="svg-icon edit" viewBox="0 0 14 16">
|
||||
<path fill-rule="evenodd" d="M0 12v3h3l8-8-3-3-8 8zm3 2H1v-2h1v1h1v1zm10.3-9.3L12 6 9 3l1.3-1.3a.996.996 0 0 1 1.41 0l1.59 1.59c.39.39.39 1.02 0 1.41z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="#" class="delete" i18n-title="deleteStyleLabel" tabindex="0">
|
||||
<svg class="svg-icon remove" viewBox="0 0 14 16">
|
||||
<path fill-rule="evenodd" d="M11 2H9c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1H2c-.55 0-1 .45-1 1v1c0 .55.45 1 1 1v9c0 .55.45 1 1 1h7c.55 0 1-.45 1-1V5c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 12H3V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9zm1-10H2V3h9v1z"/>
|
||||
</svg>
|
||||
<div class="menu">
|
||||
<label class="menu-item exclude-by-domain button">
|
||||
<div class="menu-icon">
|
||||
<div class="checkbox-container">
|
||||
<input type="checkbox" class="exclude-by-domain-checkbox">
|
||||
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
<span i18n-text="excludeStyleByDomainLabel"></span>
|
||||
</label>
|
||||
<label class="menu-item exclude-by-url button">
|
||||
<div class="menu-icon">
|
||||
<div class="checkbox-container">
|
||||
<input type="checkbox" class="exclude-by-url-checkbox">
|
||||
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
<span i18n-text="excludeStyleByUrlLabel"></span>
|
||||
</label>
|
||||
<a href="#" class="menu-item delete">
|
||||
<div class="menu-icon">
|
||||
<svg class="svg-icon remove" viewBox="0 0 14 16">
|
||||
<path fill-rule="evenodd" d="M11 2H9c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1H2c-.55 0-1 .45-1 1v1c0 .55.45 1 1 1v9c0 .55.45 1 1 1h7c.55 0 1-.45 1-1V5c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 12H3V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9zm1-10H2V3h9v1z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span i18n-text="deleteStyleLabel"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -241,8 +271,8 @@
|
|||
<path d="M6.2,0C5.8,0,5.4,0.4,5.4,0.8v0.7C5,1.7,4.6,1.8,4.3,2L3.8,1.5C3.6,1.4,3.4,1.3,3.2,1.3S2.7,1.4,2.6,1.5L1.5,2.6c-0.3,0.3-0.3,0.9,0,1.2L2,4.3C1.8,4.6,1.7,5,1.5,5.4H0.8C0.4,5.4,0,5.8,0,6.2v1.5c0,0.5,0.4,0.8,0.8,0.8h0.7C1.7,9,1.8,9.4,2,9.7l-0.5,0.5c-0.3,0.3-0.3,0.8,0,1.2l1.1,1.1c0.3,0.3,0.9,0.3,1.2,0L4.3,12c0.4,0.2,0.8,0.4,1.2,0.5v0.7c0,0.5,0.4,0.8,0.8,0.8h1.5c0.5,0,0.8-0.4,0.8-0.8v-0.7C9,12.3,9.4,12.2,9.7,12l0.5,0.5c0.3,0.3,0.9,0.3,1.2,0l1.1-1.1c0.3-0.3,0.3-0.8,0-1.2L12,9.7c0.2-0.4,0.4-0.8,0.5-1.2h0.7c0.5,0,0.8-0.4,0.8-0.8V6.2c0-0.5-0.4-0.8-0.8-0.8h-0.7C12.3,5,12.2,4.6,12,4.3l0.5-0.5c0.3-0.3,0.3-0.9,0-1.2l-1.1-1.1c-0.2-0.2-0.4-0.2-0.6-0.2s-0.4,0.1-0.6,0.2L9.7,2C9.4,1.8,9,1.7,8.6,1.5V0.8C8.6,0.4,8.2,0,7.8,0L6.2,0z M6.8,0.8h0.4c0.2,0,0.4,0.2,0.4,0.4v1.2c0.8,0.1,1.6,0.4,2.3,0.9l0.8-0.8c0.2-0.2,0.4-0.2,0.6,0l0.3,0.3c0.2,0.2,0.2,0.4,0,0.6l-0.8,0.8c0.5,0.7,0.8,1.4,0.9,2.3h1.2c0.2,0,0.4,0.2,0.4,0.4v0.4c0,0.2-0.2,0.4-0.4,0.4h-1.2c-0.1,0.8-0.4,1.6-0.9,2.3l0.8,0.8c0.2,0.2,0.2,0.4,0,0.6l-0.3,0.3c-0.2,0.2-0.4,0.2-0.6,0l-0.8-0.8c-0.7,0.5-1.4,0.8-2.3,0.9v1.2c0,0.2-0.2,0.4-0.4,0.4H6.8c-0.2,0-0.4-0.2-0.4-0.4v-1.2c-0.8-0.1-1.6-0.4-2.3-0.9l-0.8,0.8c-0.2,0.2-0.4,0.2-0.6,0l-0.3-0.3c-0.2-0.2-0.2-0.4,0-0.6l0.8-0.8C2.8,9.2,2.5,8.4,2.4,7.6H1.2C1,7.6,0.8,7.4,0.8,7.2V6.8c0-0.2,0.2-0.4,0.4-0.4h1.2c0.1-0.8,0.4-1.6,0.9-2.3L2.5,3.3c-0.2-0.2-0.2-0.4,0-0.6l0.3-0.3c0.2-0.2,0.4-0.2,0.6,0l0.8,0.8c0.7-0.5,1.4-0.8,2.3-0.9V1.2C6.4,1,6.6,0.8,6.8,0.8L6.8,0.8z M7,3.6C5.1,3.6,3.6,5.1,3.6,7c0,0,0,0,0,0c0,1.9,1.5,3.4,3.4,3.4c1.9,0,3.4-1.5,3.4-3.4C10.4,5.1,8.9,3.6,7,3.6C7,3.6,7,3.6,7,3.6z M7,4.8c1.2,0,2.2,1,2.2,2.2c0,1.2-1,2.2-2.2,2.2c-1.2,0-2.2-1-2.2-2.2C4.8,5.8,5.8,4.8,7,4.8z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="svg-icon-config-uso" viewBox="0 0 14 14">
|
||||
<path d="M2,3h4v2H4v6h6V9h2v4H2V3z M8,1h6v6l-2.2-2.2l-4,4L6.2,7.2l4-4L8,1z"/>
|
||||
<symbol id="svg-icon-config-uso" viewBox="0 0 20 20">
|
||||
<path d="M4,4h5v2H6v8h8v-3h2v5H4V4z M11,3h6v6l-2-2l-4,4L9,9l4-4L11,3z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="svg-icon-help" viewBox="0 0 14 16">
|
||||
|
|
105
popup/popup.css
105
popup/popup.css
|
@ -173,16 +173,17 @@ body.blocked > DIV {
|
|||
}
|
||||
|
||||
/* entry */
|
||||
|
||||
.entry {
|
||||
position: relative;
|
||||
}
|
||||
.entry-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 26px;
|
||||
padding: 0 14px 0 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
html[style] .entry {
|
||||
html[style] .entry-content {
|
||||
padding: 0 16px 0 0;
|
||||
}
|
||||
|
||||
|
@ -192,6 +193,7 @@ html[style] .entry {
|
|||
|
||||
.entry .actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.style-name {
|
||||
|
@ -264,9 +266,34 @@ html[style*="border"] .entry:nth-child(11):before {
|
|||
}
|
||||
|
||||
.entry .actions > * {
|
||||
display: inline-block;
|
||||
padding: 0 1px;
|
||||
margin: 0 1px;
|
||||
height: 26px;
|
||||
width: 18px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.entry .actions > .menu-button {
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
.entry .actions > a.configure {
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.entry .actions > a.configure[target="_blank"] {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.svg-icon.config {
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
a.configure[target="_blank"] .svg-icon.config {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.not-applied .checker,
|
||||
|
@ -286,6 +313,72 @@ html[style*="border"] .entry:nth-child(11):before {
|
|||
color: darkred;
|
||||
}
|
||||
|
||||
/* entry menu */
|
||||
.entry .menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
top: 100%;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
height: 0;
|
||||
transition: height .25s ease-out, opacity .5s ease-in;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
.entry.menu-active .menu {
|
||||
/* FIXME: avoid hard coded height */
|
||||
height: 72px;
|
||||
opacity: 1;
|
||||
}
|
||||
/* accessibility */
|
||||
.menu-item {
|
||||
display: none;
|
||||
border: none;
|
||||
align-items: center;
|
||||
padding: 0 0 0 20px;
|
||||
height: 24px;
|
||||
background: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
.entry.menu-active.accessible-items .menu-item {
|
||||
display: flex;
|
||||
}
|
||||
.entry .menu-item.delete {
|
||||
cursor: pointer;
|
||||
}
|
||||
.entry .menu-item.delete:hover {
|
||||
color: #000;
|
||||
}
|
||||
.entry .menu-item > span {
|
||||
margin-top: 1px;
|
||||
}
|
||||
.entry .menu-item:hover,
|
||||
.entry .menu-item:active {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
transition: background-color .25s;
|
||||
}
|
||||
.entry .menu-icon {
|
||||
width: 26px;
|
||||
}
|
||||
.entry .menu-icon > * {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.entry .menu-item.disabled {
|
||||
opacity: 0.5;
|
||||
background-color: transparent;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* checkbox */
|
||||
.checkbox-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.regexp-problem-indicator {
|
||||
background-color: #d00;
|
||||
width: 14px;
|
||||
|
|
|
@ -309,6 +309,11 @@ function createStyleElement(style) {
|
|||
indicator.appendChild(document.createTextNode('!'));
|
||||
indicator.onclick = handleEvent.indicator;
|
||||
$('.main-controls', entry).appendChild(indicator);
|
||||
|
||||
$('.menu-button', entry).onclick = handleEvent.toggleMenu;
|
||||
|
||||
$('.exclude-by-domain-checkbox', entry).onchange = e => handleEvent.toggleExclude(e, 'domain');
|
||||
$('.exclude-by-url-checkbox', entry).onchange = e => handleEvent.toggleExclude(e, 'url');
|
||||
}
|
||||
|
||||
style = Object.assign(entry.styleMeta, style);
|
||||
|
@ -329,9 +334,35 @@ function createStyleElement(style) {
|
|||
entry.classList.toggle('not-applied', style.excluded || style.sloppy);
|
||||
entry.classList.toggle('regexp-partial', style.sloppy);
|
||||
|
||||
$('.exclude-by-domain-checkbox', entry).checked = styleExcluded(style, 'domain');
|
||||
|
||||
const excludeByUrlCheckbox = $('.exclude-by-url-checkbox', entry);
|
||||
const isRedundant = getExcludeRule('domain') === getExcludeRule('url');
|
||||
excludeByUrlCheckbox.checked = !isRedundant && styleExcluded(style, 'url');
|
||||
excludeByUrlCheckbox.disabled = isRedundant;
|
||||
|
||||
const excludeByUrlLabel = $('.exclude-by-url', entry);
|
||||
excludeByUrlLabel.classList.toggle('disabled', isRedundant);
|
||||
excludeByUrlLabel.title = isRedundant ?
|
||||
chrome.i18n.getMessage('excludeStyleByUrlRedundant') : '';
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
function styleExcluded({exclusions}, type) {
|
||||
if (!exclusions) {
|
||||
return false;
|
||||
}
|
||||
const rule = getExcludeRule(type);
|
||||
return exclusions.includes(rule);
|
||||
}
|
||||
|
||||
function getExcludeRule(type) {
|
||||
if (type === 'domain') {
|
||||
return new URL(tabURL).origin + '/*';
|
||||
}
|
||||
return tabURL + '*';
|
||||
}
|
||||
|
||||
Object.assign(handleEvent, {
|
||||
|
||||
|
@ -356,10 +387,29 @@ Object.assign(handleEvent, {
|
|||
.then(sortStylesInPlace);
|
||||
},
|
||||
|
||||
toggleExclude(event, type) {
|
||||
const entry = handleEvent.getClickedStyleElement(event);
|
||||
if (event.target.checked) {
|
||||
API.addExclusion(entry.styleMeta.id, getExcludeRule(type));
|
||||
} else {
|
||||
API.removeExclusion(entry.styleMeta.id, getExcludeRule(type));
|
||||
}
|
||||
},
|
||||
|
||||
toggleMenu(event) {
|
||||
const entry = handleEvent.getClickedStyleElement(event);
|
||||
entry.classList.toggle('menu-active');
|
||||
setTimeout(() => {
|
||||
entry.classList.toggle('accessible-items');
|
||||
}, 250);
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
delete(event) {
|
||||
const entry = handleEvent.getClickedStyleElement(event);
|
||||
const id = entry.styleId;
|
||||
const box = $('#confirm');
|
||||
const cancel = $('[data-cmd="cancel"]');
|
||||
box.dataset.display = true;
|
||||
box.style.cssText = '';
|
||||
$('b', box).textContent = $('.style-name', entry).textContent;
|
||||
|
@ -368,7 +418,7 @@ Object.assign(handleEvent, {
|
|||
$('[data-cmd="cancel"]', box).onclick = () => confirm(false);
|
||||
window.onkeydown = event => {
|
||||
const keyCode = event.keyCode || event.which;
|
||||
if (!event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey
|
||||
if (document.activeElement !== cancel && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey
|
||||
&& (keyCode === 13 || keyCode === 27)) {
|
||||
event.preventDefault();
|
||||
confirm(keyCode === 13);
|
||||
|
|
|
@ -34,11 +34,11 @@ class Reporter {
|
|||
* verification back to the main API.
|
||||
* @class Reporter
|
||||
* @constructor
|
||||
* @param {String[]} lines The text lines of the source.
|
||||
* @param {Object} ruleset The set of rules to work with, including if
|
||||
* @param {String[]} lines - The text lines of the source.
|
||||
* @param {Object} ruleset - The set of rules to work with, including if
|
||||
* they are errors or warnings.
|
||||
* @param {Object} explicitly allowed lines
|
||||
* @param {[][]} ingore list of line ranges to be ignored
|
||||
* @param {Object} allow - explicitly allowed lines
|
||||
* @param {[][]} ingore - list of line ranges to be ignored
|
||||
*/
|
||||
constructor(lines, ruleset, allow, ignore) {
|
||||
this.messages = [];
|
||||
|
@ -126,6 +126,9 @@ var CSSLint = (() => {
|
|||
};
|
||||
const rules = [];
|
||||
|
||||
// previous CSSLint overrides are used to decide whether the parserlib's cache should be reset
|
||||
let prevOverrides;
|
||||
|
||||
return Object.assign(new parserlib.util.EventTarget(), {
|
||||
|
||||
addRule(rule) {
|
||||
|
@ -193,8 +196,13 @@ var CSSLint = (() => {
|
|||
rules[id] &&
|
||||
rules[id].init(parser, reporter));
|
||||
|
||||
// TODO: when ruleset is unchanged we can try to invalidate only line ranges in 'allow' and 'ignore'
|
||||
const newOvr = [ruleset, allow, ignore];
|
||||
const reuseCache = !prevOverrides || JSON.stringify(prevOverrides) === JSON.stringify(newOvr);
|
||||
prevOverrides = newOvr;
|
||||
|
||||
try {
|
||||
parser.parse(text, {reuseCache: true});
|
||||
parser.parse(text, {reuseCache});
|
||||
} catch (ex) {
|
||||
reporter.error('Fatal error, cannot continue: ' + ex.message, ex.line, ex.col, {});
|
||||
}
|
||||
|
@ -219,17 +227,50 @@ var CSSLint = (() => {
|
|||
},
|
||||
});
|
||||
|
||||
// Example 1:
|
||||
|
||||
/* csslint ignore:start */
|
||||
// the chunk of code where errors won't be reported
|
||||
// the chunk's start is hardwired to the line of the opening comment
|
||||
// the chunk's end is hardwired to the line of the closing comment
|
||||
/* csslint ignore:end */
|
||||
|
||||
// Example 2:
|
||||
|
||||
/* csslint allow:rulename1,rulename2,... */
|
||||
// allows to break the specified rules on the next single line of code
|
||||
|
||||
// Example 3:
|
||||
|
||||
/* csslint rulename1 */
|
||||
/* csslint rulename2:N */
|
||||
/* csslint rulename3:N, rulename4:N */
|
||||
|
||||
// entire code is affected;
|
||||
// comments futher down the code extend/override previous comments of this kind
|
||||
// values for N:
|
||||
// "2" or "true" means "error"
|
||||
// "1" or nothing means "warning" - note in this case ":" can also be omitted
|
||||
// "0" or "false" means "ignore"
|
||||
// (the quotes are added here for convenience, don't put them in the actual comments)
|
||||
|
||||
function applyEmbeddedOverrides(text, ruleset, allow, ignore) {
|
||||
let ignoreStart = null;
|
||||
let ignoreEnd = null;
|
||||
let lineno = 0;
|
||||
let eol = -1;
|
||||
let m;
|
||||
|
||||
for (let eol = 0, m; (m = RX_EMBEDDED.exec(text)); lineno++) {
|
||||
eol = (text.indexOf('\n', eol) + 1 || text.length + 1) - 1;
|
||||
if (eol < m.index) continue;
|
||||
while ((m = RX_EMBEDDED.exec(text))) {
|
||||
// account for the lines between the previous and current match
|
||||
while (eol <= m.index) {
|
||||
eol = text.indexOf('\n', eol + 1);
|
||||
if (eol < 0) eol = text.length;
|
||||
lineno++;
|
||||
}
|
||||
|
||||
const ovr = m[1].toLowerCase();
|
||||
const cmd = ovr.split(':', 1);
|
||||
const cmd = ovr.split(':', 1)[0];
|
||||
const i = cmd.length + 1;
|
||||
|
||||
switch (cmd.trim()) {
|
||||
|
@ -246,15 +287,13 @@ var CSSLint = (() => {
|
|||
}
|
||||
|
||||
case 'ignore':
|
||||
if (ovr.lastIndexOf('start', i) > 0) {
|
||||
if (ignoreStart === null) {
|
||||
ignoreStart = lineno;
|
||||
}
|
||||
if (ovr.includes('start')) {
|
||||
ignoreStart = ignoreStart || lineno;
|
||||
break;
|
||||
}
|
||||
if (ovr.lastIndexOf('end', i) > 0) {
|
||||
if (ovr.includes('end')) {
|
||||
ignoreEnd = lineno;
|
||||
if (ignoreStart !== null && ignoreEnd !== null) {
|
||||
if (ignoreStart && ignoreEnd) {
|
||||
ignore.push([ignoreStart, ignoreEnd]);
|
||||
ignoreStart = ignoreEnd = null;
|
||||
}
|
||||
|
@ -273,7 +312,7 @@ var CSSLint = (() => {
|
|||
}
|
||||
|
||||
// Close remaining ignore block, if any
|
||||
if (ignoreStart !== null) {
|
||||
if (ignoreStart) {
|
||||
ignore.push([ignoreStart, lineno]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -194,6 +194,7 @@ self.parserlib = (() => {
|
|||
'border-bottom-right-radius': '<x-one-radius>',
|
||||
'border-bottom-style': '<border-style>',
|
||||
'border-bottom-width': '<border-width>',
|
||||
'border-boundary': 'none | parent | display',
|
||||
'border-inline-color': '<color>{1,2}',
|
||||
'border-inline-end': '<border-shorthand>',
|
||||
'border-inline-end-color': '<color>',
|
||||
|
@ -467,6 +468,7 @@ self.parserlib = (() => {
|
|||
'marquee-speed': 1,
|
||||
'marquee-style': 1,
|
||||
'mask': 1,
|
||||
'mask-image': '[ none | <image> | <uri> ]#',
|
||||
'max-height': 'none | <width-height>',
|
||||
'max-width': 'none | <width-height>',
|
||||
'min-height': 'auto | <width-height>',
|
||||
|
@ -496,7 +498,9 @@ self.parserlib = (() => {
|
|||
'outline-offset': '<length>',
|
||||
'outline-style': '<border-style> | auto',
|
||||
'outline-width': '<border-width>',
|
||||
'overflow': '<overflow>',
|
||||
'overflow': '<overflow>{1,2}',
|
||||
'overflow-block': '<overflow>',
|
||||
'overflow-inline': '<overflow>',
|
||||
'overflow-style': 1,
|
||||
'overflow-wrap': 'normal | break-word',
|
||||
'overflow-x': '<overflow>',
|
||||
|
@ -549,7 +553,7 @@ self.parserlib = (() => {
|
|||
'rest-before': 1,
|
||||
'richness': 1,
|
||||
'right': '<width>',
|
||||
'rotate': 'none | <number>{3}? <angle>',
|
||||
'rotate': 'none | [ x | y | z | <number>{3} ]? && <angle>',
|
||||
'rotation': 1,
|
||||
'rotation-point': 1,
|
||||
'row-gap': '<row-gap>',
|
||||
|
@ -560,6 +564,7 @@ self.parserlib = (() => {
|
|||
|
||||
// S
|
||||
'scale': 'none | <number>{1,3}',
|
||||
'shape-inside': 'auto | outside-shape | [ <basic-shape> || shape-box ] | <image> | display',
|
||||
'shape-rendering': 'auto | optimizeSpeed | crispEdges | geometricPrecision',
|
||||
'size': 1,
|
||||
'speak': 'normal | none | spell-out',
|
||||
|
@ -598,15 +603,18 @@ self.parserlib = (() => {
|
|||
'text-decoration-skip': 'none | [ objects || [ spaces | [ leading-spaces || trailing-spaces ] ] || ' +
|
||||
'edges || box-decoration ]',
|
||||
'text-decoration-style': '<text-decoration-style>',
|
||||
'text-emphasis': 1,
|
||||
'text-emphasis': '<text-emphasis-style> || <color>',
|
||||
'text-emphasis-style': '<text-emphasis-style>',
|
||||
'text-emphasis-position': '[ over | under ] && [ right | left ]?',
|
||||
'text-height': 1,
|
||||
'text-indent': '<length> | <percentage>',
|
||||
'text-justify': 'auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida',
|
||||
'text-outline': 1,
|
||||
'text-overflow': 'clip | ellipsis',
|
||||
'text-rendering': 'auto | optimizeSpeed | optimizeLegibility | geometricPrecision',
|
||||
'text-shadow': 'none | [ [ <color> && <length>{2,3} ] | <length>{2,3} ]#',
|
||||
'text-shadow': 'none | [ <color>? && <length>{2,3} ]#',
|
||||
'text-transform': 'capitalize | uppercase | lowercase | none',
|
||||
'text-underline-position': 'auto | [ under || [ left | right ] ]',
|
||||
'text-wrap': 'normal | none | avoid',
|
||||
'top': '<width>',
|
||||
'touch-action': 'auto | none | pan-x | pan-y | pan-left | pan-right | pan-up | pan-down | manipulation',
|
||||
|
@ -689,7 +697,7 @@ self.parserlib = (() => {
|
|||
|
||||
'<basic-shape>': 'inset() | circle() | ellipse() | polygon()',
|
||||
|
||||
'<bg-image>': '<image> | <gradient> | none',
|
||||
'<bg-image>': '<image> | none',
|
||||
|
||||
'<blend-mode>': 'normal | multiply | screen | overlay | darken | lighten | color-dodge | ' +
|
||||
'color-burn | hard-light | soft-light | difference | exclusion | hue | ' +
|
||||
|
@ -773,7 +781,7 @@ self.parserlib = (() => {
|
|||
return this['<ident>'](part) && !this['<generic-family>'](part);
|
||||
},
|
||||
|
||||
'<image>': '<uri>',
|
||||
'<image>': '<uri> | <gradient> | cross-fade()',
|
||||
|
||||
'<inflexible-breadth>': '<length-percentage> | min-content | max-content | auto',
|
||||
|
||||
|
@ -832,7 +840,7 @@ self.parserlib = (() => {
|
|||
return this['<number>'](part) && part.value >= 0 && part.value <= 1;
|
||||
},
|
||||
|
||||
'<overflow>': 'visible | hidden | scroll | auto',
|
||||
'<overflow>': 'visible | hidden | clip | scroll | auto',
|
||||
|
||||
'<overflow-position>': 'unsafe | safe',
|
||||
|
||||
|
@ -882,12 +890,15 @@ self.parserlib = (() => {
|
|||
if (part.tokenType === Tokens.USO_VAR) return true;
|
||||
if (part.type !== 'function' || !part.expr) return false;
|
||||
const subparts = part.expr.parts;
|
||||
return subparts.length &&
|
||||
lower(part.name) === 'var' &&
|
||||
subparts[0].type === 'custom-property' && (
|
||||
subparts.length === 1 ||
|
||||
subparts[1].text === ','
|
||||
);
|
||||
if (!subparts.length) return false;
|
||||
const name = lower(part.name);
|
||||
return (
|
||||
name === 'var' && subparts[0].type === 'custom-property' ||
|
||||
name === 'env' && subparts[0].type === 'identifier'
|
||||
) && (
|
||||
subparts.length === 1 ||
|
||||
subparts[1].text === ','
|
||||
);
|
||||
},
|
||||
|
||||
'<width>': '<length> | <percentage> | auto',
|
||||
|
@ -1039,18 +1050,16 @@ self.parserlib = (() => {
|
|||
'<hsl-color>': '[ <number> | <angle> ] <percentage>{2} [ / <nonnegative-number-or-percentage> ]? | ' +
|
||||
'[ <number> | <angle> ] , <percentage>#{2} [ , <nonnegative-number-or-percentage> ]?',
|
||||
|
||||
// inset? && [ <length>{2,4} && <color>? ]
|
||||
'<shadow>': Matcher =>
|
||||
Matcher.many(
|
||||
[true],
|
||||
Matcher.cast('<length>').braces(2, 4),
|
||||
'inset',
|
||||
'<color>'),
|
||||
'<shadow>': 'inset? && [ <length>{2,4} && <color>? ]',
|
||||
|
||||
'<single-timing-function>': 'linear | <cubic-bezier-timing-function> | <step-timing-function> | frames()',
|
||||
|
||||
'<text-decoration-line>': 'none | [ underline || overline || line-through || blink ]',
|
||||
|
||||
'<text-emphasis-style>': 'none | ' +
|
||||
'[ [ filled | open ] || [ dot | circle | double-circle | triangle | sesame ] ] | ' +
|
||||
'<string>',
|
||||
|
||||
'<track-list>': '[ <line-names>? [ <track-size> | <track-repeat> ] ]+ <line-names>?',
|
||||
|
||||
'<track-repeat>': 'repeat( [ <positive-integer> ] , [ <line-names>? <track-size> ]+ <line-names>? )',
|
||||
|
@ -1408,6 +1417,7 @@ self.parserlib = (() => {
|
|||
{name: 'NOT'},
|
||||
{name: 'ANY', text: ['any', '-webkit-any', '-moz-any']},
|
||||
{name: 'MATCHES'},
|
||||
{name: 'IS'},
|
||||
|
||||
/*
|
||||
* Defined in CSS3 Paged Media
|
||||
|
@ -1881,7 +1891,8 @@ self.parserlib = (() => {
|
|||
const p = required === false ? Matcher.prec.OROR : Matcher.prec.ANDAND;
|
||||
const s = ms.map((m, i) => {
|
||||
if (required !== false && !required[i]) {
|
||||
return m.toString(Matcher.prec.MOD) + '?';
|
||||
const str = m.toString(Matcher.prec.MOD);
|
||||
return str.endsWith('?') ? str : str + '?';
|
||||
}
|
||||
return m.toString(p);
|
||||
}).join(required === false ? ' || ' : ' && ');
|
||||
|
@ -1919,10 +1930,22 @@ self.parserlib = (() => {
|
|||
function andand() {
|
||||
// andand = seq ( " && " seq)*
|
||||
const m = [seq()];
|
||||
let reqPrev = !isOptional(m[0]);
|
||||
const required = [reqPrev];
|
||||
while (reader.readMatch(' && ')) {
|
||||
m.push(seq());
|
||||
const item = seq();
|
||||
const req = !isOptional(item);
|
||||
// Matcher.many apparently can't handle optional items first
|
||||
if (req && !reqPrev) {
|
||||
m.unshift(item);
|
||||
required.unshift(req);
|
||||
} else {
|
||||
m.push(item);
|
||||
required.push(req);
|
||||
reqPrev = req;
|
||||
}
|
||||
}
|
||||
return m.length === 1 ? m[0] : Matcher.andand.apply(Matcher, m);
|
||||
return m.length === 1 ? m[0] : Matcher.many(required, ...m);
|
||||
}
|
||||
|
||||
function seq() {
|
||||
|
@ -1977,6 +2000,10 @@ self.parserlib = (() => {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function isOptional(item) {
|
||||
return !Array.isArray(item.options) && item.toString().endsWith('?');
|
||||
}
|
||||
})();
|
||||
|
||||
//endregion
|
||||
|
@ -2663,7 +2690,7 @@ self.parserlib = (() => {
|
|||
known.add(value.text);
|
||||
|
||||
function throwEndExpected(token, force) {
|
||||
if (force || token.name !== 'var' || token.type !== 'function') {
|
||||
if (force || (token.name !== 'var' && token.name !== 'env') || token.type !== 'function') {
|
||||
throw new ValidationError(`Expected end of value but found '${token.text}'.`, token);
|
||||
}
|
||||
}
|
||||
|
@ -3012,11 +3039,13 @@ self.parserlib = (() => {
|
|||
/*
|
||||
* Potential tokens:
|
||||
* - ANY
|
||||
* - IS
|
||||
* - MATCHES
|
||||
* - NOT
|
||||
* - CHAR
|
||||
*/
|
||||
case ':':
|
||||
return this.notOrAnyOrMatchesToken(c, pos);
|
||||
return this.notOrIsToken(c, pos);
|
||||
|
||||
/*
|
||||
* Potential tokens:
|
||||
|
@ -3224,16 +3253,20 @@ self.parserlib = (() => {
|
|||
}
|
||||
|
||||
// NOT
|
||||
// IS
|
||||
// ANY
|
||||
// MATCHES
|
||||
// CHAR
|
||||
notOrAnyOrMatchesToken(first, pos) {
|
||||
notOrIsToken(first, pos) {
|
||||
// first is always ':'
|
||||
const reader = this._reader;
|
||||
const func = reader.readMatch(/(not|(-(moz|webkit)-)?any|matches)\(/iy);
|
||||
const func = reader.readMatch(/(not|is|(-(moz|webkit)-)?(any|matches))\(/iy);
|
||||
if (func) {
|
||||
const lcase = func[0].toLowerCase();
|
||||
const type =
|
||||
func.startsWith('n') || func.startsWith('N') ? Tokens.NOT :
|
||||
func.startsWith('m') || func.startsWith('M') ? Tokens.MATCHES : Tokens.ANY;
|
||||
lcase === 'n' ? Tokens.NOT :
|
||||
lcase === 'i' ? Tokens.IS :
|
||||
lcase === 'm' ? Tokens.MATCHES : Tokens.ANY;
|
||||
return this.createToken(type, first + func, pos);
|
||||
}
|
||||
return this.charToken(first, pos);
|
||||
|
@ -4239,14 +4272,25 @@ self.parserlib = (() => {
|
|||
|
||||
_viewport() {
|
||||
const stream = this._tokenStream;
|
||||
stream.mustMatch(Tokens.VIEWPORT_SYM);
|
||||
const start = stream.mustMatch(Tokens.VIEWPORT_SYM);
|
||||
|
||||
this.fire('startviewport');
|
||||
// only viewport-fit is allowed but we're reusing MediaQuery syntax unit,
|
||||
// and accept anything for the sake of simplicity since the spec isn't yet final:
|
||||
// https://drafts.csswg.org/css-round-display/#extending-viewport-rule
|
||||
const descriptors = this._mediaQueryList();
|
||||
|
||||
this.fire({
|
||||
type: 'startviewport',
|
||||
descriptors,
|
||||
}, start);
|
||||
|
||||
this._ws();
|
||||
this._readDeclarations();
|
||||
|
||||
this.fire('endviewport');
|
||||
this.fire({
|
||||
type: 'endviewport',
|
||||
descriptors,
|
||||
});
|
||||
}
|
||||
|
||||
_document() {
|
||||
|
@ -4664,13 +4708,13 @@ self.parserlib = (() => {
|
|||
return value.length ? value : null;
|
||||
}
|
||||
|
||||
_anyOrMatches() {
|
||||
_is() {
|
||||
const stream = this._tokenStream;
|
||||
if (!stream.match([Tokens.ANY, Tokens.MATCHES])) return null;
|
||||
if (!stream.match([Tokens.IS, Tokens.ANY, Tokens.MATCHES])) return null;
|
||||
|
||||
let arg;
|
||||
const start = stream._token;
|
||||
const type = start.type === Tokens.ANY ? 'any' : 'matches';
|
||||
const type = lower(Tokens[start.type].name);
|
||||
const value =
|
||||
start.value +
|
||||
this._ws() +
|
||||
|
@ -5380,6 +5424,7 @@ self.parserlib = (() => {
|
|||
[Tokens.MEDIA_SYM, Parser.prototype._media],
|
||||
[Tokens.SUPPORTS_SYM, Parser.prototype._supports],
|
||||
[Tokens.DOCUMENT_SYM, Parser.prototype._documentMisplaced],
|
||||
[Tokens.VIEWPORT_SYM, Parser.prototype._viewport],
|
||||
]),
|
||||
|
||||
media: new Map([
|
||||
|
@ -5396,8 +5441,9 @@ self.parserlib = (() => {
|
|||
[Tokens.DOT, Parser.prototype._class],
|
||||
[Tokens.LBRACKET, Parser.prototype._attrib],
|
||||
[Tokens.COLON, Parser.prototype._pseudo],
|
||||
[Tokens.ANY, Parser.prototype._anyOrMatches],
|
||||
[Tokens.MATCHES, Parser.prototype._anyOrMatches],
|
||||
[Tokens.IS, Parser.prototype._is],
|
||||
[Tokens.ANY, Parser.prototype._is],
|
||||
[Tokens.MATCHES, Parser.prototype._is],
|
||||
[Tokens.NOT, Parser.prototype._negation],
|
||||
]),
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user