@digicole/pdfmake-rtl 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +128 -0
- package/LICENSE +22 -0
- package/README.md +675 -0
- package/build/pdfmake.js +76236 -0
- package/build/pdfmake.js.map +1 -0
- package/build/pdfmake.min.js +3 -0
- package/build/pdfmake.min.js.map +1 -0
- package/build/vfs_fonts.js +8 -0
- package/build-vfs.js +44 -0
- package/index.html +927 -0
- package/index.js +26 -0
- package/package.json +124 -0
- package/src/3rd-party/svg-to-pdfkit/LICENSE +9 -0
- package/src/3rd-party/svg-to-pdfkit/source.js +2552 -0
- package/src/3rd-party/svg-to-pdfkit.js +3 -0
- package/src/browser-extensions/URLBrowserResolver.js +96 -0
- package/src/browser-extensions/pdfMake.js +355 -0
- package/src/browser-extensions/virtual-fs.js +55 -0
- package/src/columnCalculator.js +157 -0
- package/src/docMeasure.js +810 -0
- package/src/docPreprocessor.js +273 -0
- package/src/documentContext.js +340 -0
- package/src/elementWriter.js +411 -0
- package/src/fontProvider.js +68 -0
- package/src/helpers.js +138 -0
- package/src/imageMeasure.js +62 -0
- package/src/layoutBuilder.js +1197 -0
- package/src/line.js +104 -0
- package/src/pageElementWriter.js +174 -0
- package/src/pdfKitEngine.js +21 -0
- package/src/printer.js +727 -0
- package/src/qrEnc.js +791 -0
- package/src/rtlUtils.js +485 -0
- package/src/standardPageSizes.js +54 -0
- package/src/styleContextStack.js +138 -0
- package/src/svgMeasure.js +70 -0
- package/src/tableProcessor.js +606 -0
- package/src/textDecorator.js +157 -0
- package/src/textTools.js +391 -0
- package/src/traversalTracker.js +47 -0
package/src/rtlUtils.js
ADDED
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* RTL (Right-to-Left) utilities for handling Arabic, Persian (Farsi), and Urdu languages
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Unicode ranges for Arabic script (includes Persian and Urdu characters)
|
|
8
|
+
var ARABIC_RANGE = [
|
|
9
|
+
[0x0600, 0x06FF], // Arabic block
|
|
10
|
+
[0x0750, 0x077F], // Arabic Supplement
|
|
11
|
+
[0x08A0, 0x08FF], // Arabic Extended-A
|
|
12
|
+
[0xFB50, 0xFDFF], // Arabic Presentation Forms-A
|
|
13
|
+
[0xFE70, 0xFEFF] // Arabic Presentation Forms-B
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
// Unicode ranges for Persian (Farsi) specific characters
|
|
17
|
+
var PERSIAN_RANGE = [
|
|
18
|
+
[0x06A9, 0x06AF], // Persian Kaf, Gaf
|
|
19
|
+
[0x06C0, 0x06C3], // Persian Heh, Teh Marbuta variants
|
|
20
|
+
[0x06CC, 0x06CE], // Persian Yeh variants
|
|
21
|
+
[0x06D0, 0x06D5], // Persian Yeh Barree, Arabic-Indic digits
|
|
22
|
+
[0x200C, 0x200D] // Zero Width Non-Joiner, Zero Width Joiner (used in Persian)
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
// Unicode ranges for Urdu specific characters
|
|
26
|
+
var URDU_RANGE = [
|
|
27
|
+
[0x0679, 0x0679], // Urdu Tteh
|
|
28
|
+
[0x067E, 0x067E], // Urdu Peh
|
|
29
|
+
[0x0686, 0x0686], // Urdu Tcheh
|
|
30
|
+
[0x0688, 0x0688], // Urdu Ddal
|
|
31
|
+
[0x0691, 0x0691], // Urdu Rreh
|
|
32
|
+
[0x0698, 0x0698], // Urdu Jeh
|
|
33
|
+
[0x06A9, 0x06A9], // Urdu Keheh
|
|
34
|
+
[0x06AF, 0x06AF], // Urdu Gaf
|
|
35
|
+
[0x06BA, 0x06BA], // Urdu Noon Ghunna
|
|
36
|
+
[0x06BE, 0x06BE], // Urdu Heh Doachashmee
|
|
37
|
+
[0x06C1, 0x06C1], // Urdu Heh Goal
|
|
38
|
+
[0x06D2, 0x06D2], // Urdu Yeh Barree
|
|
39
|
+
[0x06D3, 0x06D3] // Urdu Yeh Barree with Hamza
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
// Strong RTL characters (Arabic, Persian, Urdu)
|
|
43
|
+
var RTL_CHARS = /[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF\u200C-\u200D]/;
|
|
44
|
+
|
|
45
|
+
// Strong LTR characters (Latin, etc.)
|
|
46
|
+
var LTR_CHARS = /[A-Za-z\u00C0-\u024F\u1E00-\u1EFF]/;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check if a character is in Arabic script (includes Persian and Urdu)
|
|
50
|
+
* @param {string} char - Single character to check
|
|
51
|
+
* @return {boolean} - True if character is Arabic/Persian/Urdu
|
|
52
|
+
*/
|
|
53
|
+
function isArabicChar(char) {
|
|
54
|
+
var code = char.charCodeAt(0);
|
|
55
|
+
return ARABIC_RANGE.some(function(range) {
|
|
56
|
+
return code >= range[0] && code <= range[1];
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Check if a character is in Persian (Farsi) script
|
|
62
|
+
* @param {string} char - Single character to check
|
|
63
|
+
* @return {boolean} - True if character is Persian
|
|
64
|
+
*/
|
|
65
|
+
function isPersianChar(char) {
|
|
66
|
+
var code = char.charCodeAt(0);
|
|
67
|
+
return PERSIAN_RANGE.some(function(range) {
|
|
68
|
+
return code >= range[0] && code <= range[1];
|
|
69
|
+
}) || isArabicChar(char); // Persian uses Arabic base + extensions
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Check if a character is in Urdu script
|
|
74
|
+
* @param {string} char - Single character to check
|
|
75
|
+
* @return {boolean} - True if character is Urdu
|
|
76
|
+
*/
|
|
77
|
+
function isUrduChar(char) {
|
|
78
|
+
var code = char.charCodeAt(0);
|
|
79
|
+
return URDU_RANGE.some(function(range) {
|
|
80
|
+
return code >= range[0] && code <= range[1];
|
|
81
|
+
}) || isArabicChar(char); // Urdu uses Arabic base + extensions
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Check if a character requires RTL rendering
|
|
86
|
+
* @param {string} char - Single character to check
|
|
87
|
+
* @return {boolean} - True if character requires RTL
|
|
88
|
+
*/
|
|
89
|
+
function isRTLChar(char) {
|
|
90
|
+
return RTL_CHARS.test(char);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Check if a character is strongly LTR
|
|
95
|
+
* @param {string} char - Single character to check
|
|
96
|
+
* @return {boolean} - True if character is strongly LTR
|
|
97
|
+
*/
|
|
98
|
+
function isLTRChar(char) {
|
|
99
|
+
return LTR_CHARS.test(char);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Determine the predominant text direction of a string
|
|
104
|
+
* @param {string} text - Text to analyze
|
|
105
|
+
* @return {string} - 'rtl', 'ltr', or 'neutral'
|
|
106
|
+
*/
|
|
107
|
+
function getTextDirection(text) {
|
|
108
|
+
if (!text || typeof text !== 'string') {
|
|
109
|
+
return 'neutral';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
var rtlCount = 0;
|
|
113
|
+
var ltrCount = 0;
|
|
114
|
+
|
|
115
|
+
for (var i = 0; i < text.length; i++) {
|
|
116
|
+
var char = text.charAt(i);
|
|
117
|
+
if (isRTLChar(char)) {
|
|
118
|
+
rtlCount++;
|
|
119
|
+
} else if (isLTRChar(char)) {
|
|
120
|
+
ltrCount++;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// If we have any strong directional characters
|
|
125
|
+
if (rtlCount > 0 || ltrCount > 0) {
|
|
126
|
+
if (rtlCount > ltrCount) {
|
|
127
|
+
return 'rtl';
|
|
128
|
+
} else if (ltrCount > rtlCount) {
|
|
129
|
+
return 'ltr';
|
|
130
|
+
} else {
|
|
131
|
+
// Equal counts - slight preference for RTL if both exist
|
|
132
|
+
return rtlCount > 0 ? 'rtl' : 'ltr';
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return 'neutral';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Check if text contains any RTL characters
|
|
141
|
+
* @param {string} text - Text to check
|
|
142
|
+
* @return {boolean} - True if text contains RTL characters
|
|
143
|
+
*/
|
|
144
|
+
function containsRTL(text) {
|
|
145
|
+
if (!text || typeof text !== 'string') {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return RTL_CHARS.test(text);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Check if text is primarily Arabic, Persian, or Urdu
|
|
153
|
+
* @param {string} text - Text to check
|
|
154
|
+
* @return {boolean} - True if text is primarily Arabic/Persian/Urdu
|
|
155
|
+
*/
|
|
156
|
+
function isArabicText(text) {
|
|
157
|
+
if (!text || typeof text !== 'string') {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
var rtlCount = 0;
|
|
162
|
+
var totalStrongChars = 0;
|
|
163
|
+
|
|
164
|
+
for (var i = 0; i < text.length; i++) {
|
|
165
|
+
var char = text.charAt(i);
|
|
166
|
+
if (isArabicChar(char) || isPersianChar(char) || isUrduChar(char)) {
|
|
167
|
+
rtlCount++;
|
|
168
|
+
totalStrongChars++;
|
|
169
|
+
} else if (isRTLChar(char) || isLTRChar(char)) {
|
|
170
|
+
totalStrongChars++;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// If we have any strong characters and RTL represents at least 30%
|
|
175
|
+
// (lowered threshold for mixed text)
|
|
176
|
+
return totalStrongChars > 0 && (rtlCount / totalStrongChars) >= 0.3;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Process RTL text for proper display
|
|
181
|
+
* For modern PDF libraries, we rely on the underlying engine for BiDi processing
|
|
182
|
+
* We should NOT reverse word order manually - that breaks Arabic text
|
|
183
|
+
* @param {string} text - Text to process
|
|
184
|
+
* @return {string} - Text (unchanged for proper BiDi handling)
|
|
185
|
+
*/
|
|
186
|
+
function reverseRTLText(text) {
|
|
187
|
+
if (!text || typeof text !== 'string') {
|
|
188
|
+
return text;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// DO NOT reverse Arabic text word order!
|
|
192
|
+
// Arabic text should maintain its natural word order
|
|
193
|
+
// Only the display direction (alignment) should be RTL
|
|
194
|
+
// The PDF engine handles proper BiDi rendering
|
|
195
|
+
return text;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Apply RTL processing to text if needed
|
|
200
|
+
* @param {string} text - Original text
|
|
201
|
+
* @param {string} direction - Explicit direction override ('rtl', 'ltr', or null)
|
|
202
|
+
* @return {Object} - { text: processedText, isRTL: boolean }
|
|
203
|
+
*/
|
|
204
|
+
function processRTLText(text, direction) {
|
|
205
|
+
if (!text || typeof text !== 'string' || getTextDirection(text) !== 'rtl') {
|
|
206
|
+
return { text: text, isRTL: false };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
var isRTL = false;
|
|
210
|
+
|
|
211
|
+
if (direction === 'rtl') {
|
|
212
|
+
isRTL = true;
|
|
213
|
+
} else if (direction === 'ltr') {
|
|
214
|
+
isRTL = false;
|
|
215
|
+
} else {
|
|
216
|
+
// Auto-detect direction
|
|
217
|
+
var textDir = getTextDirection(text);
|
|
218
|
+
isRTL = textDir === 'rtl';
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Keep original text - no word reversal needed
|
|
222
|
+
// The PDF engine handles proper BiDi rendering
|
|
223
|
+
return {
|
|
224
|
+
text: text,
|
|
225
|
+
isRTL: isRTL
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Reverse table row cells for RTL layout
|
|
231
|
+
* @param {Array} row - Table row array
|
|
232
|
+
* @return {Array} - Reversed row array
|
|
233
|
+
*/
|
|
234
|
+
function reverseTableRow(row) {
|
|
235
|
+
if (!Array.isArray(row)) {
|
|
236
|
+
return row;
|
|
237
|
+
}
|
|
238
|
+
return row.slice().reverse();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Process table for RTL layout if supportRTL is enabled
|
|
243
|
+
* @param {Object} tableNode - Table definition object
|
|
244
|
+
* @return {Object} - Processed table node
|
|
245
|
+
*/
|
|
246
|
+
function processRTLTable(tableNode) {
|
|
247
|
+
if (!tableNode || !tableNode.supportRTL || !tableNode.table || !tableNode.table.body) {
|
|
248
|
+
return tableNode;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Don't clone the entire object - just modify the table data in place
|
|
252
|
+
// Reverse each row in the table body for RTL layout
|
|
253
|
+
tableNode.table.body = tableNode.table.body.map(function(row) {
|
|
254
|
+
return reverseTableRow(row);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// Also reverse the widths array if it exists
|
|
258
|
+
if (tableNode.table.widths && Array.isArray(tableNode.table.widths)) {
|
|
259
|
+
tableNode.table.widths = tableNode.table.widths.slice().reverse();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return tableNode;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Apply automatic RTL detection and formatting to any text element
|
|
267
|
+
* @param {Object|string} element - Text element or string
|
|
268
|
+
* @return {Object} - Enhanced element with RTL properties
|
|
269
|
+
*/
|
|
270
|
+
function autoApplyRTL(element) {
|
|
271
|
+
if (!element) return element;
|
|
272
|
+
|
|
273
|
+
// Handle string elements
|
|
274
|
+
if (typeof element === 'string') {
|
|
275
|
+
var direction = getTextDirection(element);
|
|
276
|
+
if (direction === 'rtl') {
|
|
277
|
+
return {
|
|
278
|
+
text: element,
|
|
279
|
+
alignment: 'right',
|
|
280
|
+
font: 'Nillima' // Use Arabic font for RTL text
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
return element;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Handle object elements
|
|
287
|
+
if (typeof element === 'object' && element.text) {
|
|
288
|
+
var textDirection = getTextDirection(element.text);
|
|
289
|
+
|
|
290
|
+
if (textDirection === 'rtl') {
|
|
291
|
+
// Auto-apply RTL properties if not already set
|
|
292
|
+
if (!element.alignment) {
|
|
293
|
+
element.alignment = 'right';
|
|
294
|
+
}
|
|
295
|
+
if (!element.font && isArabicText(element.text)) {
|
|
296
|
+
element.font = 'Nillima';
|
|
297
|
+
}
|
|
298
|
+
} else if (textDirection === 'ltr') {
|
|
299
|
+
// Auto-apply LTR properties if not already set
|
|
300
|
+
if (!element.alignment) {
|
|
301
|
+
element.alignment = 'left';
|
|
302
|
+
}
|
|
303
|
+
if (!element.font) {
|
|
304
|
+
element.font = 'Roboto';
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return element;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Process list items for RTL support including bullet positioning
|
|
314
|
+
* @param {Array|Object} listItems - ul/ol content
|
|
315
|
+
* @return {Array|Object} - Processed list with RTL support
|
|
316
|
+
*/
|
|
317
|
+
function processRTLList(listItems) {
|
|
318
|
+
if (!listItems) return listItems;
|
|
319
|
+
|
|
320
|
+
function processListItem(item) {
|
|
321
|
+
if (typeof item === 'string') {
|
|
322
|
+
var direction = getTextDirection(item);
|
|
323
|
+
if (direction === 'rtl') {
|
|
324
|
+
return {
|
|
325
|
+
text: item,
|
|
326
|
+
alignment: 'right',
|
|
327
|
+
font: 'Nillima',
|
|
328
|
+
markerColor: '#2c5282'
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
return item;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (typeof item === 'object') {
|
|
335
|
+
// Process the main text
|
|
336
|
+
if (item.text) {
|
|
337
|
+
var textDirection = getTextDirection(item.text);
|
|
338
|
+
if (textDirection === 'rtl') {
|
|
339
|
+
if (!item.alignment) item.alignment = 'right';
|
|
340
|
+
if (!item.font && isArabicText(item.text)) item.font = 'Nillima';
|
|
341
|
+
if (!item.markerColor) item.markerColor = '#2c5282';
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Process nested ul/ol recursively
|
|
346
|
+
if (item.ul) {
|
|
347
|
+
item.ul = processRTLList(item.ul);
|
|
348
|
+
}
|
|
349
|
+
if (item.ol) {
|
|
350
|
+
item.ol = processRTLList(item.ol);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return item;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (Array.isArray(listItems)) {
|
|
358
|
+
return listItems.map(processListItem);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return processListItem(listItems);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Process table for automatic RTL detection and layout
|
|
366
|
+
* @param {Object} tableNode - Table definition object
|
|
367
|
+
* @return {Object} - Processed table node
|
|
368
|
+
*/
|
|
369
|
+
function processAutoRTLTable(tableNode) {
|
|
370
|
+
if (!tableNode || !tableNode.table || !tableNode.table.body) {
|
|
371
|
+
return tableNode;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Check if table contains RTL content
|
|
375
|
+
var hasRTLContent = false;
|
|
376
|
+
var rtlCellCount = 0;
|
|
377
|
+
var totalCells = 0;
|
|
378
|
+
|
|
379
|
+
tableNode.table.body.forEach(function(row) {
|
|
380
|
+
if (Array.isArray(row)) {
|
|
381
|
+
row.forEach(function(cell) {
|
|
382
|
+
totalCells++;
|
|
383
|
+
var cellText = typeof cell === 'string' ? cell : (cell && cell.text ? cell.text : '');
|
|
384
|
+
if (containsRTL(cellText)) {
|
|
385
|
+
rtlCellCount++;
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// If more than 30% of cells contain RTL content, treat as RTL table
|
|
392
|
+
hasRTLContent = totalCells > 0 && (rtlCellCount / totalCells) >= 0.3;
|
|
393
|
+
|
|
394
|
+
if (hasRTLContent) {
|
|
395
|
+
// Reverse table columns for RTL layout
|
|
396
|
+
tableNode.table.body = tableNode.table.body.map(function(row) {
|
|
397
|
+
return reverseTableRow(row);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
// Reverse widths if defined
|
|
401
|
+
if (tableNode.table.widths && Array.isArray(tableNode.table.widths)) {
|
|
402
|
+
tableNode.table.widths = tableNode.table.widths.slice().reverse();
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Auto-apply RTL styles to cells
|
|
406
|
+
tableNode.table.body = tableNode.table.body.map(function(row) {
|
|
407
|
+
if (Array.isArray(row)) {
|
|
408
|
+
return row.map(function(cell) {
|
|
409
|
+
return autoApplyRTL(cell);
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
return row;
|
|
413
|
+
});
|
|
414
|
+
} else {
|
|
415
|
+
// For non-RTL tables, still auto-apply font and alignment per cell
|
|
416
|
+
tableNode.table.body = tableNode.table.body.map(function(row) {
|
|
417
|
+
if (Array.isArray(row)) {
|
|
418
|
+
return row.map(function(cell) {
|
|
419
|
+
return autoApplyRTL(cell);
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
return row;
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return tableNode;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Process any document element for automatic RTL detection
|
|
431
|
+
* @param {Object|Array|string} element - Document element
|
|
432
|
+
* @return {Object|Array|string} - Processed element
|
|
433
|
+
*/
|
|
434
|
+
function processAutoRTLElement(element) {
|
|
435
|
+
if (!element) return element;
|
|
436
|
+
|
|
437
|
+
// Handle arrays (like content arrays)
|
|
438
|
+
if (Array.isArray(element)) {
|
|
439
|
+
return element.map(processAutoRTLElement);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Handle text elements
|
|
443
|
+
if (typeof element === 'string' || (element && element.text)) {
|
|
444
|
+
element = autoApplyRTL(element);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Handle tables
|
|
448
|
+
if (element && element.table) {
|
|
449
|
+
element = processAutoRTLTable(element);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Handle lists
|
|
453
|
+
if (element && element.ul) {
|
|
454
|
+
element.ul = processRTLList(element.ul);
|
|
455
|
+
}
|
|
456
|
+
if (element && element.ol) {
|
|
457
|
+
element.ol = processRTLList(element.ol);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Handle columns
|
|
461
|
+
if (element && element.columns && Array.isArray(element.columns)) {
|
|
462
|
+
element.columns = element.columns.map(processAutoRTLElement);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return element;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
module.exports = {
|
|
469
|
+
isArabicChar: isArabicChar,
|
|
470
|
+
isPersianChar: isPersianChar,
|
|
471
|
+
isUrduChar: isUrduChar,
|
|
472
|
+
isRTLChar: isRTLChar,
|
|
473
|
+
isLTRChar: isLTRChar,
|
|
474
|
+
getTextDirection: getTextDirection,
|
|
475
|
+
containsRTL: containsRTL,
|
|
476
|
+
isArabicText: isArabicText,
|
|
477
|
+
reverseRTLText: reverseRTLText,
|
|
478
|
+
processRTLText: processRTLText,
|
|
479
|
+
reverseTableRow: reverseTableRow,
|
|
480
|
+
processRTLTable: processRTLTable,
|
|
481
|
+
autoApplyRTL: autoApplyRTL,
|
|
482
|
+
processRTLList: processRTLList,
|
|
483
|
+
processAutoRTLTable: processAutoRTLTable,
|
|
484
|
+
processAutoRTLElement: processAutoRTLElement
|
|
485
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
'4A0': [4767.87, 6740.79],
|
|
5
|
+
'2A0': [3370.39, 4767.87],
|
|
6
|
+
A0: [2383.94, 3370.39],
|
|
7
|
+
A1: [1683.78, 2383.94],
|
|
8
|
+
A2: [1190.55, 1683.78],
|
|
9
|
+
A3: [841.89, 1190.55],
|
|
10
|
+
A4: [595.28, 841.89],
|
|
11
|
+
A5: [419.53, 595.28],
|
|
12
|
+
A6: [297.64, 419.53],
|
|
13
|
+
A7: [209.76, 297.64],
|
|
14
|
+
A8: [147.40, 209.76],
|
|
15
|
+
A9: [104.88, 147.40],
|
|
16
|
+
A10: [73.70, 104.88],
|
|
17
|
+
B0: [2834.65, 4008.19],
|
|
18
|
+
B1: [2004.09, 2834.65],
|
|
19
|
+
B2: [1417.32, 2004.09],
|
|
20
|
+
B3: [1000.63, 1417.32],
|
|
21
|
+
B4: [708.66, 1000.63],
|
|
22
|
+
B5: [498.90, 708.66],
|
|
23
|
+
B6: [354.33, 498.90],
|
|
24
|
+
B7: [249.45, 354.33],
|
|
25
|
+
B8: [175.75, 249.45],
|
|
26
|
+
B9: [124.72, 175.75],
|
|
27
|
+
B10: [87.87, 124.72],
|
|
28
|
+
C0: [2599.37, 3676.54],
|
|
29
|
+
C1: [1836.85, 2599.37],
|
|
30
|
+
C2: [1298.27, 1836.85],
|
|
31
|
+
C3: [918.43, 1298.27],
|
|
32
|
+
C4: [649.13, 918.43],
|
|
33
|
+
C5: [459.21, 649.13],
|
|
34
|
+
C6: [323.15, 459.21],
|
|
35
|
+
C7: [229.61, 323.15],
|
|
36
|
+
C8: [161.57, 229.61],
|
|
37
|
+
C9: [113.39, 161.57],
|
|
38
|
+
C10: [79.37, 113.39],
|
|
39
|
+
RA0: [2437.80, 3458.27],
|
|
40
|
+
RA1: [1729.13, 2437.80],
|
|
41
|
+
RA2: [1218.90, 1729.13],
|
|
42
|
+
RA3: [864.57, 1218.90],
|
|
43
|
+
RA4: [609.45, 864.57],
|
|
44
|
+
SRA0: [2551.18, 3628.35],
|
|
45
|
+
SRA1: [1814.17, 2551.18],
|
|
46
|
+
SRA2: [1275.59, 1814.17],
|
|
47
|
+
SRA3: [907.09, 1275.59],
|
|
48
|
+
SRA4: [637.80, 907.09],
|
|
49
|
+
EXECUTIVE: [521.86, 756.00],
|
|
50
|
+
FOLIO: [612.00, 936.00],
|
|
51
|
+
LEGAL: [612.00, 1008.00],
|
|
52
|
+
LETTER: [612.00, 792.00],
|
|
53
|
+
TABLOID: [792.00, 1224.00]
|
|
54
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var isString = require('./helpers').isString;
|
|
4
|
+
var isArray = require('./helpers').isArray;
|
|
5
|
+
var isUndefined = require('./helpers').isUndefined;
|
|
6
|
+
var isNull = require('./helpers').isNull;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates an instance of StyleContextStack used for style inheritance and style overrides
|
|
10
|
+
*
|
|
11
|
+
* @constructor
|
|
12
|
+
* @this {StyleContextStack}
|
|
13
|
+
* @param {Object} named styles dictionary
|
|
14
|
+
* @param {Object} optional default style definition
|
|
15
|
+
*/
|
|
16
|
+
function StyleContextStack(styleDictionary, defaultStyle) {
|
|
17
|
+
this.defaultStyle = defaultStyle || {};
|
|
18
|
+
this.styleDictionary = styleDictionary;
|
|
19
|
+
this.styleOverrides = [];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Creates cloned version of current stack
|
|
24
|
+
* @return {StyleContextStack} current stack snapshot
|
|
25
|
+
*/
|
|
26
|
+
StyleContextStack.prototype.clone = function () {
|
|
27
|
+
var stack = new StyleContextStack(this.styleDictionary, this.defaultStyle);
|
|
28
|
+
|
|
29
|
+
this.styleOverrides.forEach(function (item) {
|
|
30
|
+
stack.styleOverrides.push(item);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return stack;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Pushes style-name or style-overrides-object onto the stack for future evaluation
|
|
38
|
+
*
|
|
39
|
+
* @param {String|Object} styleNameOrOverride style-name (referring to styleDictionary) or
|
|
40
|
+
* a new dictionary defining overriding properties
|
|
41
|
+
*/
|
|
42
|
+
StyleContextStack.prototype.push = function (styleNameOrOverride) {
|
|
43
|
+
this.styleOverrides.push(styleNameOrOverride);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Removes last style-name or style-overrides-object from the stack
|
|
48
|
+
*
|
|
49
|
+
* @param {Number} howMany - optional number of elements to be popped (if not specified,
|
|
50
|
+
* one element will be removed from the stack)
|
|
51
|
+
*/
|
|
52
|
+
StyleContextStack.prototype.pop = function (howMany) {
|
|
53
|
+
howMany = howMany || 1;
|
|
54
|
+
|
|
55
|
+
while (howMany-- > 0) {
|
|
56
|
+
this.styleOverrides.pop();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Creates a set of named styles or/and a style-overrides-object based on the item,
|
|
62
|
+
* pushes those elements onto the stack for future evaluation and returns the number
|
|
63
|
+
* of elements pushed, so they can be easily poped then.
|
|
64
|
+
*
|
|
65
|
+
* @param {Object} item - an object with optional style property and/or style overrides
|
|
66
|
+
* @return the number of items pushed onto the stack
|
|
67
|
+
*/
|
|
68
|
+
StyleContextStack.prototype.autopush = function (item) {
|
|
69
|
+
if (isString(item)) {
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
var styleNames = [];
|
|
74
|
+
|
|
75
|
+
if (item.style) {
|
|
76
|
+
if (isArray(item.style)) {
|
|
77
|
+
styleNames = item.style;
|
|
78
|
+
} else {
|
|
79
|
+
styleNames = [item.style];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for (var i = 0, l = styleNames.length; i < l; i++) {
|
|
84
|
+
this.push(styleNames[i]);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// rather than spend significant time making a styleOverrideObject, just add item
|
|
88
|
+
this.push(item);
|
|
89
|
+
return styleNames.length + 1;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Automatically pushes elements onto the stack, using autopush based on item,
|
|
94
|
+
* executes callback and then pops elements back. Returns value returned by callback
|
|
95
|
+
*
|
|
96
|
+
* @param {Object} item - an object with optional style property and/or style overrides
|
|
97
|
+
* @param {Function} function to be called between autopush and pop
|
|
98
|
+
* @return {Object} value returned by callback
|
|
99
|
+
*/
|
|
100
|
+
StyleContextStack.prototype.auto = function (item, callback) {
|
|
101
|
+
var pushedItems = this.autopush(item);
|
|
102
|
+
var result = callback();
|
|
103
|
+
|
|
104
|
+
if (pushedItems > 0) {
|
|
105
|
+
this.pop(pushedItems);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return result;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Evaluates stack and returns value of a named property
|
|
113
|
+
*
|
|
114
|
+
* @param {String} property - property name
|
|
115
|
+
* @return property value or null if not found
|
|
116
|
+
*/
|
|
117
|
+
StyleContextStack.prototype.getProperty = function (property) {
|
|
118
|
+
if (this.styleOverrides) {
|
|
119
|
+
for (var i = this.styleOverrides.length - 1; i >= 0; i--) {
|
|
120
|
+
var item = this.styleOverrides[i];
|
|
121
|
+
|
|
122
|
+
if (isString(item)) {
|
|
123
|
+
// named-style-override
|
|
124
|
+
var style = this.styleDictionary[item];
|
|
125
|
+
if (style && !isUndefined(style[property]) && !isNull(style[property])) {
|
|
126
|
+
return style[property];
|
|
127
|
+
}
|
|
128
|
+
} else if (!isUndefined(item[property]) && !isNull(item[property])) {
|
|
129
|
+
// style-overrides-object
|
|
130
|
+
return item[property];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return this.defaultStyle && this.defaultStyle[property];
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
module.exports = StyleContextStack;
|