@breakside/jskit 2022.22.3 → 2022.25.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.
Files changed (98) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/JS/XMLSerializer.js +9 -4
  3. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  4. package/Frameworks/FontKit.jsframework/Info.json +2 -2
  5. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  6. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  7. package/Frameworks/Foundation.jsframework/JS/JSAttributedString.js +279 -6
  8. package/Frameworks/Foundation.jsframework/JS/JSFileManager+Node.js +2 -2
  9. package/Frameworks/Foundation.jsframework/JS/JSFont.js +39 -15
  10. package/Frameworks/Foundation.jsframework/JS/JSFontDescriptor+HTML.js +8 -0
  11. package/Frameworks/Foundation.jsframework/JS/JSFontDescriptor.js +105 -27
  12. package/Frameworks/Foundation.jsframework/JS/JSParagraphStyle.js +71 -0
  13. package/Frameworks/Foundation.jsframework/JS/JSTextAttachment.js +1 -1
  14. package/Frameworks/Foundation.jsframework/JS/JSTextContainer.js +56 -29
  15. package/Frameworks/Foundation.jsframework/JS/JSTextFrame.js +2 -32
  16. package/Frameworks/Foundation.jsframework/JS/JSTextFramesetter.js +125 -22
  17. package/Frameworks/Foundation.jsframework/JS/JSTextLayoutManager.js +11 -3
  18. package/Frameworks/Foundation.jsframework/JS/JSTextLine.js +4 -3
  19. package/Frameworks/Foundation.jsframework/JS/JSTextRun.js +5 -3
  20. package/Frameworks/Foundation.jsframework/JS/JSTextTypesetter.js +41 -25
  21. package/Frameworks/Foundation.jsframework/JS/JSZip.js +97 -76
  22. package/Frameworks/Foundation.jsframework/JS/String+JS.js +69 -0
  23. package/Frameworks/Foundation.jsframework/JS/UnicodeChar.js +8 -0
  24. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  25. package/Frameworks/Foundation.jsframework/sources.json +26 -22
  26. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  27. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  28. package/Info.json +2 -2
  29. package/Node/io.breakside.jskit-bundle.js +2 -2
  30. package/Node/jskit +8 -7
  31. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  32. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  33. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  34. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  35. package/Root/Frameworks/ChartKit/CHAxis.js +5 -5
  36. package/Root/Frameworks/ChartKit/CHPieChart.js +1 -1
  37. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  38. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  39. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  40. package/Root/Frameworks/DOM/Info.yaml +1 -1
  41. package/Root/Frameworks/DOM/XMLSerializer.js +9 -4
  42. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  43. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  44. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  45. package/Root/Frameworks/Foundation/JSAttributedString.js +279 -6
  46. package/Root/Frameworks/Foundation/JSFileManager+Node.js +2 -2
  47. package/Root/Frameworks/Foundation/JSFont.js +39 -15
  48. package/Root/Frameworks/Foundation/JSFontDescriptor+HTML.js +8 -0
  49. package/Root/Frameworks/Foundation/JSFontDescriptor.js +105 -27
  50. package/Root/Frameworks/Foundation/JSParagraphStyle.js +71 -0
  51. package/Root/Frameworks/Foundation/JSTextAttachment.js +1 -1
  52. package/Root/Frameworks/Foundation/JSTextContainer.js +56 -29
  53. package/Root/Frameworks/Foundation/JSTextFrame.js +2 -32
  54. package/Root/Frameworks/Foundation/JSTextFramesetter.js +125 -22
  55. package/Root/Frameworks/Foundation/JSTextLayoutManager.js +11 -3
  56. package/Root/Frameworks/Foundation/JSTextLine.js +4 -3
  57. package/Root/Frameworks/Foundation/JSTextRun.js +5 -3
  58. package/Root/Frameworks/Foundation/JSTextTypesetter.js +41 -25
  59. package/Root/Frameworks/Foundation/JSZip.js +97 -76
  60. package/Root/Frameworks/Foundation/String+JS.js +69 -0
  61. package/Root/Frameworks/Foundation/UnicodeChar.js +8 -0
  62. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  63. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  64. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  65. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  66. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  67. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  68. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  69. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  70. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  71. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  72. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  73. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  74. package/Root/Frameworks/UIKit/UIBasicAnimation.js +1 -1
  75. package/Root/Frameworks/UIKit/UIHTMLApplication.js +1 -1
  76. package/Root/Frameworks/UIKit/UIHTMLContentEditableTextInputManager.js +36 -0
  77. package/Root/Frameworks/UIKit/UIHTMLDisplayServer.js +1 -1
  78. package/Root/Frameworks/UIKit/UIHTMLTextField.js +1 -1
  79. package/Root/Frameworks/UIKit/UIHTMLTextFrame.js +19 -91
  80. package/Root/Frameworks/UIKit/UIHTMLTextFramesetter.js +52 -9
  81. package/Root/Frameworks/UIKit/UIHTMLTextLine.js +95 -30
  82. package/Root/Frameworks/UIKit/UIHTMLTextRun.js +22 -9
  83. package/Root/Frameworks/UIKit/UIHTMLTextTypesetter.js +334 -459
  84. package/Root/Frameworks/UIKit/UIHTMLWindowServer.js +16 -0
  85. package/Root/Frameworks/UIKit/UIImageLayer.js +14 -7
  86. package/Root/Frameworks/UIKit/UIScrollView.js +12 -0
  87. package/Root/Frameworks/UIKit/UISegmentedControl.js +6 -6
  88. package/Root/Frameworks/UIKit/UITextAttachmentView.js +1 -1
  89. package/Root/Frameworks/UIKit/UITextEditor.js +210 -25
  90. package/Root/Frameworks/UIKit/UITextField.js +58 -31
  91. package/Root/Frameworks/UIKit/UITextInput.js +3 -1
  92. package/Root/Frameworks/UIKit/UITextInputManager.js +2 -2
  93. package/Root/Frameworks/UIKit/UITextLayer.js +39 -26
  94. package/Root/Frameworks/UIKit/UITokenField.js +4 -4
  95. package/Root/Frameworks/UIKit/UIView.js +3 -1
  96. package/Root/Frameworks/UIKit/UIWindow.js +16 -3
  97. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  98. package/package.json +1 -1
@@ -14,6 +14,7 @@
14
14
  // limitations under the License.
15
15
 
16
16
  // #import "JSObject.js"
17
+ // #import "JSProtocol.js"
17
18
  // #import "CoreTypes.js"
18
19
  // #import "JSAttributedString.js"
19
20
  // #import "JSFont.js"
@@ -26,6 +27,12 @@
26
27
 
27
28
  var logger = JSLog("foundation", "text");
28
29
 
30
+ JSProtocol("JSTextTypesetterDelegate", JSProtocol, {
31
+
32
+ typesetterAttributesForStringAttributes: function(typesetter, stringAttributes){}
33
+
34
+ });
35
+
29
36
  JSClass("JSTextTypesetter", JSObject, {
30
37
 
31
38
  attributedString: JSDynamicProperty('_attributedString'),
@@ -68,7 +75,8 @@ JSClass("JSTextTypesetter", JSObject, {
68
75
 
69
76
  _createEmptyLine: function(range){
70
77
  var attributes = this._attributedString.attributesAtIndex(range.location);
71
- var font = JSTextTypesetter.FontFromAttributes(attributes);
78
+ attributes = this.resolveAttributes(attributes);
79
+ var font = attributes.font;
72
80
  return JSTextLine.initWithHeight(font.lineHeight, -font.descender, range.location);
73
81
  },
74
82
 
@@ -129,16 +137,18 @@ JSClass("JSTextTypesetter", JSObject, {
129
137
 
130
138
  var iterator = this._attributedString.string.userPerceivedCharacterIterator(range.location);
131
139
  var runIterator = this._attributedString.runIterator(range.location);
132
- var initialLineAttributes = runIterator.attributes;
133
140
  var codeIterator;
134
141
  var attachment;
142
+ var attributes;
135
143
  // TODO: support mask character (only important if we need to rasterize a password field, which isn't a major use case)
136
144
  // Create run descriptors that at fill the line, maybe going a bit over
137
145
  do {
138
146
 
147
+ attributes = this.resolveAttributes(runIterator.attributes);
148
+
139
149
  // If we're at the start of a new run, make a new run descriptor
140
150
  if (runDescriptor === null){
141
- runDescriptor = JSTextTypesetterRunDescriptor(remainingRange.location, runIterator.attributes);
151
+ runDescriptor = JSTextTypesetterRunDescriptor(remainingRange.location, attributes);
142
152
  runDescriptors.push(runDescriptor);
143
153
  preferredFont = runDescriptor.font;
144
154
  }
@@ -146,9 +156,10 @@ JSClass("JSTextTypesetter", JSObject, {
146
156
  // Check some properties of this character
147
157
  newline = iterator.isMandatoryLineBreak;
148
158
  printable = !newline && !iterator.isWhiteSpace;
159
+ attachment = runIterator.attachment;
149
160
 
150
161
  // Adjust the run's font if needed
151
- if (runIterator.range.length == 1 && iterator.firstCharacter.code == JSAttributedString.SpecialCharacter.attachment){
162
+ if (attachment !== null){
152
163
  // 1. Attachment font:
153
164
  // Attachment runs use a special "attachment font" that can draw the attachment rather
154
165
  // than draw a glyph. It's perhaps a little strange to call an attachment a font, but
@@ -156,7 +167,6 @@ JSClass("JSTextTypesetter", JSObject, {
156
167
  // here is actually a specially drawn attachment. The attachment font has a single glyph
157
168
  // that corresponds to the 0xFFFC attachment character code, whose width matches the
158
169
  // attachment's width
159
- attachment = runIterator.attributes[JSAttributedString.Attribute.attachment];
160
170
  attachment.layout(preferredFont, width);
161
171
  usedWidth += attachment.size.width;
162
172
  runDescriptor.glyphs.push(0);
@@ -169,7 +179,7 @@ JSClass("JSTextTypesetter", JSObject, {
169
179
  // If our preferred font has a glyph for the character, but we're in a run
170
180
  // that is using a fallback font, create a new run, switching back to the preferred font
171
181
  if (runDescriptor.font !== preferredFont){
172
- runDescriptor = JSTextTypesetterRunDescriptor(remainingRange.location, runIterator.attributes);
182
+ runDescriptor = JSTextTypesetterRunDescriptor(remainingRange.location, attributes);
173
183
  runDescriptors.push(runDescriptor);
174
184
  }
175
185
  }else{
@@ -179,7 +189,7 @@ JSClass("JSTextTypesetter", JSObject, {
179
189
  // If the fallback doesn't match our run, adjust the run or create a new run depending on if it's emtpy
180
190
  if (fallbackFont !== runDescriptor.font){
181
191
  if (runDescriptor.length > 0){
182
- runDescriptor = JSTextTypesetterRunDescriptor(remainingRange.location, runIterator.attributes);
192
+ runDescriptor = JSTextTypesetterRunDescriptor(remainingRange.location, attributes);
183
193
  runDescriptors.push(runDescriptor);
184
194
  }
185
195
  runDescriptor.font = fallbackFont;
@@ -317,7 +327,27 @@ JSClass("JSTextTypesetter", JSObject, {
317
327
  if (ranges.length === 0){
318
328
  ranges.push(JSTextTypesetterPrintableRange(location, 0, 0));
319
329
  }
320
- }
330
+ },
331
+
332
+ delegate: null,
333
+
334
+ resolveAttributes: function(attributes){
335
+ if (attributes.font){
336
+ if (attributes.bold || attributes.italic){
337
+ attributes = JSCopy(attributes);
338
+ if (attributes.bold){
339
+ attributes.font = attributes.font.fontWithWeight(JSFont.Weight.bold);
340
+ }
341
+ if (attributes.italic){
342
+ attributes.font = attributes.font.fontWithStyle(JSFont.Style.italic);
343
+ }
344
+ }
345
+ }
346
+ if (this.delegate && this.delegate.typesetterAttributesForStringAttributes){
347
+ attributes = this.delegate.typesetterAttributesForStringAttributes(this, attributes);
348
+ }
349
+ return attributes;
350
+ },
321
351
 
322
352
  });
323
353
 
@@ -329,8 +359,8 @@ var JSTextTypesetterRunDescriptor = function(location, attributes){
329
359
  this.location = location.location;
330
360
  this.attributes = location.attributes;
331
361
  this.length = location.length;
332
- this.glyphs = location.glyphs;
333
- this.glyphCharacterLengths = location.glyphCharacterLengths;
362
+ this.glyphs = JSCopy(location.glyphs);
363
+ this.glyphCharacterLengths = JSCopy(location.glyphCharacterLengths);
334
364
  this.font = location.font;
335
365
  }else{
336
366
  this.location = location;
@@ -338,7 +368,7 @@ var JSTextTypesetterRunDescriptor = function(location, attributes){
338
368
  this.length = 0;
339
369
  this.glyphs = [];
340
370
  this.glyphCharacterLengths = [];
341
- this.font = JSTextTypesetter.FontFromAttributes(attributes);
371
+ this.font = attributes.font || null;
342
372
  }
343
373
  };
344
374
 
@@ -357,18 +387,4 @@ var JSTextTypesetterPrintableRange = function(location, length, width){
357
387
  }
358
388
  };
359
389
 
360
- JSTextTypesetter.FontFromAttributes = function(attributes){
361
- var font = attributes[JSAttributedString.Attribute.font];
362
- if (!font){
363
- return null;
364
- }
365
- if (attributes[JSAttributedString.Attribute.bold]){
366
- font = font.fontWithWeight(JSFont.Weight.bold);
367
- }
368
- if (attributes[JSAttributedString.Attribute.italic]){
369
- font = font.fontWithStyle(JSFont.Style.italic);
370
- }
371
- return font;
372
- };
373
-
374
390
  })();
@@ -1,6 +1,9 @@
1
1
  // #import "JSObject.js"
2
2
  // #import "Promise+JS.js"
3
3
  // #import "JSCRC32.js"
4
+ // #import "JSDate.js"
5
+ // #import "JSCalendar.js"
6
+ // #import "Deflate.js"
4
7
  "use strict";
5
8
 
6
9
  JSClass("JSZip", JSObject, {
@@ -14,61 +17,89 @@ JSClass("JSZip", JSObject, {
14
17
  offset: 0,
15
18
 
16
19
  addFile: function(file, completion, target){
20
+ return this.addFileInDirectory(file, "", {}, completion, target);
21
+ },
22
+
23
+ addFileInDirectory: function(file, directory, attributes, completion, target){
17
24
  if (!completion){
18
25
  completion = Promise.completion(Promise.resolveNull);
19
26
  }
27
+ if (directory.startsWith("/")){
28
+ directory = directory.substr(1);
29
+ }
30
+ if (directory.length > 1 && !directory.endsWith("/")){
31
+ directory = directory + "/";
32
+ }
20
33
  file.readData(function(data){
21
34
  if (data === null){
22
35
  completion.call(target, new Error("Failed to read file data"));
23
36
  return;
24
37
  }
25
- this.addDataForFilename(data, file.name, completion, target);
38
+ var error = null;
39
+ try{
40
+ this.addDataForFilename(data, directory + file.name, attributes);
41
+ }catch (e){
42
+ error = e;
43
+ }
44
+ completion.call(target, error);
26
45
  }, this);
27
46
  return completion.promise;
28
47
  },
29
48
 
30
- addDataForFilename: function(data, name, completion, target){
31
- if (!completion){
32
- completion = Promise.completion(Promise.resolveNull);
33
- }
34
- var error = null;
35
- try{
36
- var encodedName = name.utf8();
37
- var header = JSData.initWithLength(30 + encodedName.length);
38
- var dataView = header.dataView();
39
- var crc = JSCRC32(data);
40
- dataView.setUint32(0, 0x04034b50, true);
41
- dataView.setUint16(4, 20, true);
42
- dataView.setUint16(6, 0, true);
43
- dataView.setUint16(8, 0, true); // no compression
44
- dataView.setUint16(10, 0, true); // date
45
- dataView.setUint16(12, 0, true); // date
46
- dataView.setUint32(14, crc, true);
47
- dataView.setUint32(18, data.length, true);
48
- dataView.setUint32(22, data.length, true);
49
- dataView.setUint16(26, encodedName.length, true);
50
- dataView.setUint16(28, 0, true);
51
- encodedName.copyTo(header, 30);
52
- this.directory.push({
53
- name: name,
54
- offset: this.offset,
55
- header: header
56
- });
57
- this.addChunk(header);
58
- this.addChunk(data);
59
- }catch (e){
60
- error = e;
49
+ addDataForFilename: function(data, name, attributes, deflate){
50
+ var encodedName = name.utf8();
51
+ var header = JSData.initWithLength(30 + encodedName.length);
52
+ var dataView = header.dataView();
53
+ var crc = JSCRC32(data);
54
+ var dateComponents = JSCalendar.gregorian.componentsFromDate(JSCalendar.Unit.day | JSCalendar.Unit.month | JSCalendar.Unit.year | JSCalendar.Unit.hour | JSCalendar.Unit.minute | JSCalendar.Unit.second, attributes.updated !== undefined ? JSDate.initWithTimeIntervalSince1970(attributes.updated) : JSDate.now, JSTimeZone.local || JSTimeZone.utc);
55
+ var dosDate = ((dateComponents.year - 1980) << 9) | ((dateComponents.month) << 5) | (dateComponents.day);
56
+ var dosTime = ((dateComponents.hour) << 11) | ((dateComponents.minute) << 5) | (Math.floor(dateComponents.second / 2));
57
+ var storedData = data;
58
+ var method = 0;
59
+ if (deflate){
60
+ var stream = DeflateStream();
61
+ stream.input = data;
62
+ stream.output = JSData.initWithLength(data.length);
63
+ stream.deflate(true);
64
+ if (stream.state === DeflateStream.State.done){
65
+ storedData = stream.output.subdataInRange(JSRange(0, stream.outputOffset));
66
+ method = 8;
67
+ }
61
68
  }
62
- completion.call(target, error);
63
- return completion.promise;
69
+ // Local File Header (APPNOTE.txt 4.3.7)
70
+ // Everything is little-endian
71
+ dataView.setUint32(0, 0x04034b50, true); // signtature
72
+ dataView.setUint16(4, 0x0014, true); // version needed to extract (2.0)
73
+ dataView.setUint16(6, 0, true); // general purpose flags
74
+ dataView.setUint16(8, method, true); // compression method (0=none, 8=deflate)
75
+ dataView.setUint16(10, dosTime, true); // last modified time (MS-DOS)
76
+ dataView.setUint16(12, dosDate, true); // last modified date (MS-DOS)
77
+ dataView.setUint32(14, crc, true); // crc-32 (magic number 0xdebb20e3, preconditioned to 0xffffffff, post-conditioned by one's compliment)
78
+ dataView.setUint32(18, storedData.length, true); // compressed size
79
+ dataView.setUint32(22, data.length, true); // uncompressed size
80
+ dataView.setUint16(26, encodedName.length, true); // name length
81
+ dataView.setUint16(28, 0, true); // extra field length
82
+ encodedName.copyTo(header, 30); // name (NOT null-terminated)
83
+ this.directory.push({
84
+ name: name,
85
+ offset: this.offset,
86
+ header: header
87
+ });
88
+ this.chunks.push(header);
89
+ this.chunks.push(storedData);
90
+ this.offset += header.length + storedData.length;
91
+ this._data = null;
64
92
  },
65
93
 
66
- close: function(completion, target){
67
- if (!completion){
68
- completion = Promise.completion(Promise.resolveNull);
69
- }
70
- var error = null;
71
- try{
94
+ directory: null,
95
+
96
+ chunks: null,
97
+
98
+ data: JSReadOnlyProperty("_data", null),
99
+
100
+ getData: function(){
101
+ if (this._data === null){
102
+ var chunks = JSCopy(this.chunks);
72
103
  var i, l;
73
104
  var centralDirectoryOffset = this.offset;
74
105
  var centralDirectorySize = 0;
@@ -77,49 +108,39 @@ JSClass("JSZip", JSObject, {
77
108
  var dataView;
78
109
  var file;
79
110
  for (i = 0, l = this.directory.length; i < l; ++i){
111
+ // Central Directory File Header (APPNOTE.txt 4.3.12)
112
+ // Everything is little-endian
80
113
  file = this.directory[i];
81
114
  header = JSData.initWithLength(46 + (file.header.length - 30));
82
115
  dataView = header.dataView();
83
- dataView.setUint32(0, 0x02014b50, true);
84
- dataView.setUint16(4, 0, true);
85
- file.header.subdataInRange(JSRange(4, 26)).copyTo(header, 6);
86
- dataView.setUint16(32, 0, true);
87
- dataView.setUint16(34, 0, true);
88
- dataView.setUint16(36, 0, true);
89
- dataView.setUint32(38, 0, true);
90
- dataView.setUint32(42, file.offset, true);
91
- file.header.subdataInRange(JSRange(30, file.header.length - 30)).copyTo(header, 46);
116
+ dataView.setUint32(0, 0x02014b50, true); // signature
117
+ dataView.setUint16(4, 0x0314, true); // version made by (UNIX=3, 2.0)
118
+ file.header.subdataInRange(JSRange(4, 26)).copyTo(header, 6); // copy from local header
119
+ dataView.setUint16(32, 0, true); // commenet length
120
+ dataView.setUint16(34, 0, true); // disk number start
121
+ dataView.setUint16(36, 0, true); // internal file attributes
122
+ dataView.setUint32(38, 0, true); // external file attributes
123
+ dataView.setUint32(42, file.offset, true); // offset of local header relative to first disk
124
+ file.header.subdataInRange(JSRange(30, file.header.length - 30)).copyTo(header, 46); // name (ALWAYS forward slashes for directories)
92
125
  centralDirectorySize += header.length;
93
- this.addChunk(header);
126
+ chunks.push(header);
94
127
  }
128
+ // End of Central Directory Record (APPNOTE.txt 4.3.16)
129
+ // everything is little-endian
95
130
  var end = JSData.initWithLength(22);
96
131
  dataView = end.dataView();
97
- dataView.setUint32(0, 0x06054b50, true);
98
- dataView.setUint16(4, 0, true);
99
- dataView.setUint16(6, 0, true);
100
- dataView.setUint16(8, this.directory.length, true);
101
- dataView.setUint16(10, this.directory.length, true);
102
- dataView.setUint32(12, centralDirectorySize, true);
103
- dataView.setUint32(16, centralDirectoryOffset, true);
104
- dataView.setUint16(20, 0, true);
105
- this.addChunk(end);
106
- this._data = JSData.initWithChunks(this.chunks);
107
- }catch (e){
108
- error = e;
132
+ dataView.setUint32(0, 0x06054b50, true); // signature
133
+ dataView.setUint16(4, 0, true); // number of this disk
134
+ dataView.setUint16(6, 0, true); // number of the disk with the start of central directory
135
+ dataView.setUint16(8, this.directory.length, true); // number of central directory items on this disk
136
+ dataView.setUint16(10, this.directory.length, true); // number of central directory items total
137
+ dataView.setUint32(12, centralDirectorySize, true); // size of central directory
138
+ dataView.setUint32(16, centralDirectoryOffset, true); // offset to central directory with respect to starting disk
139
+ dataView.setUint16(20, 0, true); // zip file comemnt length
140
+ chunks.push(end);
141
+ this._data = JSData.initWithChunks(chunks);
109
142
  }
110
- completion.call(target, error);
111
- return completion.promise;
112
- },
113
-
114
- addChunk: function(chunk){
115
- this.chunks.push(chunk);
116
- this.offset += chunk.length;
117
- },
118
-
119
- directory: null,
120
-
121
- chunks: null,
122
-
123
- data: JSReadOnlyProperty("_data", null),
143
+ return this._data;
144
+ }
124
145
 
125
146
  });
@@ -244,6 +244,25 @@ Object.defineProperties(String.prototype, {
244
244
  }
245
245
  },
246
246
 
247
+ rangeForParagraphAtIndex: {
248
+ enumerable: false,
249
+ value: function String_rangeForParagraphAtIndex(index){
250
+ var iterator1 = this.userPerceivedCharacterIterator(index);
251
+ var startIndex = iterator1.range.location;
252
+ var iterator2 = UserPerceivedCharacterIterator(iterator1);
253
+ iterator1.decrement();
254
+ while (!iterator1.isParagraphBreak){
255
+ startIndex = iterator1.range.location;
256
+ iterator1.decrement();
257
+ }
258
+ while (!iterator2.isParagraphBreak){
259
+ iterator2.increment();
260
+ }
261
+ var endIndex = iterator2.range.end;
262
+ return JSRange(startIndex, endIndex - startIndex);
263
+ }
264
+ },
265
+
247
266
  // -------------------------------------------------------------------------
248
267
  // MARK: - Changing a String
249
268
 
@@ -359,6 +378,34 @@ Object.defineProperties(String.prototype, {
359
378
  }
360
379
  },
361
380
 
381
+ utf16be: {
382
+ configurable: true,
383
+ enumerable: false,
384
+ value: function String_utf16be(){
385
+ var utf16 = JSData.initWithLength(this.length * 2);
386
+ var dataView = utf16.dataView();
387
+ var j = 0;
388
+ for (var i = 0, l = this.length; i < l; ++i, j += 2){
389
+ dataView.setUint16(j, this.charCodeAt(i));
390
+ }
391
+ return utf16;
392
+ }
393
+ },
394
+
395
+ utf16le: {
396
+ configurable: true,
397
+ enumerable: false,
398
+ value: function String_utf16le(){
399
+ var utf16 = JSData.initWithLength(this.length * 2);
400
+ var dataView = utf16.dataView();
401
+ var j = 0;
402
+ for (var i = 0, l = this.length; i < l; ++i, j += 2){
403
+ dataView.setUint16(j, this.charCodeAt(i), true);
404
+ }
405
+ return utf16;
406
+ }
407
+ },
408
+
362
409
  latin1: {
363
410
  enumerable: false,
364
411
  value: function String_latin1(){
@@ -387,6 +434,12 @@ Object.defineProperties(String.prototype, {
387
434
  if (encoding == String.Encoding.latin1){
388
435
  return this.latin1();
389
436
  }
437
+ if (encoding == String.Encoding.utf16be){
438
+ return this.utf16be();
439
+ }
440
+ if (encoding == String.Encoding.utf16le){
441
+ return this.utf16le();
442
+ }
390
443
  return null;
391
444
  }
392
445
  },
@@ -1125,6 +1178,22 @@ Object.defineProperties(UserPerceivedCharacterIterator.prototype, {
1125
1178
  // can start with CR, we know the second character must be LF.
1126
1179
  return this._unicodeIterator.character.isLineBreak;
1127
1180
  }
1181
+ },
1182
+
1183
+ isParagraphBreak: {
1184
+ enumerable: true,
1185
+ configurable: false,
1186
+ get: function UserPerceivedCharacterIterator_isMandatoryLineBreak(){
1187
+ if (this._unicodeIterator.character === null){
1188
+ return true;
1189
+ }
1190
+ // Note that even though we're only checking the first character,
1191
+ // it will match the multi-char CRLF sequence, which is considered
1192
+ // to be a single user perceived character. In this case, only
1193
+ // the CR is checked, but since no other user perceived character
1194
+ // can start with CR, we know the second character must be LF.
1195
+ return this._unicodeIterator.character.isParagraphBreak;
1196
+ }
1128
1197
  }
1129
1198
 
1130
1199
  });
@@ -778,6 +778,14 @@ UnicodeChar.prototype = Object.create(Object.prototype, {
778
778
  Object.defineProperty(this, 'isLineBreak', {value: this.code === UnicodeChar.LineBreaks.newLine || this.code === UnicodeChar.LineBreaks.formFeed || this.code === UnicodeChar.LineBreaks.carriageReturn || this.code === UnicodeChar.LineBreaks.nextLine || this.code === UnicodeChar.LineBreaks.lineSeparator || this.code === UnicodeChar.LineBreaks.paragraphSeparator});
779
779
  return this.isLineBreak;
780
780
  }
781
+ },
782
+
783
+ isParagraphBreak: {
784
+ configurable: true,
785
+ get: function UnicodeChar_lazy_isParagraphBreak(){
786
+ Object.defineProperty(this, 'isParagraphBreak', {value: this.code === UnicodeChar.LineBreaks.newLine || this.code === UnicodeChar.LineBreaks.formFeed || this.code === UnicodeChar.LineBreaks.carriageReturn || this.code === UnicodeChar.LineBreaks.nextLine || this.code === UnicodeChar.LineBreaks.paragraphSeparator});
787
+ return this.isParagraphBreak;
788
+ }
781
789
  }
782
790
 
783
791
  });
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ImageKit
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.MediaKit
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.MediaKitUI
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.NotificationKit
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2021 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.PDFKit
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.QRKit
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.SearchKit
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.SecurityKit
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKit
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKitTesting
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.TestKit
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKit
3
- JSBundleVersion: 2022.22.3
3
+ JSBundleVersion: 2022.25.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -88,7 +88,7 @@ JSClass('UIBasicAnimation', UIPropertyAnimation, {
88
88
  var progress = this.timingFunction(this._state.currentPercentage);
89
89
  this.isComplete = this._state.isComplete();
90
90
  this._updateContext[this._updateProperty] = this.interpolation(this._fromValue, this._toValue, progress);
91
- if (this._updateContext === this._layer.presentation && this._updateProperty === "bounds"){
91
+ if (this._updateContext === this._layer.presentation && (this._updateProperty === "bounds" || this._updateProperty === "imageFrame")){
92
92
  this._layer.setNeedsDisplay();
93
93
  }
94
94
  },
@@ -69,7 +69,7 @@ JSClass("UIHTMLApplication", UIApplication, {
69
69
  if (options === undefined){
70
70
  options = {};
71
71
  }
72
- if (options.replacingApplication){
72
+ if (options.replacingApplication || url.scheme === "mailto" || url.scheme === "tel"){
73
73
  var application = this;
74
74
  var open = function(){
75
75
  application.domWindow.location.href = url.encodedString;