From 61351bcb2f7d7aa082d33908d5e5aa878363c785 Mon Sep 17 00:00:00 2001 From: tophf Date: Tue, 29 Aug 2017 00:12:42 +0300 Subject: [PATCH 1/7] re-lint only changed rules --- edit/edit.js | 9 +- edit/lint-codemirror-helper.js | 278 ++++++++++++++++++++++++++++++--- edit/lint.js | 11 +- 3 files changed, 267 insertions(+), 31 deletions(-) diff --git a/edit/edit.js b/edit/edit.js index 1690b93f..a85e7065 100644 --- a/edit/edit.js +++ b/edit/edit.js @@ -182,7 +182,8 @@ function initCodeMirror() { highlightSelectionMatches: {showToken: /[#.\-\w]/, annotateScrollbar: true}, hintOptions: {}, lint: linterConfig.getForCodeMirror(), - lintReportDelay: prefs.get('editor.lintReportDelay'), + lintReportDelay: 500, + //lintReportDelay: prefs.get('editor.lintReportDelay'), styleActiveLine: true, theme: 'default', keyMap: prefs.get('editor.keyMap'), @@ -461,10 +462,14 @@ function setupCodeMirror(textarea, index) { return cm; } -function indicateCodeChange(cm) { +function indicateCodeChange(cm, change) { const section = cm.getSection(); setCleanItem(section, cm.isClean(section.savedValue)); updateTitle(); + if (change) { + cm.stylusChanges = cm.stylusChanges || []; + cm.stylusChanges.push(change); + } updateLintReportIfEnabled(cm); } diff --git a/edit/lint-codemirror-helper.js b/edit/lint-codemirror-helper.js index 588a202c..864edc97 100644 --- a/edit/lint-codemirror-helper.js +++ b/edit/lint-codemirror-helper.js @@ -1,31 +1,257 @@ /* global CodeMirror CSSLint stylelint linterConfig */ 'use strict'; -CodeMirror.registerHelper('lint', 'csslint', code => - CSSLint.verify(code, deepCopy(linterConfig.getCurrent('csslint'))) - .messages.map(message => ({ - from: CodeMirror.Pos(message.line - 1, message.col - 1), - to: CodeMirror.Pos(message.line - 1, message.col), - message: message.message + ` (${message.rule.id})`, - severity : message.type - })) -); +(() => { + let config; + const cmpPos = CodeMirror.cmpPos; -CodeMirror.registerHelper('lint', 'stylelint', code => - stylelint.lint({ - code, - config: deepCopy(linterConfig.getCurrent('stylelint')), - }).then(({results}) => { - if (!results[0]) { - return []; + CodeMirror.registerHelper('lint', 'csslint', (code, options, cm) => + copyOldIssues(cm, lintChangedRanges(cm, csslintOnRange)) + ); + + CodeMirror.registerHelper('lint', 'stylelint', (code, options, cm) => + Promise.all(lintChangedRanges(cm, stylelintOnRange)) + .then(results => copyOldIssues(cm, results)) + ); + + function csslintOnRange(range) { + return CSSLint.verify(range.code, config).messages + .map(item => + cookResult( + range, + item.line, + item.col, + item.message.replace(/ at line \d+, col \d+/, '') + ` (${item.rule.id})`, + item.type + ) + ); + } + + function stylelintOnRange(range) { + return stylelint.lint({code: range.code, config}) + .then(({results}) => ((results[0] || {}).warnings || []) + .map(item => + cookResult( + range, + item.line, + item.column, + item.text + .replace('Unexpected ', '') + .replace(/^./, firstLetter => firstLetter.toUpperCase()), + item.severity + ) + ) + ); + } + + function cookResult(range, line, col, message, severity) { + line--; + col--; + const realL = line + range.from.line; + const realC = col + (line === 0 ? range.from.ch : 0); + return { + from: CodeMirror.Pos(realL, realC), + to: CodeMirror.Pos(realL, realC + 1), + message, + severity, + }; + } + + function lintChangedRanges(cm, lintFunction) { + const EOF = CodeMirror.Pos(cm.doc.size - 1, cm.getLine(cm.doc.size - 1).length); + // cache the config for subsequent *lintOnRange + config = deepCopy(linterConfig.getCurrent()); + let ranges; + if (!cm.stylusChanges || !cm.stylusChanges.length) { + // first run: lint everything + // the temp monkeypatch in updateLintReport() is there + // only to allow sep=false that returns a line array + ranges = [{ + code: cm.getValue(false).join('\n'), + from: {line: 0, ch: 0}, + to: EOF, + }]; + } else { + // sort by 'from' position in ascending order + const changes = cm.stylusChanges.sort((a, b) => cmpPos(a.from, b.from)); + // merge pass 1 + ranges = mergeRanges(changes); + // extend up to previous } and down to next } + for (const range of ranges) { + range.from = findBlockEndBefore(range.from, 2); + range.to = findBlockEndAfter(range.to, 2); + } + // merge pass 2 on the extended ranges + ranges = mergeRanges(ranges); } - return results[0].warnings.map(warning => ({ - from: CodeMirror.Pos(warning.line - 1, warning.column - 1), - to: CodeMirror.Pos(warning.line - 1, warning.column), - message: warning.text - .replace('Unexpected ', '') - .replace(/^./, firstLetter => firstLetter.toUpperCase()), - severity : warning.severity - })); - }) -); + // fill the code and run lintFunction + const results = []; + for (const range of ranges) { + range.code = cm.getRange(range.from, range.to); + results.push(lintFunction(range)); + } + // reset the changes queue and pass the ranges to updateLintReport + (cm.stylusChanges || []).length = 0; + cm.state.lint.changedRanges = ranges; + return results; + + function findBlockEndBefore(pos, repetitions = 1) { + const PREV_CMT_END = find('*/', pos, -1); + const PREV_CMT_START = (prev => cmp(prev, pos) < 0 && prev)(find('/*', PREV_CMT_END, +1)); + const NEXT_CMT_END = PREV_CMT_START && (find('*/', PREV_CMT_START, +1) || EOF); + const cursor = cm.getSearchCursor(/\/\*|\*\/|}/, pos, {caseFold: false}); + let cmtStart = PREV_CMT_START; + let cmtEnd = cmtStart && cmp(NEXT_CMT_END, pos) > 0 && NEXT_CMT_END; + let blockEnd; + while (cursor.findPrevious()) { + switch (cursor.pos.match[0]) { + case '}': + if (!cmtStart || cmp(cmtStart, cursor.pos.to) > 0) { + blockEnd = cursor.pos.to; + if (--repetitions <= 0) { + return blockEnd; + } + } + break; + case '/*': + cmtStart = cursor.pos.to; + if (cmp(cmtEnd, blockEnd) > 0) { + blockEnd = null; + } + break; + case '*/': + cmtEnd = cursor.pos.to; + if (blockEnd && --repetitions <= 0) { + return blockEnd; + } + break; + } + } + return blockEnd || {line: 0, ch: 0}; + } + + function findBlockEndAfter(pos, repetitions = 1) { + const PREV_CMT_END = find('*/', pos, -1); + const PREV_CMT_START = (prev => cmp(prev, pos) < 0 && prev)(find('/*', PREV_CMT_END, +1)); + const cursor = cm.getSearchCursor(/\/\*|\*\/|}/, pos, {caseFold: false}); + let cmtStart = PREV_CMT_START; + while (cursor.findNext()) { + switch (cursor.pos.match[0]) { + case '}': + if (!cmtStart && --repetitions <= 0) { + return cursor.pos.to; + } + break; + case '/*': + cmtStart = cmtStart || cursor.pos.from; + break; + case '*/': + cmtStart = null; + break; + } + } + return EOF; + } + + function find(query, pos, direction) { + const cursor = cm.getSearchCursor(query, pos, {caseFold: false}); + return direction > 0 + ? cursor.findNext() && cursor.from() + : cursor.findPrevious() && cursor.to(); + } + + function cmp(a, b) { + if (!a && !b) { + return 0; + } + if (!a) { + return -1; + } + if (!b) { + return 1; + } + return cmpPos(a, b); + } + } + + function mergeRanges(sorted) { + const ranges = []; + let lastChange = {from: {}, to: {line: -1, ch: -1}}; + for (const change of sorted) { + if (cmpPos(change.from, change.to) > 0) { + // straighten the inverted range + const from = change.from; + change.from = change.to; + change.to = from; + } + if (cmpPos(change.from, lastChange.to) > 0) { + ranges.push({ + from: change.from, + to: change.to, + code: '', + }); + } else if (cmpPos(change.to, lastChange.to) > 0) { + ranges[ranges.length - 1].to = change.to; + } + lastChange = change; + } + return ranges; + } + + function copyOldIssues(cm, newAnns) { + const EOF = CodeMirror.Pos(cm.doc.size - 1, cm.getLine(cm.doc.size - 1).length); + + const oldMarkers = cm.state.lint.marked; + let oldIndex = 0; + let oldAnn = (oldMarkers[0] || {}).__annotation; + + const newRanges = cm.state.lint.changedRanges || []; + let newIndex = 0; + let newRange = newRanges[0]; + + const finalAnns = []; + const unique = new Set(); + const pushUnique = item => { + const key = item.line + ' ' + item.ch + ' ' + item.message; + if (!unique.has(key)) { + unique.add(key); + finalAnns.push(item); + } + }; + + const t0 = performance.now(); + while (oldAnn && cmpPos(oldAnn.from, EOF) < 0 || newRange) { + if (performance.now() - t0 > 500) { + console.error('infinite loop canceled', + JSON.stringify([ + newAnns, + oldMarkers[0] && oldMarkers.map(m => ({from: m.__annotation.from, to: m.__annotation.to})), + newRanges.map(r => Object.assign(r, {code: undefined})) + ]) + ); + break; + } + // copy old issues prior to current newRange + // eslint-disable-next-line no-unmodified-loop-condition + while (oldAnn && (!newRange || cmpPos(oldAnn.to, newRange.from) < 0)) { + pushUnique(oldAnn); + oldIndex++; + oldAnn = (oldMarkers[oldIndex] || {}).__annotation; + } + // skip all old issues within newRange + if (newRange) { + while (oldAnn && cmpPos(oldAnn.to, newRange.to) <= 0) { + oldAnn = (oldMarkers[oldIndex++] || {}).__annotation; + } + } + // copy all newRange prior to current oldAnn + // eslint-disable-next-line no-unmodified-loop-condition + while (newRange && (!oldAnn || cmpPos(newRange.to, oldAnn.from) <= 0)) { + newAnns[newIndex].forEach(pushUnique); + newIndex++; + newRange = newRanges[newIndex]; + } + } + return finalAnns; + } +})(); diff --git a/edit/lint.js b/edit/lint.js index e8cc1fc9..91710a0c 100644 --- a/edit/lint.js +++ b/edit/lint.js @@ -196,17 +196,22 @@ function updateLintReport(cm, delay) { update(cm); return; } + const state = cm.state.lint; if (delay > 0) { - setTimeout(cm => { + clearTimeout((state || {}).lintTimeout); + (state || {}).lintTimeout = setTimeout(cm => { + // the temp monkeypatch only allows sep=false that returns a line array + // because during editing this is what we need, not the combined text + const _getValue = cm.getValue; + cm.getValue = sep => (sep === false ? _getValue.call(cm, sep) : ''); if (cm.performLint) { cm.performLint(); + cm.getValue = _getValue; update(cm); } }, delay, cm); return; } - // eslint-disable-next-line no-var - var state = cm.state.lint; if (!state) { return; } From 05e0e7004b8df8141b006ef17d94d2c46278a42f Mon Sep 17 00:00:00 2001 From: tophf Date: Tue, 29 Aug 2017 20:44:22 +0300 Subject: [PATCH 2/7] improvements --- edit/lint-codemirror-helper.js | 47 ++++++++++++++++++++++++++++------ edit/lint.js | 2 +- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/edit/lint-codemirror-helper.js b/edit/lint-codemirror-helper.js index 864edc97..086a8243 100644 --- a/edit/lint-codemirror-helper.js +++ b/edit/lint-codemirror-helper.js @@ -62,8 +62,13 @@ // cache the config for subsequent *lintOnRange config = deepCopy(linterConfig.getCurrent()); let ranges; - if (!cm.stylusChanges || !cm.stylusChanges.length) { + if ( + !cm.stylusChanges || + !cm.stylusChanges.length || + cm.stylusChanges.some(change => change.origin === 'setValue') + ) { // first run: lint everything + cm.state.lint.marked = []; // the temp monkeypatch in updateLintReport() is there // only to allow sep=false that returns a line array ranges = [{ @@ -74,12 +79,22 @@ } else { // sort by 'from' position in ascending order const changes = cm.stylusChanges.sort((a, b) => cmpPos(a.from, b.from)); + // extend ranges with pasted text + for (const change of changes) { + const addedLines = Math.max(0, change.text.length - 1); + const removedLines = Math.max(0, change.removed.length - 1); + const delta = addedLines - removedLines; + change.to = CodeMirror.Pos( + Math.max(0, change.to.line + delta), + Math.max(0, change.to.ch + change.text.last.length - change.removed.last.length + 1) + ); + } // merge pass 1 ranges = mergeRanges(changes); // extend up to previous } and down to next } for (const range of ranges) { range.from = findBlockEndBefore(range.from, 2); - range.to = findBlockEndAfter(range.to, 2); + range.to = findBlockEndAfter(range.from, 4); } // merge pass 2 on the extended ranges ranges = mergeRanges(ranges); @@ -99,18 +114,25 @@ const PREV_CMT_END = find('*/', pos, -1); const PREV_CMT_START = (prev => cmp(prev, pos) < 0 && prev)(find('/*', PREV_CMT_END, +1)); const NEXT_CMT_END = PREV_CMT_START && (find('*/', PREV_CMT_START, +1) || EOF); - const cursor = cm.getSearchCursor(/\/\*|\*\/|}/, pos, {caseFold: false}); + const cursor = cm.getSearchCursor(/\/\*|\*\/|[{}]/, pos, {caseFold: false}); let cmtStart = PREV_CMT_START; let cmtEnd = cmtStart && cmp(NEXT_CMT_END, pos) > 0 && NEXT_CMT_END; + let blockStart; let blockEnd; while (cursor.findPrevious()) { switch (cursor.pos.match[0]) { + case '{': + if (!cmtStart || cmp(cmtStart, cursor.pos.to) > 0) { + blockStart = cursor.pos.from; + } + break; case '}': if (!cmtStart || cmp(cmtStart, cursor.pos.to) > 0) { blockEnd = cursor.pos.to; - if (--repetitions <= 0) { + if (--repetitions <= 0 || !blockStart) { return blockEnd; } + blockStart = null; } break; case '/*': @@ -118,6 +140,9 @@ if (cmp(cmtEnd, blockEnd) > 0) { blockEnd = null; } + if (cmp(cmtEnd, blockStart) > 0) { + blockStart = null; + } break; case '*/': cmtEnd = cursor.pos.to; @@ -133,13 +158,19 @@ function findBlockEndAfter(pos, repetitions = 1) { const PREV_CMT_END = find('*/', pos, -1); const PREV_CMT_START = (prev => cmp(prev, pos) < 0 && prev)(find('/*', PREV_CMT_END, +1)); - const cursor = cm.getSearchCursor(/\/\*|\*\/|}/, pos, {caseFold: false}); + const cursor = cm.getSearchCursor(/\/\*|\*\/|[{}]/, pos, {caseFold: false}); let cmtStart = PREV_CMT_START; + let depth = 0; while (cursor.findNext()) { switch (cursor.pos.match[0]) { + case '{': + if (!cmtStart) { + depth++; + } + break; case '}': - if (!cmtStart && --repetitions <= 0) { - return cursor.pos.to; + if (!cmtStart && (--depth <= 0 && --repetitions <= 0)) { + return depth < 0 ? cursor.pos.from : cursor.pos.to; } break; case '/*': @@ -212,7 +243,7 @@ const finalAnns = []; const unique = new Set(); const pushUnique = item => { - const key = item.line + ' ' + item.ch + ' ' + item.message; + const key = item.from.line + ' ' + item.from.ch + ' ' + item.message; if (!unique.has(key)) { unique.add(key); finalAnns.push(item); diff --git a/edit/lint.js b/edit/lint.js index 91710a0c..ab2b401c 100644 --- a/edit/lint.js +++ b/edit/lint.js @@ -206,9 +206,9 @@ function updateLintReport(cm, delay) { cm.getValue = sep => (sep === false ? _getValue.call(cm, sep) : ''); if (cm.performLint) { cm.performLint(); - cm.getValue = _getValue; update(cm); } + cm.getValue = _getValue; }, delay, cm); return; } From 854bdea61e7055a21ea355522ca96bba1b53b00e Mon Sep 17 00:00:00 2001 From: tophf Date: Tue, 29 Aug 2017 23:36:56 +0300 Subject: [PATCH 3/7] show lint report on open earlier --- edit/edit.js | 16 +++++++++++----- edit/lint.js | 7 ++++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/edit/edit.js b/edit/edit.js index a85e7065..791dee65 100644 --- a/edit/edit.js +++ b/edit/edit.js @@ -1257,7 +1257,6 @@ function initWithStyle({style, codeIsUpdated}) { updateTitle(); return; } - // if this was done in response to an update, we need to clear existing sections getSections().forEach(div => { div.remove(); }); const queue = style.sections.length ? style.sections.slice() : [{code: ''}]; @@ -1278,11 +1277,18 @@ function initWithStyle({style, codeIsUpdated}) { const sectionDiv = addSection(null, queue.shift()); maximizeCodeHeight(sectionDiv, !queue.length); const cm = sectionDiv.CodeMirror; - if (CodeMirror.lint) { + if (prefs.get('editor.linter')) { setTimeout(() => { - cm.setOption('lint', CodeMirror.defaults.lint); - updateLintReport(cm, 0); - }, prefs.get('editor.lintDelay')); + cm.setOption('lint', linterConfig.getForCodeMirror()); + updateLintReport(cm, 100); + if (!queue.length) { + setTimeout(() => { + const state = cm.state.lint || {}; + clearTimeout(state.renderTimeout); + renderLintReport(); + }, 100); + } + }); } } } diff --git a/edit/lint.js b/edit/lint.js index ab2b401c..d259a2c3 100644 --- a/edit/lint.js +++ b/edit/lint.js @@ -191,15 +191,16 @@ function updateLinter({immediately} = {}) { } function updateLintReport(cm, delay) { + const state = cm.state.lint || {}; if (delay === 0) { // immediately show pending csslint/stylelint messages in onbeforeunload and save + clearTimeout(state.lintTimeout); update(cm); return; } - const state = cm.state.lint; if (delay > 0) { - clearTimeout((state || {}).lintTimeout); - (state || {}).lintTimeout = setTimeout(cm => { + clearTimeout(state.lintTimeout); + state.lintTimeout = setTimeout(cm => { // the temp monkeypatch only allows sep=false that returns a line array // because during editing this is what we need, not the combined text const _getValue = cm.getValue; From ca8eda20ffeaa9fefbfe21adf736819698b532fd Mon Sep 17 00:00:00 2001 From: tophf Date: Tue, 29 Aug 2017 23:53:25 +0300 Subject: [PATCH 4/7] fixup onbeforeunload --- edit/lint.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/edit/lint.js b/edit/lint.js index d259a2c3..b91e56d5 100644 --- a/edit/lint.js +++ b/edit/lint.js @@ -191,7 +191,7 @@ function updateLinter({immediately} = {}) { } function updateLintReport(cm, delay) { - const state = cm.state.lint || {}; + const state = cm && cm.state.lint || {}; if (delay === 0) { // immediately show pending csslint/stylelint messages in onbeforeunload and save clearTimeout(state.lintTimeout); @@ -219,7 +219,7 @@ function updateLintReport(cm, delay) { // user is editing right now: postpone updating the report for the new issues (default: 500ms lint + 4500ms) // or update it as soon as possible (default: 500ms lint + 100ms) in case an existing issue was just fixed clearTimeout(state.reportTimeout); - state.reportTimeout = setTimeout(update, state.options.delay + 100, cm); + state.reportTimeout = setTimeout(update, (state.options || {}).delay + 100, cm); state.postponeNewIssues = delay === undefined || delay === null; function update(cm) { From 562998e4b2f93b2a960558bcfab0b12e1ed63e55 Mon Sep 17 00:00:00 2001 From: tophf Date: Wed, 30 Aug 2017 01:25:15 +0300 Subject: [PATCH 5/7] lint on import --- edit/edit.js | 30 ++++++------------------------ edit/lint.js | 22 ++++++++++++++++++---- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/edit/edit.js b/edit/edit.js index 791dee65..67cebbad 100644 --- a/edit/edit.js +++ b/edit/edit.js @@ -470,7 +470,7 @@ function indicateCodeChange(cm, change) { cm.stylusChanges = cm.stylusChanges || []; cm.stylusChanges.push(change); } - updateLintReportIfEnabled(cm); + updateLintReport(cm); } function getSectionForChild(e) { @@ -597,7 +597,7 @@ window.onbeforeunload = () => { if (isCleanGlobal()) { return; } - updateLintReportIfEnabled(null, 0); + updateLintReport(null, 0); // neither confirm() nor custom messages work in modern browsers but just in case return t('styleChangesNotSaved'); }; @@ -1275,21 +1275,9 @@ function initWithStyle({style, codeIsUpdated}) { function add() { const sectionDiv = addSection(null, queue.shift()); - maximizeCodeHeight(sectionDiv, !queue.length); - const cm = sectionDiv.CodeMirror; - if (prefs.get('editor.linter')) { - setTimeout(() => { - cm.setOption('lint', linterConfig.getForCodeMirror()); - updateLintReport(cm, 100); - if (!queue.length) { - setTimeout(() => { - const state = cm.state.lint || {}; - clearTimeout(state.renderTimeout); - renderLintReport(); - }, 100); - } - }); - } + const isLast = !queue.length; + maximizeCodeHeight(sectionDiv, isLast); + updateLintReport(sectionDiv.CodeMirror, !isLast && 100); } } @@ -1427,14 +1415,8 @@ function validate() { return null; } -function updateLintReportIfEnabled(cm, time) { - if (CodeMirror.lint) { - updateLintReport(cm, time); - } -} - function save() { - updateLintReportIfEnabled(null, 0); + updateLintReport(null, 0); // save the contents of the CodeMirror editors back into the textareas for (let i = 0; i < editors.length; i++) { diff --git a/edit/lint.js b/edit/lint.js index b91e56d5..e3419cc0 100644 --- a/edit/lint.js +++ b/edit/lint.js @@ -191,7 +191,24 @@ function updateLinter({immediately} = {}) { } function updateLintReport(cm, delay) { - const state = cm && cm.state.lint || {}; + if (!CodeMirror.defaults.lint) { + return; + } + if (cm && !cm.options.lint) { + setTimeout(() => { + if (cm.options.lint) { + return; + } + cm.setOption('lint', linterConfig.getForCodeMirror()); + if (!delay) { + setTimeout(() => { + clearTimeout((cm.state.lint || {}).renderTimeout); + renderLintReport(); + }, 100); + } + }); + } + const state = cm && cm.state && cm.state.lint || {}; if (delay === 0) { // immediately show pending csslint/stylelint messages in onbeforeunload and save clearTimeout(state.lintTimeout); @@ -213,9 +230,6 @@ function updateLintReport(cm, delay) { }, delay, cm); return; } - if (!state) { - return; - } // user is editing right now: postpone updating the report for the new issues (default: 500ms lint + 4500ms) // or update it as soon as possible (default: 500ms lint + 100ms) in case an existing issue was just fixed clearTimeout(state.reportTimeout); From d3ed4ced92dbfa0bf49ba16fe7057edfe8aa5a98 Mon Sep 17 00:00:00 2001 From: tophf Date: Wed, 30 Aug 2017 01:30:45 +0300 Subject: [PATCH 6/7] create code box in write-new-style editor immediately --- edit/edit.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/edit/edit.js b/edit/edit.js index 67cebbad..82a339de 100644 --- a/edit/edit.js +++ b/edit/edit.js @@ -1212,14 +1212,11 @@ function init() { section[CssToProperty[i]] = [params[i]]; } } - window.onload = () => { - window.onload = null; - addSection(null, section); - editors[0].setOption('lint', CodeMirror.defaults.lint); - // default to enabled - $('#enabled').checked = true; - initHooks(); - }; + addSection(null, section); + editors[0].setOption('lint', CodeMirror.defaults.lint); + // default to enabled + $('#enabled').checked = true; + initHooks(); return; } // This is an edit From 00866fb74048a62b5bc5c14fbb87c2b27f259b09 Mon Sep 17 00:00:00 2001 From: tophf Date: Wed, 30 Aug 2017 01:49:03 +0300 Subject: [PATCH 7/7] properly replace the editors in initWithStyle --- edit/edit.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/edit/edit.js b/edit/edit.js index 82a339de..7c4bdde6 100644 --- a/edit/edit.js +++ b/edit/edit.js @@ -1217,6 +1217,8 @@ function init() { // default to enabled $('#enabled').checked = true; initHooks(); + setCleanGlobal(); + updateTitle(); return; } // This is an edit @@ -1255,9 +1257,11 @@ function initWithStyle({style, codeIsUpdated}) { return; } // if this was done in response to an update, we need to clear existing sections - getSections().forEach(div => { div.remove(); }); + editors.length = 0; + getSections().forEach(div => div.remove()); const queue = style.sections.length ? style.sections.slice() : [{code: ''}]; const queueStart = new Date().getTime(); + maximizeCodeHeight.stats = null; // after 100ms the sections will be added asynchronously while (new Date().getTime() - queueStart <= 100 && queue.length) { add(); @@ -1269,16 +1273,20 @@ function initWithStyle({style, codeIsUpdated}) { } })(); initHooks(); + setCleanGlobal(); + updateTitle(); function add() { const sectionDiv = addSection(null, queue.shift()); - const isLast = !queue.length; - maximizeCodeHeight(sectionDiv, isLast); - updateLintReport(sectionDiv.CodeMirror, !isLast && 100); + maximizeCodeHeight(sectionDiv, !queue.length); } } function initHooks() { + if (initHooks.alreadyDone) { + return; + } + initHooks.alreadyDone = true; $$('#header .style-contributor').forEach(node => { node.addEventListener('change', onChange); node.addEventListener('input', onChange); @@ -1310,8 +1318,6 @@ function initHooks() { }); setupGlobalSearch(); - setCleanGlobal(); - updateTitle(); }