Merge "Lazy load HighlightJS library"

This commit is contained in:
Andrew Bonventre 2016-08-02 18:42:57 +00:00 committed by Gerrit Code Review
commit 7acf5164ba
4 changed files with 127 additions and 88 deletions

View File

@ -14,7 +14,21 @@ APP_SRCS = glob(
'test/**', 'test/**',
] + WCT_TEST_PATTERNS + PY_TEST_PATTERNS) ] + WCT_TEST_PATTERNS + PY_TEST_PATTERNS)
WEBJS = 'bower_components/webcomponentsjs/webcomponents-lite.js' # List libraries to be copied statically into the build. (i.e. Libraries not
# expected to be Vulcanized.)
WEB_JS_LIBS = [
('bower_components/webcomponentsjs', 'webcomponents-lite.js'),
('bower_components/highlightjs', 'highlight.min.js'),
]
# Map the static libraries to commands for the polygerrit_ui rule.
JS_LIBS_MKDIR_CMDS = []
JS_LIBS_UNZIP_CMDS = []
for lib in WEB_JS_LIBS:
JS_LIBS_MKDIR_CMDS.append('mkdir -p ' + lib[0])
path = lib[0] + '/' + lib[1]
cmd = 'unzip -p $(location //polygerrit-ui:polygerrit_components) %s>%s' % (path, path)
JS_LIBS_UNZIP_CMDS.append(cmd)
# TODO(dborowitz): Putting these rules in this package avoids having to handle # TODO(dborowitz): Putting these rules in this package avoids having to handle
# the app/ prefix like we would have to if this were in the parent directory. # the app/ prefix like we would have to if this were in the parent directory.
@ -26,11 +40,12 @@ genrule(
cmd = ' && '.join([ cmd = ' && '.join([
'mkdir $TMP/polygerrit_ui', 'mkdir $TMP/polygerrit_ui',
'cd $TMP/polygerrit_ui', 'cd $TMP/polygerrit_ui',
'mkdir -p {fonts,elements,bower_components/webcomponentsjs}', 'mkdir -p {fonts,elements}',
' && '.join(JS_LIBS_MKDIR_CMDS),
'unzip -qd fonts $(location //polygerrit-ui:fonts)', 'unzip -qd fonts $(location //polygerrit-ui:fonts)',
'unzip -qd elements $(location :gr-app)', 'unzip -qd elements $(location :gr-app)',
'cp -rp $SRCDIR/* .', 'cp -rp $SRCDIR/* .',
'unzip -p $(location //polygerrit-ui:polygerrit_components) %s>%s' % (WEBJS, WEBJS), ' && '.join(JS_LIBS_UNZIP_CMDS),
'cd $TMP', 'cd $TMP',
'zip -9qr $OUT .', 'zip -9qr $OUT .',
]), ]),

View File

@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<link rel="import" href="../../../bower_components/polymer/polymer.html"> <link rel="import" href="../../../bower_components/polymer/polymer.html">
<script src="../../../bower_components/highlightjs/highlight.min.js"></script>
<dom-module id="gr-syntax-layer"> <dom-module id="gr-syntax-layer">
<script src="../gr-diff/gr-diff-line.js"></script> <script src="../gr-diff/gr-diff-line.js"></script>
<script src="../gr-diff-highlight/gr-annotation.js"></script> <script src="../gr-diff-highlight/gr-annotation.js"></script>

View File

@ -31,8 +31,8 @@
'text/x-sql': 'sql', 'text/x-sql': 'sql',
'text/x-scala': 'scala', 'text/x-scala': 'scala',
}; };
var ASYNC_DELAY = 10; var ASYNC_DELAY = 10;
var HLJS_PATH = '../../../bower_components/highlightjs/highlight.min.js';
Polymer({ Polymer({
is: 'gr-syntax-layer', is: 'gr-syntax-layer',
@ -63,10 +63,6 @@
_processHandle: Number, _processHandle: Number,
}, },
attached: function() {
hljs.configure({classPrefix: 'gr-diff gr-syntax gr-syntax-'});
},
addListener: function(fn) { addListener: function(fn) {
this.push('_listeners', fn); this.push('_listeners', fn);
}, },
@ -139,36 +135,38 @@
lastNotify: {left: 1, right: 1}, lastNotify: {left: 1, right: 1},
}; };
return new Promise(function(resolve) { return this._loadHLJS().then(function() {
var nextStep = function() { return new Promise(function(resolve) {
this._processHandle = null; var nextStep = function() {
this._processNextLine(state); this._processHandle = null;
this._processNextLine(state);
// Move to the next line in the section. // Move to the next line in the section.
state.lineIndex++; state.lineIndex++;
// If the section has been exhausted, move to the next one. // If the section has been exhausted, move to the next one.
if (this._isSectionDone(state)) { if (this._isSectionDone(state)) {
state.lineIndex = 0; state.lineIndex = 0;
state.sectionIndex++; state.sectionIndex++;
} }
// If all sections have been exhausted, finish. // If all sections have been exhausted, finish.
if (state.sectionIndex >= this.diff.content.length) { if (state.sectionIndex >= this.diff.content.length) {
resolve(); resolve();
this._notify(state); this._notify(state);
return; return;
} }
if (state.sectionIndex !== 0 && state.lineIndex % 100 === 0) { if (state.sectionIndex !== 0 && state.lineIndex % 100 === 0) {
this._notify(state); this._notify(state);
this._processHandle = this.async(nextStep, ASYNC_DELAY); this._processHandle = this.async(nextStep, ASYNC_DELAY);
} else { } else {
nextStep.call(this); nextStep.call(this);
} }
}; };
this._processHandle = this.async(nextStep, 1); this._processHandle = this.async(nextStep, 1);
}.bind(this));
}.bind(this)); }.bind(this));
}, },
@ -309,5 +307,24 @@
fn(start, end, side); fn(start, end, side);
}); });
}, },
/**
* Load and configure the HighlightJS library. If the library is already
* loaded, then do nothing and resolve.
* @return {Promise}
*/
_loadHLJS: function() {
if (window.hljs) { return Promise.resolve(); }
return new Promise(function(resolve) {
var script = document.createElement('script');
script.src = HLJS_PATH;
script.onload = function() {
hljs.configure({classPrefix: 'gr-diff gr-syntax gr-syntax-'});
resolve();
};
Polymer.dom(this.root).appendChild(script);
}.bind(this));
}
}); });
})(); })();

View File

@ -131,6 +131,7 @@ limitations under the License.
test('process while disabled does nothing', function(done) { test('process while disabled does nothing', function(done) {
var processNextSpy = sandbox.spy(element, '_processNextLine'); var processNextSpy = sandbox.spy(element, '_processNextLine');
element.enabled = false; element.enabled = false;
var loadHLJSSpy = sandbox.spy(element, '_loadHLJS');
var processPromise = element.process(); var processPromise = element.process();
@ -138,76 +139,83 @@ limitations under the License.
assert.isFalse(processNextSpy.called); assert.isFalse(processNextSpy.called);
assert.equal(element._baseRanges.length, 0); assert.equal(element._baseRanges.length, 0);
assert.equal(element._revisionRanges.length, 0); assert.equal(element._revisionRanges.length, 0);
assert.isFalse(loadHLJSSpy.called);
done(); done();
}); });
}); });
test('process highlight ipsum', function(done) { suite('after hljs load', function() {
element.diff.meta_a.content_type = 'application/json'; setup(function(done) {
element.diff.meta_b.content_type = 'application/json'; element._loadHLJS().then(done);
var processNextSpy = sandbox.spy(element, '_processNextLine');
var highlightStub = sandbox.stub(hljs, 'highlight', function(
lang, line, ignore, state) {
return {
value: line.replace(/ipsum/, '<span class="foobar">ipsum</span>'),
top: state === undefined ? 1 : state + 1,
};
}); });
var processPromise = element.process(); test('process highlight ipsum', function(done) {
element.diff.meta_a.content_type = 'application/json';
element.diff.meta_b.content_type = 'application/json';
var processNextSpy = sandbox.spy(element, '_processNextLine');
var highlightStub = sandbox.stub(hljs, 'highlight', function(
lang, line, ignore, state) {
return {
value: line.replace(/ipsum/, '<span class="foobar">ipsum</span>'),
top: state === undefined ? 1 : state + 1,
};
});
processPromise.then(function() { var processPromise = element.process();
var linesA = diff.meta_a.lines;
var linesB = diff.meta_b.lines;
assert.isTrue(processNextSpy.called); processPromise.then(function() {
assert.equal(element._baseRanges.length, linesA); var linesA = diff.meta_a.lines;
assert.equal(element._revisionRanges.length, linesB); var linesB = diff.meta_b.lines;
assert.equal(highlightStub.callCount, linesA + linesB); assert.isTrue(processNextSpy.called);
assert.equal(element._baseRanges.length, linesA);
assert.equal(element._revisionRanges.length, linesB);
// The first line of both sides have a range. assert.equal(highlightStub.callCount, linesA + linesB);
[element._baseRanges[0], element._revisionRanges[0]]
.forEach(function(range) {
assert.equal(range.length, 1);
assert.equal(range[0].className, 'foobar');
assert.equal(range[0].start, 'lorem '.length);
assert.equal(range[0].length, 'ipsum'.length);
});
// There are no ranges from ll.1-12 on the left and ll.1-11 on the // The first line of both sides have a range.
// right. [element._baseRanges[0], element._revisionRanges[0]]
element._baseRanges.slice(1, 12) .forEach(function(range) {
.concat(element._revisionRanges.slice(1, 11)) assert.equal(range.length, 1);
.forEach(function(range) { assert.equal(range[0].className, 'foobar');
assert.equal(range.length, 0); assert.equal(range[0].start, 'lorem '.length);
}); assert.equal(range[0].length, 'ipsum'.length);
});
// There should be another pair of ranges on l.13 for the left and l.12 // There are no ranges from ll.1-12 on the left and ll.1-11 on the
// for the right. // right.
[element._baseRanges[13], element._revisionRanges[12]] element._baseRanges.slice(1, 12)
.forEach(function(range) { .concat(element._revisionRanges.slice(1, 11))
assert.equal(range.length, 1); .forEach(function(range) {
assert.equal(range[0].className, 'foobar'); assert.equal(range.length, 0);
assert.equal(range[0].start, 32); });
assert.equal(range[0].length, 'ipsum'.length);
});
// The next group should have a similar instance on either side. // There should be another pair of ranges on l.13 for the left and
// l.12 for the right.
[element._baseRanges[13], element._revisionRanges[12]]
.forEach(function(range) {
assert.equal(range.length, 1);
assert.equal(range[0].className, 'foobar');
assert.equal(range[0].start, 32);
assert.equal(range[0].length, 'ipsum'.length);
});
var range = element._baseRanges[15]; // The next group should have a similar instance on either side.
assert.equal(range.length, 1);
assert.equal(range[0].className, 'foobar');
assert.equal(range[0].start, 34);
assert.equal(range[0].length, 'ipsum'.length);
range = element._revisionRanges[14]; var range = element._baseRanges[15];
assert.equal(range.length, 1); assert.equal(range.length, 1);
assert.equal(range[0].className, 'foobar'); assert.equal(range[0].className, 'foobar');
assert.equal(range[0].start, 35); assert.equal(range[0].start, 34);
assert.equal(range[0].length, 'ipsum'.length); assert.equal(range[0].length, 'ipsum'.length);
done(); range = element._revisionRanges[14];
assert.equal(range.length, 1);
assert.equal(range[0].className, 'foobar');
assert.equal(range[0].start, 35);
assert.equal(range[0].length, 'ipsum'.length);
done();
});
}); });
}); });