UNPKG

19 kBJavaScriptView Raw
1/**
2 * @licstart The following is the entire license notice for the
3 * Javascript code in this page
4 *
5 * Copyright 2017 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
24var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
25
26var FontInspector = function FontInspectorClosure() {
27 var fonts;
28 var active = false;
29 var fontAttribute = 'data-font-name';
30 function removeSelection() {
31 var divs = document.querySelectorAll('div[' + fontAttribute + ']');
32 for (var i = 0, ii = divs.length; i < ii; ++i) {
33 var div = divs[i];
34 div.className = '';
35 }
36 }
37 function resetSelection() {
38 var divs = document.querySelectorAll('div[' + fontAttribute + ']');
39 for (var i = 0, ii = divs.length; i < ii; ++i) {
40 var div = divs[i];
41 div.className = 'debuggerHideText';
42 }
43 }
44 function selectFont(fontName, show) {
45 var divs = document.querySelectorAll('div[' + fontAttribute + '=' + fontName + ']');
46 for (var i = 0, ii = divs.length; i < ii; ++i) {
47 var div = divs[i];
48 div.className = show ? 'debuggerShowText' : 'debuggerHideText';
49 }
50 }
51 function textLayerClick(e) {
52 if (!e.target.dataset.fontName || e.target.tagName.toUpperCase() !== 'DIV') {
53 return;
54 }
55 var fontName = e.target.dataset.fontName;
56 var selects = document.getElementsByTagName('input');
57 for (var i = 0; i < selects.length; ++i) {
58 var select = selects[i];
59 if (select.dataset.fontName !== fontName) {
60 continue;
61 }
62 select.checked = !select.checked;
63 selectFont(fontName, select.checked);
64 select.scrollIntoView();
65 }
66 }
67 return {
68 id: 'FontInspector',
69 name: 'Font Inspector',
70 panel: null,
71 manager: null,
72 init: function init(pdfjsLib) {
73 var panel = this.panel;
74 panel.setAttribute('style', 'padding: 5px;');
75 var tmp = document.createElement('button');
76 tmp.addEventListener('click', resetSelection);
77 tmp.textContent = 'Refresh';
78 panel.appendChild(tmp);
79 fonts = document.createElement('div');
80 panel.appendChild(fonts);
81 },
82 cleanup: function cleanup() {
83 fonts.textContent = '';
84 },
85 enabled: false,
86 get active() {
87 return active;
88 },
89 set active(value) {
90 active = value;
91 if (active) {
92 document.body.addEventListener('click', textLayerClick, true);
93 resetSelection();
94 } else {
95 document.body.removeEventListener('click', textLayerClick, true);
96 removeSelection();
97 }
98 },
99 fontAdded: function fontAdded(fontObj, url) {
100 var _this = this;
101
102 function properties(obj, list) {
103 var moreInfo = document.createElement('table');
104 for (var i = 0; i < list.length; i++) {
105 var tr = document.createElement('tr');
106 var td1 = document.createElement('td');
107 td1.textContent = list[i];
108 tr.appendChild(td1);
109 var td2 = document.createElement('td');
110 td2.textContent = obj[list[i]].toString();
111 tr.appendChild(td2);
112 moreInfo.appendChild(tr);
113 }
114 return moreInfo;
115 }
116 var moreInfo = properties(fontObj, ['name', 'type']);
117 var fontName = fontObj.loadedName;
118 var font = document.createElement('div');
119 var name = document.createElement('span');
120 name.textContent = fontName;
121 var download = document.createElement('a');
122 if (url) {
123 url = /url\(['"]?([^\)"']+)/.exec(url);
124 download.href = url[1];
125 } else if (fontObj.data) {
126 url = URL.createObjectURL(new Blob([fontObj.data], { type: fontObj.mimeType }));
127 download.href = url;
128 }
129 download.textContent = 'Download';
130 var logIt = document.createElement('a');
131 logIt.href = '';
132 logIt.textContent = 'Log';
133 logIt.addEventListener('click', function (event) {
134 event.preventDefault();
135 console.log(fontObj);
136 });
137 var select = document.createElement('input');
138 select.setAttribute('type', 'checkbox');
139 select.dataset.fontName = fontName;
140 select.addEventListener('click', function (select, fontName) {
141 return function () {
142 selectFont(fontName, select.checked);
143 };
144 }(select, fontName));
145 font.appendChild(select);
146 font.appendChild(name);
147 font.appendChild(document.createTextNode(' '));
148 font.appendChild(download);
149 font.appendChild(document.createTextNode(' '));
150 font.appendChild(logIt);
151 font.appendChild(moreInfo);
152 fonts.appendChild(font);
153 setTimeout(function () {
154 if (_this.active) {
155 resetSelection();
156 }
157 }, 2000);
158 }
159 };
160}();
161var opMap;
162var StepperManager = function StepperManagerClosure() {
163 var steppers = [];
164 var stepperDiv = null;
165 var stepperControls = null;
166 var stepperChooser = null;
167 var breakPoints = Object.create(null);
168 return {
169 id: 'Stepper',
170 name: 'Stepper',
171 panel: null,
172 manager: null,
173 init: function init(pdfjsLib) {
174 var self = this;
175 this.panel.setAttribute('style', 'padding: 5px;');
176 stepperControls = document.createElement('div');
177 stepperChooser = document.createElement('select');
178 stepperChooser.addEventListener('change', function (event) {
179 self.selectStepper(this.value);
180 });
181 stepperControls.appendChild(stepperChooser);
182 stepperDiv = document.createElement('div');
183 this.panel.appendChild(stepperControls);
184 this.panel.appendChild(stepperDiv);
185 if (sessionStorage.getItem('pdfjsBreakPoints')) {
186 breakPoints = JSON.parse(sessionStorage.getItem('pdfjsBreakPoints'));
187 }
188 opMap = Object.create(null);
189 for (var key in pdfjsLib.OPS) {
190 opMap[pdfjsLib.OPS[key]] = key;
191 }
192 },
193 cleanup: function cleanup() {
194 stepperChooser.textContent = '';
195 stepperDiv.textContent = '';
196 steppers = [];
197 },
198 enabled: false,
199 active: false,
200 create: function create(pageIndex) {
201 var debug = document.createElement('div');
202 debug.id = 'stepper' + pageIndex;
203 debug.setAttribute('hidden', true);
204 debug.className = 'stepper';
205 stepperDiv.appendChild(debug);
206 var b = document.createElement('option');
207 b.textContent = 'Page ' + (pageIndex + 1);
208 b.value = pageIndex;
209 stepperChooser.appendChild(b);
210 var initBreakPoints = breakPoints[pageIndex] || [];
211 var stepper = new Stepper(debug, pageIndex, initBreakPoints);
212 steppers.push(stepper);
213 if (steppers.length === 1) {
214 this.selectStepper(pageIndex, false);
215 }
216 return stepper;
217 },
218 selectStepper: function selectStepper(pageIndex, selectPanel) {
219 var i;
220 pageIndex = pageIndex | 0;
221 if (selectPanel) {
222 this.manager.selectPanel(this);
223 }
224 for (i = 0; i < steppers.length; ++i) {
225 var stepper = steppers[i];
226 if (stepper.pageIndex === pageIndex) {
227 stepper.panel.removeAttribute('hidden');
228 } else {
229 stepper.panel.setAttribute('hidden', true);
230 }
231 }
232 var options = stepperChooser.options;
233 for (i = 0; i < options.length; ++i) {
234 var option = options[i];
235 option.selected = (option.value | 0) === pageIndex;
236 }
237 },
238 saveBreakPoints: function saveBreakPoints(pageIndex, bps) {
239 breakPoints[pageIndex] = bps;
240 sessionStorage.setItem('pdfjsBreakPoints', JSON.stringify(breakPoints));
241 }
242 };
243}();
244var Stepper = function StepperClosure() {
245 function c(tag, textContent) {
246 var d = document.createElement(tag);
247 if (textContent) {
248 d.textContent = textContent;
249 }
250 return d;
251 }
252 function simplifyArgs(args) {
253 if (typeof args === 'string') {
254 var MAX_STRING_LENGTH = 75;
255 return args.length <= MAX_STRING_LENGTH ? args : args.substr(0, MAX_STRING_LENGTH) + '...';
256 }
257 if ((typeof args === 'undefined' ? 'undefined' : _typeof(args)) !== 'object' || args === null) {
258 return args;
259 }
260 if ('length' in args) {
261 var simpleArgs = [],
262 i,
263 ii;
264 var MAX_ITEMS = 10;
265 for (i = 0, ii = Math.min(MAX_ITEMS, args.length); i < ii; i++) {
266 simpleArgs.push(simplifyArgs(args[i]));
267 }
268 if (i < args.length) {
269 simpleArgs.push('...');
270 }
271 return simpleArgs;
272 }
273 var simpleObj = {};
274 for (var key in args) {
275 simpleObj[key] = simplifyArgs(args[key]);
276 }
277 return simpleObj;
278 }
279 function Stepper(panel, pageIndex, initialBreakPoints) {
280 this.panel = panel;
281 this.breakPoint = 0;
282 this.nextBreakPoint = null;
283 this.pageIndex = pageIndex;
284 this.breakPoints = initialBreakPoints;
285 this.currentIdx = -1;
286 this.operatorListIdx = 0;
287 }
288 Stepper.prototype = {
289 init: function init(operatorList) {
290 var panel = this.panel;
291 var content = c('div', 'c=continue, s=step');
292 var table = c('table');
293 content.appendChild(table);
294 table.cellSpacing = 0;
295 var headerRow = c('tr');
296 table.appendChild(headerRow);
297 headerRow.appendChild(c('th', 'Break'));
298 headerRow.appendChild(c('th', 'Idx'));
299 headerRow.appendChild(c('th', 'fn'));
300 headerRow.appendChild(c('th', 'args'));
301 panel.appendChild(content);
302 this.table = table;
303 this.updateOperatorList(operatorList);
304 },
305 updateOperatorList: function updateOperatorList(operatorList) {
306 var self = this;
307 function cboxOnClick() {
308 var x = +this.dataset.idx;
309 if (this.checked) {
310 self.breakPoints.push(x);
311 } else {
312 self.breakPoints.splice(self.breakPoints.indexOf(x), 1);
313 }
314 StepperManager.saveBreakPoints(self.pageIndex, self.breakPoints);
315 }
316 var MAX_OPERATORS_COUNT = 15000;
317 if (this.operatorListIdx > MAX_OPERATORS_COUNT) {
318 return;
319 }
320 var chunk = document.createDocumentFragment();
321 var operatorsToDisplay = Math.min(MAX_OPERATORS_COUNT, operatorList.fnArray.length);
322 for (var i = this.operatorListIdx; i < operatorsToDisplay; i++) {
323 var line = c('tr');
324 line.className = 'line';
325 line.dataset.idx = i;
326 chunk.appendChild(line);
327 var checked = this.breakPoints.includes(i);
328 var args = operatorList.argsArray[i] || [];
329 var breakCell = c('td');
330 var cbox = c('input');
331 cbox.type = 'checkbox';
332 cbox.className = 'points';
333 cbox.checked = checked;
334 cbox.dataset.idx = i;
335 cbox.onclick = cboxOnClick;
336 breakCell.appendChild(cbox);
337 line.appendChild(breakCell);
338 line.appendChild(c('td', i.toString()));
339 var fn = opMap[operatorList.fnArray[i]];
340 var decArgs = args;
341 if (fn === 'showText') {
342 var glyphs = args[0];
343 var newArgs = [];
344 var str = [];
345 for (var j = 0; j < glyphs.length; j++) {
346 var glyph = glyphs[j];
347 if ((typeof glyph === 'undefined' ? 'undefined' : _typeof(glyph)) === 'object' && glyph !== null) {
348 str.push(glyph.fontChar);
349 } else {
350 if (str.length > 0) {
351 newArgs.push(str.join(''));
352 str = [];
353 }
354 newArgs.push(glyph);
355 }
356 }
357 if (str.length > 0) {
358 newArgs.push(str.join(''));
359 }
360 decArgs = [newArgs];
361 }
362 line.appendChild(c('td', fn));
363 line.appendChild(c('td', JSON.stringify(simplifyArgs(decArgs))));
364 }
365 if (operatorsToDisplay < operatorList.fnArray.length) {
366 line = c('tr');
367 var lastCell = c('td', '...');
368 lastCell.colspan = 4;
369 chunk.appendChild(lastCell);
370 }
371 this.operatorListIdx = operatorList.fnArray.length;
372 this.table.appendChild(chunk);
373 },
374 getNextBreakPoint: function getNextBreakPoint() {
375 this.breakPoints.sort(function (a, b) {
376 return a - b;
377 });
378 for (var i = 0; i < this.breakPoints.length; i++) {
379 if (this.breakPoints[i] > this.currentIdx) {
380 return this.breakPoints[i];
381 }
382 }
383 return null;
384 },
385 breakIt: function breakIt(idx, callback) {
386 StepperManager.selectStepper(this.pageIndex, true);
387 var self = this;
388 var dom = document;
389 self.currentIdx = idx;
390 var listener = function listener(e) {
391 switch (e.keyCode) {
392 case 83:
393 dom.removeEventListener('keydown', listener);
394 self.nextBreakPoint = self.currentIdx + 1;
395 self.goTo(-1);
396 callback();
397 break;
398 case 67:
399 dom.removeEventListener('keydown', listener);
400 var breakPoint = self.getNextBreakPoint();
401 self.nextBreakPoint = breakPoint;
402 self.goTo(-1);
403 callback();
404 break;
405 }
406 };
407 dom.addEventListener('keydown', listener);
408 self.goTo(idx);
409 },
410 goTo: function goTo(idx) {
411 var allRows = this.panel.getElementsByClassName('line');
412 for (var x = 0, xx = allRows.length; x < xx; ++x) {
413 var row = allRows[x];
414 if ((row.dataset.idx | 0) === idx) {
415 row.style.backgroundColor = 'rgb(251,250,207)';
416 row.scrollIntoView();
417 } else {
418 row.style.backgroundColor = null;
419 }
420 }
421 }
422 };
423 return Stepper;
424}();
425var Stats = function Stats() {
426 var stats = [];
427 function clear(node) {
428 while (node.hasChildNodes()) {
429 node.removeChild(node.lastChild);
430 }
431 }
432 function getStatIndex(pageNumber) {
433 for (var i = 0, ii = stats.length; i < ii; ++i) {
434 if (stats[i].pageNumber === pageNumber) {
435 return i;
436 }
437 }
438 return false;
439 }
440 return {
441 id: 'Stats',
442 name: 'Stats',
443 panel: null,
444 manager: null,
445 init: function init(pdfjsLib) {
446 this.panel.setAttribute('style', 'padding: 5px;');
447 },
448
449 enabled: false,
450 active: false,
451 add: function add(pageNumber, stat) {
452 if (!stat) {
453 return;
454 }
455 var statsIndex = getStatIndex(pageNumber);
456 if (statsIndex !== false) {
457 var b = stats[statsIndex];
458 this.panel.removeChild(b.div);
459 stats.splice(statsIndex, 1);
460 }
461 var wrapper = document.createElement('div');
462 wrapper.className = 'stats';
463 var title = document.createElement('div');
464 title.className = 'title';
465 title.textContent = 'Page: ' + pageNumber;
466 var statsDiv = document.createElement('div');
467 statsDiv.textContent = stat.toString();
468 wrapper.appendChild(title);
469 wrapper.appendChild(statsDiv);
470 stats.push({
471 pageNumber: pageNumber,
472 div: wrapper
473 });
474 stats.sort(function (a, b) {
475 return a.pageNumber - b.pageNumber;
476 });
477 clear(this.panel);
478 for (var i = 0, ii = stats.length; i < ii; ++i) {
479 this.panel.appendChild(stats[i].div);
480 }
481 },
482 cleanup: function cleanup() {
483 stats = [];
484 clear(this.panel);
485 }
486 };
487}();
488window.PDFBug = function PDFBugClosure() {
489 var panelWidth = 300;
490 var buttons = [];
491 var activePanel = null;
492 return {
493 tools: [FontInspector, StepperManager, Stats],
494 enable: function enable(ids) {
495 var all = false,
496 tools = this.tools;
497 if (ids.length === 1 && ids[0] === 'all') {
498 all = true;
499 }
500 for (var i = 0; i < tools.length; ++i) {
501 var tool = tools[i];
502 if (all || ids.includes(tool.id)) {
503 tool.enabled = true;
504 }
505 }
506 if (!all) {
507 tools.sort(function (a, b) {
508 var indexA = ids.indexOf(a.id);
509 indexA = indexA < 0 ? tools.length : indexA;
510 var indexB = ids.indexOf(b.id);
511 indexB = indexB < 0 ? tools.length : indexB;
512 return indexA - indexB;
513 });
514 }
515 },
516 init: function init(pdfjsLib, container) {
517 var ui = document.createElement('div');
518 ui.id = 'PDFBug';
519 var controls = document.createElement('div');
520 controls.setAttribute('class', 'controls');
521 ui.appendChild(controls);
522 var panels = document.createElement('div');
523 panels.setAttribute('class', 'panels');
524 ui.appendChild(panels);
525 container.appendChild(ui);
526 container.style.right = panelWidth + 'px';
527 var tools = this.tools;
528 var self = this;
529 for (var i = 0; i < tools.length; ++i) {
530 var tool = tools[i];
531 var panel = document.createElement('div');
532 var panelButton = document.createElement('button');
533 panelButton.textContent = tool.name;
534 panelButton.addEventListener('click', function (selected) {
535 return function (event) {
536 event.preventDefault();
537 self.selectPanel(selected);
538 };
539 }(i));
540 controls.appendChild(panelButton);
541 panels.appendChild(panel);
542 tool.panel = panel;
543 tool.manager = this;
544 if (tool.enabled) {
545 tool.init(pdfjsLib);
546 } else {
547 panel.textContent = tool.name + ' is disabled. To enable add ' + ' "' + tool.id + '" to the pdfBug parameter ' + 'and refresh (separate multiple by commas).';
548 }
549 buttons.push(panelButton);
550 }
551 this.selectPanel(0);
552 },
553 cleanup: function cleanup() {
554 for (var i = 0, ii = this.tools.length; i < ii; i++) {
555 if (this.tools[i].enabled) {
556 this.tools[i].cleanup();
557 }
558 }
559 },
560 selectPanel: function selectPanel(index) {
561 if (typeof index !== 'number') {
562 index = this.tools.indexOf(index);
563 }
564 if (index === activePanel) {
565 return;
566 }
567 activePanel = index;
568 var tools = this.tools;
569 for (var j = 0; j < tools.length; ++j) {
570 if (j === index) {
571 buttons[j].setAttribute('class', 'active');
572 tools[j].active = true;
573 tools[j].panel.removeAttribute('hidden');
574 } else {
575 buttons[j].setAttribute('class', '');
576 tools[j].active = false;
577 tools[j].panel.setAttribute('hidden', 'true');
578 }
579 }
580 }
581 };
582}();
\No newline at end of file