add a terse invocation syntax for $element and rename it to $create
This commit is contained in:
parent
6e142a7444
commit
c0c60fb7a2
|
@ -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}]
|
||||||
|
|
|
@ -25,53 +25,25 @@ function createAppliesToLineWidget(cm) {
|
||||||
|
|
||||||
TPL = {
|
TPL = {
|
||||||
container:
|
container:
|
||||||
$element({className: 'applies-to', appendChild: [
|
$create('div.applies-to', [
|
||||||
$element({tag: 'label', appendChild: t('appliesLabel')}),
|
$create('label', t('appliesLabel')),
|
||||||
$element({tag: 'ul', className: 'applies-to-list'}),
|
$create('ul.applies-to-list'),
|
||||||
]}),
|
]),
|
||||||
listItem: $element({
|
listItem:
|
||||||
tag: 'li',
|
$create('li.applies-to-item', [
|
||||||
className: 'applies-to-item',
|
$create('select.applies-type', [
|
||||||
appendChild: [
|
$create('option', {value: 'url'}, t('appliesUrlOption')),
|
||||||
$element({
|
$create('option', {value: 'url-prefix'}, t('appliesUrlPrefixOption')),
|
||||||
tag: 'select',
|
$create('option', {value: 'domain'}, t('appliesDomainOption')),
|
||||||
className: 'applies-type',
|
$create('option', {value: 'regexp'}, t('appliesRegexpOption')),
|
||||||
appendChild: [
|
]),
|
||||||
[t('appliesUrlOption'), 'url'],
|
$create('input.applies-value'),
|
||||||
[t('appliesUrlPrefixOption'), 'url-prefix'],
|
$create('button.test-regexp', t('styleRegexpTestButton')),
|
||||||
[t('appliesDomainOption'), 'domain'],
|
$create('button.remove-applies-to', t('appliesRemove')),
|
||||||
[t('appliesRegexpOption'), 'regexp']
|
$create('button.add-applies-to', t('appliesAdd')),
|
||||||
].map(([textContent, value]) => $element({
|
]),
|
||||||
tag: 'option',
|
appliesToEverything:
|
||||||
value,
|
$create('li.applies-to-everything', t('appliesToEverything')),
|
||||||
textContent,
|
|
||||||
})),
|
|
||||||
}),
|
|
||||||
$element({
|
|
||||||
tag: 'input',
|
|
||||||
className: 'applies-value',
|
|
||||||
}),
|
|
||||||
$element({
|
|
||||||
tag: 'button',
|
|
||||||
className: 'test-regexp',
|
|
||||||
textContent: t('styleRegexpTestButton'),
|
|
||||||
}),
|
|
||||||
$element({
|
|
||||||
tag: 'button',
|
|
||||||
className: 'remove-applies-to',
|
|
||||||
textContent: t('appliesRemove'),
|
|
||||||
}),
|
|
||||||
$element({
|
|
||||||
tag: 'button',
|
|
||||||
className: 'add-applies-to',
|
|
||||||
textContent: t('appliesAdd'),
|
|
||||||
})
|
|
||||||
]}),
|
|
||||||
appliesToEverything: $element({
|
|
||||||
tag: 'li',
|
|
||||||
className: 'applies-to-everything',
|
|
||||||
textContent: t('appliesToEverything'),
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CLICK_ROUTE = {
|
CLICK_ROUTE = {
|
||||||
|
@ -164,7 +136,7 @@ function createAppliesToLineWidget(cm) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
styleVariables = $element({tag: 'style'});
|
styleVariables = $create('style');
|
||||||
fromLine = 0;
|
fromLine = 0;
|
||||||
toLine = cm.doc.size;
|
toLine = cm.doc.size;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'),
|
||||||
|
|
18
edit/edit.js
18
edit/edit.js
|
@ -457,22 +457,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 +520,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,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +613,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';
|
||||||
|
|
126
edit/lint.js
126
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;
|
||||||
|
|
||||||
|
@ -388,35 +368,29 @@ function showLintHelp() {
|
||||||
: 'https://github.com/CSSLint/csslint/issues/535';
|
: 'https://github.com/CSSLint/csslint/issues/535';
|
||||||
let headerLink, template;
|
let headerLink, template;
|
||||||
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 = linterConfig.allRuleIds.csslint.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',
|
$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'),
|
return showHelp(t('linterIssues'),
|
||||||
$element({appendChild: [
|
$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),
|
|
||||||
}),
|
|
||||||
]})
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,41 +439,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 +470,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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ var regExpTester = (() => {
|
||||||
if (!isInit) {
|
if (!isInit) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
showHelp('', $element({className: 'regexp-report'}));
|
showHelp('', $create('.regexp-report'));
|
||||||
} else if (!state && isShown()) {
|
} else if (!state && 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,12 +160,11 @@ var regExpTester = (() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
report.appendChild($element({
|
report.appendChild(
|
||||||
tag: 'p',
|
$create('p.regexp-report-note',
|
||||||
className: 'regexp-report-note',
|
t('styleRegexpTestNote')
|
||||||
appendChild: t('styleRegexpTestNote').split(/(\\+)/)
|
.split(/(\\+)/)
|
||||||
.map(s => s.startsWith('\\') ? $element({tag: 'code', textContent: s}) : s),
|
.map(s => (s.startsWith('\\') ? $create('code', s) : s))));
|
||||||
}));
|
|
||||||
showHelp(t('styleRegexpTestTitle'), report);
|
showHelp(t('styleRegexpTestTitle'), report);
|
||||||
|
|
||||||
report.onclick = event => {
|
report.onclick = event => {
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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() {
|
||||||
|
@ -230,26 +215,23 @@
|
||||||
|
|
||||||
function buildWarning(err) {
|
function buildWarning(err) {
|
||||||
const contents = Array.isArray(err) ?
|
const contents = Array.isArray(err) ?
|
||||||
$element({tag: 'pre', textContent: err.join('\n')}) :
|
$create('pre', err.join('\n')) :
|
||||||
[err && err.message || err || 'Unknown error'];
|
[err && err.message || err || 'Unknown error'];
|
||||||
if (Number.isInteger(err.index)) {
|
if (Number.isInteger(err.index)) {
|
||||||
const pos = cm.posFromIndex(err.index);
|
const pos = cm.posFromIndex(err.index);
|
||||||
contents[0] = `${pos.line + 1}:${pos.ch + 1} ` + contents[0];
|
contents[0] = `${pos.line + 1}:${pos.ch + 1} ` + contents[0];
|
||||||
contents.push($element({
|
contents.push($create('pre', drawLinePointer(pos)));
|
||||||
tag: 'pre',
|
|
||||||
textContent: drawLinePointer(pos)
|
|
||||||
}));
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
cm.scrollIntoView({line: pos.line + 1, ch: pos.ch}, window.innerHeight / 4);
|
cm.scrollIntoView({line: pos.line + 1, ch: pos.ch}, window.innerHeight / 4);
|
||||||
cm.setCursor(pos.line, pos.ch + 1);
|
cm.setCursor(pos.line, pos.ch + 1);
|
||||||
cm.focus();
|
cm.focus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return $element({className: 'warning', appendChild: [
|
return $create('.warning', [
|
||||||
t('parseUsercssError'),
|
t('parseUsercssError'),
|
||||||
'\n',
|
'\n',
|
||||||
...contents,
|
...contents,
|
||||||
]});
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawLinePointer(pos) {
|
function drawLinePointer(pos) {
|
||||||
|
@ -281,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')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
87
js/dom.js
87
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,35 +166,88 @@ 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]);
|
element.setAttributeNS(null, attr, opt[attr]);
|
||||||
|
@ -203,11 +255,12 @@ function $element(opt) {
|
||||||
} 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 +270,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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,30 @@ 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',
|
||||||
tag: '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
|
|
||||||
}))
|
|
||||||
});
|
|
||||||
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,
|
|
||||||
],
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
|
|
|
@ -84,14 +84,14 @@ 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')}";
|
||||||
}
|
}
|
||||||
`}));
|
`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
});
|
});
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user