@breakside/jskit 2022.22.2 → 2022.22.3

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 (45) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  3. package/Frameworks/DOM.jsframework/sources.json +10 -3
  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/FontKit.jsframework/sources.json +34 -2
  7. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  8. package/Frameworks/Foundation.jsframework/JS/JSAttributedString.js +69 -20
  9. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  10. package/Frameworks/Foundation.jsframework/sources.json +159 -1
  11. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  12. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  13. package/Frameworks/SecurityKit.jsframework/sources.json +43 -2
  14. package/Info.json +2 -2
  15. package/Node/Builder.js +20 -9
  16. package/Node/FrameworkBuilder.js +22 -2
  17. package/Node/Project.js +22 -2
  18. package/Node/io.breakside.jskit-bundle.js +2 -2
  19. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  20. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  21. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  22. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  23. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  24. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  25. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  26. package/Root/Frameworks/DOM/Info.yaml +1 -1
  27. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  28. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  29. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  30. package/Root/Frameworks/Foundation/JSAttributedString.js +69 -20
  31. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  32. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  33. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  34. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  35. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  36. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  37. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  38. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  39. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  40. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  41. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  42. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  43. package/Root/Frameworks/UIKit/UILabel.js +43 -10
  44. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  45. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.DOM",
4
- "JSBundleVersion": "2022.22.2",
4
+ "JSBundleVersion": "2022.22.3",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "DOM+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "a302ede5223899a33db877d1cba370054efd6902"
12
+ "GitRevision": "6f0b376edf61fbea02fd94b92f86de9e17d3b716"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.DOM",
6
- "JSBundleVersion": "2022.22.2",
6
+ "JSBundleVersion": "2022.22.3",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
11
11
  "node": "DOM+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "a302ede5223899a33db877d1cba370054efd6902"
14
+ "GitRevision": "6f0b376edf61fbea02fd94b92f86de9e17d3b716"
15
15
  },
16
16
  "Resources": [],
17
17
  "ResourceLookup": {
@@ -4,14 +4,16 @@
4
4
  "files": [
5
5
  "DOM.js"
6
6
  ],
7
- "features": []
7
+ "features": [],
8
+ "globals": []
8
9
  },
9
10
  "html": {
10
11
  "frameworks": [],
11
12
  "files": [
12
13
  "DOM+HTML.js"
13
14
  ],
14
- "features": []
15
+ "features": [],
16
+ "globals": []
15
17
  },
16
18
  "node": {
17
19
  "frameworks": [
@@ -33,6 +35,11 @@
33
35
  "XMLSerializer.js",
34
36
  "DOM+Node.js"
35
37
  ],
36
- "features": []
38
+ "features": [],
39
+ "globals": [
40
+ "DOM",
41
+ "DOMParser",
42
+ "XMLSerializer"
43
+ ]
37
44
  }
38
45
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.FontKit",
4
- "JSBundleVersion": "2022.22.2",
4
+ "JSBundleVersion": "2022.22.3",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
8
8
  "html": "FontKit+HTML.js"
9
9
  },
10
10
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
11
- "GitRevision": "a302ede5223899a33db877d1cba370054efd6902"
11
+ "GitRevision": "6f0b376edf61fbea02fd94b92f86de9e17d3b716"
12
12
  }
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.JSKit.FontKit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.FontKit",
6
- "JSBundleVersion": "2022.22.2",
6
+ "JSBundleVersion": "2022.22.3",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
10
10
  "html": "FontKit+HTML.js"
11
11
  },
12
12
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
13
- "GitRevision": "a302ede5223899a33db877d1cba370054efd6902"
13
+ "GitRevision": "6f0b376edf61fbea02fd94b92f86de9e17d3b716"
14
14
  },
15
15
  "Resources": [],
16
16
  "ResourceLookup": {
@@ -12,7 +12,38 @@
12
12
  "FNTFontDescriptor.js",
13
13
  "FontKit.js"
14
14
  ],
15
- "features": []
15
+ "features": [],
16
+ "globals": [
17
+ "FNTOpenTypeFont",
18
+ "FNTOpenTypeFontTable",
19
+ "FNTOpenTypeFontTableHead",
20
+ "FNTOpenTypeFontTableName",
21
+ "FNTOpenTypeFontTableHhea",
22
+ "FNTOpenTypeFontTableHmtx",
23
+ "FNTOpenTypeFontTableCmap",
24
+ "FNTOpenTypeFontTableOS2",
25
+ "FNTOpenTypeFontTableMaxp",
26
+ "FNTOpenTypeFontTablePost",
27
+ "FNTOpenTypeFontTableCFF",
28
+ "FNTOpenTypeFontTableGlyf",
29
+ "FNTOpenTypeFontTableLoca",
30
+ "FNTOpenTypeFontCmap",
31
+ "FNTOpenTypeFontCmapNull",
32
+ "FNTOpenTypeFontCmap0",
33
+ "FNTOpenTypeFontCmap4",
34
+ "FNTOpenTypeFontCmap6",
35
+ "FNTOpenTypeFontCmap10",
36
+ "FNTOpenTypeFontCmap12",
37
+ "FNTOpenTypeFontCmap13",
38
+ "FNTOpenTypeGlyph",
39
+ "FNTOpenTypeSimpleGlyph",
40
+ "FNTOpenTypeCompoundGlyph",
41
+ "FNTOpenTypeConstructor",
42
+ "FNTType1Font",
43
+ "FNTAdobeNamesToUnicode",
44
+ "FNTCompactFontFormat",
45
+ "FNTFontDescriptor"
46
+ ]
16
47
  },
17
48
  "html": {
18
49
  "frameworks": [],
@@ -20,6 +51,7 @@
20
51
  "FNTFontDescriptor+HTML.js",
21
52
  "FontKit+HTML.js"
22
53
  ],
23
- "features": []
54
+ "features": [],
55
+ "globals": []
24
56
  }
25
57
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.Foundation",
4
- "JSBundleVersion": "2022.22.2",
4
+ "JSBundleVersion": "2022.22.3",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "Foundation+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "a302ede5223899a33db877d1cba370054efd6902"
12
+ "GitRevision": "6f0b376edf61fbea02fd94b92f86de9e17d3b716"
13
13
  }
@@ -294,6 +294,44 @@ JSClass("JSAttributedString", JSObject, {
294
294
  return new JSAttributedStringRunIterator(this, index);
295
295
  },
296
296
 
297
+ longestRangeOfAttributeAtIndex: function(attributeName, index){
298
+ return this.longestRangeOfAttributesAtIndex([attributeName], index);
299
+ },
300
+
301
+ longestRangeOfAttributesAtIndex: function(attributeNames, index){
302
+ var runIndex = this._runIndexForStringIndex(index);
303
+ var run = this._runs[runIndex];
304
+ var range = JSRange(run.range);
305
+ var attributes = {};
306
+ var i, l;
307
+ for (i = 0, l = attributeNames.length; i < l; ++i){
308
+ attributes[attributeNames[i]] = run.attributes[attributeNames[i]];
309
+ }
310
+ i = runIndex - 1;
311
+ while (i >= 0){
312
+ run = this._runs[i];
313
+ if (run.containsEqualAttributes(attributes)){
314
+ range.length = range.end - run.range.location;
315
+ range.location = run.range.location;
316
+ }else{
317
+ break;
318
+ }
319
+ --i;
320
+ }
321
+ i = runIndex + 1;
322
+ l = this._runs.length;
323
+ while (i < l){
324
+ run = this._runs[i];
325
+ if (run.containsEqualAttributes(attributes)){
326
+ range.length = run.range.end - range.location;
327
+ }else{
328
+ break;
329
+ }
330
+ ++i;
331
+ }
332
+ return range;
333
+ },
334
+
297
335
  // MARK: - Formatting
298
336
 
299
337
  replaceFormat: function(){
@@ -339,7 +377,7 @@ JSClass("JSAttributedString", JSObject, {
339
377
  var runA;
340
378
  for (var runIndex = lastRunIndex - 1; runIndex >= expandedRunRange.location; --runIndex){
341
379
  runA = this._runs[runIndex];
342
- if (runA.hasIdenticalAttributes(runB)){
380
+ if (runA.onlyContainsEqualAttributes(runB.attributes)){
343
381
  this._runs.splice(runIndex, 1);
344
382
  runB.range.location = runA.range.location;
345
383
  runB.range.length += runA.range.length;
@@ -358,7 +396,7 @@ JSClass("JSAttributedString", JSObject, {
358
396
  }
359
397
  var runA = this._runs[runIndex - 1];
360
398
  var runB = this._runs[runIndex];
361
- if (runA.hasIdenticalAttributes(runB)){
399
+ if (runA.onlyContainsEqualAttributes(runB.attributes)){
362
400
  this._runs.splice(runIndex, 1);
363
401
  runA.range.length += runB.range.length;
364
402
  }
@@ -471,35 +509,46 @@ function JSAttributedStringRun(range, attributes){
471
509
 
472
510
  JSAttributedStringRun.prototype = {
473
511
 
474
- hasIdenticalAttributes: function(other){
512
+ containsEqualAttributes: function(attributes){
475
513
  var attribute;
476
514
  var a, b;
477
- for (attribute in this.attributes){
478
- if (attribute in other.attributes){
479
- a = this.attributes[attribute];
480
- b = other.attributes[attribute];
481
- if (a.isEqual){
482
- if (!a.isEqual(b)){
483
- return false;
484
- }
485
- }else if (b.isEqual){
486
- if (!b.isEqual(a)){
487
- return false;
488
- }
489
- }else if (a != b){
515
+ for (attribute in attributes){
516
+ a = attributes[attribute];
517
+ b = this.attributes[attribute];
518
+ if (a === undefined){
519
+ if (!!b){
490
520
  return false;
491
521
  }
492
- }else{
522
+ }else if (a === null){
523
+ if (b !== null && b !== undefined){
524
+ return false;
525
+ }
526
+ }else if (a.isEqual){
527
+ if (b === null || b === undefined){
528
+ return false;
529
+ }
530
+ if (!a.isEqual(b)){
531
+ return false;
532
+ }
533
+ }else if (a != b){
493
534
  return false;
494
535
  }
495
536
  }
496
- for (attribute in other.attributes){
497
- if (!(attribute in this.attributes)){
537
+ return true;
538
+ },
539
+
540
+ onlyContainsEqualAttributes: function(attributes){
541
+ if (!this.containsEqualAttributes(attributes)){
542
+ return false;
543
+ }
544
+ var attribute;
545
+ for (attribute in this.attributes){
546
+ if (!(attribute in attributes)){
498
547
  return false;
499
548
  }
500
549
  }
501
550
  return true;
502
- }
551
+ },
503
552
 
504
553
  };
505
554
 
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.Foundation",
6
- "JSBundleVersion": "2022.22.2",
6
+ "JSBundleVersion": "2022.22.3",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
11
11
  "node": "Foundation+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "a302ede5223899a33db877d1cba370054efd6902"
14
+ "GitRevision": "6f0b376edf61fbea02fd94b92f86de9e17d3b716"
15
15
  },
16
16
  "Resources": [
17
17
  {
@@ -122,6 +122,146 @@
122
122
  "setInterval",
123
123
  "ArrayBuffer",
124
124
  "Uint8Array"
125
+ ],
126
+ "globals": [
127
+ "JSCopy",
128
+ "JSDeepCopy",
129
+ "JSResolveDottedName",
130
+ "JSSetDottedName",
131
+ "JSSize",
132
+ "JSPoint",
133
+ "JSInsets",
134
+ "JSRect",
135
+ "JSAffineTransform",
136
+ "JSRange",
137
+ "JSConstraintBox",
138
+ "JSLineBreakMode",
139
+ "JSTextAlignment",
140
+ "UnicodeProperties",
141
+ "UnicodeChar",
142
+ "JSData",
143
+ "Promise",
144
+ "JSMath",
145
+ "JSCubicBezier",
146
+ "JSBinarySearcher",
147
+ "JSIndexRange",
148
+ "JSIndexSet",
149
+ "JSIndexPath",
150
+ "JSIndexPathRange",
151
+ "JSIndexPathSet",
152
+ "UUID",
153
+ "JSClass",
154
+ "JSCustomProperty",
155
+ "JSDynamicProperty",
156
+ "JSReadOnlyProperty",
157
+ "JSLazyInitProperty",
158
+ "JSOutlet",
159
+ "JSProtocol",
160
+ "JSIsNullValueTransformer",
161
+ "JSIsNotNullValueTransformer",
162
+ "JSIsEmptyValueTransformer",
163
+ "JSIsNotEmptyValueTransformer",
164
+ "JSNegateBooleanValueTransformer",
165
+ "JSCommaSeparatedListValueTransformer",
166
+ "JSObject",
167
+ "JSLog",
168
+ "JSObjectGraphLoading",
169
+ "JSObjectGraph",
170
+ "JSDate",
171
+ "JSTimeZone",
172
+ "JSTimeInterval",
173
+ "JSCalendar",
174
+ "JSGregorianCalendar",
175
+ "JSLocale",
176
+ "JSMediaType",
177
+ "JSFile",
178
+ "JSDataFile",
179
+ "JSBundle",
180
+ "JSBundleResourceFile",
181
+ "JSFormFieldMap",
182
+ "JSFormField",
183
+ "JSURL",
184
+ "JSMIMEHeaderMap",
185
+ "JSMIMEHeader",
186
+ "JSURLRequest",
187
+ "JSURLSession",
188
+ "JSURLResponse",
189
+ "JSURLResponseError",
190
+ "JSXMLParser",
191
+ "JSImage",
192
+ "_JSResourceImage",
193
+ "_JSDataImage",
194
+ "_JSURLImage",
195
+ "JSTextAttachment",
196
+ "JSAttributedString",
197
+ "JSSpec",
198
+ "JSArrayController",
199
+ "JSSparseArrayController",
200
+ "JSColorSpace",
201
+ "JSXYZColorSpace",
202
+ "JSXYZScaledColorSpace",
203
+ "JSLabColorSpace",
204
+ "JSRGBColorSpace",
205
+ "JSGrayColorSpace",
206
+ "JSDerivedColorSpace",
207
+ "JSMappedColorSpace",
208
+ "JSIndexedColorSpace",
209
+ "JSNamedColorSpace",
210
+ "JSColor",
211
+ "JSGradient",
212
+ "HuffmanTree",
213
+ "DeflateStream",
214
+ "Deflate",
215
+ "Adler32",
216
+ "Zlib",
217
+ "ZlibStream",
218
+ "JSFontDescriptor",
219
+ "JSDataFontDescriptor",
220
+ "JSResourceFontDescriptor",
221
+ "JSTestFontDescriptor",
222
+ "JSFont",
223
+ "JSPath",
224
+ "JSContext",
225
+ "JSDateFormatter",
226
+ "JSNumberFormatter",
227
+ "JSTextLayoutManager",
228
+ "JSTextRun",
229
+ "JSTextLine",
230
+ "JSTextTypesetter",
231
+ "JSTextFrame",
232
+ "JSTextFramesetter",
233
+ "JSTextContainer",
234
+ "JSTextLayoutManagerDelegate",
235
+ "JSTextStorage",
236
+ "JSTimer",
237
+ "JSRunLoop",
238
+ "JSIPAddress",
239
+ "JSURLSessionTask",
240
+ "JSURLSessionDataTask",
241
+ "JSURLSessionUploadTask",
242
+ "JSURLSessionStreamTask",
243
+ "JSURLSessionDelegate",
244
+ "JSURLSessionStreamTaskDelegate",
245
+ "JSHTTPResponseParserDelegate",
246
+ "JSHTTPResponseParser",
247
+ "JSHTTPWebSocketParser",
248
+ "JSHTTPWebSocketParserDelegate",
249
+ "JSNotification",
250
+ "JSNotificationCenter",
251
+ "JSFileManager",
252
+ "JSFileEnumerator",
253
+ "JSFileArrayFileEnumerator",
254
+ "JSUserDefaults",
255
+ "JSUndoManager",
256
+ "JSDistributedNotificationCenter",
257
+ "JSSynchronizer",
258
+ "JSCRC32",
259
+ "JSZip",
260
+ "JSIterativeHash",
261
+ "JSSHA1Hash",
262
+ "JSMD5Hash",
263
+ "JSArguments",
264
+ "JSEnvironment"
125
265
  ]
126
266
  },
127
267
  "html": {
@@ -156,6 +296,16 @@
156
296
  "FileReader",
157
297
  "URL.createObjectURL",
158
298
  "URL.revokeObjectURL"
299
+ ],
300
+ "globals": [
301
+ "JSHTMLHTTPClient",
302
+ "JSHTMLURLSessionDataTask",
303
+ "JSHTMLURLSessionUploadTask",
304
+ "JSHTMLURLSessionStreamTask",
305
+ "JSHTMLFileManager",
306
+ "JSHTMLFile",
307
+ "JSHTMLFileListFileEnumerator",
308
+ "JSHTMLFileSystemEntryFileEnumerator"
159
309
  ]
160
310
  },
161
311
  "node": {
@@ -175,6 +325,14 @@
175
325
  "JSAMQPNotificationCenter.js",
176
326
  "Foundation+Node.js"
177
327
  ],
178
- "features": []
328
+ "features": [],
329
+ "globals": [
330
+ "JSNodeFileManager",
331
+ "JSNodeHTTPClient",
332
+ "JSNodeURLSessionDataTask",
333
+ "JSNodeURLSessionUploadTask",
334
+ "JSNodeURLSessionStreamTask",
335
+ "JSAMQPNotificationCenter"
336
+ ]
179
337
  }
180
338
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
4
- "JSBundleVersion": "2022.22.2",
4
+ "JSBundleVersion": "2022.22.3",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "SecurityKit+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "a302ede5223899a33db877d1cba370054efd6902"
12
+ "GitRevision": "6f0b376edf61fbea02fd94b92f86de9e17d3b716"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
6
- "JSBundleVersion": "2022.22.2",
6
+ "JSBundleVersion": "2022.22.3",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
11
11
  "node": "SecurityKit+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "a302ede5223899a33db877d1cba370054efd6902"
14
+ "GitRevision": "6f0b376edf61fbea02fd94b92f86de9e17d3b716"
15
15
  },
16
16
  "Resources": [],
17
17
  "ResourceLookup": {
@@ -23,7 +23,40 @@
23
23
  "SECCBOR.js",
24
24
  "SecurityKit.js"
25
25
  ],
26
- "features": []
26
+ "features": [],
27
+ "globals": [
28
+ "SECKey",
29
+ "SECDataKey",
30
+ "SECJSONWebAlgorithms",
31
+ "SECCipher",
32
+ "SECCipherAESCipherBlockChaining",
33
+ "SECCipherAESCounter",
34
+ "SECCipherAESGaloisCounterMode",
35
+ "SECCipherRC4",
36
+ "SECHash",
37
+ "SECVerify",
38
+ "SECKeychain",
39
+ "SECHMAC",
40
+ "SECSign",
41
+ "SECJSONWebToken",
42
+ "SECPassword",
43
+ "SECASN1Value",
44
+ "SECASN1Boolean",
45
+ "SECASN1Integer",
46
+ "SECASN1BitString",
47
+ "SECASN1OctetString",
48
+ "SECASN1ObjectIdentifier",
49
+ "SECASN1Sequence",
50
+ "SECASN1UTF8String",
51
+ "SECASN1Optional",
52
+ "SECASN1Unknown",
53
+ "SECASN1Parser",
54
+ "SECOneTimePassword",
55
+ "SECKeystore",
56
+ "SECDeviceAuthentication",
57
+ "SECCBOR",
58
+ "SECCBORParser"
59
+ ]
27
60
  },
28
61
  "html": {
29
62
  "frameworks": [],
@@ -42,6 +75,11 @@
42
75
  "features": [
43
76
  "window.crypto.subtle",
44
77
  "window.crypto.subtle"
78
+ ],
79
+ "globals": [
80
+ "SECHTMLKey",
81
+ "SECHTMLDeviceAuthentication",
82
+ "SECHTMLPasswordCredentialKeychain"
45
83
  ]
46
84
  },
47
85
  "node": {
@@ -56,6 +94,9 @@
56
94
  "SECPassword+Node.js",
57
95
  "SecurityKit+Node.js"
58
96
  ],
59
- "features": []
97
+ "features": [],
98
+ "globals": [
99
+ "SECNodeKey"
100
+ ]
60
101
  }
61
102
  }
package/Info.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "JSBundleType": "node",
3
3
  "JSBundleIdentifier": "io.breakside.jskit",
4
- "JSBundleVersion": "2022.22.2",
4
+ "JSBundleVersion": "2022.22.3",
5
5
  "JSExecutableName": "jskit",
6
6
  "NPMOrganization": "breakside",
7
7
  "JSResources": [
8
8
  "Tests/HTMLTestRunner.js",
9
9
  "Tests/NodeTestRunner.js"
10
10
  ],
11
- "GitRevision": "a302ede5223899a33db877d1cba370054efd6902"
11
+ "GitRevision": "6f0b376edf61fbea02fd94b92f86de9e17d3b716"
12
12
  }
package/Node/Builder.js CHANGED
@@ -174,20 +174,31 @@ JSClass("Builder", JSObject, {
174
174
  if (!seen.has(name)){
175
175
  seen.add(name);
176
176
  // If the framework was pre-built, then it can only have
177
- // dependencies on standard frameworks, so that's the only
178
- // place we'll look.
179
- //
177
+ // dependencies on other pre-built frameworks, which
178
+ // are other .jsframework bundles or JSKit frameworks
179
+ //
180
180
  // If we built the framework, then we already added its
181
181
  // dependencies based on its build reuslts and won't get here.
182
- let candidateURL = this.fileManager.urlForPath(JSKitRootDirectoryPath).appendingPathComponents(["Frameworks", name], true);
183
- let exists = await this.fileManager.itemExistsAtURL(candidateURL);
184
- if (!exists){
185
- throw new Error("Cannot find framework %s, (required by %s)".sprintf(name, url.lastPathComponent));
182
+ let includeDirectoryURLs = this.project.includeDirectoryURLs;
183
+ let url = null;
184
+ for (let i = 0, l = includeDirectoryURLs.length; i < l && url === null; ++i){
185
+ let directoryURL = includeDirectoryURLs[i];
186
+ let candidateURL = directoryURL.appendingPathComponent(name + '.jsframework', true);
187
+ let found = await this.fileManager.itemExistsAtURL(candidateURL);
188
+ if (found){
189
+ url = candidateURL;
190
+ }
191
+ }
192
+ if (url === null){
193
+ url = this.fileManager.urlForPath(JSKitRootDirectoryPath).appendingPathComponents(["Frameworks", name], true);
194
+ let found = await this.fileManager.itemExistsAtURL(url);
195
+ if (!found){
196
+ throw new Error("Cannot find framework %s, (required by %s)".sprintf(name, url.lastPathComponent));
197
+ }
186
198
  }
187
- this.printer.print("\nAdding dependency %s\n".sprintf(name));
188
199
  imports.push({
189
200
  name: name,
190
- url: candidateURL
201
+ url: url
191
202
  });
192
203
  }
193
204
  }
@@ -138,9 +138,10 @@ JSClass("FrameworkBuilder", Builder, {
138
138
  var genericFrameworks = new Set();
139
139
  var genericFiles = new Set();
140
140
  var genericFeatures = new Set();
141
+ var genericGlobals = new Set();
141
142
  var sources = {};
142
143
  for (let env in this.bundleEnvironments){
143
- sources[env] = {frameworks: [], files: [], features: []};
144
+ sources[env] = {frameworks: [], files: [], features: [], globals: []};
144
145
  let imports = this.importsByEnvironment[env];
145
146
  for (let i = 0, l = imports.frameworks.length; i < l; ++i){
146
147
  let framework = imports.frameworks[i];
@@ -176,6 +177,15 @@ JSClass("FrameworkBuilder", Builder, {
176
177
  sources[env].features.push(feature);
177
178
  }
178
179
  }
180
+ for (let i = 0, l = imports.globals.length; i < l; ++i){
181
+ let name = imports.globals[i];
182
+ if (env == 'generic'){
183
+ genericGlobals.add(name);
184
+ }
185
+ if (env == 'generic' || !genericGlobals.has(name)){
186
+ sources[env].globals.push(name);
187
+ }
188
+ }
179
189
  }
180
190
  return sources;
181
191
  },
@@ -185,6 +195,7 @@ JSClass("FrameworkBuilder", Builder, {
185
195
  var genericFrameworks = new Set();
186
196
  var genericFiles = new Set();
187
197
  var genericFeatures = new Set();
198
+ var genericGlobals = new Set();
188
199
  var sources = {};
189
200
  var copyright = this.project.getInfoString("JSCopyright", this.resources);
190
201
  var licenseString = await this.project.licenseNoticeString();
@@ -195,7 +206,7 @@ JSClass("FrameworkBuilder", Builder, {
195
206
  }
196
207
  var header = "%s (%s)\n----\n%s%s".sprintf(this.project.info.JSBundleIdentifier, this.project.info.JSBundleVersion, copyright, licenseString);
197
208
  for (let env in this.bundleEnvironments){
198
- sources[env] = {frameworks: [], files: [], features: []};
209
+ sources[env] = {frameworks: [], files: [], features: [], globals: []};
199
210
  let filename = this.bundleEnvironments[env];
200
211
  let compilation = JavascriptCompilation.initWithName(filename, this.sourcesURL, this.fileManager);
201
212
  var fullSourcesURL = this.sourcesURL.appendingPathComponent("_debug", true);
@@ -238,6 +249,15 @@ JSClass("FrameworkBuilder", Builder, {
238
249
  sources[env].features.push(feature);
239
250
  }
240
251
  }
252
+ for (let i = 0, l = imports.globals.length; i < l; ++i){
253
+ let name = imports.globals[i];
254
+ if (env == 'generic'){
255
+ genericGlobals.add(name);
256
+ }
257
+ if (env == 'generic' || !genericGlobals.has(name)){
258
+ sources[env].globals.push(name);
259
+ }
260
+ }
241
261
  }
242
262
  return sources;
243
263
  },
package/Node/Project.js CHANGED
@@ -310,7 +310,8 @@ JSClass("Project", JSObject, {
310
310
  var result = {
311
311
  files: [],
312
312
  frameworks: [],
313
- features: []
313
+ features: [],
314
+ globals: []
314
315
  };
315
316
  var visited = {
316
317
  paths: new Set(),
@@ -359,6 +360,11 @@ JSClass("Project", JSObject, {
359
360
  result.features.push(feature);
360
361
  }
361
362
  }
363
+ let globals = js.globals();
364
+ for (let i = 0, l = globals.length; i < l; ++i){
365
+ let name = globals[i];
366
+ result.globals.push(name);
367
+ }
362
368
  }
363
369
  };
364
370
 
@@ -443,7 +449,21 @@ JSClass("Project", JSObject, {
443
449
  let url = await this.urlForFrameworkName(name, includeDirectoryURLs);
444
450
  if (url !== null){
445
451
  if (url.fileExtension === '.jsframework'){
446
- // TODO: extract from built framework
452
+ let sourcesURL = url.appendingPathComponent("sources.json");
453
+ let data = await this.fileManager.contentsAtURL(sourcesURL);
454
+ let sources = JSON.parse(data.stringByDecodingUTF8());
455
+ if (sources.generic.globals){
456
+ for (let name of sources.generic.globals){
457
+ globals.push(name);
458
+ }
459
+ }
460
+ for (let env of envs){
461
+ if ((env in sources) && sources[env].globals){
462
+ for (let name of sources[env].globals){
463
+ globals.push(name);
464
+ }
465
+ }
466
+ }
447
467
  }else{
448
468
  let frameworkProject = Project.initWithURL(url);
449
469
  try{
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.jskit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "node",
5
5
  "JSBundleIdentifier": "io.breakside.jskit",
6
- "JSBundleVersion": "2022.22.2",
6
+ "JSBundleVersion": "2022.22.3",
7
7
  "JSExecutableName": "jskit",
8
8
  "NPMOrganization": "breakside",
9
9
  "JSResources": [
10
10
  "Tests/HTMLTestRunner.js",
11
11
  "Tests/NodeTestRunner.js"
12
12
  ],
13
- "GitRevision": "a302ede5223899a33db877d1cba370054efd6902"
13
+ "GitRevision": "6f0b376edf61fbea02fd94b92f86de9e17d3b716"
14
14
  },
15
15
  "Resources": [
16
16
  {
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKit
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSIncludeDirectories:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKitTesting
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
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.AuthKit
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
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.CSSOM
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
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.ChartKit
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
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.ConferenceKit
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
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.DBKit
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
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.DOM
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
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.Dispatch
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
4
4
  JSCopyright: Copyright © 2020 Breakside Inc.
5
5
  JSBundleEnvironments:
6
6
  html: Dispatch+HTML.js
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.FontKit
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
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.Foundation
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -294,6 +294,44 @@ JSClass("JSAttributedString", JSObject, {
294
294
  return new JSAttributedStringRunIterator(this, index);
295
295
  },
296
296
 
297
+ longestRangeOfAttributeAtIndex: function(attributeName, index){
298
+ return this.longestRangeOfAttributesAtIndex([attributeName], index);
299
+ },
300
+
301
+ longestRangeOfAttributesAtIndex: function(attributeNames, index){
302
+ var runIndex = this._runIndexForStringIndex(index);
303
+ var run = this._runs[runIndex];
304
+ var range = JSRange(run.range);
305
+ var attributes = {};
306
+ var i, l;
307
+ for (i = 0, l = attributeNames.length; i < l; ++i){
308
+ attributes[attributeNames[i]] = run.attributes[attributeNames[i]];
309
+ }
310
+ i = runIndex - 1;
311
+ while (i >= 0){
312
+ run = this._runs[i];
313
+ if (run.containsEqualAttributes(attributes)){
314
+ range.length = range.end - run.range.location;
315
+ range.location = run.range.location;
316
+ }else{
317
+ break;
318
+ }
319
+ --i;
320
+ }
321
+ i = runIndex + 1;
322
+ l = this._runs.length;
323
+ while (i < l){
324
+ run = this._runs[i];
325
+ if (run.containsEqualAttributes(attributes)){
326
+ range.length = run.range.end - range.location;
327
+ }else{
328
+ break;
329
+ }
330
+ ++i;
331
+ }
332
+ return range;
333
+ },
334
+
297
335
  // MARK: - Formatting
298
336
 
299
337
  replaceFormat: function(){
@@ -339,7 +377,7 @@ JSClass("JSAttributedString", JSObject, {
339
377
  var runA;
340
378
  for (var runIndex = lastRunIndex - 1; runIndex >= expandedRunRange.location; --runIndex){
341
379
  runA = this._runs[runIndex];
342
- if (runA.hasIdenticalAttributes(runB)){
380
+ if (runA.onlyContainsEqualAttributes(runB.attributes)){
343
381
  this._runs.splice(runIndex, 1);
344
382
  runB.range.location = runA.range.location;
345
383
  runB.range.length += runA.range.length;
@@ -358,7 +396,7 @@ JSClass("JSAttributedString", JSObject, {
358
396
  }
359
397
  var runA = this._runs[runIndex - 1];
360
398
  var runB = this._runs[runIndex];
361
- if (runA.hasIdenticalAttributes(runB)){
399
+ if (runA.onlyContainsEqualAttributes(runB.attributes)){
362
400
  this._runs.splice(runIndex, 1);
363
401
  runA.range.length += runB.range.length;
364
402
  }
@@ -471,35 +509,46 @@ function JSAttributedStringRun(range, attributes){
471
509
 
472
510
  JSAttributedStringRun.prototype = {
473
511
 
474
- hasIdenticalAttributes: function(other){
512
+ containsEqualAttributes: function(attributes){
475
513
  var attribute;
476
514
  var a, b;
477
- for (attribute in this.attributes){
478
- if (attribute in other.attributes){
479
- a = this.attributes[attribute];
480
- b = other.attributes[attribute];
481
- if (a.isEqual){
482
- if (!a.isEqual(b)){
483
- return false;
484
- }
485
- }else if (b.isEqual){
486
- if (!b.isEqual(a)){
487
- return false;
488
- }
489
- }else if (a != b){
515
+ for (attribute in attributes){
516
+ a = attributes[attribute];
517
+ b = this.attributes[attribute];
518
+ if (a === undefined){
519
+ if (!!b){
490
520
  return false;
491
521
  }
492
- }else{
522
+ }else if (a === null){
523
+ if (b !== null && b !== undefined){
524
+ return false;
525
+ }
526
+ }else if (a.isEqual){
527
+ if (b === null || b === undefined){
528
+ return false;
529
+ }
530
+ if (!a.isEqual(b)){
531
+ return false;
532
+ }
533
+ }else if (a != b){
493
534
  return false;
494
535
  }
495
536
  }
496
- for (attribute in other.attributes){
497
- if (!(attribute in this.attributes)){
537
+ return true;
538
+ },
539
+
540
+ onlyContainsEqualAttributes: function(attributes){
541
+ if (!this.containsEqualAttributes(attributes)){
542
+ return false;
543
+ }
544
+ var attribute;
545
+ for (attribute in this.attributes){
546
+ if (!(attribute in attributes)){
498
547
  return false;
499
548
  }
500
549
  }
501
550
  return true;
502
- }
551
+ },
503
552
 
504
553
  };
505
554
 
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ImageKit
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
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.2
3
+ JSBundleVersion: 2022.22.3
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -174,11 +174,14 @@ JSClass('UILabel', UIView, {
174
174
  var attributes = this.attributedText.attributesAtIndex(index);
175
175
  this._didDrag = false;
176
176
  if (attributes.link){
177
- var range = this.attributedText.rangeOfRunAtIndex(index);
178
- var layer = UILayer.init();
179
- layer.frame = this.layer.textLayoutManager.rectsForCharacterRange(range)[0].rectWithInsets(JSInsets(-1, -2));
180
- layer.cornerRadius = 2;
181
- layer.backgroundColor = JSColor.black.colorWithAlpha(0.2);
177
+ var range = this.attributedText.longestRangeOfAttributeAtIndex("link", index);
178
+ var layer = UILabelLinkLayer.init();
179
+ layer.pathColor = (attributes.textColor || this.textColor).colorWithAlpha(0.2);
180
+ var rects = this.layer.textLayoutManager.rectsForCharacterRange(range);
181
+ var i, l;
182
+ for (i = 0, l = rects.length; i < l; ++i){
183
+ layer.addRect(rects[i]);
184
+ }
182
185
  this.layer.addSublayer(layer);
183
186
  this._mouseDownAction = {
184
187
  link: attributes.link,
@@ -271,11 +274,14 @@ JSClass('UILabel', UIView, {
271
274
  var index = this.layer.textLayoutManager.characterIndexAtPoint(location);
272
275
  var attributes = this.attributedText.attributesAtIndex(index);
273
276
  if (attributes.link){
274
- var range = this.attributedText.rangeOfRunAtIndex(index);
275
- var layer = UILayer.init();
276
- layer.frame = this.layer.textLayoutManager.rectsForCharacterRange(range)[0].rectWithInsets(JSInsets(-1, -2));
277
- layer.cornerRadius = 2;
278
- layer.backgroundColor = JSColor.black.colorWithAlpha(0.2);
277
+ var range = this.attributedText.longestRangeOfAttributeAtIndex("link", index);
278
+ var layer = UILabelLinkLayer.init();
279
+ layer.pathColor = (attributes.textColor || this.textColor).colorWithAlpha(0.2);
280
+ var rects = this.layer.textLayoutManager.rectsForCharacterRange(range);
281
+ var i, l;
282
+ for (i = 0, l = rects.length; i < l; ++i){
283
+ layer.addRect(rects[i]);
284
+ }
279
285
  this.layer.addSublayer(layer);
280
286
  this._touchAction = {
281
287
  link: attributes.link,
@@ -379,4 +385,31 @@ JSClass('UILabel', UIView, {
379
385
 
380
386
  });
381
387
 
388
+ JSClass("UILabelLinkLayer", UILayer, {
389
+
390
+ pathColor: null,
391
+
392
+ init: function(){
393
+ UILabelLinkLayer.$super.init.call(this);
394
+ this.path = JSPath.init();
395
+ this.pathColor = JSColor.black;
396
+ this.setNeedsDisplay();
397
+ },
398
+
399
+ addRect: function(rect){
400
+ this.path.addRoundedRect(rect.rectWithInsets(JSInsets(-1, -2)), 2);
401
+ this.frame = this.path.boundingRect;
402
+ },
403
+
404
+ drawInContext: function(context){
405
+ context.save();
406
+ context.translateBy(-this.path.boundingRect.origin.x, -this.path.boundingRect.origin.y);
407
+ context.setFillColor(this.pathColor);
408
+ context.addPath(this.path);
409
+ context.fillPath();
410
+ context.restore();
411
+ },
412
+
413
+ });
414
+
382
415
  UILabel.layerClass = UITextLayer;
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKitTesting
3
- JSBundleVersion: 2022.22.2
3
+ JSBundleVersion: 2022.22.3
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "node": ">=10.10.0"
10
10
  },
11
11
  "name": "@breakside/jskit",
12
- "version": "2022.22.2",
12
+ "version": "2022.22.3",
13
13
  "license": "SEE LICENSE IN LICENSE.txt",
14
14
  "files": [
15
15
  "*"