stylus/edit/util.js
eight 2fd531e253 Rewrite linter system (#487)
* Add: implement new linter system

* Refactor: pull out editor worker

* Switch to new linter and worker

* Enable eslint cache

* Fix: undefined error

* Windows compatibility

* Fix: refresh linter if the editor.linter changes

* Add: stylelint

* Add: getStylelintRules, getCsslintRules

* Fix: logic to get correct linter

* WIP: linter-report

* Fix: toggle hidden state

* Add: matain the order of lint report for section editor

* Add: unhook event

* Add: gotoLintIssue

* Fix: shouldn't delete rule.init

* Add: linter-help-dialog

* Drop linterConfig

* Add: linter-config-dialog, cacheFn

* Add: use cacheFn

* Drop lint.js

* Add: refresh. Fix report order

* Fix: hide empty table

* Add: updateCount. Fix table caption

* Switch to new linter/worker

* Fix: remove unneeded comment

* Fix: cacheFn -> cacheFirstCall

* Fix: use cacheFirstCall

* Fix: cache metaIndex

* Fix: i < trs.length

* Fix: drop isEmpty

* Fix: expose some simple states to global

* Fix: return object code style

* Fix: use proxy to reflect API

* Fix: eslint-disable-line -> eslint-disable-next-line

* Fix: requestId -> id

* Fix: one-liner

* Fix: one-liner

* Fix: move dom event block to top

* Fix: pending -> pendingResponse

* Fix: onSuccess -> onUpdated

* Fix: optimize row removing when i === 0

* Fix: hook/unhook -> enableForEditor/disableForEditor

* Fix: linter.refresh -> linter.run

* Fix: some shadowing

* Fix: simplify getAnnotations

* Fix: cacheFirstCall -> memoize

* Fix: table.update -> table.updateCaption

* Fix: unneeded reassign

* Fix: callbacks -> listeners

* Fix: don't compose but extend

* Refactor: replace linter modules with linter-defaults and linter-engines

* Fix: implement linter fallbacks

* Fix: linter.onChange -> linter.onLintingUpdated

* Fix: cms -> tables

* Fix: parseMozFormat is not called correctly

* Move csslint-loader to background

* Fix: watch config changes

* Fix: switch to LINTER_DEFAULTS

* Fix: csslint-loader -> parserlib-loader
2018-10-01 09:03:17 -05:00

137 lines
2.9 KiB
JavaScript

'use strict';
function dirtyReporter() {
const dirty = new Map();
const onchanges = [];
function add(obj, value) {
const saved = dirty.get(obj);
if (!saved) {
dirty.set(obj, {type: 'add', newValue: value});
} else if (saved.type === 'remove') {
if (saved.savedValue === value) {
dirty.delete(obj);
} else {
saved.newValue = value;
saved.type = 'modify';
}
}
}
function remove(obj, value) {
const saved = dirty.get(obj);
if (!saved) {
dirty.set(obj, {type: 'remove', savedValue: value});
} else if (saved.type === 'add') {
dirty.delete(obj);
} else if (saved.type === 'modify') {
saved.type = 'remove';
}
}
function modify(obj, oldValue, newValue) {
const saved = dirty.get(obj);
if (!saved) {
if (oldValue !== newValue) {
dirty.set(obj, {type: 'modify', savedValue: oldValue, newValue});
}
} else if (saved.type === 'modify') {
if (saved.savedValue === newValue) {
dirty.delete(obj);
} else {
saved.newValue = newValue;
}
} else if (saved.type === 'add') {
saved.newValue = newValue;
}
}
function clear(obj) {
if (obj === undefined) {
dirty.clear();
} else {
dirty.delete(obj);
}
}
function isDirty() {
return dirty.size > 0;
}
function onChange(cb) {
// make sure the callback doesn't throw
onchanges.push(cb);
}
function wrap(obj) {
for (const key of ['add', 'remove', 'modify', 'clear']) {
obj[key] = trackChange(obj[key]);
}
return obj;
}
function emitChange() {
for (const cb of onchanges) {
cb();
}
}
function trackChange(fn) {
return function () {
const dirty = isDirty();
const result = fn.apply(null, arguments);
if (dirty !== isDirty()) {
emitChange();
}
return result;
};
}
function has(key) {
return dirty.has(key);
}
return wrap({add, remove, modify, clear, isDirty, onChange, has});
}
function sectionsToMozFormat(style) {
const propertyToCss = {
urls: 'url',
urlPrefixes: 'url-prefix',
domains: 'domain',
regexps: 'regexp',
};
return style.sections.map(section => {
let cssMds = [];
for (const i in propertyToCss) {
if (section[i]) {
cssMds = cssMds.concat(section[i].map(v =>
propertyToCss[i] + '("' + v.replace(/\\/g, '\\\\') + '")'
));
}
}
return cssMds.length ?
'@-moz-document ' + cssMds.join(', ') + ' {\n' + section.code + '\n}' :
section.code;
}).join('\n\n');
}
function clipString(str, limit = 100) {
return str.length <= limit ? str : str.substr(0, limit) + '...';
}
// this is a decorator. Cache the first call
function memoize(fn) {
let cached = false;
let result;
return (...args) => {
if (!cached) {
result = fn(...args);
cached = true;
}
return result;
};
}