@breakside/jskit 2022.22.1 → 2022.23.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/Frameworks/DOM.jsframework/Info.json +2 -2
- package/Frameworks/DOM.jsframework/JS/XMLSerializer.js +9 -4
- package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
- package/Frameworks/DOM.jsframework/sources.json +10 -3
- package/Frameworks/FontKit.jsframework/Info.json +2 -2
- package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
- package/Frameworks/FontKit.jsframework/sources.json +34 -2
- package/Frameworks/Foundation.jsframework/Info.json +2 -2
- package/Frameworks/Foundation.jsframework/JS/JSAttributedString.js +213 -20
- package/Frameworks/Foundation.jsframework/JS/JSFont.js +39 -15
- package/Frameworks/Foundation.jsframework/JS/JSFontDescriptor+HTML.js +8 -0
- package/Frameworks/Foundation.jsframework/JS/JSFontDescriptor.js +105 -27
- package/Frameworks/Foundation.jsframework/JS/JSTextAttachment.js +6 -1
- package/Frameworks/Foundation.jsframework/JS/JSTextRun.js +3 -0
- package/Frameworks/Foundation.jsframework/JS/String+JS.js +34 -0
- package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/sources.json +167 -8
- package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
- package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
- package/Frameworks/SecurityKit.jsframework/sources.json +43 -2
- package/Info.json +2 -2
- package/Node/Builder.js +20 -9
- package/Node/FrameworkBuilder.js +22 -2
- package/Node/Project.js +22 -2
- package/Node/io.breakside.jskit-bundle.js +2 -2
- package/Node/jskit +7 -7
- package/Root/Frameworks/APIKit/Info.yaml +1 -1
- package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/AuthKit/Info.yaml +1 -1
- package/Root/Frameworks/CSSOM/Info.yaml +1 -1
- package/Root/Frameworks/ChartKit/Info.yaml +1 -1
- package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
- package/Root/Frameworks/DBKit/Info.yaml +1 -1
- package/Root/Frameworks/DOM/Info.yaml +1 -1
- package/Root/Frameworks/DOM/XMLSerializer.js +9 -4
- package/Root/Frameworks/Dispatch/Info.yaml +1 -1
- package/Root/Frameworks/FontKit/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/JSAttributedString.js +213 -20
- package/Root/Frameworks/Foundation/JSFont.js +39 -15
- package/Root/Frameworks/Foundation/JSFontDescriptor+HTML.js +8 -0
- package/Root/Frameworks/Foundation/JSFontDescriptor.js +105 -27
- package/Root/Frameworks/Foundation/JSTextAttachment.js +6 -1
- package/Root/Frameworks/Foundation/JSTextRun.js +3 -0
- package/Root/Frameworks/Foundation/String+JS.js +34 -0
- package/Root/Frameworks/ImageKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
- package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
- package/Root/Frameworks/PDFKit/Info.yaml +1 -1
- package/Root/Frameworks/QRKit/Info.yaml +1 -1
- package/Root/Frameworks/SearchKit/Info.yaml +1 -1
- package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/TestKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/UIHTMLTextFrame.js +3 -0
- package/Root/Frameworks/UIKit/UIHTMLTextRun.js +3 -1
- package/Root/Frameworks/UIKit/UIHTMLTextTypesetter.js +14 -0
- package/Root/Frameworks/UIKit/UILabel.js +43 -10
- package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
- package/package.json +1 -1
package/Node/FrameworkBuilder.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
6
|
+
"JSBundleVersion": "2022.23.0",
|
|
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": "
|
|
13
|
+
"GitRevision": "e2a77335b26d1a321448e73eb7b733cdd0714cc8"
|
|
14
14
|
},
|
|
15
15
|
"Resources": [
|
|
16
16
|
{
|
package/Node/jskit
CHANGED
|
@@ -49,19 +49,19 @@ require("./../Frameworks/Foundation.jsframework/JS/JSURLResponse.js");
|
|
|
49
49
|
require("./../Frameworks/Foundation.jsframework/JS/JSXMLParser.js");
|
|
50
50
|
require("./../Frameworks/Foundation.jsframework/JS/JSImage.js");
|
|
51
51
|
require("./../Frameworks/Foundation.jsframework/JS/JSTextAttachment.js");
|
|
52
|
-
require("./../Frameworks/Foundation.jsframework/JS/JSAttributedString.js");
|
|
53
|
-
require("./../Frameworks/Foundation.jsframework/JS/JSSpec.js");
|
|
54
|
-
require("./../Frameworks/Foundation.jsframework/JS/JSArrayController.js");
|
|
55
|
-
require("./../Frameworks/Foundation.jsframework/JS/JSSparseArrayController.js");
|
|
56
|
-
require("./../Frameworks/Foundation.jsframework/JS/JSColorSpace.js");
|
|
57
|
-
require("./../Frameworks/Foundation.jsframework/JS/JSColor.js");
|
|
58
|
-
require("./../Frameworks/Foundation.jsframework/JS/JSGradient.js");
|
|
59
52
|
require("./../Frameworks/Foundation.jsframework/JS/Huffman.js");
|
|
60
53
|
require("./../Frameworks/Foundation.jsframework/JS/Deflate.js");
|
|
61
54
|
require("./../Frameworks/Foundation.jsframework/JS/Adler32.js");
|
|
62
55
|
require("./../Frameworks/Foundation.jsframework/JS/Zlib.js");
|
|
63
56
|
require("./../Frameworks/Foundation.jsframework/JS/JSFontDescriptor.js");
|
|
64
57
|
require("./../Frameworks/Foundation.jsframework/JS/JSFont.js");
|
|
58
|
+
require("./../Frameworks/Foundation.jsframework/JS/JSColorSpace.js");
|
|
59
|
+
require("./../Frameworks/Foundation.jsframework/JS/JSColor.js");
|
|
60
|
+
require("./../Frameworks/Foundation.jsframework/JS/JSAttributedString.js");
|
|
61
|
+
require("./../Frameworks/Foundation.jsframework/JS/JSSpec.js");
|
|
62
|
+
require("./../Frameworks/Foundation.jsframework/JS/JSArrayController.js");
|
|
63
|
+
require("./../Frameworks/Foundation.jsframework/JS/JSSparseArrayController.js");
|
|
64
|
+
require("./../Frameworks/Foundation.jsframework/JS/JSGradient.js");
|
|
65
65
|
require("./../Frameworks/Foundation.jsframework/JS/JSPath.js");
|
|
66
66
|
require("./../Frameworks/Foundation.jsframework/JS/JSContext.js");
|
|
67
67
|
require("./../Frameworks/Foundation.jsframework/JS/JSDateFormatter.js");
|
|
@@ -113,10 +113,15 @@ XMLSerializer.prototype = {
|
|
|
113
113
|
str += " " + node.name;
|
|
114
114
|
}
|
|
115
115
|
if (node.publicId.length > 0){
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
value = node.publicId.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
117
|
+
str += ' PUBLIC "%s"'.sprintf(value);
|
|
118
|
+
if (node.systemId.length > 0){
|
|
119
|
+
value = node.systemId.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
120
|
+
str += ' "%s"'.sprintf(value);
|
|
121
|
+
}
|
|
122
|
+
}else if (node.systemId.length > 0){
|
|
123
|
+
value = node.systemId.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
124
|
+
str += ' SYSTEM "%s"'.sprintf(value);
|
|
120
125
|
}
|
|
121
126
|
str += ">\n";
|
|
122
127
|
}
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
// #import "Javascript.js"
|
|
17
17
|
// #import "JSObject.js"
|
|
18
18
|
// #import "JSTextAttachment.js"
|
|
19
|
+
// #import "JSFont.js"
|
|
20
|
+
// #import "JSColor.js"
|
|
19
21
|
'use strict';
|
|
20
22
|
|
|
21
23
|
(function(){
|
|
@@ -40,6 +42,123 @@ JSClass("JSAttributedString", JSObject, {
|
|
|
40
42
|
this._runs = [run];
|
|
41
43
|
},
|
|
42
44
|
|
|
45
|
+
initFromDictionary: function(dictionary){
|
|
46
|
+
this._string = typeof(dictionary.string) === "string" ? dictionary.string : "";
|
|
47
|
+
this._runs = [];
|
|
48
|
+
var i, l;
|
|
49
|
+
var runDictionary;
|
|
50
|
+
var run;
|
|
51
|
+
var attributes;
|
|
52
|
+
var name;
|
|
53
|
+
var location = 0;
|
|
54
|
+
var length;
|
|
55
|
+
var maxLength = this._string.length;
|
|
56
|
+
var decodeAttribute = function(name, value){
|
|
57
|
+
switch (name){
|
|
58
|
+
case JSAttributedString.Attribute.font:
|
|
59
|
+
return JSAttributedString.AttributeDecoder.font(value);
|
|
60
|
+
case JSAttributedString.Attribute.textColor:
|
|
61
|
+
case JSAttributedString.Attribute.backgroundColor:
|
|
62
|
+
return JSAttributedString.AttributeDecoder.color(value);
|
|
63
|
+
case JSAttributedString.Attribute.link:
|
|
64
|
+
return JSAttributedString.AttributeDecoder.url(value);
|
|
65
|
+
case JSAttributedString.Attribute.cursor:
|
|
66
|
+
return JSAttributedString.AttributeDecoder.skip(value);
|
|
67
|
+
case JSAttributedString.Attribute.attachment:
|
|
68
|
+
// TODO:
|
|
69
|
+
return JSAttributedString.AttributeDecoder.skip(value);
|
|
70
|
+
case JSAttributedString.Attribute.maskCharacter:
|
|
71
|
+
return JSAttributedString.AttributeDecoder.string(value);
|
|
72
|
+
case JSAttributedString.Attribute.bold:
|
|
73
|
+
case JSAttributedString.Attribute.italic:
|
|
74
|
+
case JSAttributedString.Attribute.underline:
|
|
75
|
+
case JSAttributedString.Attribute.strike:
|
|
76
|
+
return JSAttributedString.AttributeDecoder.boolean(value);
|
|
77
|
+
case JSAttributedString.Attribute.lineHeight:
|
|
78
|
+
case JSAttributedString.Attribute.lineSpacing:
|
|
79
|
+
return JSAttributedString.AttributeDecoder.number(value);
|
|
80
|
+
case JSAttributedString.Attribute.textAlignment:
|
|
81
|
+
// TODO: validate
|
|
82
|
+
case JSAttributedString.Attribute.lineBreakMode:
|
|
83
|
+
// TODO: validate
|
|
84
|
+
default:
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
};
|
|
89
|
+
if (dictionary.runs instanceof Array){
|
|
90
|
+
for (i = 0, l = dictionary.runs.length; i < l && maxLength > 0; ++i){
|
|
91
|
+
runDictionary = dictionary.runs[i];
|
|
92
|
+
attributes = {};
|
|
93
|
+
length = typeof(runDictionary.length) === "number" ? Math.min(maxLength, Math.floor(runDictionary.length)) : 0;
|
|
94
|
+
if (length > 0 && typeof(runDictionary.attributes) === "object"){
|
|
95
|
+
for (name in runDictionary.attributes){
|
|
96
|
+
attributes[name] = decodeAttribute(name, runDictionary.attributes[name]);
|
|
97
|
+
}
|
|
98
|
+
this._runs.push(JSAttributedStringRun(JSRange(location, length), attributes));
|
|
99
|
+
}
|
|
100
|
+
location += length;
|
|
101
|
+
maxLength -= length;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (maxLength > 0){
|
|
105
|
+
this._runs.push(JSAttributedStringRun(JSRange(location, maxLength), {}));
|
|
106
|
+
}
|
|
107
|
+
if (this._runs.length === 0){
|
|
108
|
+
this._runs.push(JSAttributedStringRun(JSRange(0, 0), {}));
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
dictionaryRepresentation: function(){
|
|
113
|
+
var dictionary = {
|
|
114
|
+
string: this._string,
|
|
115
|
+
runs: []
|
|
116
|
+
};
|
|
117
|
+
var i, l;
|
|
118
|
+
var run;
|
|
119
|
+
var name;
|
|
120
|
+
var runDictionary;
|
|
121
|
+
var encodeAttribute = function(name, value){
|
|
122
|
+
switch (name){
|
|
123
|
+
case JSAttributedString.Attribute.font:
|
|
124
|
+
return JSAttributedString.AttributeEncoder.font(value);
|
|
125
|
+
case JSAttributedString.Attribute.textColor:
|
|
126
|
+
case JSAttributedString.Attribute.backgroundColor:
|
|
127
|
+
return JSAttributedString.AttributeEncoder.color(value);
|
|
128
|
+
case JSAttributedString.Attribute.link:
|
|
129
|
+
return JSAttributedString.AttributeEncoder.url(value);
|
|
130
|
+
case JSAttributedString.Attribute.cursor:
|
|
131
|
+
return JSAttributedString.Attribute.Encoder.skip(value);
|
|
132
|
+
case JSAttributedString.Attribute.attachment:
|
|
133
|
+
// TODO:
|
|
134
|
+
return JSAttributedString.Attribute.Encoder.skip(value);
|
|
135
|
+
case JSAttributedString.Attribute.bold:
|
|
136
|
+
case JSAttributedString.Attribute.italic:
|
|
137
|
+
case JSAttributedString.Attribute.underline:
|
|
138
|
+
case JSAttributedString.Attribute.strike:
|
|
139
|
+
case JSAttributedString.Attribute.lineHeight:
|
|
140
|
+
case JSAttributedString.Attribute.lineSpacing:
|
|
141
|
+
case JSAttributedString.Attribute.textAlignment:
|
|
142
|
+
case JSAttributedString.Attribute.lineBreakMode:
|
|
143
|
+
case JSAttributedString.Attribute.maskCharacter:
|
|
144
|
+
default:
|
|
145
|
+
return value;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
for (i = 0, l = this._runs.length; i < l; ++i){
|
|
149
|
+
run = this._runs[i];
|
|
150
|
+
runDictionary = {
|
|
151
|
+
length: run.range.length,
|
|
152
|
+
attributes: {}
|
|
153
|
+
};
|
|
154
|
+
for (name in run.attributes){
|
|
155
|
+
runDictionary.attributes[name] = encodeAttribute(name, run.attributes[name]);
|
|
156
|
+
}
|
|
157
|
+
dictionary.runs.push(runDictionary);
|
|
158
|
+
}
|
|
159
|
+
return dictionary;
|
|
160
|
+
},
|
|
161
|
+
|
|
43
162
|
initWithAttributedString: function(attributedString, defaultAttributes){
|
|
44
163
|
this._string = attributedString.string;
|
|
45
164
|
this._runs = [];
|
|
@@ -294,6 +413,44 @@ JSClass("JSAttributedString", JSObject, {
|
|
|
294
413
|
return new JSAttributedStringRunIterator(this, index);
|
|
295
414
|
},
|
|
296
415
|
|
|
416
|
+
longestRangeOfAttributeAtIndex: function(attributeName, index){
|
|
417
|
+
return this.longestRangeOfAttributesAtIndex([attributeName], index);
|
|
418
|
+
},
|
|
419
|
+
|
|
420
|
+
longestRangeOfAttributesAtIndex: function(attributeNames, index){
|
|
421
|
+
var runIndex = this._runIndexForStringIndex(index);
|
|
422
|
+
var run = this._runs[runIndex];
|
|
423
|
+
var range = JSRange(run.range);
|
|
424
|
+
var attributes = {};
|
|
425
|
+
var i, l;
|
|
426
|
+
for (i = 0, l = attributeNames.length; i < l; ++i){
|
|
427
|
+
attributes[attributeNames[i]] = run.attributes[attributeNames[i]];
|
|
428
|
+
}
|
|
429
|
+
i = runIndex - 1;
|
|
430
|
+
while (i >= 0){
|
|
431
|
+
run = this._runs[i];
|
|
432
|
+
if (run.containsEqualAttributes(attributes)){
|
|
433
|
+
range.length = range.end - run.range.location;
|
|
434
|
+
range.location = run.range.location;
|
|
435
|
+
}else{
|
|
436
|
+
break;
|
|
437
|
+
}
|
|
438
|
+
--i;
|
|
439
|
+
}
|
|
440
|
+
i = runIndex + 1;
|
|
441
|
+
l = this._runs.length;
|
|
442
|
+
while (i < l){
|
|
443
|
+
run = this._runs[i];
|
|
444
|
+
if (run.containsEqualAttributes(attributes)){
|
|
445
|
+
range.length = run.range.end - range.location;
|
|
446
|
+
}else{
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
++i;
|
|
450
|
+
}
|
|
451
|
+
return range;
|
|
452
|
+
},
|
|
453
|
+
|
|
297
454
|
// MARK: - Formatting
|
|
298
455
|
|
|
299
456
|
replaceFormat: function(){
|
|
@@ -339,7 +496,7 @@ JSClass("JSAttributedString", JSObject, {
|
|
|
339
496
|
var runA;
|
|
340
497
|
for (var runIndex = lastRunIndex - 1; runIndex >= expandedRunRange.location; --runIndex){
|
|
341
498
|
runA = this._runs[runIndex];
|
|
342
|
-
if (runA.
|
|
499
|
+
if (runA.onlyContainsEqualAttributes(runB.attributes)){
|
|
343
500
|
this._runs.splice(runIndex, 1);
|
|
344
501
|
runB.range.location = runA.range.location;
|
|
345
502
|
runB.range.length += runA.range.length;
|
|
@@ -358,7 +515,7 @@ JSClass("JSAttributedString", JSObject, {
|
|
|
358
515
|
}
|
|
359
516
|
var runA = this._runs[runIndex - 1];
|
|
360
517
|
var runB = this._runs[runIndex];
|
|
361
|
-
if (runA.
|
|
518
|
+
if (runA.onlyContainsEqualAttributes(runB.attributes)){
|
|
362
519
|
this._runs.splice(runIndex, 1);
|
|
363
520
|
runA.range.length += runB.range.length;
|
|
364
521
|
}
|
|
@@ -443,6 +600,31 @@ JSAttributedString.Attribute = {
|
|
|
443
600
|
link: "link"
|
|
444
601
|
};
|
|
445
602
|
|
|
603
|
+
JSAttributedString.AttributeEncoder = {
|
|
604
|
+
skip: function(value){ return undefined; },
|
|
605
|
+
identity: function(value){ return value; },
|
|
606
|
+
dataBase64: function(value){ return value.base64StringRepresentation(); },
|
|
607
|
+
dataBase64URL: function(value){ return value.base64URLStringRepresentation(); },
|
|
608
|
+
dataHex: function(value){ return value.hexStringRepresentation(); },
|
|
609
|
+
url: function(value){ return value.encodedString; },
|
|
610
|
+
font: function(value){ return value.dictionaryRepresentation(); },
|
|
611
|
+
color: function(value){ return value.dictionaryRepresentation(); },
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
JSAttributedString.AttributeDecoder = {
|
|
615
|
+
skip: function(value){ return undefined; },
|
|
616
|
+
identity: function(value){ return value; },
|
|
617
|
+
dataBase64: function(value){ return value.dataByDecodingBase64(); },
|
|
618
|
+
dataBase64URL: function(value){ return value.dataByDecodingBase64URL(); },
|
|
619
|
+
dataHex: function(value){ return value.dataByDecodingHex(); },
|
|
620
|
+
url: function(value){ return JSURL.initWithString(value); },
|
|
621
|
+
font: function(value){ return JSFont.initFromDictionary(value); },
|
|
622
|
+
color: function(value){ return JSColor.initFromDictionary(value); },
|
|
623
|
+
boolean: function(value){ return typeof(value) === "boolean" ? value : undefined; },
|
|
624
|
+
number: function(value){ return typeof(value) === "number" ? value : undefined; },
|
|
625
|
+
string: function(value){ return typeof(value) === "string" ? value : undefined; },
|
|
626
|
+
};
|
|
627
|
+
|
|
446
628
|
JSAttributedString.SpecialCharacter = {
|
|
447
629
|
attachment: 0xFFFC,
|
|
448
630
|
attachmentUTF16: "\uFFFC"
|
|
@@ -471,35 +653,46 @@ function JSAttributedStringRun(range, attributes){
|
|
|
471
653
|
|
|
472
654
|
JSAttributedStringRun.prototype = {
|
|
473
655
|
|
|
474
|
-
|
|
656
|
+
containsEqualAttributes: function(attributes){
|
|
475
657
|
var attribute;
|
|
476
658
|
var a, b;
|
|
477
|
-
for (attribute in
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
if (
|
|
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){
|
|
659
|
+
for (attribute in attributes){
|
|
660
|
+
a = attributes[attribute];
|
|
661
|
+
b = this.attributes[attribute];
|
|
662
|
+
if (a === undefined){
|
|
663
|
+
if (!!b){
|
|
490
664
|
return false;
|
|
491
665
|
}
|
|
492
|
-
}else{
|
|
666
|
+
}else if (a === null){
|
|
667
|
+
if (b !== null && b !== undefined){
|
|
668
|
+
return false;
|
|
669
|
+
}
|
|
670
|
+
}else if (a.isEqual){
|
|
671
|
+
if (b === null || b === undefined){
|
|
672
|
+
return false;
|
|
673
|
+
}
|
|
674
|
+
if (!a.isEqual(b)){
|
|
675
|
+
return false;
|
|
676
|
+
}
|
|
677
|
+
}else if (a != b){
|
|
493
678
|
return false;
|
|
494
679
|
}
|
|
495
680
|
}
|
|
496
|
-
|
|
497
|
-
|
|
681
|
+
return true;
|
|
682
|
+
},
|
|
683
|
+
|
|
684
|
+
onlyContainsEqualAttributes: function(attributes){
|
|
685
|
+
if (!this.containsEqualAttributes(attributes)){
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
var attribute;
|
|
689
|
+
for (attribute in this.attributes){
|
|
690
|
+
if (!(attribute in attributes)){
|
|
498
691
|
return false;
|
|
499
692
|
}
|
|
500
693
|
}
|
|
501
694
|
return true;
|
|
502
|
-
}
|
|
695
|
+
},
|
|
503
696
|
|
|
504
697
|
};
|
|
505
698
|
|