UNPKG

20.9 kBJavaScriptView Raw
1/**
2 * @licstart The following is the entire license notice for the
3 * Javascript code in this page
4 *
5 * Copyright 2019 Mozilla Foundation
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * @licend The above is the entire license notice for the
20 * Javascript code in this page
21 */
22'use strict';
23
24function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
25
26var FontInspector = function FontInspectorClosure() {
27 var fonts, createObjectURL;
28 var active = false;
29 var fontAttribute = 'data-font-name';
30
31 function removeSelection() {
32 var divs = document.querySelectorAll("span[".concat(fontAttribute, "]"));
33 var _iteratorNormalCompletion = true;
34 var _didIteratorError = false;
35 var _iteratorError = undefined;
36
37 try {
38 for (var _iterator = divs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
39 var div = _step.value;
40 div.className = '';
41 }
42 } catch (err) {
43 _didIteratorError = true;
44 _iteratorError = err;
45 } finally {
46 try {
47 if (!_iteratorNormalCompletion && _iterator["return"] != null) {
48 _iterator["return"]();
49 }
50 } finally {
51 if (_didIteratorError) {
52 throw _iteratorError;
53 }
54 }
55 }
56 }
57
58 function resetSelection() {
59 var divs = document.querySelectorAll("span[".concat(fontAttribute, "]"));
60 var _iteratorNormalCompletion2 = true;
61 var _didIteratorError2 = false;
62 var _iteratorError2 = undefined;
63
64 try {
65 for (var _iterator2 = divs[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
66 var div = _step2.value;
67 div.className = 'debuggerHideText';
68 }
69 } catch (err) {
70 _didIteratorError2 = true;
71 _iteratorError2 = err;
72 } finally {
73 try {
74 if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
75 _iterator2["return"]();
76 }
77 } finally {
78 if (_didIteratorError2) {
79 throw _iteratorError2;
80 }
81 }
82 }
83 }
84
85 function selectFont(fontName, show) {
86 var divs = document.querySelectorAll("span[".concat(fontAttribute, "=").concat(fontName, "]"));
87 var _iteratorNormalCompletion3 = true;
88 var _didIteratorError3 = false;
89 var _iteratorError3 = undefined;
90
91 try {
92 for (var _iterator3 = divs[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
93 var div = _step3.value;
94 div.className = show ? 'debuggerShowText' : 'debuggerHideText';
95 }
96 } catch (err) {
97 _didIteratorError3 = true;
98 _iteratorError3 = err;
99 } finally {
100 try {
101 if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
102 _iterator3["return"]();
103 }
104 } finally {
105 if (_didIteratorError3) {
106 throw _iteratorError3;
107 }
108 }
109 }
110 }
111
112 function textLayerClick(e) {
113 if (!e.target.dataset.fontName || e.target.tagName.toUpperCase() !== 'SPAN') {
114 return;
115 }
116
117 var fontName = e.target.dataset.fontName;
118 var selects = document.getElementsByTagName('input');
119
120 for (var i = 0; i < selects.length; ++i) {
121 var select = selects[i];
122
123 if (select.dataset.fontName !== fontName) {
124 continue;
125 }
126
127 select.checked = !select.checked;
128 selectFont(fontName, select.checked);
129 select.scrollIntoView();
130 }
131 }
132
133 return {
134 id: 'FontInspector',
135 name: 'Font Inspector',
136 panel: null,
137 manager: null,
138 init: function init(pdfjsLib) {
139 var panel = this.panel;
140 panel.setAttribute('style', 'padding: 5px;');
141 var tmp = document.createElement('button');
142 tmp.addEventListener('click', resetSelection);
143 tmp.textContent = 'Refresh';
144 panel.appendChild(tmp);
145 fonts = document.createElement('div');
146 panel.appendChild(fonts);
147 createObjectURL = pdfjsLib.createObjectURL;
148 },
149 cleanup: function cleanup() {
150 fonts.textContent = '';
151 },
152 enabled: false,
153
154 get active() {
155 return active;
156 },
157
158 set active(value) {
159 active = value;
160
161 if (active) {
162 document.body.addEventListener('click', textLayerClick, true);
163 resetSelection();
164 } else {
165 document.body.removeEventListener('click', textLayerClick, true);
166 removeSelection();
167 }
168 },
169
170 fontAdded: function fontAdded(fontObj, url) {
171 var _this = this;
172
173 function properties(obj, list) {
174 var moreInfo = document.createElement('table');
175
176 for (var i = 0; i < list.length; i++) {
177 var tr = document.createElement('tr');
178 var td1 = document.createElement('td');
179 td1.textContent = list[i];
180 tr.appendChild(td1);
181 var td2 = document.createElement('td');
182 td2.textContent = obj[list[i]].toString();
183 tr.appendChild(td2);
184 moreInfo.appendChild(tr);
185 }
186
187 return moreInfo;
188 }
189
190 var moreInfo = properties(fontObj, ['name', 'type']);
191 var fontName = fontObj.loadedName;
192 var font = document.createElement('div');
193 var name = document.createElement('span');
194 name.textContent = fontName;
195 var download = document.createElement('a');
196
197 if (url) {
198 url = /url\(['"]?([^\)"']+)/.exec(url);
199 download.href = url[1];
200 } else if (fontObj.data) {
201 download.href = createObjectURL(fontObj.data, fontObj.mimeType);
202 }
203
204 download.textContent = 'Download';
205 var logIt = document.createElement('a');
206 logIt.href = '';
207 logIt.textContent = 'Log';
208 logIt.addEventListener('click', function (event) {
209 event.preventDefault();
210 console.log(fontObj);
211 });
212 var select = document.createElement('input');
213 select.setAttribute('type', 'checkbox');
214 select.dataset.fontName = fontName;
215 select.addEventListener('click', function (select, fontName) {
216 return function () {
217 selectFont(fontName, select.checked);
218 };
219 }(select, fontName));
220 font.appendChild(select);
221 font.appendChild(name);
222 font.appendChild(document.createTextNode(' '));
223 font.appendChild(download);
224 font.appendChild(document.createTextNode(' '));
225 font.appendChild(logIt);
226 font.appendChild(moreInfo);
227 fonts.appendChild(font);
228 setTimeout(function () {
229 if (_this.active) {
230 resetSelection();
231 }
232 }, 2000);
233 }
234 };
235}();
236
237var opMap;
238
239var StepperManager = function StepperManagerClosure() {
240 var steppers = [];
241 var stepperDiv = null;
242 var stepperControls = null;
243 var stepperChooser = null;
244 var breakPoints = Object.create(null);
245 return {
246 id: 'Stepper',
247 name: 'Stepper',
248 panel: null,
249 manager: null,
250 init: function init(pdfjsLib) {
251 var self = this;
252 this.panel.setAttribute('style', 'padding: 5px;');
253 stepperControls = document.createElement('div');
254 stepperChooser = document.createElement('select');
255 stepperChooser.addEventListener('change', function (event) {
256 self.selectStepper(this.value);
257 });
258 stepperControls.appendChild(stepperChooser);
259 stepperDiv = document.createElement('div');
260 this.panel.appendChild(stepperControls);
261 this.panel.appendChild(stepperDiv);
262
263 if (sessionStorage.getItem('pdfjsBreakPoints')) {
264 breakPoints = JSON.parse(sessionStorage.getItem('pdfjsBreakPoints'));
265 }
266
267 opMap = Object.create(null);
268
269 for (var key in pdfjsLib.OPS) {
270 opMap[pdfjsLib.OPS[key]] = key;
271 }
272 },
273 cleanup: function cleanup() {
274 stepperChooser.textContent = '';
275 stepperDiv.textContent = '';
276 steppers = [];
277 },
278 enabled: false,
279 active: false,
280 create: function create(pageIndex) {
281 var debug = document.createElement('div');
282 debug.id = 'stepper' + pageIndex;
283 debug.setAttribute('hidden', true);
284 debug.className = 'stepper';
285 stepperDiv.appendChild(debug);
286 var b = document.createElement('option');
287 b.textContent = 'Page ' + (pageIndex + 1);
288 b.value = pageIndex;
289 stepperChooser.appendChild(b);
290 var initBreakPoints = breakPoints[pageIndex] || [];
291 var stepper = new Stepper(debug, pageIndex, initBreakPoints);
292 steppers.push(stepper);
293
294 if (steppers.length === 1) {
295 this.selectStepper(pageIndex, false);
296 }
297
298 return stepper;
299 },
300 selectStepper: function selectStepper(pageIndex, selectPanel) {
301 var i;
302 pageIndex = pageIndex | 0;
303
304 if (selectPanel) {
305 this.manager.selectPanel(this);
306 }
307
308 for (i = 0; i < steppers.length; ++i) {
309 var stepper = steppers[i];
310
311 if (stepper.pageIndex === pageIndex) {
312 stepper.panel.removeAttribute('hidden');
313 } else {
314 stepper.panel.setAttribute('hidden', true);
315 }
316 }
317
318 var options = stepperChooser.options;
319
320 for (i = 0; i < options.length; ++i) {
321 var option = options[i];
322 option.selected = (option.value | 0) === pageIndex;
323 }
324 },
325 saveBreakPoints: function saveBreakPoints(pageIndex, bps) {
326 breakPoints[pageIndex] = bps;
327 sessionStorage.setItem('pdfjsBreakPoints', JSON.stringify(breakPoints));
328 }
329 };
330}();
331
332var Stepper = function StepperClosure() {
333 function c(tag, textContent) {
334 var d = document.createElement(tag);
335
336 if (textContent) {
337 d.textContent = textContent;
338 }
339
340 return d;
341 }
342
343 function simplifyArgs(args) {
344 if (typeof args === 'string') {
345 var MAX_STRING_LENGTH = 75;
346 return args.length <= MAX_STRING_LENGTH ? args : args.substring(0, MAX_STRING_LENGTH) + '...';
347 }
348
349 if (_typeof(args) !== 'object' || args === null) {
350 return args;
351 }
352
353 if ('length' in args) {
354 var simpleArgs = [],
355 i,
356 ii;
357 var MAX_ITEMS = 10;
358
359 for (i = 0, ii = Math.min(MAX_ITEMS, args.length); i < ii; i++) {
360 simpleArgs.push(simplifyArgs(args[i]));
361 }
362
363 if (i < args.length) {
364 simpleArgs.push('...');
365 }
366
367 return simpleArgs;
368 }
369
370 var simpleObj = {};
371
372 for (var key in args) {
373 simpleObj[key] = simplifyArgs(args[key]);
374 }
375
376 return simpleObj;
377 }
378
379 function Stepper(panel, pageIndex, initialBreakPoints) {
380 this.panel = panel;
381 this.breakPoint = 0;
382 this.nextBreakPoint = null;
383 this.pageIndex = pageIndex;
384 this.breakPoints = initialBreakPoints;
385 this.currentIdx = -1;
386 this.operatorListIdx = 0;
387 }
388
389 Stepper.prototype = {
390 init: function init(operatorList) {
391 var panel = this.panel;
392 var content = c('div', 'c=continue, s=step');
393 var table = c('table');
394 content.appendChild(table);
395 table.cellSpacing = 0;
396 var headerRow = c('tr');
397 table.appendChild(headerRow);
398 headerRow.appendChild(c('th', 'Break'));
399 headerRow.appendChild(c('th', 'Idx'));
400 headerRow.appendChild(c('th', 'fn'));
401 headerRow.appendChild(c('th', 'args'));
402 panel.appendChild(content);
403 this.table = table;
404 this.updateOperatorList(operatorList);
405 },
406 updateOperatorList: function updateOperatorList(operatorList) {
407 var self = this;
408
409 function cboxOnClick() {
410 var x = +this.dataset.idx;
411
412 if (this.checked) {
413 self.breakPoints.push(x);
414 } else {
415 self.breakPoints.splice(self.breakPoints.indexOf(x), 1);
416 }
417
418 StepperManager.saveBreakPoints(self.pageIndex, self.breakPoints);
419 }
420
421 var MAX_OPERATORS_COUNT = 15000;
422
423 if (this.operatorListIdx > MAX_OPERATORS_COUNT) {
424 return;
425 }
426
427 var chunk = document.createDocumentFragment();
428 var operatorsToDisplay = Math.min(MAX_OPERATORS_COUNT, operatorList.fnArray.length);
429
430 for (var i = this.operatorListIdx; i < operatorsToDisplay; i++) {
431 var line = c('tr');
432 line.className = 'line';
433 line.dataset.idx = i;
434 chunk.appendChild(line);
435 var checked = this.breakPoints.includes(i);
436 var args = operatorList.argsArray[i] || [];
437 var breakCell = c('td');
438 var cbox = c('input');
439 cbox.type = 'checkbox';
440 cbox.className = 'points';
441 cbox.checked = checked;
442 cbox.dataset.idx = i;
443 cbox.onclick = cboxOnClick;
444 breakCell.appendChild(cbox);
445 line.appendChild(breakCell);
446 line.appendChild(c('td', i.toString()));
447 var fn = opMap[operatorList.fnArray[i]];
448 var decArgs = args;
449
450 if (fn === 'showText') {
451 var glyphs = args[0];
452 var newArgs = [];
453 var str = [];
454
455 for (var j = 0; j < glyphs.length; j++) {
456 var glyph = glyphs[j];
457
458 if (_typeof(glyph) === 'object' && glyph !== null) {
459 str.push(glyph.fontChar);
460 } else {
461 if (str.length > 0) {
462 newArgs.push(str.join(''));
463 str = [];
464 }
465
466 newArgs.push(glyph);
467 }
468 }
469
470 if (str.length > 0) {
471 newArgs.push(str.join(''));
472 }
473
474 decArgs = [newArgs];
475 }
476
477 line.appendChild(c('td', fn));
478 line.appendChild(c('td', JSON.stringify(simplifyArgs(decArgs))));
479 }
480
481 if (operatorsToDisplay < operatorList.fnArray.length) {
482 line = c('tr');
483 var lastCell = c('td', '...');
484 lastCell.colspan = 4;
485 chunk.appendChild(lastCell);
486 }
487
488 this.operatorListIdx = operatorList.fnArray.length;
489 this.table.appendChild(chunk);
490 },
491 getNextBreakPoint: function getNextBreakPoint() {
492 this.breakPoints.sort(function (a, b) {
493 return a - b;
494 });
495
496 for (var i = 0; i < this.breakPoints.length; i++) {
497 if (this.breakPoints[i] > this.currentIdx) {
498 return this.breakPoints[i];
499 }
500 }
501
502 return null;
503 },
504 breakIt: function breakIt(idx, callback) {
505 StepperManager.selectStepper(this.pageIndex, true);
506 var self = this;
507 var dom = document;
508 self.currentIdx = idx;
509
510 var listener = function listener(e) {
511 switch (e.keyCode) {
512 case 83:
513 dom.removeEventListener('keydown', listener);
514 self.nextBreakPoint = self.currentIdx + 1;
515 self.goTo(-1);
516 callback();
517 break;
518
519 case 67:
520 dom.removeEventListener('keydown', listener);
521 var breakPoint = self.getNextBreakPoint();
522 self.nextBreakPoint = breakPoint;
523 self.goTo(-1);
524 callback();
525 break;
526 }
527 };
528
529 dom.addEventListener('keydown', listener);
530 self.goTo(idx);
531 },
532 goTo: function goTo(idx) {
533 var allRows = this.panel.getElementsByClassName('line');
534
535 for (var x = 0, xx = allRows.length; x < xx; ++x) {
536 var row = allRows[x];
537
538 if ((row.dataset.idx | 0) === idx) {
539 row.style.backgroundColor = 'rgb(251,250,207)';
540 row.scrollIntoView();
541 } else {
542 row.style.backgroundColor = null;
543 }
544 }
545 }
546 };
547 return Stepper;
548}();
549
550var Stats = function Stats() {
551 var stats = [];
552
553 function clear(node) {
554 while (node.hasChildNodes()) {
555 node.removeChild(node.lastChild);
556 }
557 }
558
559 function getStatIndex(pageNumber) {
560 for (var i = 0, ii = stats.length; i < ii; ++i) {
561 if (stats[i].pageNumber === pageNumber) {
562 return i;
563 }
564 }
565
566 return false;
567 }
568
569 return {
570 id: 'Stats',
571 name: 'Stats',
572 panel: null,
573 manager: null,
574 init: function init(pdfjsLib) {
575 this.panel.setAttribute('style', 'padding: 5px;');
576 },
577 enabled: false,
578 active: false,
579 add: function add(pageNumber, stat) {
580 if (!stat) {
581 return;
582 }
583
584 var statsIndex = getStatIndex(pageNumber);
585
586 if (statsIndex !== false) {
587 var b = stats[statsIndex];
588 this.panel.removeChild(b.div);
589 stats.splice(statsIndex, 1);
590 }
591
592 var wrapper = document.createElement('div');
593 wrapper.className = 'stats';
594 var title = document.createElement('div');
595 title.className = 'title';
596 title.textContent = 'Page: ' + pageNumber;
597 var statsDiv = document.createElement('div');
598 statsDiv.textContent = stat.toString();
599 wrapper.appendChild(title);
600 wrapper.appendChild(statsDiv);
601 stats.push({
602 pageNumber: pageNumber,
603 div: wrapper
604 });
605 stats.sort(function (a, b) {
606 return a.pageNumber - b.pageNumber;
607 });
608 clear(this.panel);
609
610 for (var i = 0, ii = stats.length; i < ii; ++i) {
611 this.panel.appendChild(stats[i].div);
612 }
613 },
614 cleanup: function cleanup() {
615 stats = [];
616 clear(this.panel);
617 }
618 };
619}();
620
621window.PDFBug = function PDFBugClosure() {
622 var panelWidth = 300;
623 var buttons = [];
624 var activePanel = null;
625 return {
626 tools: [FontInspector, StepperManager, Stats],
627 enable: function enable(ids) {
628 var all = false,
629 tools = this.tools;
630
631 if (ids.length === 1 && ids[0] === 'all') {
632 all = true;
633 }
634
635 for (var i = 0; i < tools.length; ++i) {
636 var tool = tools[i];
637
638 if (all || ids.includes(tool.id)) {
639 tool.enabled = true;
640 }
641 }
642
643 if (!all) {
644 tools.sort(function (a, b) {
645 var indexA = ids.indexOf(a.id);
646 indexA = indexA < 0 ? tools.length : indexA;
647 var indexB = ids.indexOf(b.id);
648 indexB = indexB < 0 ? tools.length : indexB;
649 return indexA - indexB;
650 });
651 }
652 },
653 init: function init(pdfjsLib, container) {
654 var ui = document.createElement('div');
655 ui.id = 'PDFBug';
656 var controls = document.createElement('div');
657 controls.setAttribute('class', 'controls');
658 ui.appendChild(controls);
659 var panels = document.createElement('div');
660 panels.setAttribute('class', 'panels');
661 ui.appendChild(panels);
662 container.appendChild(ui);
663 container.style.right = panelWidth + 'px';
664 var tools = this.tools;
665 var self = this;
666
667 for (var i = 0; i < tools.length; ++i) {
668 var tool = tools[i];
669 var panel = document.createElement('div');
670 var panelButton = document.createElement('button');
671 panelButton.textContent = tool.name;
672 panelButton.addEventListener('click', function (selected) {
673 return function (event) {
674 event.preventDefault();
675 self.selectPanel(selected);
676 };
677 }(i));
678 controls.appendChild(panelButton);
679 panels.appendChild(panel);
680 tool.panel = panel;
681 tool.manager = this;
682
683 if (tool.enabled) {
684 tool.init(pdfjsLib);
685 } else {
686 panel.textContent = tool.name + ' is disabled. To enable add ' + ' "' + tool.id + '" to the pdfBug parameter ' + 'and refresh (separate multiple by commas).';
687 }
688
689 buttons.push(panelButton);
690 }
691
692 this.selectPanel(0);
693 },
694 cleanup: function cleanup() {
695 for (var i = 0, ii = this.tools.length; i < ii; i++) {
696 if (this.tools[i].enabled) {
697 this.tools[i].cleanup();
698 }
699 }
700 },
701 selectPanel: function selectPanel(index) {
702 if (typeof index !== 'number') {
703 index = this.tools.indexOf(index);
704 }
705
706 if (index === activePanel) {
707 return;
708 }
709
710 activePanel = index;
711 var tools = this.tools;
712
713 for (var j = 0; j < tools.length; ++j) {
714 if (j === index) {
715 buttons[j].setAttribute('class', 'active');
716 tools[j].active = true;
717 tools[j].panel.removeAttribute('hidden');
718 } else {
719 buttons[j].setAttribute('class', '');
720 tools[j].active = false;
721 tools[j].panel.setAttribute('hidden', 'true');
722 }
723 }
724 }
725 };
726}();
\No newline at end of file