Merge branch 'master' of https://github.com/openstyles/stylus
This commit is contained in:
commit
f580c10e85
|
@ -55,7 +55,8 @@ globals:
|
||||||
animateElement: false
|
animateElement: false
|
||||||
$: false
|
$: false
|
||||||
$$: false
|
$$: false
|
||||||
$element: false
|
$create: false
|
||||||
|
$createLink: false
|
||||||
# prefs.js
|
# prefs.js
|
||||||
prefs: false
|
prefs: false
|
||||||
setupLivePrefs: false
|
setupLivePrefs: false
|
||||||
|
@ -236,7 +237,7 @@ rules:
|
||||||
one-var: [0]
|
one-var: [0]
|
||||||
operator-assignment: [2, always]
|
operator-assignment: [2, always]
|
||||||
operator-linebreak: [2, after, overrides: {"?": ignore, ":": ignore, "&&": ignore, "||": ignore}]
|
operator-linebreak: [2, after, overrides: {"?": ignore, ":": ignore, "&&": ignore, "||": ignore}]
|
||||||
padded-blocks: [2, never]
|
padded-blocks: [0]
|
||||||
prefer-numeric-literals: [2]
|
prefer-numeric-literals: [2]
|
||||||
prefer-rest-params: [0]
|
prefer-rest-params: [0]
|
||||||
prefer-const: [1, {destructuring: any, ignoreReadBeforeAssign: true}]
|
prefer-const: [1, {destructuring: any, ignoreReadBeforeAssign: true}]
|
||||||
|
|
|
@ -377,6 +377,10 @@
|
||||||
"message": "Open this style on userstyles.org to customize via 'Advanced Style Settings'",
|
"message": "Open this style on userstyles.org to customize via 'Advanced Style Settings'",
|
||||||
"description": "Tooltip for a button that opens style on userstyles.org for customizing"
|
"description": "Tooltip for a button that opens style on userstyles.org for customizing"
|
||||||
},
|
},
|
||||||
|
"filteredStylesAllHidden": {
|
||||||
|
"message": "Currently applied filters match no styles",
|
||||||
|
"description": "Text shown when no styles match currently applied filter in the style manager"
|
||||||
|
},
|
||||||
"findStylesForSite": {
|
"findStylesForSite": {
|
||||||
"message": "Find styles",
|
"message": "Find styles",
|
||||||
"description": "Text for a link that gets a list of styles for the current site"
|
"description": "Text for a link that gets a list of styles for the current site"
|
||||||
|
@ -774,6 +778,10 @@
|
||||||
"message": "Invalid regexps skipped",
|
"message": "Invalid regexps skipped",
|
||||||
"description": "RegExp test report: label for the invalid expressions"
|
"description": "RegExp test report: label for the invalid expressions"
|
||||||
},
|
},
|
||||||
|
"styleRegexpTestNote": {
|
||||||
|
"message": "Note: use a single \\ for escaping in the regexp input field, which will be automatically converted to \\\\ in the style code as per specification for quoted strings in CSS.",
|
||||||
|
"description": "RegExp test report: a note displayed at the bottom of the dialog"
|
||||||
|
},
|
||||||
"styleRegexpPartialExplanation": {
|
"styleRegexpPartialExplanation": {
|
||||||
"message": "This style uses partially matching regexps in violation of <a href='https://developer.mozilla.org/docs/Web/CSS/@document'>CSS4 @document specification</a> which requires a full URL match. The affected CSS sections were not applied to the page. This style was probably created in Stylish-for-Chrome which incorrectly checks 'regexp()' rules since the very first version (known bug)."
|
"message": "This style uses partially matching regexps in violation of <a href='https://developer.mozilla.org/docs/Web/CSS/@document'>CSS4 @document specification</a> which requires a full URL match. The affected CSS sections were not applied to the page. This style was probably created in Stylish-for-Chrome which incorrectly checks 'regexp()' rules since the very first version (known bug)."
|
||||||
},
|
},
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
"description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)"
|
"description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)"
|
||||||
},
|
},
|
||||||
"installButton": {
|
"installButton": {
|
||||||
"message": "安裝",
|
"message": "安裝樣式",
|
||||||
"description": "Label for install button"
|
"description": "Label for install button"
|
||||||
},
|
},
|
||||||
"styleMetaErrorCheckbox": {
|
"styleMetaErrorCheckbox": {
|
||||||
|
@ -47,6 +47,10 @@
|
||||||
"message": "無效的 JSON 格式",
|
"message": "無效的 JSON 格式",
|
||||||
"description": "Setting linter config with invalid JSON"
|
"description": "Setting linter config with invalid JSON"
|
||||||
},
|
},
|
||||||
|
"popupHotkeysTooltip": {
|
||||||
|
"message": "點選以檢視可用的快捷鍵",
|
||||||
|
"description": "Tooltip displayed when hovering the right edge of the extension popup"
|
||||||
|
},
|
||||||
"optionsBadgeNormal": {
|
"optionsBadgeNormal": {
|
||||||
"message": "背景顏色",
|
"message": "背景顏色",
|
||||||
"description": ""
|
"description": ""
|
||||||
|
@ -330,6 +334,10 @@
|
||||||
"message": "顯示生效的樣式數目",
|
"message": "顯示生效的樣式數目",
|
||||||
"description": "Label (must be very short) for the checkbox in the toolbar button context menu controlling toolbar badge text."
|
"description": "Label (must be very short) for the checkbox in the toolbar button context menu controlling toolbar badge text."
|
||||||
},
|
},
|
||||||
|
"popupHotkeysInfo": {
|
||||||
|
"message": "<1>-<9>、<0>,數字鍵盤也可以 — 切換第 N 個樣式(0 是切換到第 10 個)\n<A>-<Z> 切換以該字母為名稱第一個字的樣式\n<Shift> 開啟編輯器而非切換\n<Numpad +> 啟用列出的樣式\n<Numpad –> 停用列出的樣式\n<Numpad *> 與 <`> (倒引號)— 切換初始啟用的樣式;不要在彈出式視窗開啟時套用到後來啟用的樣式,這樣您就可以在測試完後復原初始選擇:僅停用全部,然後切換。<Numpad –> <Numpad *>\n更多資訊請見 wiki",
|
||||||
|
"description": "NOTE1: preserve < and > symbols so that <hotkey> is styled as a key.\nNOTE2: the last line is displayed as a text of the link to the wiki page.\nNOTE3: this is the list of hotkeys displayed after clicking the right edge of the extension popup."
|
||||||
|
},
|
||||||
"cm_lineWrapping": {
|
"cm_lineWrapping": {
|
||||||
"message": "自動換行",
|
"message": "自動換行",
|
||||||
"description": "Label for the checkbox controlling word wrap option for the style editor."
|
"description": "Label for the checkbox controlling word wrap option for the style editor."
|
||||||
|
@ -934,7 +942,7 @@
|
||||||
"description": "Label for the checkbox in the style editor."
|
"description": "Label for the checkbox in the style editor."
|
||||||
},
|
},
|
||||||
"installButtonReinstall": {
|
"installButtonReinstall": {
|
||||||
"message": "重新安裝",
|
"message": "重新安裝樣式",
|
||||||
"description": "Label for reinstall button"
|
"description": "Label for reinstall button"
|
||||||
},
|
},
|
||||||
"linterInvalidConfigError": {
|
"linterInvalidConfigError": {
|
||||||
|
@ -1036,7 +1044,7 @@
|
||||||
"description": ""
|
"description": ""
|
||||||
},
|
},
|
||||||
"installButtonUpdate": {
|
"installButtonUpdate": {
|
||||||
"message": "更新",
|
"message": "更新樣式",
|
||||||
"description": "Label for update button"
|
"description": "Label for update button"
|
||||||
},
|
},
|
||||||
"backupButtons": {
|
"backupButtons": {
|
||||||
|
@ -1052,7 +1060,7 @@
|
||||||
"description": "Label for the button to go to the edit style page"
|
"description": "Label for the button to go to the edit style page"
|
||||||
},
|
},
|
||||||
"installButtonInstalled": {
|
"installButtonInstalled": {
|
||||||
"message": "已安裝",
|
"message": "樣式已安裝",
|
||||||
"description": "Text displayed when the style is successfully installed"
|
"description": "Text displayed when the style is successfully installed"
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
|
|
|
@ -238,6 +238,9 @@ function getStyles(options) {
|
||||||
cachedStyles.byId.clear();
|
cachedStyles.byId.clear();
|
||||||
for (const style of cachedStyles.list) {
|
for (const style of cachedStyles.list) {
|
||||||
cachedStyles.byId.set(style.id, style);
|
cachedStyles.byId.set(style.id, style);
|
||||||
|
if (!style.name) {
|
||||||
|
style.name = 'ID: ' + style.id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedStyles.mutex.inProgress = false;
|
cachedStyles.mutex.inProgress = false;
|
||||||
|
|
|
@ -56,26 +56,26 @@ var updater = {
|
||||||
|
|
||||||
'ignoreDigest' option is set on the second manual individual update check on the manage page.
|
'ignoreDigest' option is set on the second manual individual update check on the manage page.
|
||||||
*/
|
*/
|
||||||
const maybeUpdate = style.usercssData ? maybeUpdateUsercss : maybeUpdateUSO;
|
return Promise.resolve(style)
|
||||||
return (ignoreDigest ? Promise.resolve() : calcStyleDigest(style))
|
.then([calcStyleDigest][!ignoreDigest ? 0 : 'skip'])
|
||||||
.then(checkIfEdited)
|
.then([checkIfEdited][!ignoreDigest ? 0 : 'skip'])
|
||||||
.then(maybeUpdate)
|
.then([maybeUpdateUSO, maybeUpdateUsercss][style.usercssData ? 1 : 0])
|
||||||
.then(maybeValidate)
|
|
||||||
.then(maybeSave)
|
.then(maybeSave)
|
||||||
.then(saved => {
|
.then(reportSuccess)
|
||||||
|
.catch(reportFailure);
|
||||||
|
|
||||||
|
function reportSuccess(saved) {
|
||||||
observer(updater.UPDATED, saved);
|
observer(updater.UPDATED, saved);
|
||||||
updater.log(updater.UPDATED + ` #${saved.id} ${saved.name}`);
|
updater.log(updater.UPDATED + ` #${saved.id} ${saved.name}`);
|
||||||
})
|
}
|
||||||
.catch(err => {
|
|
||||||
|
function reportFailure(err) {
|
||||||
observer(updater.SKIPPED, style, err);
|
observer(updater.SKIPPED, style, err);
|
||||||
err = err === 0 ? 'server unreachable' : err;
|
err = err === 0 ? 'server unreachable' : err;
|
||||||
updater.log(updater.SKIPPED + ` (${err}) #${style.id} ${style.name}`);
|
updater.log(updater.SKIPPED + ` (${err}) #${style.id} ${style.name}`);
|
||||||
});
|
}
|
||||||
|
|
||||||
function checkIfEdited(digest) {
|
function checkIfEdited(digest) {
|
||||||
if (ignoreDigest) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (style.originalDigest && style.originalDigest !== digest) {
|
if (style.originalDigest && style.originalDigest !== digest) {
|
||||||
return Promise.reject(updater.EDITED);
|
return Promise.reject(updater.EDITED);
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,7 @@ var updater = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function maybeUpdateUsercss() {
|
function maybeUpdateUsercss() {
|
||||||
|
// TODO: when sourceCode is > 100kB use http range request(s) for version check
|
||||||
return download(style.updateUrl).then(text => {
|
return download(style.updateUrl).then(text => {
|
||||||
const json = usercss.buildMeta(text);
|
const json = usercss.buildMeta(text);
|
||||||
const {usercssData: {version}} = style;
|
const {usercssData: {version}} = style;
|
||||||
|
@ -104,6 +105,8 @@ var updater = {
|
||||||
// re-install is invalid in a soft upgrade
|
// re-install is invalid in a soft upgrade
|
||||||
if (!ignoreDigest) {
|
if (!ignoreDigest) {
|
||||||
return Promise.reject(updater.SAME_VERSION);
|
return Promise.reject(updater.SAME_VERSION);
|
||||||
|
} else if (text === style.sourceCode) {
|
||||||
|
return Promise.reject(updater.SAME_CODE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -114,38 +117,31 @@ var updater = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function maybeValidate(json) {
|
function maybeSave(json = {}) {
|
||||||
if (json.usercssData) {
|
|
||||||
// usercss is already validated while building
|
// usercss is already validated while building
|
||||||
return json;
|
if (!json.usercssData && !styleJSONseemsValid(json)) {
|
||||||
}
|
|
||||||
if (!styleJSONseemsValid(json)) {
|
|
||||||
return Promise.reject(updater.ERROR_JSON);
|
return Promise.reject(updater.ERROR_JSON);
|
||||||
}
|
}
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
function maybeSave(json) {
|
|
||||||
json.id = style.id;
|
json.id = style.id;
|
||||||
json.updateDate = Date.now();
|
json.updateDate = Date.now();
|
||||||
|
json.reason = 'update';
|
||||||
|
// keep current state
|
||||||
|
delete json.enabled;
|
||||||
|
// keep local name customizations
|
||||||
|
delete json.name;
|
||||||
|
|
||||||
if (styleSectionsEqual(json, style)) {
|
if (styleSectionsEqual(json, style)) {
|
||||||
// JSONs may have different order of items even if sections are effectively equal
|
// update digest even if save === false as there might be just a space added etc.
|
||||||
// so we'll update the digest anyway
|
|
||||||
// always update digest even if (save === false)
|
|
||||||
saveStyle(Object.assign(json, {reason: 'update-digest'}));
|
saveStyle(Object.assign(json, {reason: 'update-digest'}));
|
||||||
return Promise.reject(updater.SAME_CODE);
|
return Promise.reject(updater.SAME_CODE);
|
||||||
} else if (!style.originalDigest && !ignoreDigest) {
|
} else if (!style.originalDigest && !ignoreDigest) {
|
||||||
return Promise.reject(updater.MAYBE_EDITED);
|
return Promise.reject(updater.MAYBE_EDITED);
|
||||||
}
|
}
|
||||||
if (!save) {
|
|
||||||
return json;
|
return !save ? json :
|
||||||
}
|
json.usercssData
|
||||||
json.reason = 'update';
|
? usercssHelper.save(json)
|
||||||
if (json.usercssData) {
|
: saveStyle(json);
|
||||||
return usercssHelper.save(json);
|
|
||||||
}
|
|
||||||
json.name = null; // keep local name customizations
|
|
||||||
return saveStyle(json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function styleJSONseemsValid(json) {
|
function styleJSONseemsValid(json) {
|
||||||
|
|
|
@ -386,6 +386,7 @@
|
||||||
let restorationCounter = 0;
|
let restorationCounter = 0;
|
||||||
let observing = false;
|
let observing = false;
|
||||||
let sorting = false;
|
let sorting = false;
|
||||||
|
let timer;
|
||||||
// allow any types of elements between ours, except for the following:
|
// allow any types of elements between ours, except for the following:
|
||||||
const ORDERED_TAGS = ['head', 'body', 'style', 'link'];
|
const ORDERED_TAGS = ['head', 'body', 'style', 'link'];
|
||||||
|
|
||||||
|
@ -395,6 +396,10 @@
|
||||||
function init() {
|
function init() {
|
||||||
docRootObserver = new MutationObserver(sortStyleElements);
|
docRootObserver = new MutationObserver(sortStyleElements);
|
||||||
Object.assign(docRootObserver, {start, stop});
|
Object.assign(docRootObserver, {start, stop});
|
||||||
|
if (!chrome.app) {
|
||||||
|
// compensate for Firefox missing a step when loading the tab in background
|
||||||
|
setTimeout(sortStyleElements);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function start({sort = false} = {}) {
|
function start({sort = false} = {}) {
|
||||||
if (sort && sortStyleMap()) {
|
if (sort && sortStyleMap()) {
|
||||||
|
@ -453,8 +458,8 @@
|
||||||
if (sorting) {
|
if (sorting) {
|
||||||
sorting = false;
|
sorting = false;
|
||||||
docRootObserver.takeRecords();
|
docRootObserver.takeRecords();
|
||||||
setTimeout(start);
|
clearTimeout(timer);
|
||||||
//docRootObserver.start();
|
timer = setTimeout(start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function isMovable(el) {
|
function isMovable(el) {
|
||||||
|
|
73
edit.html
73
edit.html
|
@ -3,6 +3,9 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="global.css">
|
||||||
|
<link rel="stylesheet" href="edit/edit.css">
|
||||||
|
|
||||||
<style id="firefox-transitions-bug-suppressor">
|
<style id="firefox-transitions-bug-suppressor">
|
||||||
/* restrict to FF */
|
/* restrict to FF */
|
||||||
@supports (-moz-appearance:none) {
|
@supports (-moz-appearance:none) {
|
||||||
|
@ -21,7 +24,6 @@
|
||||||
<script src="js/script-loader.js"></script>
|
<script src="js/script-loader.js"></script>
|
||||||
<script src="js/moz-parser.js"></script>
|
<script src="js/moz-parser.js"></script>
|
||||||
<script src="content/apply.js"></script>
|
<script src="content/apply.js"></script>
|
||||||
<link rel="stylesheet" href="edit/edit.css">
|
|
||||||
<script src="edit/lint.js"></script>
|
<script src="edit/lint.js"></script>
|
||||||
<script src="edit/util.js"></script>
|
<script src="edit/util.js"></script>
|
||||||
<script src="edit/regexp-tester.js"></script>
|
<script src="edit/regexp-tester.js"></script>
|
||||||
|
@ -70,17 +72,19 @@
|
||||||
<script src="edit/codemirror-default.js"></script>
|
<script src="edit/codemirror-default.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/edit/codemirror-default.css">
|
<link rel="stylesheet" href="/edit/codemirror-default.css">
|
||||||
<link id="cm-theme" rel="stylesheet">
|
|
||||||
|
|
||||||
<template data-id="appliesTo">
|
<template data-id="appliesTo">
|
||||||
<li>
|
<li>
|
||||||
|
<div class="select-resizer">
|
||||||
<select name="applies-type" class="applies-type style-contributor">
|
<select name="applies-type" class="applies-type style-contributor">
|
||||||
<option value="url" i18n-text="appliesUrlOption"></option>
|
<option value="url" i18n-text="appliesUrlOption"></option>
|
||||||
<option value="url-prefix" i18n-text="appliesUrlPrefixOption"></option>
|
<option value="url-prefix" i18n-text="appliesUrlPrefixOption"></option>
|
||||||
<option value="domain" i18n-text="appliesDomainOption"></option>
|
<option value="domain" i18n-text="appliesDomainOption"></option>
|
||||||
<option value="regexp" i18n-text="appliesRegexpOption"></option>
|
<option value="regexp" i18n-text="appliesRegexpOption"></option>
|
||||||
</select>
|
</select>
|
||||||
<input name="applies-value" class="applies-value style-contributor">
|
<svg class="svg-icon select-arrow"><use xlink:href="#svg-icon-select-arrow"/></svg>
|
||||||
|
</div>
|
||||||
|
<input name="applies-value" class="applies-value style-contributor" spellcheck="false">
|
||||||
<button class="remove-applies-to" i18n-text="appliesRemove"></button>
|
<button class="remove-applies-to" i18n-text="appliesRemove"></button>
|
||||||
<button class="add-applies-to" i18n-text="appliesAdd"></button>
|
<button class="add-applies-to" i18n-text="appliesAdd"></button>
|
||||||
</li>
|
</li>
|
||||||
|
@ -157,7 +161,7 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><input i18n-placeholder="helpKeyMapHotkey" type="search" class="can-close-on-esc"></th>
|
<th><input i18n-placeholder="helpKeyMapHotkey" type="search" class="can-close-on-esc"></th>
|
||||||
<th><input i18n-placeholder="helpKeyMapCommand" type="search" class="can-close-on-esc"></th>
|
<th><input i18n-placeholder="helpKeyMapCommand" type="search" class="can-close-on-esc" spellcheck="false"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -179,8 +183,10 @@
|
||||||
<a id="url" target="_blank"><svg class="svg-icon"><use xlink:href="#svg-icon-external-link"/></svg></a>
|
<a id="url" target="_blank"><svg class="svg-icon"><use xlink:href="#svg-icon-external-link"/></svg></a>
|
||||||
</div>
|
</div>
|
||||||
<div id="basic-info-enabled">
|
<div id="basic-info-enabled">
|
||||||
|
<label id="enabled-label" i18n-text="styleEnabledLabel">
|
||||||
<input type="checkbox" id="enabled" class="style-contributor">
|
<input type="checkbox" id="enabled" class="style-contributor">
|
||||||
<label for="enabled" id="enabled-label" i18n-text="styleEnabledLabel"></label><!--
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</label><!--
|
||||||
--><svg id="toggle-style-help" class="svg-icon info">
|
--><svg id="toggle-style-help" class="svg-icon info">
|
||||||
<use xlink:href="#svg-icon-help"/>
|
<use xlink:href="#svg-icon-help"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -201,30 +207,40 @@
|
||||||
<details id="options" data-pref="editor.options.expanded">
|
<details id="options" data-pref="editor.options.expanded">
|
||||||
<summary><h2 id="options-heading" i18n-text="optionsHeading"></h2></summary>
|
<summary><h2 id="options-heading" i18n-text="optionsHeading"></h2></summary>
|
||||||
<div class="option">
|
<div class="option">
|
||||||
|
<label id="lineWrapping-label" i18n-text="cm_lineWrapping">
|
||||||
<input id="editor.lineWrapping" type="checkbox">
|
<input id="editor.lineWrapping" type="checkbox">
|
||||||
<label id="lineWrapping-label" for="editor.lineWrapping" i18n-text="cm_lineWrapping"></label>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="option">
|
<div class="option">
|
||||||
|
<label id="smartIndent-label" i18n-text="cm_smartIndent">
|
||||||
<input id="editor.smartIndent" type="checkbox">
|
<input id="editor.smartIndent" type="checkbox">
|
||||||
<label id="smartIndent-label" for="editor.smartIndent" i18n-text="cm_smartIndent"></label>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="option">
|
<div class="option">
|
||||||
|
<label id="indentWithTabs-label" i18n-text="cm_indentWithTabs">
|
||||||
<input id="editor.indentWithTabs" type="checkbox">
|
<input id="editor.indentWithTabs" type="checkbox">
|
||||||
<label id="indentWithTabs-label" for="editor.indentWithTabs" i18n-text="cm_indentWithTabs"></label>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="option">
|
<div class="option">
|
||||||
|
<label i18n-text="cm_autoCloseBrackets" i18n-title="cm_autoCloseBracketsTooltip">
|
||||||
<input id="editor.autoCloseBrackets" type="checkbox">
|
<input id="editor.autoCloseBrackets" type="checkbox">
|
||||||
<label for="editor.autoCloseBrackets"
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
i18n-text="cm_autoCloseBrackets"
|
</label>
|
||||||
i18n-title="cm_autoCloseBracketsTooltip"></label>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="option">
|
<div class="option">
|
||||||
|
<label i18n-text="cm_autocompleteOnTyping">
|
||||||
<input id="editor.autocompleteOnTyping" type="checkbox">
|
<input id="editor.autocompleteOnTyping" type="checkbox">
|
||||||
<label for="editor.autocompleteOnTyping" i18n-text="cm_autocompleteOnTyping"></label>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="option">
|
<div class="option">
|
||||||
|
<label i18n-text="cm_colorpicker">
|
||||||
<input id="editor.colorpicker" type="checkbox">
|
<input id="editor.colorpicker" type="checkbox">
|
||||||
<label for="editor.colorpicker" i18n-text="cm_colorpicker"></label>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</label>
|
||||||
<span class="svg-inline-wrapper" i18n-title="shortcutsNote">
|
<span class="svg-inline-wrapper" i18n-title="shortcutsNote">
|
||||||
<svg id="colorpicker-settings" class="svg-icon settings">
|
<svg id="colorpicker-settings" class="svg-icon settings">
|
||||||
<use xlink:href="#svg-icon-settings"/>
|
<use xlink:href="#svg-icon-settings"/>
|
||||||
|
@ -232,10 +248,10 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="option usercss-only">
|
<div class="option usercss-only">
|
||||||
|
<label i18n-text="appliesLineWidgetLabel" i18n-title="appliesLineWidgetWarning">
|
||||||
<input id="editor.appliesToLineWidget" type="checkbox">
|
<input id="editor.appliesToLineWidget" type="checkbox">
|
||||||
<label for="editor.appliesToLineWidget"
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
i18n-text="appliesLineWidgetLabel"
|
</label>
|
||||||
i18n-title="appliesLineWidgetWarning"></label>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="option aligned">
|
<div class="option aligned">
|
||||||
<label id="tabSize-label" for="editor.tabSize" i18n-text="cm_tabSize"></label>
|
<label id="tabSize-label" for="editor.tabSize" i18n-text="cm_tabSize"></label>
|
||||||
|
@ -243,30 +259,42 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="option aligned">
|
<div class="option aligned">
|
||||||
<label id="keyMap-label" for="editor.keyMap" i18n-text="cm_keyMap"></label>
|
<label id="keyMap-label" for="editor.keyMap" i18n-text="cm_keyMap"></label>
|
||||||
|
<div class="select-resizer">
|
||||||
<select id="editor.keyMap"></select>
|
<select id="editor.keyMap"></select>
|
||||||
|
<svg class="svg-icon select-arrow"><use xlink:href="#svg-icon-select-arrow"/></svg>
|
||||||
|
</div>
|
||||||
<span class="svg-inline-wrapper">
|
<span class="svg-inline-wrapper">
|
||||||
<svg id="keyMap-help" class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg>
|
<svg id="keyMap-help" class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="option aligned">
|
<div class="option aligned">
|
||||||
<label id="theme-label" for="editor.theme" i18n-text="cm_theme"></label>
|
<label id="theme-label" for="editor.theme" i18n-text="cm_theme"></label>
|
||||||
|
<div class="select-resizer">
|
||||||
<select id="editor.theme"></select>
|
<select id="editor.theme"></select>
|
||||||
|
<svg class="svg-icon select-arrow"><use xlink:href="#svg-icon-select-arrow"/></svg>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="option aligned">
|
<div class="option aligned">
|
||||||
<label id="highlight-label" for="editor.matchHighlight" i18n-text="cm_matchHighlight"></label>
|
<label id="highlight-label" for="editor.matchHighlight" i18n-text="cm_matchHighlight"></label>
|
||||||
|
<div class="select-resizer">
|
||||||
<select id="editor.matchHighlight">
|
<select id="editor.matchHighlight">
|
||||||
<option i18n-text="cm_matchHighlightToken" value="token">
|
<option i18n-text="cm_matchHighlightToken" value="token">
|
||||||
<option i18n-text="cm_matchHighlightSelection" value="selection">
|
<option i18n-text="cm_matchHighlightSelection" value="selection">
|
||||||
<option i18n-text="genericDisabledLabel" value="">
|
<option i18n-text="genericDisabledLabel" value="">
|
||||||
</select>
|
</select>
|
||||||
|
<svg class="svg-icon select-arrow"><use xlink:href="#svg-icon-select-arrow"/></svg>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="option aligned">
|
<div class="option aligned">
|
||||||
<label id="linter-label" for="editor.linter" i18n-text="cm_linter"></label>
|
<label id="linter-label" for="editor.linter" i18n-text="cm_linter"></label>
|
||||||
|
<div class="select-resizer">
|
||||||
<select id="editor.linter">
|
<select id="editor.linter">
|
||||||
<option value="csslint" selected>CSSLint</option>
|
<option value="csslint" selected>CSSLint</option>
|
||||||
<option value="stylelint">Stylelint</option>
|
<option value="stylelint">Stylelint</option>
|
||||||
<option value="" i18n-text="genericDisabledLabel"></option>
|
<option value="" i18n-text="genericDisabledLabel"></option>
|
||||||
</select>
|
</select>
|
||||||
|
<svg class="svg-icon select-arrow"><use xlink:href="#svg-icon-select-arrow"/></svg>
|
||||||
|
</div>
|
||||||
<span class="svg-inline-wrapper" i18n-title="linterConfigTooltip">
|
<span class="svg-inline-wrapper" i18n-title="linterConfigTooltip">
|
||||||
<svg id="linter-settings" class="svg-icon settings">
|
<svg id="linter-settings" class="svg-icon settings">
|
||||||
<use xlink:href="#svg-icon-settings"/>
|
<use xlink:href="#svg-icon-settings"/>
|
||||||
|
@ -299,18 +327,31 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none">
|
<svg xmlns="http://www.w3.org/2000/svg" style="display: none">
|
||||||
|
|
||||||
<symbol id="svg-icon-external-link" viewBox="0 0 8 8">
|
<symbol id="svg-icon-external-link" viewBox="0 0 8 8">
|
||||||
<path d="M0 0v8h8v-2h-1v1h-6v-6h1v-1h-2zm4 0l1.5 1.5-2.5 2.5 1 1 2.5-2.5 1.5 1.5v-4h-4z"></path>
|
<path d="M0 0v8h8v-2h-1v1h-6v-6h1v-1h-2zm4 0l1.5 1.5-2.5 2.5 1 1 2.5-2.5 1.5 1.5v-4h-4z"></path>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
|
||||||
<symbol id="svg-icon-help" viewBox="0 0 14 16" i18n-alt="helpAlt">
|
<symbol id="svg-icon-help" viewBox="0 0 14 16" i18n-alt="helpAlt">
|
||||||
<path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path>
|
<path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
|
||||||
<symbol id="svg-icon-close" viewBox="0 0 12 16">
|
<symbol id="svg-icon-close" viewBox="0 0 12 16">
|
||||||
<path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path>
|
<path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"></path>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
|
||||||
<symbol id="svg-icon-settings" viewBox="0 0 16 16">
|
<symbol id="svg-icon-settings" viewBox="0 0 16 16">
|
||||||
<path d="M8,0C7.6,0,7.3,0,6.9,0.1v2.2C6.1,2.5,5.4,2.8,4.8,3.2L3.2,1.6c-0.6,0.4-1.1,1-1.6,1.6l1.6,1.6C2.8,5.4,2.5,6.1,2.3,6.9H0.1C0,7.3,0,7.6,0,8c0,0.4,0,0.7,0.1,1.1h2.2c0.1,0.8,0.4,1.5,0.9,2.1l-1.6,1.6c0.4,0.6,1,1.1,1.6,1.6l1.6-1.6c0.6,0.4,1.4,0.7,2.1,0.9v2.2C7.3,16,7.6,16,8,16c0.4,0,0.7,0,1.1-0.1v-2.2c0.8-0.1,1.5-0.4,2.1-0.9l1.6,1.6c0.6-0.4,1.1-1,1.6-1.6l-1.6-1.6c0.4-0.6,0.7-1.4,0.9-2.1h2.2C16,8.7,16,8.4,16,8c0-0.4,0-0.7-0.1-1.1h-2.2c-0.1-0.8-0.4-1.5-0.9-2.1l1.6-1.6c-0.4-0.6-1-1.1-1.6-1.6l-1.6,1.6c-0.6-0.4-1.4-0.7-2.1-0.9V0.1C8.7,0,8.4,0,8,0z M8,4.3c2.1,0,3.7,1.7,3.7,3.7c0,0,0,0,0,0c0,2.1-1.7,3.7-3.7,3.7c0,0,0,0,0,0c-2.1,0-3.7-1.7-3.7-3.7c0,0,0,0,0,0C4.3,5.9,5.9,4.3,8,4.3C8,4.3,8,4.3,8,4.3z"/>
|
<path d="M8,0C7.6,0,7.3,0,6.9,0.1v2.2C6.1,2.5,5.4,2.8,4.8,3.2L3.2,1.6c-0.6,0.4-1.1,1-1.6,1.6l1.6,1.6C2.8,5.4,2.5,6.1,2.3,6.9H0.1C0,7.3,0,7.6,0,8c0,0.4,0,0.7,0.1,1.1h2.2c0.1,0.8,0.4,1.5,0.9,2.1l-1.6,1.6c0.4,0.6,1,1.1,1.6,1.6l1.6-1.6c0.6,0.4,1.4,0.7,2.1,0.9v2.2C7.3,16,7.6,16,8,16c0.4,0,0.7,0,1.1-0.1v-2.2c0.8-0.1,1.5-0.4,2.1-0.9l1.6,1.6c0.6-0.4,1.1-1,1.6-1.6l-1.6-1.6c0.4-0.6,0.7-1.4,0.9-2.1h2.2C16,8.7,16,8.4,16,8c0-0.4,0-0.7-0.1-1.1h-2.2c-0.1-0.8-0.4-1.5-0.9-2.1l1.6-1.6c-0.4-0.6-1-1.1-1.6-1.6l-1.6,1.6c-0.6-0.4-1.4-0.7-2.1-0.9V0.1C8.7,0,8.4,0,8,0z M8,4.3c2.1,0,3.7,1.7,3.7,3.7c0,0,0,0,0,0c0,2.1-1.7,3.7-3.7,3.7c0,0,0,0,0,0c-2.1,0-3.7-1.7-3.7-3.7c0,0,0,0,0,0C4.3,5.9,5.9,4.3,8,4.3C8,4.3,8,4.3,8,4.3z"/>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
|
||||||
|
<symbol id="svg-icon-select-arrow" viewBox="0 0 1792 1792">
|
||||||
|
<path fill-rule="evenodd" d="M1408 704q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol id="svg-icon-checked" viewBox="0 0 1000 1000">
|
||||||
|
<path fill-rule="evenodd" d="M983.2,184.3L853,69.8c-4-3.5-9.3-5.3-14.5-5c-5.3,0.4-10.3,2.8-13.8,6.8L352.3,609.2L184.4,386.9c-3.2-4.2-8-7-13.2-7.8c-5.3-0.8-10.6,0.6-14.9,3.9L18,487.5c-8.8,6.7-10.6,19.3-3.9,28.1L325,927.2c3.6,4.8,9.3,7.7,15.3,8c0.2,0,0.5,0,0.7,0c5.8,0,11.3-2.5,15.1-6.8L985,212.6C992.3,204.3,991.5,191.6,983.2,184.3z"/>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,79 +1,12 @@
|
||||||
/* global regExpTester debounce messageBox CodeMirror */
|
/* global regExpTester debounce messageBox CodeMirror template */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function templateCache(cache) {
|
|
||||||
function clone(id) {
|
|
||||||
if (typeof cache[id] === 'function') {
|
|
||||||
cache[id] = cache[id]();
|
|
||||||
}
|
|
||||||
return cache[id].cloneNode(true);
|
|
||||||
}
|
|
||||||
return {clone};
|
|
||||||
}
|
|
||||||
|
|
||||||
function createAppliesToLineWidget(cm) {
|
function createAppliesToLineWidget(cm) {
|
||||||
const APPLIES_TYPE = [
|
|
||||||
[t('appliesUrlOption'), 'url'],
|
|
||||||
[t('appliesUrlPrefixOption'), 'url-prefix'],
|
|
||||||
[t('appliesDomainOption'), 'domain'],
|
|
||||||
[t('appliesRegexpOption'), 'regexp']
|
|
||||||
];
|
|
||||||
const THROTTLE_DELAY = 400;
|
const THROTTLE_DELAY = 400;
|
||||||
|
let TPL, EVENTS, CLICK_ROUTE;
|
||||||
let widgets = [];
|
let widgets = [];
|
||||||
let fromLine, toLine, styleVariables;
|
let fromLine, toLine, styleVariables;
|
||||||
let initialized = false;
|
let initialized = false;
|
||||||
|
|
||||||
const template = templateCache({
|
|
||||||
container: () =>
|
|
||||||
$element({className: 'applies-to', appendChild: [
|
|
||||||
$element({tag: 'label', appendChild: t('appliesLabel')}),
|
|
||||||
$element({
|
|
||||||
tag: 'ul',
|
|
||||||
className: 'applies-to-list'
|
|
||||||
})
|
|
||||||
]}),
|
|
||||||
listItem: () =>
|
|
||||||
$element({tag: 'li', appendChild: [
|
|
||||||
$element({
|
|
||||||
tag: 'select',
|
|
||||||
className: 'applies-type',
|
|
||||||
appendChild: APPLIES_TYPE.map(([label, value]) => $element({
|
|
||||||
tag: 'option',
|
|
||||||
value: value,
|
|
||||||
textContent: label
|
|
||||||
}))
|
|
||||||
}),
|
|
||||||
$element({
|
|
||||||
tag: 'input',
|
|
||||||
className: 'applies-value'
|
|
||||||
}),
|
|
||||||
$element({
|
|
||||||
tag: 'button',
|
|
||||||
type: 'button',
|
|
||||||
className: 'applies-to-regexp-test',
|
|
||||||
textContent: t('styleRegexpTestButton')
|
|
||||||
}),
|
|
||||||
$element({
|
|
||||||
tag: 'button',
|
|
||||||
type: 'button',
|
|
||||||
className: 'applies-to-remove',
|
|
||||||
textContent: t('appliesRemove')
|
|
||||||
}),
|
|
||||||
$element({
|
|
||||||
tag: 'button',
|
|
||||||
type: 'button',
|
|
||||||
className: 'applies-to-add',
|
|
||||||
textContent: t('appliesAdd')
|
|
||||||
})
|
|
||||||
]}),
|
|
||||||
appliesToEverything: () =>
|
|
||||||
$element({
|
|
||||||
tag: 'li',
|
|
||||||
className: 'applies-to-everything',
|
|
||||||
textContent: t('appliesToEverything')
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
return {toggle};
|
return {toggle};
|
||||||
|
|
||||||
function toggle(newState = !initialized) {
|
function toggle(newState = !initialized) {
|
||||||
|
@ -90,7 +23,120 @@ function createAppliesToLineWidget(cm) {
|
||||||
function init() {
|
function init() {
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
styleVariables = $element({tag: 'style'});
|
TPL = {
|
||||||
|
container:
|
||||||
|
$create('div.applies-to', [
|
||||||
|
$create('label', t('appliesLabel')),
|
||||||
|
$create('ul.applies-to-list'),
|
||||||
|
]),
|
||||||
|
listItem:
|
||||||
|
$create('li.applies-to-item', [
|
||||||
|
$create('select.applies-type', [
|
||||||
|
$create('option', {value: 'url'}, t('appliesUrlOption')),
|
||||||
|
$create('option', {value: 'url-prefix'}, t('appliesUrlPrefixOption')),
|
||||||
|
$create('option', {value: 'domain'}, t('appliesDomainOption')),
|
||||||
|
$create('option', {value: 'regexp'}, t('appliesRegexpOption')),
|
||||||
|
]),
|
||||||
|
$create('input.applies-value', {spellcheck: false}),
|
||||||
|
$create('button.test-regexp', t('styleRegexpTestButton')),
|
||||||
|
$create('button.remove-applies-to', t('appliesRemove')),
|
||||||
|
$create('button.add-applies-to', t('appliesAdd')),
|
||||||
|
]),
|
||||||
|
appliesToEverything:
|
||||||
|
$create('li.applies-to-everything', t('appliesToEverything')),
|
||||||
|
};
|
||||||
|
|
||||||
|
CLICK_ROUTE = {
|
||||||
|
'.test-regexp': (item, apply) => {
|
||||||
|
regExpTester.toggle();
|
||||||
|
regExpTester.update([apply.value.text]);
|
||||||
|
},
|
||||||
|
|
||||||
|
'.remove-applies-to': (item, apply) => {
|
||||||
|
const applies = item.closest('.applies-to').__applies;
|
||||||
|
const i = applies.indexOf(apply);
|
||||||
|
let repl;
|
||||||
|
let from;
|
||||||
|
let to;
|
||||||
|
if (applies.length < 2) {
|
||||||
|
messageBox({
|
||||||
|
contents: t('appliesRemoveError'),
|
||||||
|
buttons: [t('confirmClose')]
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (i === 0) {
|
||||||
|
from = apply.mark.find().from;
|
||||||
|
to = applies[i + 1].mark.find().from;
|
||||||
|
repl = '';
|
||||||
|
} else if (i === applies.length - 1) {
|
||||||
|
from = applies[i - 1].mark.find().to;
|
||||||
|
to = apply.mark.find().to;
|
||||||
|
repl = '';
|
||||||
|
} else {
|
||||||
|
from = applies[i - 1].mark.find().to;
|
||||||
|
to = applies[i + 1].mark.find().from;
|
||||||
|
repl = ', ';
|
||||||
|
}
|
||||||
|
cm.replaceRange(repl, from, to, 'appliesTo');
|
||||||
|
clearApply(apply);
|
||||||
|
item.remove();
|
||||||
|
applies.splice(i, 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
'.add-applies-to': (item, apply) => {
|
||||||
|
const applies = this.closest('.applies-to').__applies;
|
||||||
|
const i = applies.indexOf(apply);
|
||||||
|
const pos = apply.mark.find().to;
|
||||||
|
const text = `, ${apply.type.text}("")`;
|
||||||
|
cm.replaceRange(text, pos, pos, 'appliesTo');
|
||||||
|
const newApply = createApply(
|
||||||
|
cm.indexFromPos(pos) + 2,
|
||||||
|
apply.type.text,
|
||||||
|
'',
|
||||||
|
true
|
||||||
|
);
|
||||||
|
setupApplyMarkers(newApply);
|
||||||
|
applies.splice(i + 1, 0, newApply);
|
||||||
|
item.insertAdjacentElement('afterend', buildChildren(applies, newApply));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
EVENTS = {
|
||||||
|
onchange({target}) {
|
||||||
|
const typeElement = target.closest('.applies-type');
|
||||||
|
if (typeElement) {
|
||||||
|
const item = target.closest('.applies-to-item');
|
||||||
|
const apply = item.__apply;
|
||||||
|
changeItem(apply, 'type', typeElement.value);
|
||||||
|
item.dataset.type = apply.type.text;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
oninput({target}) {
|
||||||
|
if (target.matches('.applies-value')) {
|
||||||
|
const apply = target.closest('.applies-to-item').__apply;
|
||||||
|
debounce(changeItem, THROTTLE_DELAY, apply, 'value', target.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onfocus({target}) {
|
||||||
|
if (target.matches('.test-regexp')) {
|
||||||
|
const apply = target.closest('.applies-to-item').__apply;
|
||||||
|
updateRegexpTest(apply);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onclick({target}) {
|
||||||
|
for (const selector in CLICK_ROUTE) {
|
||||||
|
const routed = target.closest(selector);
|
||||||
|
if (routed) {
|
||||||
|
const item = routed.closest('.applies-to-item');
|
||||||
|
CLICK_ROUTE[selector].call(routed, item, item.__apply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
styleVariables = $create('style');
|
||||||
fromLine = 0;
|
fromLine = 0;
|
||||||
toLine = cm.doc.size;
|
toLine = cm.doc.size;
|
||||||
|
|
||||||
|
@ -175,7 +221,7 @@ function createAppliesToLineWidget(cm) {
|
||||||
inOp = true;
|
inOp = true;
|
||||||
cm.startOperation();
|
cm.startOperation();
|
||||||
}
|
}
|
||||||
cm.operation(doUpdate);
|
doUpdate();
|
||||||
}
|
}
|
||||||
if (inOp) {
|
if (inOp) {
|
||||||
cm.endOperation();
|
cm.endOperation();
|
||||||
|
@ -245,26 +291,29 @@ function createAppliesToLineWidget(cm) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let itemHeight;
|
let itemHeight;
|
||||||
for (const section of findAppliesTo(start, end)) {
|
for (const section of findAppliesTo(start, end)) {
|
||||||
while (removed[i] && removed[i].line.lineNo() < section.pos.line) {
|
let removedWidget = removed[i];
|
||||||
clearWidget(removed[i++]);
|
while (removedWidget && removedWidget.line.lineNo() < section.pos.line) {
|
||||||
|
clearWidget(removed[i]);
|
||||||
|
removedWidget = removed[++i];
|
||||||
}
|
}
|
||||||
for (const a of section.applies) {
|
for (const a of section.applies) {
|
||||||
setupApplyMarkers(a, lineIndexes);
|
setupApplyMarkers(a, lineIndexes);
|
||||||
}
|
}
|
||||||
if (removed[i] && removed[i].line.lineNo() === section.pos.line) {
|
if (removedWidget && removedWidget.line.lineNo() === section.pos.line) {
|
||||||
// reuse old widget
|
// reuse old widget
|
||||||
removed[i].section.applies.forEach(apply => {
|
removedWidget.section.applies.forEach(apply => {
|
||||||
apply.type.mark.clear();
|
apply.type.mark.clear();
|
||||||
apply.value.mark.clear();
|
apply.value.mark.clear();
|
||||||
});
|
});
|
||||||
removed[i].section = section;
|
removedWidget.section = section;
|
||||||
const newNode = buildElement(section);
|
const newNode = buildElement(section);
|
||||||
if (removed[i].node.parentNode) {
|
const removedNode = removedWidget.node;
|
||||||
removed[i].node.parentNode.replaceChild(newNode, removed[i].node);
|
if (removedNode.parentNode) {
|
||||||
|
removedNode.parentNode.replaceChild(newNode, removedNode);
|
||||||
}
|
}
|
||||||
removed[i].node = newNode;
|
removedWidget.node = newNode;
|
||||||
removed[i].changed();
|
removedWidget.changed();
|
||||||
yield removed[i];
|
yield removedWidget;
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -337,138 +386,71 @@ function createAppliesToLineWidget(cm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildElement({applies}) {
|
function buildElement({applies}) {
|
||||||
const el = template.clone('container');
|
const container = TPL.container.cloneNode(true);
|
||||||
const appliesToList = $('.applies-to-list', el);
|
const list = $('.applies-to-list', container);
|
||||||
applies.map(makeLi)
|
for (const apply of applies) {
|
||||||
.forEach(item => appliesToList.appendChild(item));
|
list.appendChild(buildChildren(applies, apply));
|
||||||
if (!appliesToList.childNodes.length) {
|
|
||||||
appliesToList.appendChild(template.clone('appliesToEverything'));
|
|
||||||
}
|
}
|
||||||
|
if (!list.children[0]) {
|
||||||
|
list.appendChild(TPL.appliesToEverything.cloneNode(true));
|
||||||
|
}
|
||||||
|
return Object.assign(container, EVENTS, {__applies: applies});
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildChildren(applies, apply) {
|
||||||
|
const el = TPL.listItem.cloneNode(true);
|
||||||
|
el.dataset.type = apply.type.text;
|
||||||
|
el.__apply = apply;
|
||||||
|
$('.applies-type', el).value = apply.type.text;
|
||||||
|
$('.applies-value', el).value = apply.value.text;
|
||||||
return el;
|
return el;
|
||||||
|
|
||||||
function makeLi(apply) {
|
|
||||||
const el = template.clone('listItem');
|
|
||||||
el.dataset.type = apply.type.text;
|
|
||||||
el.addEventListener('change', e => {
|
|
||||||
if (e.target.classList.contains('applies-type')) {
|
|
||||||
el.dataset.type = apply.type.text;
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
const typeInput = $('.applies-type', el);
|
function changeItem(apply, part, newText) {
|
||||||
typeInput.value = apply.type.text;
|
if (!apply) {
|
||||||
typeInput.onchange = function () {
|
|
||||||
applyChange(apply.type, this.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const valueInput = $('.applies-value', el);
|
|
||||||
valueInput.value = apply.value.text;
|
|
||||||
valueInput.oninput = function () {
|
|
||||||
debounce(applyChange, THROTTLE_DELAY, apply.value, this.value);
|
|
||||||
};
|
|
||||||
valueInput.onfocus = updateRegexpTest;
|
|
||||||
|
|
||||||
const regexpTestButton = $('.applies-to-regexp-test', el);
|
|
||||||
regexpTestButton.onclick = () => {
|
|
||||||
regExpTester.toggle();
|
|
||||||
regExpTester.update([apply.value.text]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeButton = $('.applies-to-remove', el);
|
|
||||||
removeButton.onclick = function () {
|
|
||||||
const i = applies.indexOf(apply);
|
|
||||||
let repl;
|
|
||||||
let from;
|
|
||||||
let to;
|
|
||||||
if (applies.length < 2) {
|
|
||||||
messageBox({
|
|
||||||
contents: chrome.i18n.getMessage('appliesRemoveError'),
|
|
||||||
buttons: [t('confirmClose')]
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (i === 0) {
|
part = apply[part];
|
||||||
from = apply.mark.find().from;
|
const range = part.mark.find();
|
||||||
to = applies[i + 1].mark.find().from;
|
part.mark.clear();
|
||||||
repl = '';
|
newText = newText.replace(/\\/g, '\\\\');
|
||||||
} else if (i === applies.length - 1) {
|
|
||||||
from = applies[i - 1].mark.find().to;
|
|
||||||
to = apply.mark.find().to;
|
|
||||||
repl = '';
|
|
||||||
} else {
|
|
||||||
from = applies[i - 1].mark.find().to;
|
|
||||||
to = applies[i + 1].mark.find().from;
|
|
||||||
repl = ', ';
|
|
||||||
}
|
|
||||||
cm.replaceRange(repl, from, to, 'appliesTo');
|
|
||||||
clearApply(apply);
|
|
||||||
this.closest('li').remove();
|
|
||||||
applies.splice(i, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addButton = $('.applies-to-add', el);
|
|
||||||
addButton.onclick = function () {
|
|
||||||
const i = applies.indexOf(apply);
|
|
||||||
const pos = apply.mark.find().to;
|
|
||||||
const text = `, ${apply.type.text}("")`;
|
|
||||||
cm.replaceRange(text, pos, pos, 'appliesTo');
|
|
||||||
const newApply = createApply(
|
|
||||||
cm.indexFromPos(pos) + 2,
|
|
||||||
apply.type.text,
|
|
||||||
'',
|
|
||||||
true
|
|
||||||
);
|
|
||||||
setupApplyMarkers(newApply);
|
|
||||||
applies.splice(i + 1, 0, newApply);
|
|
||||||
this.closest('li').insertAdjacentElement('afterend', makeLi(newApply));
|
|
||||||
};
|
|
||||||
|
|
||||||
return el;
|
|
||||||
|
|
||||||
function updateRegexpTest() {
|
|
||||||
if (apply.type.text === 'regexp') {
|
|
||||||
const re = apply.value.text.trim();
|
|
||||||
if (re) {
|
|
||||||
regExpTester.update([re]);
|
|
||||||
} else {
|
|
||||||
regExpTester.update([]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyChange(input, newText) {
|
|
||||||
const range = input.mark.find();
|
|
||||||
input.mark.clear();
|
|
||||||
cm.replaceRange(newText, range.from, range.to, 'appliesTo');
|
cm.replaceRange(newText, range.from, range.to, 'appliesTo');
|
||||||
input.mark = cm.markText(
|
part.mark = cm.markText(
|
||||||
range.from,
|
range.from,
|
||||||
cm.findPosH(range.from, newText.length, 'char'),
|
cm.findPosH(range.from, newText.length, 'char'),
|
||||||
{clearWhenEmpty: false}
|
{clearWhenEmpty: false}
|
||||||
);
|
);
|
||||||
input.text = newText;
|
part.text = newText;
|
||||||
|
|
||||||
if (input === apply.type) {
|
if (part === apply.type) {
|
||||||
const range = apply.mark.find();
|
const range = apply.mark.find();
|
||||||
apply.mark.clear();
|
apply.mark.clear();
|
||||||
apply.mark = cm.markText(
|
apply.mark = cm.markText(
|
||||||
input.mark.find().from,
|
part.mark.find().from,
|
||||||
range.to,
|
range.to,
|
||||||
{clearWhenEmpty: false}
|
{clearWhenEmpty: false}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRegexpTest();
|
updateRegexpTest(apply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateRegexpTest(apply) {
|
||||||
|
if (apply.type.text === 'regexp') {
|
||||||
|
const rx = apply.value.text.trim();
|
||||||
|
regExpTester.update(rx ? [rx] : {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createApply(pos, typeText, valueText, isQuoted = false) {
|
function createApply(pos, typeText, valueText, isQuoted = false) {
|
||||||
|
typeText = typeText.toLowerCase();
|
||||||
const start = pos;
|
const start = pos;
|
||||||
const typeStart = start;
|
const typeStart = start;
|
||||||
const typeEnd = typeStart + typeText.length;
|
const typeEnd = typeStart + typeText.length;
|
||||||
const valueStart = typeEnd + 1 + Number(isQuoted);
|
const valueStart = typeEnd + 1 + Number(isQuoted);
|
||||||
const valueEnd = valueStart + valueText.length;
|
const valueEnd = valueStart + valueText.length;
|
||||||
const end = valueEnd + Number(isQuoted) + 1;
|
const end = valueEnd + Number(isQuoted) + 1;
|
||||||
|
const hasSingleEscapes = /([^\\]|^)\\([^\\]|$)/.test(valueText);
|
||||||
return {
|
return {
|
||||||
start,
|
start,
|
||||||
type: {
|
type: {
|
||||||
|
@ -477,7 +459,7 @@ function createAppliesToLineWidget(cm) {
|
||||||
end: typeEnd,
|
end: typeEnd,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
text: valueText,
|
text: hasSingleEscapes ? valueText : valueText.replace(/\\\\/g, '\\'),
|
||||||
start: valueStart,
|
start: valueStart,
|
||||||
end: valueEnd,
|
end: valueEnd,
|
||||||
},
|
},
|
||||||
|
@ -487,8 +469,12 @@ function createAppliesToLineWidget(cm) {
|
||||||
|
|
||||||
function *findAppliesTo(posStart, posEnd) {
|
function *findAppliesTo(posStart, posEnd) {
|
||||||
const text = cm.getValue();
|
const text = cm.getValue();
|
||||||
const re = /^[\t ]*@-moz-document\s+/mg;
|
const re = /^[\t ]*@-moz-document[\s\n]+/gm;
|
||||||
const applyRe = /(url|url-prefix|domain|regexp)\(((['"])(?:\\\\|\\\n|\\\3|[^\n])*?\3|[^)\n]*)\)[\s,]*/iyg;
|
const applyRe = new RegExp([
|
||||||
|
/(?:\/\*[^*]*\*\/[\s\n]*)*/,
|
||||||
|
/(url|url-prefix|domain|regexp)/,
|
||||||
|
/\(((['"])(?:\\\\|\\\n|\\\3|[^\n])*?\3|[^)\n]*)\)\s*(,\s*)?/,
|
||||||
|
].map(rx => rx.source).join(''), 'giy');
|
||||||
let match;
|
let match;
|
||||||
re.lastIndex = posStart;
|
re.lastIndex = posStart;
|
||||||
while ((match = re.exec(text))) {
|
while ((match = re.exec(text))) {
|
||||||
|
|
|
@ -29,12 +29,16 @@ function beautify(event) {
|
||||||
optionHtml('border: none;', 'newline_between_properties', true) +
|
optionHtml('border: none;', 'newline_between_properties', true) +
|
||||||
optionHtml('display: block;', 'newline_before_close_brace', true) +
|
optionHtml('display: block;', 'newline_before_close_brace', true) +
|
||||||
optionHtml('}', 'newline_between_rules') +
|
optionHtml('}', 'newline_between_rules') +
|
||||||
`<label style="display: block; clear: both;"><input data-option="indent_conditional" type="checkbox"
|
`<label style="display: block; clear: both;">
|
||||||
${options.indent_conditional !== false ? 'checked' : ''}>` +
|
<input data-option="indent_conditional" type="checkbox"
|
||||||
|
${options.indent_conditional !== false ? 'checked' : ''}>
|
||||||
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>` +
|
||||||
t('styleBeautifyIndentConditional') + '</label>' +
|
t('styleBeautifyIndentConditional') + '</label>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div><button role="undo"></button></div>');
|
'<div><button role="undo"></button></div>');
|
||||||
|
|
||||||
|
$('#help-popup').className = 'wide';
|
||||||
|
|
||||||
const undoButton = $('#help-popup button[role="undo"]');
|
const undoButton = $('#help-popup button[role="undo"]');
|
||||||
undoButton.textContent = t(scope.length === 1 ? 'undo' : 'undoGlobal');
|
undoButton.textContent = t(scope.length === 1 ? 'undo' : 'undoGlobal');
|
||||||
undoButton.addEventListener('click', () => {
|
undoButton.addEventListener('click', () => {
|
||||||
|
@ -87,10 +91,17 @@ function beautify(event) {
|
||||||
const value = options[optionName];
|
const value = options[optionName];
|
||||||
return '<div newline="' + value.toString() + '">' +
|
return '<div newline="' + value.toString() + '">' +
|
||||||
'<span' + (indent ? ' indent' : '') + '>' + label + '</span>' +
|
'<span' + (indent ? ' indent' : '') + '>' + label + '</span>' +
|
||||||
|
'<div class="select-resizer">' +
|
||||||
'<select data-option="' + optionName + '">' +
|
'<select data-option="' + optionName + '">' +
|
||||||
'<option' + (value ? '' : ' selected') + '> </option>' +
|
'<option' + (value ? '' : ' selected') + '> </option>' +
|
||||||
'<option' + (value ? ' selected' : '') + '>\\n</option>' +
|
'<option' + (value ? ' selected' : '') + '>\\n</option>' +
|
||||||
'</select></div>';
|
'</select>' +
|
||||||
|
'<svg class="svg-icon select-arrow" viewBox="0 0 1792 1792">' +
|
||||||
|
'<path fill-rule="evenodd" d="M1408 704q0 26-19 45l-448 448q-19 19-45 ' +
|
||||||
|
'19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/>' +
|
||||||
|
'</svg>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,10 +115,8 @@ onDOMready().then(() => {
|
||||||
if (option.type === 'checkbox') {
|
if (option.type === 'checkbox') {
|
||||||
option = (option.labels || [])[0] || option.nextElementSibling || option;
|
option = (option.labels || [])[0] || option.nextElementSibling || option;
|
||||||
}
|
}
|
||||||
progress = document.body.appendChild($element({
|
progress = document.body.appendChild(
|
||||||
className: 'set-option-progress',
|
$create('.set-option-progress', {targetElement: option}));
|
||||||
targetElement: option,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (progress) {
|
if (progress) {
|
||||||
|
@ -222,12 +220,7 @@ onDOMready().then(() => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// avoid flicker: wait for the second stylesheet to load, then apply the theme
|
// avoid flicker: wait for the second stylesheet to load, then apply the theme
|
||||||
document.head.appendChild($element({
|
document.head.appendChild($create('link#cm-theme2', {rel: 'stylesheet', href: url}));
|
||||||
tag: 'link',
|
|
||||||
id: 'cm-theme2',
|
|
||||||
rel: 'stylesheet',
|
|
||||||
href: url
|
|
||||||
}));
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
CodeMirror.setOption(option, value);
|
CodeMirror.setOption(option, value);
|
||||||
themeLink.remove();
|
themeLink.remove();
|
||||||
|
@ -287,7 +280,7 @@ onDOMready().then(() => {
|
||||||
function optionsFromArray(parent, options) {
|
function optionsFromArray(parent, options) {
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
for (const opt of options) {
|
for (const opt of options) {
|
||||||
fragment.appendChild($element({tag: 'option', textContent: opt}));
|
fragment.appendChild($create('option', opt));
|
||||||
}
|
}
|
||||||
parent.appendChild(fragment);
|
parent.appendChild(fragment);
|
||||||
}
|
}
|
||||||
|
@ -342,16 +335,16 @@ onDOMready().then(() => {
|
||||||
customizeOpenDialog(activeCM, template.find, function (query) {
|
customizeOpenDialog(activeCM, template.find, function (query) {
|
||||||
this(query);
|
this(query);
|
||||||
searchState = activeCM.state.search;
|
searchState = activeCM.state.search;
|
||||||
if (editors.length === 1 || !searchState.query) {
|
const searchOthers = editors.length > 1 && searchState.query;
|
||||||
return;
|
|
||||||
}
|
|
||||||
editors.forEach(cm => {
|
editors.forEach(cm => {
|
||||||
if (cm !== activeCM) {
|
if (cm !== activeCM) {
|
||||||
cm.execCommand('clearSearch');
|
cm.execCommand('clearSearch');
|
||||||
|
if (searchOthers) {
|
||||||
updateState(cm, searchState);
|
updateState(cm, searchState);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (CodeMirror.cmpPos(searchState.posFrom, searchState.posTo) === 0) {
|
if (searchOthers && CodeMirror.cmpPos(searchState.posFrom, searchState.posTo) === 0) {
|
||||||
findNext(activeCM);
|
findNext(activeCM);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -69,8 +69,7 @@ var initColorpicker = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function configureColorpicker() {
|
function configureColorpicker() {
|
||||||
const input = $element({
|
const input = $create('input', {
|
||||||
tag: 'input',
|
|
||||||
type: 'search',
|
type: 'search',
|
||||||
spellcheck: false,
|
spellcheck: false,
|
||||||
value: prefs.get('editor.colorpicker.hotkey'),
|
value: prefs.get('editor.colorpicker.hotkey'),
|
||||||
|
|
|
@ -27,6 +27,20 @@ body {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************ checkbox & select************/
|
||||||
|
#options > div[class="option"] {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#basic-info-enabled {
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
padding-left: 16px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
/************ header ************/
|
/************ header ************/
|
||||||
#header {
|
#header {
|
||||||
width: 280px;
|
width: 280px;
|
||||||
|
@ -61,9 +75,7 @@ body {
|
||||||
margin-top: 0.1rem;
|
margin-top: 0.1rem;
|
||||||
min-height: 1.4rem;
|
min-height: 1.4rem;
|
||||||
}
|
}
|
||||||
input[type="checkbox"] {
|
|
||||||
margin-left: 0.1rem;
|
|
||||||
}
|
|
||||||
/* basic info */
|
/* basic info */
|
||||||
#basic-info {
|
#basic-info {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
@ -136,14 +148,21 @@ input:invalid {
|
||||||
margin-left: -13px;
|
margin-left: -13px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header summary h2 {
|
#header summary h2 {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-bottom: 1px dotted transparent;
|
border-bottom: 1px dotted transparent;
|
||||||
|
margin-top: .1em;
|
||||||
|
margin-bottom: .1em;
|
||||||
}
|
}
|
||||||
#header summary h2:hover {
|
|
||||||
|
#header summary:hover h2 {
|
||||||
border-color: #bbb;
|
border-color: #bbb;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header summary svg {
|
#header summary svg {
|
||||||
margin-top: -3px;
|
margin-top: -3px;
|
||||||
}
|
}
|
||||||
|
@ -159,8 +178,9 @@ input:invalid {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding-left: .25em;
|
padding-left: .25em;
|
||||||
}
|
}
|
||||||
#options .option.aligned > * {
|
#options .option.aligned > label {
|
||||||
padding-right: 0.25rem;
|
padding: .1rem .25rem 0 0;
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
.set-option-progress {
|
.set-option-progress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -306,7 +326,7 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 0.35rem;
|
margin-bottom: 0.35rem;
|
||||||
}
|
}
|
||||||
.applies-to li > *:not(button) {
|
.applies-to li > *:not(button):not(.select-resizer) {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
min-height: 1.4rem;
|
min-height: 1.4rem;
|
||||||
margin-left: 0.35rem;
|
margin-left: 0.35rem;
|
||||||
|
@ -396,9 +416,12 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
}
|
}
|
||||||
|
#help-popup.big,
|
||||||
|
#help-popup.wide {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
#help-popup.big {
|
#help-popup.big {
|
||||||
box-shadow: rgba(0, 0, 0, 0.45) 0px 0px 0px 100000px !important;
|
box-shadow: rgba(0, 0, 0, 0.45) 0px 0px 0px 100000px !important;
|
||||||
max-width: 100%;
|
|
||||||
left: calc(280px - 3rem);
|
left: calc(280px - 3rem);
|
||||||
}
|
}
|
||||||
#help-popup.big .CodeMirror {
|
#help-popup.big .CodeMirror {
|
||||||
|
@ -526,10 +549,11 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
||||||
/************ CSS beautifier ************/
|
/************ CSS beautifier ************/
|
||||||
.beautify-options {
|
.beautify-options {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-family: monospace;
|
|
||||||
}
|
}
|
||||||
.beautify-options div {
|
.beautify-options div {
|
||||||
float: left;
|
float: left;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
.beautify-options div[newline="true"] + div {
|
.beautify-options div[newline="true"] + div {
|
||||||
clear: left;
|
clear: left;
|
||||||
|
@ -537,18 +561,30 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
||||||
.beautify-options div[newline="true"] + div span[indent] {
|
.beautify-options div[newline="true"] + div span[indent] {
|
||||||
padding-left: 2rem;
|
padding-left: 2rem;
|
||||||
}
|
}
|
||||||
|
.beautify-options > label {
|
||||||
|
top: 1em;
|
||||||
|
margin: 1ex 0;
|
||||||
|
}
|
||||||
|
.firefox .beautify-options > label input {
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
.beautify-options:after {
|
.beautify-options:after {
|
||||||
clear: both;
|
clear: both;
|
||||||
display: block;
|
display: block;
|
||||||
content: " ";
|
content: "";
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
}
|
}
|
||||||
.beautify-options span {
|
.beautify-options span {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
.beautify-options select {
|
.beautify-options select {
|
||||||
border: none;
|
border: none;
|
||||||
background-color: rgba(0, 0, 0, 0.05);
|
background: linear-gradient(90deg, rgba(0, 0, 0, .05) 18px, rgba(0, 0, 0, .02) 24px);
|
||||||
|
font-family: monospace;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-left: 4px;
|
||||||
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************ single editor **************/
|
/************ single editor **************/
|
||||||
|
@ -671,12 +707,6 @@ html:not(.usercss) .usercss-only,
|
||||||
#options h2 {
|
#options h2 {
|
||||||
margin: 0 0 .5em;
|
margin: 0 0 .5em;
|
||||||
}
|
}
|
||||||
#options .aligned > *:not(.svg-inline-wrapper) {
|
|
||||||
margin: 1px 0 0 0; /* workaround the flowing-padding column bug in webkit */
|
|
||||||
padding-right: 0.4rem;
|
|
||||||
vertical-align: baseline;
|
|
||||||
min-height: 1.4rem;
|
|
||||||
}
|
|
||||||
.option label {
|
.option label {
|
||||||
line-height: 1.25rem;
|
line-height: 1.25rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
58
edit/edit.js
58
edit/edit.js
|
@ -92,14 +92,36 @@ function preinit() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// preload the theme so that CodeMirror can calculate its metrics in DOMContentLoaded->setupLivePrefs()
|
// preload the theme so that CodeMirror can calculate its metrics in DOMContentLoaded->setupLivePrefs()
|
||||||
new MutationObserver((mutations, observer) => {
|
document.head.appendChild(
|
||||||
const themeElement = $('#cm-theme');
|
$create('link#cm-theme', {
|
||||||
if (themeElement) {
|
rel: 'stylesheet',
|
||||||
themeElement.href = prefs.get('editor.theme') === 'default' ? ''
|
href: prefs.get('editor.theme') === 'default' ? '' :
|
||||||
: 'vendor/codemirror/theme/' + prefs.get('editor.theme') + '.css';
|
'vendor/codemirror/theme/' + prefs.get('editor.theme') + '.css'
|
||||||
observer.disconnect();
|
}));
|
||||||
|
|
||||||
|
// forcefully break long labels in aligned options to prevent the entire block layout from breaking
|
||||||
|
onDOMready().then(() => new Promise(requestAnimationFrame)).then(() => {
|
||||||
|
const maxWidth2ndChild = $$('#options .aligned > :nth-child(2)')
|
||||||
|
.sort((a, b) => b.offsetWidth - a.offsetWidth)[0].offsetWidth;
|
||||||
|
const widthFor1stChild = $('#options').offsetWidth - maxWidth2ndChild;
|
||||||
|
if (widthFor1stChild > 50) {
|
||||||
|
for (const el of $$('#options .aligned > :nth-child(1)')) {
|
||||||
|
if (el.offsetWidth > widthFor1stChild) {
|
||||||
|
el.style.cssText = 'word-break: break-all; hyphens: auto;';
|
||||||
}
|
}
|
||||||
}).observe(document, {subtree: true, childList: true});
|
}
|
||||||
|
} else {
|
||||||
|
const width = $('#options').clientWidth;
|
||||||
|
document.head.appendChild($create('style', `
|
||||||
|
#options .aligned > nth-child(1) {
|
||||||
|
max-width: 70px;
|
||||||
|
}
|
||||||
|
#options .aligned > nth-child(2) {
|
||||||
|
max-width: ${width - 70}px;
|
||||||
|
}
|
||||||
|
`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (chrome.windows) {
|
if (chrome.windows) {
|
||||||
queryTabs({currentWindow: true}).then(tabs => {
|
queryTabs({currentWindow: true}).then(tabs => {
|
||||||
|
@ -387,7 +409,7 @@ function save() {
|
||||||
|
|
||||||
saveStyleSafe({
|
saveStyleSafe({
|
||||||
id: styleId,
|
id: styleId,
|
||||||
name: name,
|
name: $('#name').value.trim(),
|
||||||
enabled: $('#enabled').checked,
|
enabled: $('#enabled').checked,
|
||||||
reason: 'editSave',
|
reason: 'editSave',
|
||||||
sections: getSectionsHashes()
|
sections: getSectionsHashes()
|
||||||
|
@ -457,22 +479,20 @@ function toMozillaFormat() {
|
||||||
|
|
||||||
function fromMozillaFormat() {
|
function fromMozillaFormat() {
|
||||||
const popup = showCodeMirrorPopup(t('styleFromMozillaFormatPrompt'),
|
const popup = showCodeMirrorPopup(t('styleFromMozillaFormatPrompt'),
|
||||||
$element({appendChild: [
|
$create([
|
||||||
$element({
|
$create('button', {
|
||||||
tag: 'button',
|
|
||||||
name: 'import-append',
|
name: 'import-append',
|
||||||
textContent: t('importAppendLabel'),
|
textContent: t('importAppendLabel'),
|
||||||
title: 'Ctrl-Enter:\n' + t('importAppendTooltip'),
|
title: 'Ctrl-Enter:\n' + t('importAppendTooltip'),
|
||||||
onclick: doImport,
|
onclick: doImport,
|
||||||
}),
|
}),
|
||||||
$element({
|
$create('button', {
|
||||||
tag: 'button',
|
|
||||||
name: 'import-replace',
|
name: 'import-replace',
|
||||||
textContent: t('importReplaceLabel'),
|
textContent: t('importReplaceLabel'),
|
||||||
title: 'Ctrl-Shift-Enter:\n' + t('importReplaceTooltip'),
|
title: 'Ctrl-Shift-Enter:\n' + t('importReplaceTooltip'),
|
||||||
onclick: () => doImport({replaceOldStyle: true}),
|
onclick: () => doImport({replaceOldStyle: true}),
|
||||||
}),
|
}),
|
||||||
]}));
|
]));
|
||||||
const contents = $('.contents', popup);
|
const contents = $('.contents', popup);
|
||||||
contents.insertBefore(popup.codebox.display.wrapper, contents.firstElementChild);
|
contents.insertBefore(popup.codebox.display.wrapper, contents.firstElementChild);
|
||||||
popup.codebox.focus();
|
popup.codebox.focus();
|
||||||
|
@ -522,10 +542,8 @@ function fromMozillaFormat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function showError(errors) {
|
function showError(errors) {
|
||||||
showHelp(t('styleFromMozillaFormatError'), $element({
|
showHelp(t('styleFromMozillaFormatError'),
|
||||||
tag: 'pre',
|
$create('pre', Array.isArray(errors) ? errors.join('\n') : errors));
|
||||||
textContent: Array.isArray(errors) ? errors.join('\n') : errors,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,7 +565,7 @@ function showToggleStyleHelp() {
|
||||||
|
|
||||||
function showHelp(title = '', body) {
|
function showHelp(title = '', body) {
|
||||||
const div = $('#help-popup');
|
const div = $('#help-popup');
|
||||||
div.classList.remove('big');
|
div.className = '';
|
||||||
const contents = $('.contents', div);
|
const contents = $('.contents', div);
|
||||||
contents.textContent = '';
|
contents.textContent = '';
|
||||||
if (body) {
|
if (body) {
|
||||||
|
@ -617,7 +635,7 @@ function showCodeMirrorPopup(title, html, options) {
|
||||||
|
|
||||||
function setGlobalProgress(done, total) {
|
function setGlobalProgress(done, total) {
|
||||||
const progressElement = $('#global-progress') ||
|
const progressElement = $('#global-progress') ||
|
||||||
total && document.body.appendChild($element({id: 'global-progress'}));
|
total && document.body.appendChild($create('#global-progress'));
|
||||||
if (total) {
|
if (total) {
|
||||||
const progress = (done / Math.max(done, total) * 100).toFixed(1);
|
const progress = (done / Math.max(done, total) * 100).toFixed(1);
|
||||||
progressElement.style.borderLeftWidth = progress + 'vw';
|
progressElement.style.borderLeftWidth = progress + 'vw';
|
||||||
|
|
136
edit/lint.js
136
edit/lint.js
|
@ -1,7 +1,6 @@
|
||||||
/* global CodeMirror messageBox */
|
/* global CodeMirror messageBox */
|
||||||
/* global editors makeSectionVisible showCodeMirrorPopup showHelp */
|
/* global editors makeSectionVisible showCodeMirrorPopup showHelp */
|
||||||
/* global loadScript require CSSLint stylelint */
|
/* global loadScript require CSSLint stylelint */
|
||||||
/* global makeLink */
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
onDOMready().then(loadLinterAssets);
|
onDOMready().then(loadLinterAssets);
|
||||||
|
@ -231,9 +230,7 @@ function updateLinter({immediately, linter = linterConfig.getName()} = {}) {
|
||||||
cm.options.gutters = guttersOption;
|
cm.options.gutters = guttersOption;
|
||||||
const el = $('.' + GUTTERS_CLASS, cm.display.gutters);
|
const el = $('.' + GUTTERS_CLASS, cm.display.gutters);
|
||||||
if (linter && !el) {
|
if (linter && !el) {
|
||||||
cm.display.gutters.appendChild($element({
|
cm.display.gutters.appendChild($create('.CodeMirror-gutter ' + GUTTERS_CLASS));
|
||||||
className: 'CodeMirror-gutter ' + GUTTERS_CLASS
|
|
||||||
}));
|
|
||||||
} else if (!linter && el) {
|
} else if (!linter && el) {
|
||||||
el.remove();
|
el.remove();
|
||||||
}
|
}
|
||||||
|
@ -281,9 +278,8 @@ function updateLintReportInternal(scope, {postponeNewIssues} = {}) {
|
||||||
const newMarkers = lintState.stylusMarkers = new Map();
|
const newMarkers = lintState.stylusMarkers = new Map();
|
||||||
const oldText = (lintState.body || {}).textContentCached || '';
|
const oldText = (lintState.body || {}).textContentCached || '';
|
||||||
const activeLine = cm.getCursor().line;
|
const activeLine = cm.getCursor().line;
|
||||||
const body = !(lintState.marked || {}).length ? {} : $element({
|
const body = !(lintState.marked || {}).length ? {} :
|
||||||
tag: 'tbody',
|
$create('tbody', lintState.marked.map(mark => {
|
||||||
appendChild: lintState.marked.map(mark => {
|
|
||||||
const info = mark.__annotation;
|
const info = mark.__annotation;
|
||||||
const {line, ch} = info.from;
|
const {line, ch} = info.from;
|
||||||
const isActiveLine = line === activeLine;
|
const isActiveLine = line === activeLine;
|
||||||
|
@ -294,27 +290,15 @@ function updateLintReportInternal(scope, {postponeNewIssues} = {}) {
|
||||||
oldMarkers.delete(pos);
|
oldMarkers.delete(pos);
|
||||||
}
|
}
|
||||||
newMarkers.set(pos, message);
|
newMarkers.set(pos, message);
|
||||||
return $element({
|
return $create(`tr.${info.severity}`, [
|
||||||
tag: 'tr',
|
$create('td', {attributes: {role: 'severity'}, dataset: {rule: info.rule}},
|
||||||
className: info.severity,
|
$create('.CodeMirror-lint-marker-' + info.severity, info.severity)),
|
||||||
appendChild: [
|
$create('td', {attributes: {role: 'line'}}, line + 1),
|
||||||
$element({
|
$create('td', {attributes: {role: 'sep'}}, ':'),
|
||||||
tag: 'td',
|
$create('td', {attributes: {role: 'col'}}, ch + 1),
|
||||||
attributes: {role: 'severity'},
|
$create('td', {attributes: {role: 'message'}, title}, message),
|
||||||
dataset: {rule: info.rule},
|
]);
|
||||||
appendChild: $element({
|
}));
|
||||||
className: 'CodeMirror-lint-marker-' + info.severity,
|
|
||||||
textContent: info.severity,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
$element({tag: 'td', attributes: {role: 'line'}, textContent: line + 1}),
|
|
||||||
$element({tag: 'td', attributes: {role: 'sep'}, textContent: ':'}),
|
|
||||||
$element({tag: 'td', attributes: {role: 'col'}, textContent: ch + 1}),
|
|
||||||
$element({tag: 'td', attributes: {role: 'message'}, textContent: message, title}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
})
|
|
||||||
});
|
|
||||||
body.textContentCached = body.textContent || '';
|
body.textContentCached = body.textContent || '';
|
||||||
lintState.body = body.textContentCached && body;
|
lintState.body = body.textContentCached && body;
|
||||||
result.changed |= oldText !== body.textContentCached;
|
result.changed |= oldText !== body.textContentCached;
|
||||||
|
@ -340,14 +324,10 @@ function renderLintReport(someBlockChanged) {
|
||||||
if (!body) {
|
if (!body) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const newBlock = $element({
|
const newBlock = $create('table', {cm}, [
|
||||||
tag: 'table',
|
$create('caption', label + ' ' + (index + 1)),
|
||||||
appendChild: [
|
|
||||||
$element({tag: 'caption', textContent: label + ' ' + (index + 1)}),
|
|
||||||
body,
|
body,
|
||||||
],
|
]);
|
||||||
cm,
|
|
||||||
});
|
|
||||||
newContent.appendChild(newBlock);
|
newContent.appendChild(newBlock);
|
||||||
issueCount += newBlock.rows.length;
|
issueCount += newBlock.rows.length;
|
||||||
|
|
||||||
|
@ -386,38 +366,36 @@ function showLintHelp() {
|
||||||
? 'https://stylelint.io/user-guide/rules/'
|
? 'https://stylelint.io/user-guide/rules/'
|
||||||
// some CSSLint rules do not have a url
|
// some CSSLint rules do not have a url
|
||||||
: 'https://github.com/CSSLint/csslint/issues/535';
|
: 'https://github.com/CSSLint/csslint/issues/535';
|
||||||
let headerLink, template;
|
let headerLink, template, csslintRules;
|
||||||
if (linter === 'csslint') {
|
if (linter === 'csslint') {
|
||||||
headerLink = makeLink('https://github.com/CSSLint/csslint/wiki/Rules-by-ID', 'CSSLint');
|
headerLink = $createLink('https://github.com/CSSLint/csslint/wiki/Rules-by-ID', 'CSSLint');
|
||||||
template = ruleID => {
|
template = ruleID => {
|
||||||
const rule = linterConfig.allRuleIds.csslint.find(rule => rule.id === ruleID);
|
const rule = csslintRules.find(rule => rule.id === ruleID);
|
||||||
return rule &&
|
return rule &&
|
||||||
$element({tag: 'li', appendChild: [
|
$create('li', [
|
||||||
$element({tag: 'b', appendChild: makeLink(rule.url || baseUrl, rule.name)}),
|
$create('b', $createLink(rule.url || baseUrl, rule.name)),
|
||||||
$element({tag: 'br'}),
|
$create('br'),
|
||||||
rule.desc,
|
rule.desc,
|
||||||
]});
|
]);
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
headerLink = makeLink(baseUrl, 'stylelint');
|
headerLink = $createLink(baseUrl, 'stylelint');
|
||||||
template = rule =>
|
template = rule =>
|
||||||
$element({
|
$create('li',
|
||||||
tag: 'li',
|
rule === 'CssSyntaxError' ? rule : $createLink(baseUrl + rule, rule));
|
||||||
appendChild: makeLink(baseUrl + rule, rule),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
const header = t('linterIssuesHelp', '\x01').split('\x01');
|
const header = t('linterIssuesHelp', '\x01').split('\x01');
|
||||||
const activeRules = new Set($$('#lint td[role="severity"]').map(el => el.dataset.rule));
|
const activeRules = new Set($$('#lint td[role="severity"]').map(el => el.dataset.rule));
|
||||||
return showHelp(t('linterIssues'),
|
Promise.resolve(linter !== 'csslint' || linterConfig.invokeWorker({action: 'getAllRuleInfos'}))
|
||||||
$element({appendChild: [
|
.then(data => {
|
||||||
|
csslintRules = data;
|
||||||
|
showHelp(t('linterIssues'),
|
||||||
|
$create([
|
||||||
header[0], headerLink, header[1],
|
header[0], headerLink, header[1],
|
||||||
$element({
|
$create('ul.rules', [...activeRules.values()].map(template)),
|
||||||
tag: 'ul',
|
])
|
||||||
className: 'rules',
|
|
||||||
appendChild: [...activeRules.values()].map(template),
|
|
||||||
}),
|
|
||||||
]})
|
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function showLinterErrorMessage(title, contents, popup) {
|
function showLinterErrorMessage(title, contents, popup) {
|
||||||
|
@ -465,41 +443,21 @@ function setupLinterPopup(config) {
|
||||||
});
|
});
|
||||||
|
|
||||||
function makeFooter() {
|
function makeFooter() {
|
||||||
const makeButton = (className, onclick, text, options = {}) =>
|
return $create('div', [
|
||||||
$element(Object.assign(options, {
|
$create('p', [
|
||||||
className,
|
|
||||||
onclick,
|
|
||||||
tag: 'button',
|
|
||||||
type: 'button',
|
|
||||||
textContent: t(text),
|
|
||||||
}));
|
|
||||||
return $element({
|
|
||||||
appendChild: [
|
|
||||||
$element({
|
|
||||||
tag: 'p',
|
|
||||||
appendChild: [
|
|
||||||
t('linterRulesLink') + ' ',
|
t('linterRulesLink') + ' ',
|
||||||
$element({
|
$createLink(
|
||||||
tag: 'a',
|
linter === 'stylelint'
|
||||||
target: '_blank',
|
|
||||||
href: linter === 'stylelint'
|
|
||||||
? 'https://stylelint.io/user-guide/rules/'
|
? 'https://stylelint.io/user-guide/rules/'
|
||||||
: 'https://github.com/CSSLint/csslint/wiki/Rules-by-ID',
|
: 'https://github.com/CSSLint/csslint/wiki/Rules-by-ID',
|
||||||
textContent: linterTitle
|
linterTitle),
|
||||||
}),
|
linter === 'csslint' ? ' ' + t('linterCSSLintSettings') : '',
|
||||||
linter === 'csslint' ? ' ' + t('linterCSSLintSettings') : ''
|
]),
|
||||||
]
|
$create('button.save', {onclick: save, title: 'Ctrl-Enter'}, t('styleSaveLabel')),
|
||||||
}),
|
$create('button.cancel', {onclick: cancel}, t('confirmClose')),
|
||||||
makeButton('save', save, 'styleSaveLabel', {title: 'Ctrl-Enter'}),
|
$create('button.reset', {onclick: reset, title: t('linterResetMessage')}, t('genericResetLabel')),
|
||||||
makeButton('cancel', cancel, 'confirmClose'),
|
$create('span.saved-message', t('genericSavedMessage')),
|
||||||
makeButton('reset', reset, 'genericResetLabel', {title: t('linterResetMessage')}),
|
]);
|
||||||
$element({
|
|
||||||
tag: 'span',
|
|
||||||
className: 'saved-message',
|
|
||||||
textContent: t('genericSavedMessage')
|
|
||||||
})
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function save(event) {
|
function save(event) {
|
||||||
|
@ -516,9 +474,7 @@ function setupLinterPopup(config) {
|
||||||
if (invalid.length) {
|
if (invalid.length) {
|
||||||
showLinterErrorMessage(linter, [
|
showLinterErrorMessage(linter, [
|
||||||
t('linterInvalidConfigError'),
|
t('linterInvalidConfigError'),
|
||||||
$element({tag: 'ul', appendChild: invalid.map(name =>
|
$create('ul', invalid.map(name => $create('li', name))),
|
||||||
$element({tag: 'li', textContent: name})),
|
|
||||||
}),
|
|
||||||
], popup);
|
], popup);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,8 @@
|
||||||
const rx = query instanceof RegExp && query;
|
const rx = query instanceof RegExp && query;
|
||||||
const sel = this.getSelection();
|
const sel = this.getSelection();
|
||||||
// current query differs from the selected text => remove the overlay
|
// current query differs from the selected text => remove the overlay
|
||||||
if (sel && (rx && !rx.test(sel) || sel.toLowerCase() !== query)) {
|
if (sel && rx && !rx.test(sel) || sel.toLowerCase() !== originalToken.toLowerCase()) {
|
||||||
|
helper.query = helper.originalToken = sel;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if token under cursor has changed => remove the overlay
|
// if token under cursor has changed => remove the overlay
|
||||||
|
@ -160,6 +161,8 @@
|
||||||
// in case the original addon won't highlight anything we need to actually remove the overlays
|
// in case the original addon won't highlight anything we need to actually remove the overlays
|
||||||
// by setting a timer that runs in the next event loop cycle and can be canceled in this cycle
|
// by setting a timer that runs in the next event loop cycle and can be canceled in this cycle
|
||||||
hookTimer: setTimeout(removeOverlayIfExpired, 0, this, state),
|
hookTimer: setTimeout(removeOverlayIfExpired, 0, this, state),
|
||||||
|
originalToken,
|
||||||
|
query,
|
||||||
};
|
};
|
||||||
// fool the original addon so it won't invoke state.matchesonscroll.clear()
|
// fool the original addon so it won't invoke state.matchesonscroll.clear()
|
||||||
state.matchesonscroll = null;
|
state.matchesonscroll = null;
|
||||||
|
|
|
@ -25,17 +25,17 @@ var regExpTester = (() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isShowed() {
|
function isShown() {
|
||||||
return Boolean($('.regexp-report'));
|
return Boolean($('.regexp-report'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle(state = !isShowed()) {
|
function toggle(state = !isShown()) {
|
||||||
if (state && !isShowed()) {
|
if (state && !isShown()) {
|
||||||
if (!isInit) {
|
if (!isInit) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
showHelp('', $element({className: 'regexp-report'}));
|
showHelp('', $create('.regexp-report'));
|
||||||
} else if (!state && isShowed()) {
|
} else if (!state && isShown()) {
|
||||||
if (isInit) {
|
if (isInit) {
|
||||||
uninit();
|
uninit();
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ var regExpTester = (() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function update(newRegexps) {
|
function update(newRegexps) {
|
||||||
if (!isShowed()) {
|
if (!isShown()) {
|
||||||
if (isInit) {
|
if (isInit) {
|
||||||
uninit();
|
uninit();
|
||||||
}
|
}
|
||||||
|
@ -108,19 +108,19 @@ var regExpTester = (() => {
|
||||||
const faviconUrl = url.startsWith(URLS.ownOrigin)
|
const faviconUrl = url.startsWith(URLS.ownOrigin)
|
||||||
? OWN_ICON
|
? OWN_ICON
|
||||||
: GET_FAVICON_URL + new URL(url).hostname;
|
: GET_FAVICON_URL + new URL(url).hostname;
|
||||||
const icon = $element({tag: 'img', src: faviconUrl});
|
const icon = $create('img', {src: faviconUrl});
|
||||||
if (match.text.length === url.length) {
|
if (match.text.length === url.length) {
|
||||||
full.push($element({appendChild: [
|
full.push($create('div', [
|
||||||
icon,
|
icon,
|
||||||
url,
|
url,
|
||||||
]}));
|
]));
|
||||||
} else {
|
} else {
|
||||||
partial.push($element({appendChild: [
|
partial.push($create('div', [
|
||||||
icon,
|
icon,
|
||||||
url.substr(0, match.pos),
|
url.substr(0, match.pos),
|
||||||
$element({tag: 'mark', textContent: match.text}),
|
$create('mark', match.text),
|
||||||
url.substr(match.pos + match.text.length),
|
url.substr(match.pos + match.text.length),
|
||||||
]}));
|
]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (full.length) {
|
if (full.length) {
|
||||||
|
@ -131,33 +131,28 @@ var regExpTester = (() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// render stats
|
// render stats
|
||||||
const report = $element({className: 'regexp-report'});
|
const report = $create('.regexp-report');
|
||||||
const br = $element({tag: 'br'});
|
const br = $create('br');
|
||||||
for (const type in stats) {
|
for (const type in stats) {
|
||||||
// top level groups: full, partial, none, invalid
|
// top level groups: full, partial, none, invalid
|
||||||
const {label, data} = stats[type];
|
const {label, data} = stats[type];
|
||||||
if (!data.length) {
|
if (!data.length) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const block = report.appendChild($element({
|
const block = report.appendChild(
|
||||||
tag: 'details',
|
$create('details', {open: true, dataset: {type}}, [
|
||||||
open: true,
|
$create('summary', label),
|
||||||
dataset: {type},
|
]));
|
||||||
appendChild: $element({tag: 'summary', appendChild: label}),
|
|
||||||
}));
|
|
||||||
// 2nd level: regexp text
|
// 2nd level: regexp text
|
||||||
for (const {text, urls} of data) {
|
for (const {text, urls} of data) {
|
||||||
if (urls) {
|
if (urls) {
|
||||||
// type is partial or full
|
// type is partial or full
|
||||||
block.appendChild($element({
|
block.appendChild(
|
||||||
tag: 'details',
|
$create('details', {open: true}, [
|
||||||
open: true,
|
$create('summary', text),
|
||||||
appendChild: [
|
|
||||||
$element({tag: 'summary', textContent: text}),
|
|
||||||
// 3rd level: tab urls
|
// 3rd level: tab urls
|
||||||
...urls,
|
...urls,
|
||||||
],
|
]));
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
// type is none or invalid
|
// type is none or invalid
|
||||||
block.appendChild(document.createTextNode(text));
|
block.appendChild(document.createTextNode(text));
|
||||||
|
@ -165,9 +160,14 @@ var regExpTester = (() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
report.appendChild(
|
||||||
|
$create('p.regexp-report-note',
|
||||||
|
t('styleRegexpTestNote')
|
||||||
|
.split(/(\\+)/)
|
||||||
|
.map(s => (s.startsWith('\\') ? $create('code', s) : s))));
|
||||||
showHelp(t('styleRegexpTestTitle'), report);
|
showHelp(t('styleRegexpTestTitle'), report);
|
||||||
|
|
||||||
$('.regexp-report').onclick = event => {
|
report.onclick = event => {
|
||||||
const target = event.target.closest('a, .regexp-report div');
|
const target = event.target.closest('a, .regexp-report div');
|
||||||
if (target) {
|
if (target) {
|
||||||
openURL({
|
openURL({
|
||||||
|
|
|
@ -390,11 +390,11 @@ function getSections() {
|
||||||
|
|
||||||
function getSectionsHashes() {
|
function getSectionsHashes() {
|
||||||
const sections = [];
|
const sections = [];
|
||||||
getSections().forEach(div => {
|
for (const div of getSections()) {
|
||||||
const meta = {urls: [], urlPrefixes: [], domains: [], regexps: []};
|
const meta = {urls: [], urlPrefixes: [], domains: [], regexps: []};
|
||||||
for (const li of $('.applies-to-list', div).childNodes) {
|
for (const li of $('.applies-to-list', div).childNodes) {
|
||||||
if (li.className === template.appliesToEverything.className) {
|
if (li.className === template.appliesToEverything.className) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
const type = $('[name=applies-type]', li).value;
|
const type = $('[name=applies-type]', li).value;
|
||||||
const value = $('[name=applies-value]', li).value;
|
const value = $('[name=applies-value]', li).value;
|
||||||
|
@ -404,11 +404,11 @@ function getSectionsHashes() {
|
||||||
}
|
}
|
||||||
const code = div.CodeMirror.getValue();
|
const code = div.CodeMirror.getValue();
|
||||||
if (/^\s*$/.test(code) && Object.keys(meta).length === 0) {
|
if (/^\s*$/.test(code) && Object.keys(meta).length === 0) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
meta.code = code;
|
meta.code = code;
|
||||||
sections.push(meta);
|
sections.push(meta);
|
||||||
});
|
}
|
||||||
return sections;
|
return sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ function showKeyMapHelp() {
|
||||||
if (index > offset) {
|
if (index > offset) {
|
||||||
cell.appendChild(document.createTextNode(text.substring(offset, index)));
|
cell.appendChild(document.createTextNode(text.substring(offset, index)));
|
||||||
}
|
}
|
||||||
cell.appendChild($element({tag: 'mark', textContent: match}));
|
cell.appendChild($create('mark', match));
|
||||||
offset = index + match.length;
|
offset = index + match.length;
|
||||||
});
|
});
|
||||||
if (offset + 1 !== text.length) {
|
if (offset + 1 !== text.length) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* global CodeMirror dirtyReporter initLint */
|
/* global CodeMirror dirtyReporter initLint */
|
||||||
/* global showToggleStyleHelp goBackToManage updateLintReportIfEnabled */
|
/* global showToggleStyleHelp goBackToManage updateLintReportIfEnabled */
|
||||||
/* global editors linterConfig updateLinter regExpTester mozParser */
|
/* global editors linterConfig updateLinter regExpTester mozParser */
|
||||||
/* global makeLink createAppliesToLineWidget messageBox */
|
/* global createAppliesToLineWidget messageBox */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function createSourceEditor(style) {
|
function createSourceEditor(style) {
|
||||||
|
@ -12,9 +12,7 @@ function createSourceEditor(style) {
|
||||||
$('#name').disabled = true;
|
$('#name').disabled = true;
|
||||||
$('#mozilla-format-container').remove();
|
$('#mozilla-format-container').remove();
|
||||||
$('#sections').textContent = '';
|
$('#sections').textContent = '';
|
||||||
$('#sections').appendChild(
|
$('#sections').appendChild($create('.single-editor'));
|
||||||
$element({className: 'single-editor'})
|
|
||||||
);
|
|
||||||
|
|
||||||
const dirty = dirtyReporter();
|
const dirty = dirtyReporter();
|
||||||
dirty.onChange(() => {
|
dirty.onChange(() => {
|
||||||
|
@ -236,15 +234,12 @@ function createSourceEditor(style) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const contents = Array.isArray(err) ?
|
const contents = Array.isArray(err) ?
|
||||||
$element({tag: 'pre', textContent: err.join('\n')}) :
|
$create('pre', err.join('\n')) :
|
||||||
[String(err)];
|
[String(err)];
|
||||||
if (Number.isInteger(err.index)) {
|
if (Number.isInteger(err.index)) {
|
||||||
const pos = cm.posFromIndex(err.index);
|
const pos = cm.posFromIndex(err.index);
|
||||||
contents[0] += ` (line ${pos.line + 1} col ${pos.ch + 1})`;
|
contents[0] += ` (line ${pos.line + 1} col ${pos.ch + 1})`;
|
||||||
contents.push($element({
|
contents.push($create('pre', drawLinePointer(pos)));
|
||||||
tag: 'pre',
|
|
||||||
textContent: drawLinePointer(pos)
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
messageBox.alert(contents);
|
messageBox.alert(contents);
|
||||||
});
|
});
|
||||||
|
|
95
global.css
Normal file
95
global.css
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
.svg-icon.checked {
|
||||||
|
position: absolute;
|
||||||
|
height: 8px;
|
||||||
|
width: 8px;
|
||||||
|
display: none;
|
||||||
|
fill: #000;
|
||||||
|
margin: 2px 0 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]:not(.slider):checked + .svg-icon.checked {
|
||||||
|
display: inline-flex;
|
||||||
|
transition: fill .1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]:not(.slider) {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
-moz-appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
pointer-events: none;
|
||||||
|
border: 1px solid hsl(0, 0%, 46%);
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
display: inline-flex;
|
||||||
|
border-radius: 2px;
|
||||||
|
background-color: hsla(0, 0%, 0%, .1);
|
||||||
|
outline: none;
|
||||||
|
margin: 0;
|
||||||
|
transition: background-color .1s, border-color .1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]:not(.slider):hover {
|
||||||
|
border-color: hsl(0, 0%, 32%);
|
||||||
|
background-color: hsl(0, 0%, 82%);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]:not(.slider):checked + .svg-icon.checked {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
transition: color .1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
-moz-appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
height: 22px;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 1px solid hsl(0, 0%, 66%);
|
||||||
|
padding: 0 20px 0 6px;
|
||||||
|
transition: color .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.firefox select {
|
||||||
|
padding: 0 20px 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-resizer {
|
||||||
|
display: inline-flex!important;
|
||||||
|
cursor: default;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.svg-icon.select-arrow {
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: default;
|
||||||
|
display: inline-flex;
|
||||||
|
height: 14px;
|
||||||
|
width: 14px;
|
||||||
|
fill: #000;
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
right: 4px;
|
||||||
|
transition: fill .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (-moz-appearance: none) {
|
||||||
|
.moz-appearance-bug .svg-icon.checked {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.moz-appearance-bug input[type="checkbox"] {
|
||||||
|
-moz-appearance: checkbox !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.moz-appearance-bug button {
|
||||||
|
padding-left: .75ex;
|
||||||
|
padding-right: .75ex;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
<title>Loading...</title>
|
<title>Loading...</title>
|
||||||
|
<link rel="stylesheet" href="global.css">
|
||||||
<link rel="stylesheet" href="/install-usercss/install-usercss.css">
|
<link rel="stylesheet" href="/install-usercss/install-usercss.css">
|
||||||
<script src="/js/messaging.js"></script>
|
<script src="/js/messaging.js"></script>
|
||||||
<script src="/js/prefs.js"></script>
|
<script src="/js/prefs.js"></script>
|
||||||
|
@ -61,10 +62,12 @@
|
||||||
<button class="install" i18n-text="installButton"></button>
|
<button class="install" i18n-text="installButton"></button>
|
||||||
<label class="set-update-url">
|
<label class="set-update-url">
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
<span></span>
|
<span></span>
|
||||||
</label>
|
</label>
|
||||||
<label class="live-reload">
|
<label class="live-reload">
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
<span i18n-text="liveReloadLabel"></span>
|
<span i18n-text="liveReloadLabel"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -86,6 +89,14 @@
|
||||||
<div class="warnings"></div>
|
<div class="warnings"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/install-usercss/install-usercss.js"></script>
|
<script src="/install-usercss/install-usercss.js"></script>
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" style="display: none !important;">
|
||||||
|
<symbol id="svg-icon-checked" viewBox="0 0 1000 1000">
|
||||||
|
<path fill-rule="evenodd" d="M983.2,184.3L853,69.8c-4-3.5-9.3-5.3-14.5-5c-5.3,0.4-10.3,2.8-13.8,6.8L352.3,609.2L184.4,386.9c-3.2-4.2-8-7-13.2-7.8c-5.3-0.8-10.6,0.6-14.9,3.9L18,487.5c-8.8,6.7-10.6,19.3-3.9,28.1L325,927.2c3.6,4.8,9.3,7.7,15.3,8c0.2,0,0.5,0,0.7,0c5.8,0,11.3-2.5,15.1-6.8L985,212.6C992.3,204.3,991.5,191.6,983.2,184.3z"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -239,6 +239,10 @@ li {
|
||||||
user-select: auto;
|
user-select: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
padding-left: 16px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
/* spinner: https://github.com/loadingio/css-spinner */
|
/* spinner: https://github.com/loadingio/css-spinner */
|
||||||
|
|
||||||
@keyframes lds-spinner {
|
@keyframes lds-spinner {
|
||||||
|
@ -353,58 +357,6 @@ li {
|
||||||
-webkit-animation-delay: 0s;
|
-webkit-animation-delay: 0s;
|
||||||
animation-delay: 0s;
|
animation-delay: 0s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* https://github.com/lukehaas/css-loaders */
|
|
||||||
/*
|
|
||||||
.spinner {
|
|
||||||
--color: currentColor;
|
|
||||||
--background-color: currentColor;
|
|
||||||
font-size: 10px;
|
|
||||||
margin: 50px auto;
|
|
||||||
text-indent: -9999em;
|
|
||||||
width: 200px;
|
|
||||||
height: 200px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #ffffff;
|
|
||||||
background: -moz-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
|
|
||||||
background: -webkit-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
|
|
||||||
background: -o-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
|
|
||||||
background: -ms-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
|
|
||||||
background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
|
|
||||||
position: relative;
|
|
||||||
-webkit-animation: load3 1.4s infinite linear;
|
|
||||||
animation: load3 1.4s infinite linear;
|
|
||||||
-webkit-transform: translateZ(0);
|
|
||||||
-ms-transform: translateZ(0);
|
|
||||||
transform: translateZ(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner:before {
|
|
||||||
width: 50%;
|
|
||||||
height: 50%;
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 100% 0 0 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
content: '';
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner:after {
|
|
||||||
background: #0dc5c1;
|
|
||||||
width: 75%;
|
|
||||||
height: 75%;
|
|
||||||
border-radius: 50%;
|
|
||||||
content: '';
|
|
||||||
margin: auto;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
@-webkit-keyframes load3 {
|
@-webkit-keyframes load3 {
|
||||||
0% {
|
0% {
|
||||||
-webkit-transform: rotate(0deg);
|
-webkit-transform: rotate(0deg);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global CodeMirror semverCompare makeLink closeCurrentTab */
|
/* global CodeMirror semverCompare closeCurrentTab */
|
||||||
/* global messageBox download chromeLocal */
|
/* global messageBox download chromeLocal */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
@ -44,11 +44,8 @@
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!installed) {
|
if (!installed) {
|
||||||
const div = $element({});
|
$('.header').appendChild($create('.lds-spinner',
|
||||||
$('.header').appendChild($element({
|
new Array(12).fill($create('div')).map(e => e.cloneNode())));
|
||||||
className: 'lds-spinner',
|
|
||||||
appendChild: new Array(12).fill(div).map(e => e.cloneNode()),
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
|
@ -101,8 +98,7 @@
|
||||||
|
|
||||||
$('.applies-to').textContent = '';
|
$('.applies-to').textContent = '';
|
||||||
getAppliesTo(style).forEach(pattern =>
|
getAppliesTo(style).forEach(pattern =>
|
||||||
$('.applies-to').appendChild($element({tag: 'li', textContent: pattern}))
|
$('.applies-to').appendChild($create('li', pattern)));
|
||||||
);
|
|
||||||
|
|
||||||
$('.external-link').textContent = '';
|
$('.external-link').textContent = '';
|
||||||
const externalLink = makeExternalLink();
|
const externalLink = makeExternalLink();
|
||||||
|
@ -125,46 +121,35 @@
|
||||||
const [, name, email, url] = match;
|
const [, name, email, url] = match;
|
||||||
const frag = document.createDocumentFragment();
|
const frag = document.createDocumentFragment();
|
||||||
if (email) {
|
if (email) {
|
||||||
frag.appendChild(makeLink(`mailto:${email}`, name));
|
frag.appendChild($createLink(`mailto:${email}`, name));
|
||||||
} else {
|
} else {
|
||||||
frag.appendChild($element({
|
frag.appendChild($create('span', name));
|
||||||
tag: 'span',
|
|
||||||
textContent: name
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
if (url) {
|
if (url) {
|
||||||
frag.appendChild(makeLink(
|
frag.appendChild($createLink(url,
|
||||||
url,
|
$create('SVG:svg.svg-icon', {viewBox: '0 0 20 20'},
|
||||||
$element({
|
$create('SVG:path', {
|
||||||
tag: 'svg#svg',
|
|
||||||
viewBox: '0 0 20 20',
|
|
||||||
class: 'svg-icon',
|
|
||||||
appendChild: $element({
|
|
||||||
tag: 'svg#path',
|
|
||||||
d: 'M4,4h5v2H6v8h8v-3h2v5H4V4z M11,3h6v6l-2-2l-4,4L9,9l4-4L11,3z'
|
d: 'M4,4h5v2H6v8h8v-3h2v5H4V4z M11,3h6v6l-2-2l-4,4L9,9l4-4L11,3z'
|
||||||
})
|
}))
|
||||||
})
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return frag;
|
return frag;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeExternalLink() {
|
function makeExternalLink() {
|
||||||
const urls = [];
|
const urls = [
|
||||||
if (data.homepageURL) {
|
data.homepageURL && [data.homepageURL, t('externalHomepage')],
|
||||||
urls.push([data.homepageURL, t('externalHomepage')]);
|
data.supportURL && [data.supportURL, t('externalSupport')],
|
||||||
}
|
];
|
||||||
if (data.supportURL) {
|
return (data.homepageURL || data.supportURL) && (
|
||||||
urls.push([data.supportURL, t('externalSupport')]);
|
$create('div', [
|
||||||
}
|
$create('h3', t('externalLink')),
|
||||||
if (urls.length) {
|
$create('ul', urls.map(args => args &&
|
||||||
return $element({appendChild: [
|
$create('li',
|
||||||
$element({tag: 'h3', textContent: t('externalLink')}),
|
$createLink(...args)
|
||||||
$element({tag: 'ul', appendChild: urls.map(args =>
|
)
|
||||||
$element({tag: 'li', appendChild: makeLink(...args)})
|
))
|
||||||
)})
|
]));
|
||||||
]});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function installButtonClass() {
|
function installButtonClass() {
|
||||||
|
@ -220,8 +205,8 @@
|
||||||
function initSourceCode(sourceCode) {
|
function initSourceCode(sourceCode) {
|
||||||
cm.setValue(sourceCode);
|
cm.setValue(sourceCode);
|
||||||
cm.refresh();
|
cm.refresh();
|
||||||
sendMessage({method: 'buildUsercss', sourceCode, checkDup: true})
|
BG.usercssHelper.build(BG.deepCopy({sourceCode, checkDup: true}))
|
||||||
.then(init)
|
.then(r => init(deepCopy(r)))
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
$('.header').classList.add('meta-init-error');
|
$('.header').classList.add('meta-init-error');
|
||||||
showError(err);
|
showError(err);
|
||||||
|
@ -229,10 +214,43 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildWarning(err) {
|
function buildWarning(err) {
|
||||||
return $element({className: 'warning', appendChild: [
|
const contents = Array.isArray(err) ?
|
||||||
|
$create('pre', err.join('\n')) :
|
||||||
|
[err && err.message || err || 'Unknown error'];
|
||||||
|
if (Number.isInteger(err.index)) {
|
||||||
|
const pos = cm.posFromIndex(err.index);
|
||||||
|
contents[0] = `${pos.line + 1}:${pos.ch + 1} ` + contents[0];
|
||||||
|
contents.push($create('pre', drawLinePointer(pos)));
|
||||||
|
setTimeout(() => {
|
||||||
|
cm.scrollIntoView({line: pos.line + 1, ch: pos.ch}, window.innerHeight / 4);
|
||||||
|
cm.setCursor(pos.line, pos.ch + 1);
|
||||||
|
cm.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return $create('.warning', [
|
||||||
t('parseUsercssError'),
|
t('parseUsercssError'),
|
||||||
$element({tag: 'pre', textContent: String(err)})
|
'\n',
|
||||||
]});
|
...contents,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawLinePointer(pos) {
|
||||||
|
const SIZE = 60;
|
||||||
|
const line = cm.getLine(pos.line);
|
||||||
|
const numTabs = pos.ch + 1 - line.slice(0, pos.ch + 1).replace(/\t/g, '').length;
|
||||||
|
const pointer = ' '.repeat(pos.ch) + '^';
|
||||||
|
const start = Math.max(Math.min(pos.ch - SIZE / 2, line.length - SIZE), 0);
|
||||||
|
const end = Math.min(Math.max(pos.ch + SIZE / 2, SIZE), line.length);
|
||||||
|
const leftPad = start !== 0 ? '...' : '';
|
||||||
|
const rightPad = end !== line.length ? '...' : '';
|
||||||
|
return (
|
||||||
|
leftPad +
|
||||||
|
line.slice(start, end).replace(/\t/g, ' '.repeat(cm.options.tabSize)) +
|
||||||
|
rightPad +
|
||||||
|
'\n' +
|
||||||
|
' '.repeat(leftPad.length + numTabs * cm.options.tabSize) +
|
||||||
|
pointer.slice(start, end)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function init({style, dup}) {
|
function init({style, dup}) {
|
||||||
|
@ -245,7 +263,7 @@
|
||||||
// update UI
|
// update UI
|
||||||
if (versionTest < 0) {
|
if (versionTest < 0) {
|
||||||
$('.actions').parentNode.insertBefore(
|
$('.actions').parentNode.insertBefore(
|
||||||
$element({className: 'warning', textContent: t('versionInvalidOlder')}),
|
$create('.warning', t('versionInvalidOlder')),
|
||||||
$('.actions')
|
$('.actions')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -258,9 +276,10 @@
|
||||||
data.version,
|
data.version,
|
||||||
]))
|
]))
|
||||||
).then(ok => ok &&
|
).then(ok => ok &&
|
||||||
sendMessage(Object.assign(style, {method: 'saveUsercss', reason: 'update'}))
|
BG.usercssHelper.save(BG.deepCopy(Object.assign(style, {reason: 'update'})))
|
||||||
.then(install)
|
.then(r => install(deepCopy(r)))
|
||||||
.catch(err => messageBox.alert(t('styleInstallFailed', err))));
|
.catch(err => messageBox.alert(t('styleInstallFailed', err)))
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// set updateUrl
|
// set updateUrl
|
||||||
|
|
91
js/dom.js
91
js/dom.js
|
@ -73,8 +73,7 @@ if (!chrome.app && chrome.windows) {
|
||||||
}
|
}
|
||||||
const iconset = ['', 'light/'][prefs.get('iconset')] || '';
|
const iconset = ['', 'light/'][prefs.get('iconset')] || '';
|
||||||
for (const size of [38, 32, 19, 16]) {
|
for (const size of [38, 32, 19, 16]) {
|
||||||
document.head.appendChild($element({
|
document.head.appendChild($create('link', {
|
||||||
tag: 'link',
|
|
||||||
rel: 'icon',
|
rel: 'icon',
|
||||||
href: `/images/icon/${iconset}${size}.png`,
|
href: `/images/icon/${iconset}${size}.png`,
|
||||||
sizes: size + 'x' + size,
|
sizes: size + 'x' + size,
|
||||||
|
@ -167,47 +166,103 @@ function $$(selector, base = document) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function $element(opt) {
|
function $create(selector = 'div', properties, children) {
|
||||||
// tag: string, default 'div', may include namespace like 'ns#tag'
|
/*
|
||||||
// appendChild: element/string or an array of elements/strings
|
$create('tag#id.class.class', ?[children])
|
||||||
// dataset: object
|
$create('tag#id.class.class', ?textContentOrChildNode)
|
||||||
// any DOM property: assigned as is
|
$create('tag#id.class.class', {properties}, ?[children])
|
||||||
const [ns, tag] = opt.tag && opt.tag.includes('#')
|
$create('tag#id.class.class', {properties}, ?textContentOrChildNode)
|
||||||
? opt.tag.split('#')
|
tag is 'div' by default, #id and .class are optional
|
||||||
: [null, opt.tag];
|
|
||||||
|
$create([children])
|
||||||
|
|
||||||
|
$create({propertiesAndOptions})
|
||||||
|
$create({propertiesAndOptions}, ?[children])
|
||||||
|
tag: string, default 'div'
|
||||||
|
appendChild: element/string or an array of elements/strings
|
||||||
|
dataset: object
|
||||||
|
any DOM property: assigned as is
|
||||||
|
|
||||||
|
tag may include namespace like 'ns:tag'
|
||||||
|
*/
|
||||||
|
let ns, tag, opt;
|
||||||
|
|
||||||
|
if (typeof selector === 'string') {
|
||||||
|
if (Array.isArray(properties) ||
|
||||||
|
properties instanceof Node ||
|
||||||
|
typeof properties !== 'object') {
|
||||||
|
opt = {};
|
||||||
|
children = properties;
|
||||||
|
} else {
|
||||||
|
opt = properties || {};
|
||||||
|
}
|
||||||
|
const idStart = (selector.indexOf('#') + 1 || selector.length + 1) - 1;
|
||||||
|
const classStart = (selector.indexOf('.') + 1 || selector.length + 1) - 1;
|
||||||
|
const id = selector.slice(idStart + 1, classStart);
|
||||||
|
if (id) {
|
||||||
|
opt.id = id;
|
||||||
|
}
|
||||||
|
const cls = selector.slice(classStart + 1);
|
||||||
|
if (cls) {
|
||||||
|
opt[selector.includes(':') ? 'class' : 'className'] =
|
||||||
|
cls.includes('.') ? cls.replace(/\./g, ' ') : cls;
|
||||||
|
}
|
||||||
|
tag = selector.slice(0, Math.min(idStart, classStart));
|
||||||
|
|
||||||
|
} else if (Array.isArray(selector)) {
|
||||||
|
tag = 'div';
|
||||||
|
opt = {};
|
||||||
|
children = selector;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
opt = selector;
|
||||||
|
tag = opt.tag;
|
||||||
|
delete opt.tag;
|
||||||
|
children = opt.appendChild || properties;
|
||||||
|
delete opt.appendChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag && tag.includes(':')) {
|
||||||
|
([ns, tag] = tag.split(':'));
|
||||||
|
}
|
||||||
|
|
||||||
const element = ns
|
const element = ns
|
||||||
? document.createElementNS(ns === 'SVG' || ns === 'svg' ? 'http://www.w3.org/2000/svg' : ns, tag)
|
? document.createElementNS(ns === 'SVG' || ns === 'svg' ? 'http://www.w3.org/2000/svg' : ns, tag)
|
||||||
: document.createElement(tag || 'div');
|
: document.createElement(tag || 'div');
|
||||||
const children = Array.isArray(opt.appendChild) ? opt.appendChild : [opt.appendChild];
|
|
||||||
for (const child of children) {
|
for (const child of Array.isArray(children) ? children : [children]) {
|
||||||
if (child) {
|
if (child) {
|
||||||
element.appendChild(child instanceof Node ? child : document.createTextNode(child));
|
element.appendChild(child instanceof Node ? child : document.createTextNode(child));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete opt.appendChild;
|
|
||||||
delete opt.tag;
|
|
||||||
if (opt.dataset) {
|
if (opt.dataset) {
|
||||||
Object.assign(element.dataset, opt.dataset);
|
Object.assign(element.dataset, opt.dataset);
|
||||||
delete opt.dataset;
|
delete opt.dataset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt.attributes) {
|
if (opt.attributes) {
|
||||||
for (const attr in opt.attributes) {
|
for (const attr in opt.attributes) {
|
||||||
element.setAttribute(attr, opt.attributes[attr]);
|
element.setAttribute(attr, opt.attributes[attr]);
|
||||||
}
|
}
|
||||||
delete opt.attributes;
|
delete opt.attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ns) {
|
if (ns) {
|
||||||
for (const attr in opt) {
|
for (const attr in opt) {
|
||||||
element.setAttributeNS(null, attr, opt[attr]);
|
const i = attr.indexOf(':') + 1;
|
||||||
|
const attrNS = i && `http://www.w3.org/1999/${attr.slice(0, i - 1)}`;
|
||||||
|
element.setAttributeNS(attrNS || null, attr, opt[attr]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Object.assign(element, opt);
|
Object.assign(element, opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function makeLink(href = '', content) {
|
function $createLink(href = '', content) {
|
||||||
const opt = {
|
const opt = {
|
||||||
tag: 'a',
|
tag: 'a',
|
||||||
target: '_blank',
|
target: '_blank',
|
||||||
|
@ -217,9 +272,9 @@ function makeLink(href = '', content) {
|
||||||
Object.assign(opt, href);
|
Object.assign(opt, href);
|
||||||
} else {
|
} else {
|
||||||
opt.href = href;
|
opt.href = href;
|
||||||
opt.appendChild = content;
|
|
||||||
}
|
}
|
||||||
return $element(opt);
|
opt.appendChild = opt.appendChild || content;
|
||||||
|
return $create(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ if (!CHROME && !chrome.browserAction.openPopup) {
|
||||||
FIREFOX = 50;
|
FIREFOX = 50;
|
||||||
browser.runtime.getBrowserInfo().then(info => {
|
browser.runtime.getBrowserInfo().then(info => {
|
||||||
FIREFOX = parseFloat(info.version);
|
FIREFOX = parseFloat(info.version);
|
||||||
document.documentElement.classList.toggle('moz-appearance-bug', FIREFOX && FIREFOX < 54);
|
document.documentElement.classList.add('moz-appearance-bug', FIREFOX && FIREFOX < 54);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,6 @@ if (BG && !BG.getStyles && BG !== window) {
|
||||||
}
|
}
|
||||||
if (!BG || BG !== window) {
|
if (!BG || BG !== window) {
|
||||||
document.documentElement.classList.toggle('firefox', FIREFOX);
|
document.documentElement.classList.toggle('firefox', FIREFOX);
|
||||||
document.documentElement.classList.toggle('moz-appearance-bug', FIREFOX && FIREFOX < 54);
|
|
||||||
document.documentElement.classList.toggle('opera', OPERA);
|
document.documentElement.classList.toggle('opera', OPERA);
|
||||||
// TODO: remove once our manifest's minimum_chrome_version is 50+
|
// TODO: remove once our manifest's minimum_chrome_version is 50+
|
||||||
// Chrome 49 doesn't report own extension pages in webNavigation apparently
|
// Chrome 49 doesn't report own extension pages in webNavigation apparently
|
||||||
|
|
|
@ -23,10 +23,11 @@ var mozParser = (() => {
|
||||||
const section = {code: '', start: {line, col}};
|
const section = {code: '', start: {line, col}};
|
||||||
// move last comment before @-moz-document inside the section
|
// move last comment before @-moz-document inside the section
|
||||||
if (!/\/\*[\s\n]*AGENT_SHEET[\s\n]*\*\//.test(lastCmt)) {
|
if (!/\/\*[\s\n]*AGENT_SHEET[\s\n]*\*\//.test(lastCmt)) {
|
||||||
|
if (lastCmt) {
|
||||||
section.code = lastCmt + '\n';
|
section.code = lastCmt + '\n';
|
||||||
const indent = outerText.match(/^\s*/)[0];
|
|
||||||
outerText = outerText.slice(0, -lastCmt.length);
|
outerText = outerText.slice(0, -lastCmt.length);
|
||||||
outerText = indent + outerText.trim();
|
}
|
||||||
|
outerText = outerText.match(/^\s*/)[0] + outerText.trim();
|
||||||
}
|
}
|
||||||
if (outerText.trim()) {
|
if (outerText.trim()) {
|
||||||
lastSection.code = outerText;
|
lastSection.code = outerText;
|
||||||
|
|
82
manage.html
82
manage.html
|
@ -4,6 +4,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title i18n-text="manageTitle"></title>
|
<title i18n-text="manageTitle"></title>
|
||||||
|
<link rel="stylesheet" href="global.css">
|
||||||
<link rel="stylesheet" href="manage/manage.css">
|
<link rel="stylesheet" href="manage/manage.css">
|
||||||
<link rel="stylesheet" href="msgbox/msgbox.css">
|
<link rel="stylesheet" href="msgbox/msgbox.css">
|
||||||
<link rel="stylesheet" href="options/onoffswitch.css">
|
<link rel="stylesheet" href="options/onoffswitch.css">
|
||||||
|
@ -54,7 +55,10 @@
|
||||||
<template data-id="styleCompact">
|
<template data-id="styleCompact">
|
||||||
<div class="entry">
|
<div class="entry">
|
||||||
<h2 class="style-name">
|
<h2 class="style-name">
|
||||||
|
<div class="checkmate">
|
||||||
<input class="checker" type="checkbox" i18n-title="toggleStyle">
|
<input class="checker" type="checkbox" i18n-title="toggleStyle">
|
||||||
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</div>
|
||||||
<a class="style-name-link"></a>
|
<a class="style-name-link"></a>
|
||||||
</h2>
|
</h2>
|
||||||
<p class="actions">
|
<p class="actions">
|
||||||
|
@ -156,50 +160,85 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body id="stylus-manage" i18n-dragndrop-hint="dragDropMessage">
|
<body id="stylus-manage" i18n-dragndrop-hint="dragDropMessage">
|
||||||
|
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<h1 id="manage-heading" i18n-text="manageHeading"></h1>
|
<h1 id="manage-heading" i18n-text="manageHeading"></h1>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
|
||||||
<legend id="filters">
|
<legend id="filters">
|
||||||
<span i18n-text="manageFilters"></span><span id="filters-stats"></span>
|
<span i18n-text="manageFilters"></span><span id="filters-stats"></span>
|
||||||
</legend>
|
</legend>
|
||||||
|
|
||||||
|
<div class="filter-selection">
|
||||||
<label>
|
<label>
|
||||||
|
<div class="checkmate">
|
||||||
<input id="manage.onlyEnabled" type="checkbox"
|
<input id="manage.onlyEnabled" type="checkbox"
|
||||||
data-filter=".enabled"
|
data-filter=".enabled"
|
||||||
data-filter-hide=".disabled">
|
data-filter-hide=".disabled">
|
||||||
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<div class="select-resizer">
|
||||||
<select id="manage.onlyEnabled.invert">
|
<select id="manage.onlyEnabled.invert">
|
||||||
<option i18n-text="manageOnlyEnabled" value="false"></option>
|
<option i18n-text="manageOnlyEnabled" value="false"></option>
|
||||||
<option i18n-text="manageOnlyDisabled" value="true"></option>
|
<option i18n-text="manageOnlyDisabled" value="true"></option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
<svg class="svg-icon select-arrow"><use xlink:href="#svg-icon-select-arrow"/></svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter-selection">
|
||||||
<label>
|
<label>
|
||||||
|
<div class="checkmate">
|
||||||
<input id="manage.onlyLocal" type="checkbox"
|
<input id="manage.onlyLocal" type="checkbox"
|
||||||
data-filter=":not(.updatable):not(.update-done)"
|
data-filter=":not(.updatable):not(.update-done)"
|
||||||
data-filter-hide=".updatable, .update-done">
|
data-filter-hide=".updatable, .update-done">
|
||||||
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<div class="select-resizer">
|
||||||
<select id="manage.onlyLocal.invert" i18n-title="manageOnlyLocalTooltip">
|
<select id="manage.onlyLocal.invert" i18n-title="manageOnlyLocalTooltip">
|
||||||
<option i18n-text="manageOnlyLocal" value="false"></option>
|
<option i18n-text="manageOnlyLocal" value="false"></option>
|
||||||
<option i18n-text="manageOnlyExternal" value="true"></option>
|
<option i18n-text="manageOnlyExternal" value="true"></option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
<svg class="svg-icon select-arrow"><use xlink:href="#svg-icon-select-arrow"/></svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter-selection">
|
||||||
<label>
|
<label>
|
||||||
|
<div class="checkmate">
|
||||||
<input id="manage.onlyUsercss" type="checkbox"
|
<input id="manage.onlyUsercss" type="checkbox"
|
||||||
data-filter=".usercss"
|
data-filter=".usercss"
|
||||||
data-filter-hide=":not(.usercss)">
|
data-filter-hide=":not(.usercss)">
|
||||||
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<div class="select-resizer">
|
||||||
<select id="manage.onlyUsercss.invert">
|
<select id="manage.onlyUsercss.invert">
|
||||||
<option i18n-text="manageOnlyUsercss" value="false"></option>
|
<option i18n-text="manageOnlyUsercss" value="false"></option>
|
||||||
<option i18n-text="manageOnlyNonUsercss" value="true"></option>
|
<option i18n-text="manageOnlyNonUsercss" value="true"></option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
<svg class="svg-icon select-arrow"><use xlink:href="#svg-icon-select-arrow"/></svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label id="onlyUpdates" class="hidden">
|
<label id="onlyUpdates" class="hidden">
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
data-filter=".can-update, .update-problem, .update-done"
|
data-filter=".can-update, .update-problem, .update-done"
|
||||||
data-filter-hide=":not(.updatable):not(.update-done), .no-update:not(.update-problem)">
|
data-filter-hide=":not(.updatable):not(.update-done), .no-update:not(.update-problem)">
|
||||||
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
<span i18n-text="manageOnlyUpdates"></span>
|
<span i18n-text="manageOnlyUpdates"></span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<input id="search" type="search" i18n-placeholder="searchStyles" spellcheck="false"
|
<input id="search" type="search" i18n-placeholder="searchStyles" spellcheck="false"
|
||||||
i18n-title="searchStylesTooltip"
|
i18n-title="searchStylesTooltip"
|
||||||
data-filter=":not(.not-matching)"
|
data-filter=":not(.not-matching)"
|
||||||
data-filter-hide=".not-matching">
|
data-filter-hide=".not-matching">
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<p class="nowrap">
|
<p class="nowrap">
|
||||||
<button id="check-all-updates" i18n-text="checkAllUpdates"><span id="update-progress"></span></button>
|
<button id="check-all-updates" i18n-text="checkAllUpdates"><span id="update-progress"></span></button>
|
||||||
<span id="update-history" i18n-title="genericHistoryLabel">
|
<span id="update-history" i18n-title="genericHistoryLabel">
|
||||||
|
@ -208,17 +247,20 @@
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<button id="apply-all-updates" class="hidden" i18n-text="applyAllUpdates"></button>
|
<button id="apply-all-updates" class="hidden" i18n-text="applyAllUpdates"></button>
|
||||||
<span id="update-all-no-updates" class="hidden" i18n-text="updateAllCheckSucceededNoUpdate"></span>
|
<span id="update-all-no-updates" class="hidden" i18n-text="updateAllCheckSucceededNoUpdate"></span>
|
||||||
<button id="check-all-updates-force" class="hidden" i18n-text="checkAllUpdatesForce"></button>
|
<button id="check-all-updates-force" class="hidden" i18n-text="checkAllUpdatesForce"></button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="edit.html">
|
<a href="edit.html">
|
||||||
<button id="add-style-label" i18n-text="addStyleLabel"></button>
|
<button id="add-style-label" i18n-text="addStyleLabel"></button>
|
||||||
</a>
|
</a>
|
||||||
<label id="newStyleAsUsercss-wrapper" class="nobreak">
|
<label id="newStyleAsUsercss-wrapper" class="nobreak">
|
||||||
<input type="checkbox" id="newStyleAsUsercss">
|
<input type="checkbox" id="newStyleAsUsercss">
|
||||||
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
<span i18n-text="manageNewStyleAsUsercss" i18n-title="optionsAdvancedNewStyleAsUsercss"></span>
|
<span i18n-text="manageNewStyleAsUsercss" i18n-title="optionsAdvancedNewStyleAsUsercss"></span>
|
||||||
<a id="usercss-wiki"
|
<a id="usercss-wiki"
|
||||||
href="https://github.com/openstyles/stylus/wiki/Usercss"
|
href="https://github.com/openstyles/stylus/wiki/Usercss"
|
||||||
|
@ -229,25 +271,38 @@
|
||||||
</a>
|
</a>
|
||||||
</label>
|
</label>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<details id="options" data-pref="manage.options.expanded">
|
<details id="options" data-pref="manage.options.expanded">
|
||||||
|
|
||||||
<summary><h2 id="options-heading" i18n-text="optionsHeading"></h2></summary>
|
<summary><h2 id="options-heading" i18n-text="optionsHeading"></h2></summary>
|
||||||
<label><input id="manage.newUI" type="checkbox"><span i18n-text="manageNewUI"></span></label>
|
|
||||||
|
<label>
|
||||||
|
<input id="manage.newUI" type="checkbox">
|
||||||
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
<span i18n-text="manageNewUI"></span>
|
||||||
|
</label>
|
||||||
|
|
||||||
<div id="newUIoptions">
|
<div id="newUIoptions">
|
||||||
<div>
|
<div>
|
||||||
|
<label for="manage.newUI.favicons" i18n-text="manageFavicons">
|
||||||
<input id="manage.newUI.favicons" type="checkbox">
|
<input id="manage.newUI.favicons" type="checkbox">
|
||||||
<label for="manage.newUI.favicons" i18n-text="manageFavicons"></label>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</label>
|
||||||
<svg class="svg-icon info" viewBox="0 0 14 16" i18n-alt="helpAlt" data-toggle-on-click="#faviconsHelp">
|
<svg class="svg-icon info" viewBox="0 0 14 16" i18n-alt="helpAlt" data-toggle-on-click="#faviconsHelp">
|
||||||
<path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path>
|
<path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<div id="faviconsHelp" class="hidden" i18n-text="manageFaviconsHelp">
|
<div id="faviconsHelp" class="hidden" i18n-text="manageFaviconsHelp">
|
||||||
<div>
|
<div>
|
||||||
|
<label for="manage.newUI.faviconsGray" i18n-text="manageFaviconsGray">
|
||||||
<input id="manage.newUI.faviconsGray" type="checkbox">
|
<input id="manage.newUI.faviconsGray" type="checkbox">
|
||||||
<label for="manage.newUI.faviconsGray" i18n-text="manageFaviconsGray"></label>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<label><input id="manage.newUI.targets" type="number" min="1" max="99"><span i18n-text="manageMaxTargets"></span></label>
|
<label><input id="manage.newUI.targets" type="number" min="1" max="99"><span i18n-text="manageMaxTargets"></span></label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<button id="manage-options-button" i18n-text="openOptionsManage"></button>
|
<button id="manage-options-button" i18n-text="openOptionsManage"></button>
|
||||||
<button id="manage-shortcuts-button" class="chromium-only"
|
<button id="manage-shortcuts-button" class="chromium-only"
|
||||||
|
@ -258,7 +313,9 @@
|
||||||
i18n-title="editorStylesButton"
|
i18n-title="editorStylesButton"
|
||||||
target="_blank"><button i18n-text="cm_theme"></button></a>
|
target="_blank"><button i18n-text="cm_theme"></button></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<div id="backup">
|
<div id="backup">
|
||||||
<h2 id="backup-title" i18n-text="backupButtons"></h2>
|
<h2 id="backup-title" i18n-text="backupButtons"></h2>
|
||||||
<span id="backup-message" i18n-text="backupMessage"></span>
|
<span id="backup-message" i18n-text="backupMessage"></span>
|
||||||
|
@ -267,13 +324,26 @@
|
||||||
<button id="unfile-all-styles" i18n-text="retrieveBckp"></button>
|
<button id="unfile-all-styles" i18n-text="retrieveBckp"></button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p id="manage-text" i18n-html="manageText"></p>
|
<p id="manage-text" i18n-html="manageText"></p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="installed"></div>
|
<div id="installed"></div>
|
||||||
|
|
||||||
<script src="manage/import-export.js"></script>
|
<script src="manage/import-export.js"></script>
|
||||||
<script src="msgbox/msgbox.js"></script>
|
<script src="msgbox/msgbox.js"></script>
|
||||||
<script src="manage/incremental-search.js" async></script>
|
<script src="manage/incremental-search.js" async></script>
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" style="display: none !important;">
|
||||||
|
<symbol id="svg-icon-checked" viewBox="0 0 1000 1000">
|
||||||
|
<path fill-rule="evenodd" d="M983.2,184.3L853,69.8c-4-3.5-9.3-5.3-14.5-5c-5.3,0.4-10.3,2.8-13.8,6.8L352.3,609.2L184.4,386.9c-3.2-4.2-8-7-13.2-7.8c-5.3-0.8-10.6,0.6-14.9,3.9L18,487.5c-8.8,6.7-10.6,19.3-3.9,28.1L325,927.2c3.6,4.8,9.3,7.7,15.3,8c0.2,0,0.5,0,0.7,0c5.8,0,11.3-2.5,15.1-6.8L985,212.6C992.3,204.3,991.5,191.6,983.2,184.3z"/>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol id="svg-icon-select-arrow" viewBox="0 0 1792 1792">
|
||||||
|
<path fill-rule="evenodd" d="M1408 704q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/* global messageBox makeLink */
|
/* global messageBox */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function configDialog(style) {
|
function configDialog(style) {
|
||||||
const varsHash = deepCopy(style.usercssData.vars) || {};
|
const data = style.usercssData;
|
||||||
|
const varsHash = deepCopy(data.vars) || {};
|
||||||
const varNames = Object.keys(varsHash);
|
const varNames = Object.keys(varsHash);
|
||||||
const vars = varNames.map(name => varsHash[name]);
|
const vars = varNames.map(name => varsHash[name]);
|
||||||
const elements = [];
|
const elements = [];
|
||||||
|
@ -12,21 +13,12 @@ function configDialog(style) {
|
||||||
renderValues();
|
renderValues();
|
||||||
|
|
||||||
return messageBox({
|
return messageBox({
|
||||||
title: `${style.name} v${style.usercssData.version}`,
|
title: `${style.name} v${data.version}`,
|
||||||
className: 'config-dialog',
|
className: 'config-dialog',
|
||||||
contents: [
|
contents: [
|
||||||
$element({
|
$create('.config-heading', data.supportURL &&
|
||||||
className: 'config-heading',
|
$createLink({className: '.external-support', href: data.supportURL}, t('externalFeedback'))),
|
||||||
appendChild: style.usercssData.supportURL && makeLink({
|
$create('.config-body', elements)
|
||||||
className: 'external-support',
|
|
||||||
href: style.usercssData.supportURL,
|
|
||||||
textContent: t('externalFeedback')
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
$element({
|
|
||||||
className: 'config-body',
|
|
||||||
appendChild: elements
|
|
||||||
})
|
|
||||||
],
|
],
|
||||||
buttons: [
|
buttons: [
|
||||||
t('confirmSave'),
|
t('confirmSave'),
|
||||||
|
@ -71,19 +63,17 @@ function configDialog(style) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
invalid.push(['*' + va.name, ': ', ...error].map(e =>
|
invalid.push(['*' + va.name, ': ', ...error].map(e =>
|
||||||
e[0] === '*' && $element({tag: 'b', textContent: e.slice(1)}) || e));
|
e[0] === '*' && $create('b', e.slice(1)) || e));
|
||||||
if (bgva) {
|
if (bgva) {
|
||||||
styleVars[va.name].value = deepCopy(bgva);
|
styleVars[va.name].value = deepCopy(bgva);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (invalid.length) {
|
if (invalid.length) {
|
||||||
messageBox.alert([
|
messageBox.alert([
|
||||||
$element({textContent: t('usercssConfigIncomplete'), style: 'max-width: 34em'}),
|
$create('div', {style: 'max-width: 34em'}, t('usercssConfigIncomplete')),
|
||||||
$element({
|
$create('ol', {style: 'text-align: left'},
|
||||||
tag: 'ol',
|
invalid.map(msg =>
|
||||||
style: 'text-align: left',
|
$create({tag: 'li', appendChild: msg}))),
|
||||||
appendChild: invalid.map(msg => $element({tag: 'li', appendChild: msg})),
|
|
||||||
}),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
return numValid && BG.usercssHelper.save(style);
|
return numValid && BG.usercssHelper.save(style);
|
||||||
|
@ -91,30 +81,28 @@ function configDialog(style) {
|
||||||
|
|
||||||
function buildConfigForm() {
|
function buildConfigForm() {
|
||||||
for (const va of vars) {
|
for (const va of vars) {
|
||||||
let appendChild;
|
let children;
|
||||||
switch (va.type) {
|
switch (va.type) {
|
||||||
case 'color':
|
case 'color':
|
||||||
appendChild = [$element({
|
va.inputColor = $create('.color-swatch', {va, onclick: showColorpicker});
|
||||||
className: 'cm-colorview',
|
children = [
|
||||||
appendChild: va.inputColor = $element({
|
$create('.cm-colorview', [
|
||||||
va,
|
va.inputColor,
|
||||||
className: 'color-swatch',
|
]),
|
||||||
onclick: showColorpicker,
|
];
|
||||||
})
|
|
||||||
})];
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'checkbox':
|
case 'checkbox':
|
||||||
va.input = $element({tag: 'input', type: 'checkbox', className: 'slider'});
|
va.input = $create('input.slider', {type: 'checkbox'});
|
||||||
va.input.onchange = () => {
|
va.input.onchange = () => {
|
||||||
va.dirty = true;
|
va.dirty = true;
|
||||||
va.value = String(Number(va.input.checked));
|
va.value = String(Number(va.input.checked));
|
||||||
};
|
};
|
||||||
appendChild = [
|
children = [
|
||||||
$element({tag: 'span', className: 'onoffswitch', appendChild: [
|
$create('span.onoffswitch', [
|
||||||
va.input,
|
va.input,
|
||||||
$element({tag: 'span'})
|
$create('span'),
|
||||||
]})
|
])
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -122,36 +110,33 @@ function configDialog(style) {
|
||||||
case 'dropdown':
|
case 'dropdown':
|
||||||
case 'image':
|
case 'image':
|
||||||
// TODO: a image picker input?
|
// TODO: a image picker input?
|
||||||
va.input = $element({
|
va.input = $create('.select-resizer', [
|
||||||
tag: 'select',
|
$create('select', va.options.map(o =>
|
||||||
appendChild: va.options.map(o => $element({
|
$create('option', {value: o.name}, o.label))),
|
||||||
tag: 'option', value: o.name, textContent: o.label
|
$create('SVG:svg.svg-icon.select-arrow',
|
||||||
}))
|
$create('SVG:use', {'xlink:href': '#svg-icon-select-arrow'})),
|
||||||
});
|
]);
|
||||||
va.input.onchange = () => {
|
va.input.onchange = () => {
|
||||||
va.dirty = true;
|
va.dirty = true;
|
||||||
va.value = va.input.value;
|
va.value = va.input.value;
|
||||||
};
|
};
|
||||||
appendChild = [va.input];
|
children = [va.input];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
va.input = $element({tag: 'input', type: 'text'});
|
va.input = $create('input', {type: 'text'});
|
||||||
va.input.oninput = () => {
|
va.input.oninput = () => {
|
||||||
va.dirty = true;
|
va.dirty = true;
|
||||||
va.value = va.input.value;
|
va.value = va.input.value;
|
||||||
};
|
};
|
||||||
appendChild = [va.input];
|
children = [va.input];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
elements.push($element({
|
elements.push(
|
||||||
tag: 'label',
|
$create(`label.config-${va.type}`, [
|
||||||
className: `config-${va.type}`,
|
$create('span', va.label),
|
||||||
appendChild: [
|
...children,
|
||||||
$element({tag: 'span', appendChild: va.label}),
|
]));
|
||||||
...appendChild,
|
|
||||||
],
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -260,6 +260,9 @@ function reapplyFilter(container = installed) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (fullPass) {
|
||||||
|
showFiltersStats({immediately: true});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function findInsertionPoint(entry) {
|
function findInsertionPoint(entry) {
|
||||||
|
@ -295,9 +298,9 @@ function reapplyFilter(container = installed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function showFiltersStats({immediately} = {}) {
|
function showFiltersStats() {
|
||||||
if (!immediately) {
|
if (!BG.cachedStyles.list) {
|
||||||
debounce(showFiltersStats, 100, {immediately: true});
|
debounce(showFiltersStats, 100);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$('#filters').classList.toggle('active', filtersSelector.hide !== '');
|
$('#filters').classList.toggle('active', filtersSelector.hide !== '');
|
||||||
|
@ -309,6 +312,8 @@ function showFiltersStats({immediately} = {}) {
|
||||||
filtersSelector.numShown = numShown;
|
filtersSelector.numShown = numShown;
|
||||||
filtersSelector.numTotal = numTotal;
|
filtersSelector.numTotal = numTotal;
|
||||||
$('#filters-stats').textContent = t('filteredStyles', [numShown, numTotal]);
|
$('#filters-stats').textContent = t('filteredStyles', [numShown, numTotal]);
|
||||||
|
document.body.classList.toggle('all-styles-hidden-by-filters',
|
||||||
|
!numShown && numTotal && filtersSelector.hide);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,18 +175,16 @@ function importFromString(jsonString) {
|
||||||
.map(kind => {
|
.map(kind => {
|
||||||
const {ids, names, legend} = stats[kind];
|
const {ids, names, legend} = stats[kind];
|
||||||
const listItemsWithId = (name, i) =>
|
const listItemsWithId = (name, i) =>
|
||||||
$element({dataset: {id: ids[i]}, textContent: name});
|
$create('div', {dataset: {id: ids[i]}}, name);
|
||||||
const listItems = name =>
|
const listItems = name =>
|
||||||
$element({textContent: name});
|
$create('div', name);
|
||||||
const block =
|
const block =
|
||||||
$element({tag: 'details', dataset: {id: kind}, appendChild: [
|
$create('details', {dataset: {id: kind}}, [
|
||||||
$element({tag: 'summary', appendChild:
|
$create('summary',
|
||||||
$element({tag: 'b', textContent: names.length + ' ' + t(legend)})
|
$create('b', names.length + ' ' + t(legend))),
|
||||||
}),
|
$create('small',
|
||||||
$element({tag: 'small', appendChild:
|
names.map(ids ? listItemsWithId : listItems)),
|
||||||
names.map(ids ? listItemsWithId : listItems)
|
]);
|
||||||
}),
|
|
||||||
]});
|
|
||||||
return block;
|
return block;
|
||||||
});
|
});
|
||||||
scrollTo(0, 0);
|
scrollTo(0, 0);
|
||||||
|
@ -308,8 +306,7 @@ $('#file-all-styles').onclick = () => {
|
||||||
const text = JSON.stringify(styles, null, '\t');
|
const text = JSON.stringify(styles, null, '\t');
|
||||||
const blob = new Blob([text], {type: 'application/json'});
|
const blob = new Blob([text], {type: 'application/json'});
|
||||||
const objectURL = URL.createObjectURL(blob);
|
const objectURL = URL.createObjectURL(blob);
|
||||||
let link = $element({
|
let link = $create('a', {
|
||||||
tag:'a',
|
|
||||||
href: objectURL,
|
href: objectURL,
|
||||||
type: 'application/json',
|
type: 'application/json',
|
||||||
download: generateFileName(),
|
download: generateFileName(),
|
||||||
|
@ -319,8 +316,7 @@ $('#file-all-styles').onclick = () => {
|
||||||
link.dispatchEvent(new MouseEvent('click'));
|
link.dispatchEvent(new MouseEvent('click'));
|
||||||
setTimeout(() => URL.revokeObjectURL(objectURL));
|
setTimeout(() => URL.revokeObjectURL(objectURL));
|
||||||
} else {
|
} else {
|
||||||
const iframe = document.body.appendChild($element({
|
const iframe = document.body.appendChild($create('iframe', {
|
||||||
tag: 'iframe',
|
|
||||||
style: 'width: 0; height: 0; position: fixed; opacity: 0;'.replace(/;/g, '!important;'),
|
style: 'width: 0; height: 0; position: fixed; opacity: 0;'.replace(/;/g, '!important;'),
|
||||||
}));
|
}));
|
||||||
doTimeout()
|
doTimeout()
|
||||||
|
|
|
@ -5,8 +5,7 @@ onDOMready().then(() => {
|
||||||
let prevText, focusedLink, focusedEntry;
|
let prevText, focusedLink, focusedEntry;
|
||||||
let prevTime = performance.now();
|
let prevTime = performance.now();
|
||||||
let focusedName = '';
|
let focusedName = '';
|
||||||
const input = $element({
|
const input = $create('textarea', {
|
||||||
tag: 'textarea',
|
|
||||||
spellcheck: false,
|
spellcheck: false,
|
||||||
oninput: incrementalSearch,
|
oninput: incrementalSearch,
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,6 +15,26 @@ body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.all-styles-hidden-by-filters:before,
|
||||||
|
body.all-styles-hidden-by-filters:after {
|
||||||
|
position: absolute;
|
||||||
|
left: calc(3rem + var(--header-width));
|
||||||
|
color: hsla(180, 40%, 45%, .3);
|
||||||
|
animation: fadein 3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.all-styles-hidden-by-filters:before {
|
||||||
|
content: "\2190"; /* left arrow */
|
||||||
|
font-size: 3rem;
|
||||||
|
top: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.all-styles-hidden-by-filters:after {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
position: absolute;
|
||||||
|
top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
a, .disabled a:hover {
|
a, .disabled a:hover {
|
||||||
color: #000;
|
color: #000;
|
||||||
transition: color .5s;
|
transition: color .5s;
|
||||||
|
@ -74,6 +94,10 @@ select {
|
||||||
fill: #aaa;
|
fill: #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#usercss-wiki svg {
|
||||||
|
margin-top: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
.nobreak {
|
.nobreak {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
@ -250,16 +274,17 @@ label.nobreak input {
|
||||||
margin-left: -13px;
|
margin-left: -13px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header summary h2 {
|
#header summary h2 {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-bottom: 1px dotted transparent;
|
border-bottom: 1px dotted transparent;
|
||||||
margin-top: .2em;
|
margin-top: .1em;
|
||||||
margin-bottom: .4em;
|
margin-bottom: .1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header summary h2:hover {
|
#header summary:hover h2 {
|
||||||
border-color: #bbb;
|
border-color: #bbb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,11 +314,107 @@ label.nobreak input {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
/************ checkbox & select************/
|
||||||
|
|
||||||
.newUI .checker {
|
.newUI .checker {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newUIoptions > div {
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-selection {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 1px;
|
}
|
||||||
margin: 0 1ex 0 0;
|
|
||||||
|
#header label {
|
||||||
|
padding-left: 16px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header .filter-selection label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 18px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 0 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header .filter-selection label .checkmate {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-top: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.firefox #header .filter-selection label .checkmate {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newUI #newUIoptions > label {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-selection select {
|
||||||
|
height: 18px;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
max-width: 100%;
|
||||||
|
padding-left: 4px;
|
||||||
|
padding-right: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.firefox .filter-selection select {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-selection .select-arrow {
|
||||||
|
margin-top: 2px;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-resizer {
|
||||||
|
cursor: default;
|
||||||
|
border: none;
|
||||||
|
max-width: calc(100% - 2em);
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.firefox .select-resizer {
|
||||||
|
left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset > label,
|
||||||
|
fieldset > .filter-selection {
|
||||||
|
transition: background-color .25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset > label:hover,
|
||||||
|
fieldset > .filter-selection:hover {
|
||||||
|
background-color: hsla(0, 0%, 50%, .2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkmate {
|
||||||
|
position: relative;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry .checkmate {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: -2px 1ex 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newUI .entry .svg-icon.checked,
|
||||||
|
.newUI .entry:hover .svg-icon.checked {
|
||||||
|
fill: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newUI .entry input[type="checkbox"]:not(.slider) {
|
||||||
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.newUI .style-name {
|
.newUI .style-name {
|
||||||
|
@ -638,13 +759,19 @@ fieldset {
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset > *:not(legend) {
|
fieldset > input,
|
||||||
|
fieldset > label {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset > label:hover {
|
#header fieldset > label {
|
||||||
background-color: hsla(0, 0%, 50%, .1);
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header fieldset > label input[type="checkbox"]:not(.slider),
|
||||||
|
#header fieldset > label input[type="checkbox"]:not(.slider):checked + .svg-icon.checked{
|
||||||
|
left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#filters {
|
#filters {
|
||||||
|
@ -665,12 +792,6 @@ fieldset > label:hover {
|
||||||
content: ": ";
|
content: ": ";
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset select {
|
|
||||||
border: none;
|
|
||||||
max-width: calc(100% - 2em);
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
#search {
|
#search {
|
||||||
width: calc(100% - 4px);
|
width: calc(100% - 4px);
|
||||||
margin: 0.25rem 4px 0;
|
margin: 0.25rem 4px 0;
|
||||||
|
@ -752,6 +873,10 @@ fieldset select {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.config-dialog .select-resizer {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
.config-dialog label:first-child {
|
.config-dialog label:first-child {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
@ -788,10 +913,13 @@ fieldset select {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.config-dialog .select-resizer,
|
||||||
.config-dialog select {
|
.config-dialog select {
|
||||||
width: auto;
|
width: auto;
|
||||||
min-width: var(--onoffswitch-width);
|
min-width: var(--onoffswitch-width);
|
||||||
max-width: 124px;
|
max-width: 124px;
|
||||||
|
left: auto;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-dialog .onoffswitch {
|
.config-dialog .onoffswitch {
|
||||||
|
@ -808,7 +936,7 @@ fieldset select {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-dialog label > :last-child:not(.onoffswitch) > :not(:last-child) {
|
.config-dialog label > :last-child:not(.onoffswitch):not(.select-resizer) > :not(:last-child) {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,6 +1026,17 @@ fieldset select {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.all-styles-hidden-by-filters:before {
|
||||||
|
content: "\2191"; /* up arrow */
|
||||||
|
top: calc(50% + 2.75rem);
|
||||||
|
left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.all-styles-hidden-by-filters:after {
|
||||||
|
top: calc(50% + 4rem);
|
||||||
|
left: 3.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
height: auto;
|
height: auto;
|
||||||
position: static;
|
position: static;
|
||||||
|
@ -972,12 +1111,3 @@ fieldset select {
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports (-moz-appearance:none) {
|
|
||||||
|
|
||||||
/* fixes for Firefox quirks */
|
|
||||||
|
|
||||||
#newStyleAsUsercss-wrapper svg {
|
|
||||||
margin-top: -2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -84,14 +84,17 @@ function initGlobalEvents() {
|
||||||
switchUI({styleOnly: true});
|
switchUI({styleOnly: true});
|
||||||
|
|
||||||
// translate CSS manually
|
// translate CSS manually
|
||||||
document.head.appendChild($element({tag: 'style', textContent: `
|
document.head.appendChild($create('style', `
|
||||||
.disabled h2::after {
|
.disabled h2::after {
|
||||||
content: "${t('genericDisabledLabel')}";
|
content: "${t('genericDisabledLabel')}";
|
||||||
}
|
}
|
||||||
#update-all-no-updates[data-skipped-edited="true"]:after {
|
#update-all-no-updates[data-skipped-edited="true"]:after {
|
||||||
content: " ${t('updateAllCheckSucceededSomeEdited')}";
|
content: " ${t('updateAllCheckSucceededSomeEdited')}";
|
||||||
}
|
}
|
||||||
`}));
|
body.all-styles-hidden-by-filters:after {
|
||||||
|
content: "${t('filteredStylesAllHidden')}";
|
||||||
|
}
|
||||||
|
`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -122,9 +122,9 @@ function reportUpdateState(state, style, details) {
|
||||||
const edited = details === BG.updater.EDITED || details === BG.updater.MAYBE_EDITED;
|
const edited = details === BG.updater.EDITED || details === BG.updater.MAYBE_EDITED;
|
||||||
entry.dataset.details = details;
|
entry.dataset.details = details;
|
||||||
if (!details) {
|
if (!details) {
|
||||||
details = t('updateCheckFailServerUnreachable');
|
details = t('updateCheckFailServerUnreachable') + '\n' + style.updateUrl;
|
||||||
} else if (typeof details === 'number') {
|
} else if (typeof details === 'number') {
|
||||||
details = t('updateCheckFailBadResponseCode', [details]);
|
details = t('updateCheckFailBadResponseCode', [details]) + '\n' + style.updateUrl;
|
||||||
} else if (details === BG.updater.EDITED) {
|
} else if (details === BG.updater.EDITED) {
|
||||||
details = t('updateCheckSkippedLocallyEdited') + '\n' + t('updateCheckManualUpdateHint');
|
details = t('updateCheckSkippedLocallyEdited') + '\n' + t('updateCheckManualUpdateHint');
|
||||||
} else if (details === BG.updater.MAYBE_EDITED) {
|
} else if (details === BG.updater.MAYBE_EDITED) {
|
||||||
|
@ -174,10 +174,7 @@ function showUpdateHistory() {
|
||||||
BG.chromeLocal.getValue('updateLog').then((lines = []) => {
|
BG.chromeLocal.getValue('updateLog').then((lines = []) => {
|
||||||
messageBox({
|
messageBox({
|
||||||
title: t('updateCheckHistory'),
|
title: t('updateCheckHistory'),
|
||||||
contents: $element({
|
contents: $create('.update-history-log', lines.join('\n')),
|
||||||
className: 'update-history-log',
|
|
||||||
textContent: lines.join('\n'),
|
|
||||||
}),
|
|
||||||
buttons: [t('confirmOK')],
|
buttons: [t('confirmOK')],
|
||||||
onshow: () => ($('#message-box-contents').scrollTop = 1e9),
|
onshow: () => ($('#message-box-contents').scrollTop = 1e9),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "Stylus",
|
"name": "Stylus",
|
||||||
"version": "1.1.7",
|
"version": "1.1.7.2",
|
||||||
"minimum_chrome_version": "49",
|
"minimum_chrome_version": "49",
|
||||||
"description": "__MSG_description__",
|
"description": "__MSG_description__",
|
||||||
"homepage_url": "http://add0n.com/stylus.html",
|
"homepage_url": "http://add0n.com/stylus.html",
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#message-box.fadeout {
|
#message-box.fadeout {
|
||||||
animation: fadeout .5s ease-in-out;
|
animation: fadeout .25s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#message-box.center {
|
#message-box.center {
|
||||||
|
|
|
@ -58,27 +58,25 @@ function messageBox({
|
||||||
removeSelf();
|
removeSelf();
|
||||||
}
|
}
|
||||||
const id = 'message-box';
|
const id = 'message-box';
|
||||||
messageBox.element = $element({id, className, appendChild: [
|
messageBox.element =
|
||||||
$element({appendChild: [
|
$create({id, className}, [
|
||||||
$element({id: `${id}-title`, textContent: title}),
|
$create([
|
||||||
$element({id: `${id}-close-icon`, appendChild:
|
$create(`#${id}-title`, title),
|
||||||
$element({tag: 'SVG#svg', class: 'svg-icon', viewBox: '0 0 20 20', appendChild:
|
$create(`#${id}-close-icon`, {onclick: messageBox.listeners.closeIcon},
|
||||||
$element({tag: 'SVG#path', d: 'M11.69,10l4.55,4.55-1.69,1.69L10,11.69,' +
|
$create('SVG:svg.svg-icon', {viewBox: '0 0 20 20'},
|
||||||
|
$create('SVG:path', {d: 'M11.69,10l4.55,4.55-1.69,1.69L10,11.69,' +
|
||||||
'5.45,16.23,3.77,14.55,8.31,10,3.77,5.45,5.45,3.77,10,8.31l4.55-4.55,1.69,1.69Z',
|
'5.45,16.23,3.77,14.55,8.31,10,3.77,5.45,5.45,3.77,10,8.31l4.55-4.55,1.69,1.69Z',
|
||||||
})
|
}))),
|
||||||
}),
|
$create(`#${id}-contents`, tHTML(contents)),
|
||||||
onclick: messageBox.listeners.closeIcon}),
|
$create(`#${id}-buttons`,
|
||||||
$element({id: `${id}-contents`, appendChild: tHTML(contents)}),
|
buttons.map((content, buttonIndex) => content &&
|
||||||
$element({id: `${id}-buttons`, appendChild:
|
$create('button', {
|
||||||
buttons.map((content, buttonIndex) => content && $element({
|
|
||||||
tag: 'button',
|
|
||||||
buttonIndex,
|
buttonIndex,
|
||||||
textContent: content.textContent || content,
|
textContent: content.textContent || content,
|
||||||
onclick: content.onclick || messageBox.listeners.button,
|
onclick: content.onclick || messageBox.listeners.button,
|
||||||
}))
|
}))),
|
||||||
}),
|
]),
|
||||||
]}),
|
]);
|
||||||
]});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindGlobalListeners() {
|
function bindGlobalListeners() {
|
||||||
|
|
19
popup.html
19
popup.html
|
@ -3,6 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="global.css">
|
||||||
<link rel="stylesheet" href="popup/popup.css">
|
<link rel="stylesheet" href="popup/popup.css">
|
||||||
<link rel="stylesheet" href="popup/search-results.css">
|
<link rel="stylesheet" href="popup/search-results.css">
|
||||||
|
|
||||||
|
@ -27,9 +28,7 @@
|
||||||
<div class="main-controls">
|
<div class="main-controls">
|
||||||
<label class="style-name">
|
<label class="style-name">
|
||||||
<input class="checker" type="checkbox">
|
<input class="checker" type="checkbox">
|
||||||
<svg class="svg-icon checked" viewBox="0 0 1000 1000">
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
<path fill-rule="evenodd" d="M983.2,184.3L853,69.8c-4-3.5-9.3-5.3-14.5-5c-5.3,0.4-10.3,2.8-13.8,6.8L352.3,609.2L184.4,386.9c-3.2-4.2-8-7-13.2-7.8c-5.3-0.8-10.6,0.6-14.9,3.9L18,487.5c-8.8,6.7-10.6,19.3-3.9,28.1L325,927.2c3.6,4.8,9.3,7.7,15.3,8c0.2,0,0.5,0,0.7,0c5.8,0,11.3-2.5,15.1-6.8L985,212.6C992.3,204.3,991.5,191.6,983.2,184.3z"/>
|
|
||||||
</svg>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
|
@ -141,11 +140,10 @@
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<div id="disable-all-wrapper">
|
<div id="disable-all-wrapper">
|
||||||
<div class="main-controls">
|
<div class="main-controls">
|
||||||
|
<label id="disableAll-label" i18n-text="disableAllStyles">
|
||||||
<input id="disableAll" type="checkbox">
|
<input id="disableAll" type="checkbox">
|
||||||
<svg class="svg-icon checked" viewBox="0 0 1000 1000">
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
<path fill-rule="evenodd" d="M983.2,184.3L853,69.8c-4-3.5-9.3-5.3-14.5-5c-5.3,0.4-10.3,2.8-13.8,6.8L352.3,609.2L184.4,386.9c-3.2-4.2-8-7-13.2-7.8c-5.3-0.8-10.6,0.6-14.9,3.9L18,487.5c-8.8,6.7-10.6,19.3-3.9,28.1L325,927.2c3.6,4.8,9.3,7.7,15.3,8c0.2,0,0.5,0,0.7,0c5.8,0,11.3-2.5,15.1-6.8L985,212.6C992.3,204.3,991.5,191.6,983.2,184.3z"/>
|
</label>
|
||||||
</svg>
|
|
||||||
<label id="disableAll-label" for="disableAll" i18n-text="disableAllStyles"></label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="searchResults" class="hidden">
|
<div id="searchResults" class="hidden">
|
||||||
|
@ -193,5 +191,12 @@
|
||||||
i18n-title="shortcutsNote"></button>
|
i18n-title="shortcutsNote"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" style="display: none !important;">
|
||||||
|
<symbol id="svg-icon-checked" viewBox="0 0 1000 1000">
|
||||||
|
<path fill-rule="evenodd" d="M983.2,184.3L853,69.8c-4-3.5-9.3-5.3-14.5-5c-5.3,0.4-10.3,2.8-13.8,6.8L352.3,609.2L184.4,386.9c-3.2-4.2-8-7-13.2-7.8c-5.3-0.8-10.6,0.6-14.9,3.9L18,487.5c-8.8,6.7-10.6,19.3-3.9,28.1L325,927.2c3.6,4.8,9.3,7.7,15.3,8c0.2,0,0.5,0,0.7,0c5.8,0,11.3-2.5,15.1-6.8L985,212.6C992.3,204.3,991.5,191.6,983.2,184.3z"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -142,13 +142,13 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
line
|
line
|
||||||
.split(/(<.*?>)/)
|
.split(/(<.*?>)/)
|
||||||
.map(s => (!s.startsWith('<') ? s :
|
.map(s => (!s.startsWith('<') ? s :
|
||||||
$element({tag: 'mark', textContent: s.slice(1, -1)})));
|
$create('mark', s.slice(1, -1))));
|
||||||
const linesToElements = text =>
|
const linesToElements = text =>
|
||||||
text
|
text
|
||||||
.trim()
|
.trim()
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map((line, i, array) =>
|
.map((line, i, array) =>
|
||||||
$element(i < array.length - 1 ? {
|
$create(i < array.length - 1 ? {
|
||||||
tag: 'p',
|
tag: 'p',
|
||||||
appendChild: keysToElements(line),
|
appendChild: keysToElements(line),
|
||||||
} : {
|
} : {
|
||||||
|
@ -159,9 +159,9 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
}));
|
}));
|
||||||
[
|
[
|
||||||
linesToElements(t('popupHotkeysInfo')),
|
linesToElements(t('popupHotkeysInfo')),
|
||||||
$element({tag: 'button', textContent: t('confirmOK')}),
|
$create('button', t('confirmOK')),
|
||||||
].forEach(child => {
|
].forEach(child => {
|
||||||
container.appendChild($element({appendChild: child}));
|
container.appendChild($create('div', child));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
143
popup/popup.css
143
popup/popup.css
|
@ -22,112 +22,57 @@ body > div:not(#installed) {
|
||||||
.firefox .chromium-only {
|
.firefox .chromium-only {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
/************ checkbox ************/
|
||||||
|
|
||||||
/* there's a bug in FF 52 ESR so until we find a better workaround we won't style checkboxes in FF */
|
.style-name:hover input[type="checkbox"]:checked {
|
||||||
html.moz-appearance-bug .svg-icon.checked {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.moz-appearance-bug input[type="checkbox"] {
|
|
||||||
position: absolute;
|
|
||||||
left: 8px;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.moz-appearance-bug #disableAll {
|
|
||||||
left: -1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
html.moz-appearance-bug #disableAll-label {
|
|
||||||
padding-left: 16px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) .svg-icon.checked {
|
|
||||||
position: absolute;
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
display: none;
|
|
||||||
fill: #000;
|
|
||||||
margin: 2px 0 0 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) input[type="checkbox"]:checked + .svg-icon.checked {
|
|
||||||
display: inline-flex;
|
|
||||||
transition: fill .25s;
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) input[type="checkbox"] {
|
|
||||||
-moz-appearance: none;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
border: 1px solid hsl(0, 0%, 46%);
|
|
||||||
height: 12px;
|
|
||||||
width: 12px;
|
|
||||||
display: inline-flex;
|
|
||||||
border-radius: 2px;
|
|
||||||
background-color: hsl(0, 0%, 94%);
|
|
||||||
outline: none;
|
|
||||||
margin: 0;
|
|
||||||
transition: background-color .25s, border-color .25s;
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) input[type="checkbox"]:checked:hover,
|
|
||||||
html:not(.moz-appearance-bug) .style-name:hover input[type="checkbox"]:checked {
|
|
||||||
border-color: hsl(0, 0%, 32%);
|
border-color: hsl(0, 0%, 32%);
|
||||||
background-color: hsl(0, 0%, 82%);
|
background-color: hsl(0, 0%, 82%);
|
||||||
}
|
}
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) input[type="checkbox"]:hover,
|
.style-name:hover input[type="checkbox"] {
|
||||||
html:not(.moz-appearance-bug) .style-name:hover input[type="checkbox"],
|
|
||||||
html:not(.moz-appearance-bug) .entry.disabled .style-name:hover input[type="checkbox"] {
|
|
||||||
border-color: hsl(0, 0%, 32%);
|
border-color: hsl(0, 0%, 32%);
|
||||||
background-color: hsl(0, 0%, 82%);
|
background-color: hsl(0, 0%, 82%);
|
||||||
}
|
}
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) #installed.disabled + .actions #disableAll:checked + .svg-icon.checked {
|
#disable-all-wrapper input[type="checkbox"]:not(.slider):checked + .svg-icon.checked {
|
||||||
fill: hsl(0, 68%, 42%);
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) #installed.disabled + .actions #disableAll:checked {
|
|
||||||
border-color: hsl(0, 68%, 50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) #installed.disabled + .actions #disableAll:checked:hover + .svg-icon.checked {
|
|
||||||
fill: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) #disableAll:hover {
|
|
||||||
border-color: hsl(0, 68%, 50%);
|
|
||||||
background-color: hsl(20, 70%, 75%);
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) #disableAll:hover + .svg-icon + label {
|
|
||||||
color: hsl(0, 68%, 42%);
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) #installed.disabled + .actions #disableAll:checked:hover {
|
|
||||||
border-color: hsl(0, 50%, 56%);
|
|
||||||
background-color: hsl(0, 50%, 56%);
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) .style-name .checker,
|
|
||||||
html:not(.moz-appearance-bug) .style-name .svg-icon.checked {
|
|
||||||
position: absolute;
|
|
||||||
top: 7px;
|
|
||||||
left: 9px;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
html:not(.moz-appearance-bug) #disable-all-wrapper .main-controls .svg-icon.checked {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
#installed.disabled + .actions #disableAll:checked + .svg-icon.checked {
|
||||||
transition: color .25s;
|
fill: hsl(0, 68%, 42%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#installed.disabled + .actions #disableAll:checked {
|
||||||
|
border-color: hsl(0, 68%, 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#installed.disabled + .actions #disableAll:checked:hover + .svg-icon.checked {
|
||||||
|
fill: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#disableAll:hover {
|
||||||
|
border-color: hsl(0, 68%, 50%);
|
||||||
|
background-color: hsl(20, 70%, 75%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#disableAll-label:hover {
|
||||||
|
color: hsl(0, 68%, 42%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#installed.disabled + .actions #disableAll:checked:hover {
|
||||||
|
border-color: hsl(0, 50%, 56%);
|
||||||
|
background-color: hsl(0, 50%, 56%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#installed .style-name .checker,
|
||||||
|
#installed .style-name .svg-icon.checked {
|
||||||
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
left: 9px;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#disable-all-wrapper {
|
#disable-all-wrapper {
|
||||||
|
@ -140,18 +85,14 @@ label {
|
||||||
}
|
}
|
||||||
|
|
||||||
#disable-all-wrapper .main-controls label {
|
#disable-all-wrapper .main-controls label {
|
||||||
|
padding-left: 16px;
|
||||||
|
position: relative;
|
||||||
|
transition: color .25s;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding-left: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#no-styles {
|
#no-styles {
|
||||||
margin: 0 .75em;
|
font-style: italic;
|
||||||
font-weight: bold;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
#no-styles:before {
|
|
||||||
content: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.checker {
|
.checker {
|
||||||
|
@ -222,6 +163,10 @@ html[style] .entry {
|
||||||
padding: 0 16px 0 0;
|
padding: 0 16px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#no-styles.entry {
|
||||||
|
padding: 0 14px;
|
||||||
|
}
|
||||||
|
|
||||||
html[style] .entry:nth-child(-n+10):before,
|
html[style] .entry:nth-child(-n+10):before,
|
||||||
html[style] .entry:nth-child(10):before {
|
html[style] .entry:nth-child(10):before {
|
||||||
right: 7px;
|
right: 7px;
|
||||||
|
|
|
@ -929,7 +929,7 @@
|
||||||
((cm.display.renderedView || [])[0] || {}).text || cm.display.lineDiv;
|
((cm.display.renderedView || [])[0] || {}).text || cm.display.lineDiv;
|
||||||
for (let el = start; el; el = el.parentElement) {
|
for (let el = start; el; el = el.parentElement) {
|
||||||
const bgColor = getComputedStyle(el).backgroundColor;
|
const bgColor = getComputedStyle(el).backgroundColor;
|
||||||
const [r, g, b, a = 255] = bgColor.match(/\d+/g).map(Number);
|
const [r, g, b, a = 255] = (bgColor.match(/\d+/g) || []).map(Number);
|
||||||
if (!a) {
|
if (!a) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10994,6 +10994,11 @@ self.onmessage = ({data: {action = 'run', code, config}}) => {
|
||||||
self.postMessage(CSSLint.getRules().map(rule => rule.id));
|
self.postMessage(CSSLint.getRules().map(rule => rule.id));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 'getAllRuleInfos':
|
||||||
|
// the functions are non-tranferable
|
||||||
|
self.postMessage(CSSLint.getRules().map(rule => JSON.parse(JSON.stringify(rule))));
|
||||||
|
return;
|
||||||
|
|
||||||
case 'run':
|
case 'run':
|
||||||
Object.defineProperty(config, 'errors', {get: () => 0, set: () => 0});
|
Object.defineProperty(config, 'errors', {get: () => 0, set: () => 0});
|
||||||
config['uso-vars'] = 1;
|
config['uso-vars'] = 1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user