@breakside/jskit 2026.10.0 → 2026.11.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 (61) 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/FontKit.jsframework/Info.json +2 -2
  4. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  5. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  6. package/Frameworks/Foundation.jsframework/JS/JSNodeHTTPClient.js +34 -14
  7. package/Frameworks/Foundation.jsframework/JS/JSNodeURLSessionDataTask.js +2 -2
  8. package/Frameworks/Foundation.jsframework/JS/JSURLRequest.js +3 -0
  9. package/Frameworks/Foundation.jsframework/JS/JSZip.js +155 -1
  10. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  11. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  12. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  13. package/Info.json +2 -2
  14. package/Node/Docs/DocClass.js +38 -1
  15. package/Node/Docs/DocComponent.js +26 -1
  16. package/Node/Docs/DocDictionaryProperty.js +8 -0
  17. package/Node/Docs/DocEnum.js +35 -2
  18. package/Node/Docs/DocEnumOption.js +3 -0
  19. package/Node/Docs/DocExtension.js +130 -0
  20. package/Node/Docs/DocFunction.js +8 -0
  21. package/Node/Docs/DocMethod.js +3 -0
  22. package/Node/Docs/DocProperty.js +11 -0
  23. package/Node/Docs/DocProtocol.js +4 -0
  24. package/Node/Docs/DocSpec.js +4 -0
  25. package/Node/Docs/DocSpecProperty.js +8 -0
  26. package/Node/Docs/DocTopicBasedComponent.js +75 -65
  27. package/Node/Documentation.js +73 -4
  28. package/Node/HTMLProjectServer.js +1 -1
  29. package/Node/Markdown.js +2 -2
  30. package/Node/io.breakside.jskit-bundle.js +3 -3
  31. package/Node/jskit +1 -0
  32. package/Resources/doc-default.css +2 -2
  33. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  34. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  35. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  36. package/Root/Frameworks/CSSOM/Info.yaml +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/Dispatch/Info.yaml +1 -1
  42. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  43. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  44. package/Root/Frameworks/Foundation/JSNodeHTTPClient.js +34 -14
  45. package/Root/Frameworks/Foundation/JSNodeURLSessionDataTask.js +2 -2
  46. package/Root/Frameworks/Foundation/JSURLRequest.js +3 -0
  47. package/Root/Frameworks/Foundation/JSZip.js +155 -1
  48. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  49. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  50. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  51. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  52. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  53. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  54. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  55. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  56. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  57. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  58. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  59. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  60. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  61. package/package.json +1 -1
@@ -0,0 +1,130 @@
1
+ // Copyright 2020 Breakside Inc.
2
+ //
3
+ // Licensed under the Breakside Public License, Version 1.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // If a copy of the License was not distributed with this file, you may
6
+ // obtain a copy at
7
+ //
8
+ // http://breakside.io/licenses/LICENSE-1.0.txt
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ // #import "DocTopicBasedComponent.js"
17
+ 'use strict';
18
+
19
+ JSClass("DocExtension", DocTopicBasedComponent, {
20
+
21
+ kind: 'extension',
22
+ defaultChildKind: 'property',
23
+
24
+ // --------------------------------------------------------------------
25
+ // MARK: - Creating and populating
26
+
27
+ extractPropertiesFromInfo: async function(info, documentation){
28
+ await DocExtension.$super.extractPropertiesFromInfo.call(this, info, documentation);
29
+ let i = this.name.indexOf("+");
30
+ if (i < 0){
31
+ i = this.name.indexOf("(");
32
+ if (i < 0){
33
+ throw new Error("Extension %s name must include a +".sprintf(this.name));
34
+ }
35
+ }
36
+ if (this.name[i] === "("){
37
+ this.extends = info.extends || this.name.substr(0, i).trim();
38
+ i += 1;
39
+ this.extensionName = this.name.substr(i, this.name.length - 1 - i);
40
+ }else{
41
+ this.extends = info.extends || this.name.substr(0, i);
42
+ this.extensionName = this.name.substr(i + 1);
43
+ }
44
+ },
45
+
46
+ populateRelationships: function(){
47
+ DocExtension.$super.populateRelationships.call(this);
48
+ var parts = this.extends.split('.');
49
+ this.extendsComponent = this.componentForName(parts.shift());
50
+ while (parts.length > 0 && this.extendsComponent !== null){
51
+ this.extendsComponent = this.extendsComponent.childForName(parts.shift());
52
+ }
53
+ if (this.extendsComponent !== null){
54
+ if (this.extendsComponent.kind === "class"){
55
+ this.extendsComponent.addExtension(this);
56
+ }else if (this.extendsComponent.kind === "enum"){
57
+ this.extendsComponent.addExtension(this);
58
+ }
59
+ }
60
+ },
61
+
62
+ extends: null,
63
+ extensionName: null,
64
+ extendsComponent: null,
65
+
66
+ // --------------------------------------------------------------------
67
+ // MARK: - Naming
68
+
69
+ getDisplayNameForKind: function(){
70
+ return 'Extension';
71
+ },
72
+
73
+ // --------------------------------------------------------------------
74
+ // MARK: - Generating HTML
75
+
76
+ htmlArticleElements: function(document){
77
+ var elements = DocExtension.$super.htmlArticleElements.call(this, document);
78
+ var declaration = this.codeSectionElement(document, "Declaration", this.declarationCode(document));
79
+ declaration.setAttribute("class", "declaration");
80
+ elements.splice(1, 0, declaration);
81
+
82
+ let extension = document.createElement('section');
83
+ elements.push(extension);
84
+ extension.setAttribute("class", "extension");
85
+ let header = extension.appendChild(document.createElement("header"));
86
+ let h1 = header.appendChild(document.createElement("h2"));
87
+ h1.setAttribute("outline-level", "1");
88
+ h1.appendChild(document.createTextNode("Adds To"));
89
+ let p = extension.appendChild(document.createElement("p"));
90
+ let code = p.appendChild(document.createElement("code"));
91
+ let url = this.urlForCode(this.extends);
92
+ if (url !== null){
93
+ let a = code.appendChild(document.createElement("a"));
94
+ a.setAttribute("href", url.encodedString);
95
+ if (url.isAbsolute){
96
+ a.setAttribute("target", "_blank");
97
+ a.setAttribute("rel", "noopener noreferrer");
98
+ }
99
+ a.appendChild(document.createTextNode(this.extends));
100
+ }else{
101
+ code.appendChild(document.createTextNode(this.extends));
102
+ }
103
+
104
+ return elements;
105
+ },
106
+
107
+ declarationCode: function(document){
108
+ var tokens = [];
109
+ if (this.extendsComponent !== null){
110
+ if (this.extendsComponent.kind === "enum"){
111
+ tokens.push({value: this.extends, link: true});
112
+ tokens.push({value: "+= { ... }"});
113
+ }else if (this.extendsComponent.kind === "class"){
114
+ if (this.extendsComponent.inherits){
115
+ tokens.push({value: this.extends, link: true});
116
+ tokens.push({value: ".definePropertiesFromExtensions({ ... })"});
117
+ }else{
118
+ }
119
+ }
120
+ }
121
+ if (tokens.length === 0){
122
+ tokens.push({value: this.extends, link: true});
123
+ tokens.push({value: "+= { ... }"});
124
+ }
125
+ var lines = [];
126
+ lines.push(this.codeLineFromTokens(document, tokens));
127
+ return lines;
128
+ },
129
+
130
+ });
@@ -88,6 +88,10 @@
88
88
  if (url){
89
89
  let a = code.appendChild(document.createElement("a"));
90
90
  a.setAttribute("href", url.encodedString);
91
+ if (url.isAbsolute){
92
+ a.setAttribute("target", "_blank");
93
+ a.setAttribute("rel", "noopener noreferrer");
94
+ }
91
95
  a.appendChild(document.createTextNode(this.valueType));
92
96
  }else{
93
97
  code.appendChild(document.createTextNode(this.valueType));
@@ -149,6 +153,10 @@
149
153
  if (url !== null){
150
154
  let a = code.appendChild(document.createElement("a"));
151
155
  a.setAttribute("href", url.encodedString);
156
+ if (url.isAbsolute){
157
+ a.setAttribute("target", "_blank");
158
+ a.setAttribute("rel", "noopener noreferrer");
159
+ }
152
160
  a.appendChild(document.createTextNode(arg.type));
153
161
  }else{
154
162
  code.appendChild(document.createTextNode(arg.type));
@@ -37,6 +37,9 @@
37
37
 
38
38
  getTitle: function(){
39
39
  if (this.isStatic){
40
+ if (this.parent.kind == "extension"){
41
+ return "%s.%s".sprintf(this.parent.extends, this.name);
42
+ }
40
43
  return "%s.%s".sprintf(this.parent.name, this.name);
41
44
  }
42
45
  return this.name;
@@ -45,6 +45,9 @@
45
45
 
46
46
  getTitle: function(){
47
47
  if (this.isStatic){
48
+ if (this.parent.kind === "extension"){
49
+ return "%s.%s".sprintf(this.parent.extends, this.name);
50
+ }
48
51
  return "%s.%s".sprintf(this.parent.name, this.name);
49
52
  }
50
53
  return this.name;
@@ -70,6 +73,10 @@
70
73
  if (url){
71
74
  let a = code.appendChild(document.createElement("a"));
72
75
  a.setAttribute("href", url.encodedString);
76
+ if (url.isAbsolute){
77
+ a.setAttribute("target", "_blank");
78
+ a.setAttribute("rel", "noopener noreferrer");
79
+ }
73
80
  a.appendChild(document.createTextNode(this.valueType));
74
81
  }else{
75
82
  code.appendChild(document.createTextNode(this.valueType));
@@ -97,6 +104,10 @@
97
104
  li.setAttribute("class", variation.kind);
98
105
  let a = document.createElement("a");
99
106
  a.setAttribute("href", url.encodedString);
107
+ if (url.isAbsolute){
108
+ a.setAttribute("target", "_blank");
109
+ a.setAttribute("rel", "noopener noreferrer");
110
+ }
100
111
  let code = li.appendChild(document.createElement('code'));
101
112
  code.appendChild(a);
102
113
  a.appendChild(document.createTextNode(variation.name));
@@ -62,6 +62,10 @@
62
62
  if (url !== null){
63
63
  let a = code.appendChild(document.createElement("a"));
64
64
  a.setAttribute("href", url.encodedString);
65
+ if (url.isAbsolute){
66
+ a.setAttribute("target", "_blank");
67
+ a.setAttribute("rel", "noopener noreferrer");
68
+ }
65
69
  a.appendChild(document.createTextNode(this.inherits));
66
70
  }else{
67
71
  code.appendChild(document.createTextNode(this.inherits));
@@ -63,6 +63,10 @@
63
63
  let code = p.appendChild(document.createElement("code"));
64
64
  let a = code.appendChild(document.createElement("a"));
65
65
  a.setAttribute("href", url.encodedString);
66
+ if (url.isAbsolute){
67
+ a.setAttribute("target", "_blank");
68
+ a.setAttribute("rel", "noopener noreferrer");
69
+ }
66
70
  a.appendChild(document.createTextNode(inheritedSpec.title));
67
71
  }
68
72
  }
@@ -53,6 +53,10 @@
53
53
  if (url){
54
54
  let a = code.appendChild(document.createElement("a"));
55
55
  a.setAttribute("href", url.encodedString);
56
+ if (url.isAbsolute){
57
+ a.setAttribute("target", "_blank");
58
+ a.setAttribute("rel", "noopener noreferrer");
59
+ }
56
60
  a.appendChild(document.createTextNode(this.valueType));
57
61
  }else{
58
62
  code.appendChild(document.createTextNode(this.valueType));
@@ -77,6 +81,10 @@
77
81
  li.setAttribute("class", variation.kind);
78
82
  let a = document.createElement("a");
79
83
  a.setAttribute("href", url.encodedString);
84
+ if (url.isAbsolute){
85
+ a.setAttribute("target", "_blank");
86
+ a.setAttribute("rel", "noopener noreferrer");
87
+ }
80
88
  let code = li.appendChild(document.createElement('code'));
81
89
  code.appendChild(a);
82
90
  a.appendChild(document.createTextNode(variation.name));
@@ -17,7 +17,7 @@
17
17
  /* global DocFunction */
18
18
  'use strict';
19
19
 
20
- JSClass("DocTopicBasedComponent", DocComponent, {
20
+ JSClass("DocTopicBasedComponent", DocComponent, {
21
21
 
22
22
  topics: null,
23
23
  defaultChildKind: null,
@@ -75,73 +75,83 @@
75
75
  htmlArticleElements: function(document){
76
76
  var elements = DocTopicBasedComponent.$super.htmlArticleElements.call(this, document);
77
77
  if (this.topics.length > 0){
78
- var topicsSection = document.createElement("section");
79
- elements.push(topicsSection);
80
- topicsSection.setAttribute("class", "topics");
81
- let header = topicsSection.appendChild(document.createElement("header"));
82
- let h1 = header.appendChild(document.createElement("h2"));
83
- h1.setAttribute("outline-level", "1");
84
- h1.appendChild(document.createTextNode("Topics"));
85
- for (let i = 0, l = this.topics.length; i < l; ++i){
86
- let topic = this.topics[i];
87
- if (topic.members.length === 0) continue;
88
- let section = topicsSection.appendChild(document.createElement("section"));
89
- section.setAttribute("class", "topic");
90
- let header = section.appendChild(document.createElement("header"));
91
- let h1 = header.appendChild(document.createElement("h3"));
92
- h1.appendChild(document.createTextNode(topic.name));
93
- h1.setAttribute("outline-level", "2");
94
- let div = section.appendChild(document.createElement('div'));
95
- if (topic.summary){
96
- let markdown = this.createMarkdownWithString(topic.summary);
97
- let children = markdown.htmlElementsForDocument(document);
98
- for (let j = 0, k = children.length; j < k; ++j){
99
- div.appendChild(children[j]);
100
- }
78
+ elements = elements.concat(this.htmlArticleTopicsElements(document, "Topics", this.topics));
79
+ }
80
+ return elements;
81
+ },
82
+
83
+ htmlArticleTopicsElements: function(document, title, topics){
84
+ let elements = [];
85
+ var topicsSection = document.createElement("section");
86
+ elements.push(topicsSection);
87
+ topicsSection.setAttribute("class", "topics");
88
+ let header = topicsSection.appendChild(document.createElement("header"));
89
+ let h1 = header.appendChild(document.createElement("h2"));
90
+ h1.setAttribute("outline-level", "1");
91
+ h1.appendChild(document.createTextNode(title));
92
+ for (let i = 0, l = topics.length; i < l; ++i){
93
+ let topic = topics[i];
94
+ if (topic.members.length === 0) continue;
95
+ let section = topicsSection.appendChild(document.createElement("section"));
96
+ section.setAttribute("class", "topic");
97
+ let header = section.appendChild(document.createElement("header"));
98
+ let h1 = header.appendChild(document.createElement("h3"));
99
+ h1.appendChild(document.createTextNode(topic.name));
100
+ h1.setAttribute("outline-level", "2");
101
+ let div = section.appendChild(document.createElement('div'));
102
+ if (topic.summary){
103
+ let markdown = this.createMarkdownWithString(topic.summary);
104
+ let children = markdown.htmlElementsForDocument(document);
105
+ for (let j = 0, k = children.length; j < k; ++j){
106
+ div.appendChild(children[j]);
101
107
  }
102
- let list = div.appendChild(document.createElement("ul"));
103
- list.setAttribute("class", "members");
104
- for (let j = 0, k = topic.members.length; j < k; ++j){
105
- let member = topic.members[j];
106
- let item = list.appendChild(document.createElement("li"));
107
- item.setAttribute("class", member.kind);
108
- let a = document.createElement("a");
109
- let url = this.urlForComponent(member);
110
- a.setAttribute("href", url.encodedString);
111
- if (member.kind == 'framework' || member.kind == 'document'){
112
- item.appendChild(a);
113
- }else{
114
- let code = item.appendChild(document.createElement('code'));
115
- let prefix = null;
116
- if (member.kind == 'method' || member.kind == 'property'){
117
- if (member.isStatic){
118
- prefix = 'static ';
119
- }
120
- }
121
- if (prefix === null){
122
- prefix = this.prefixForMember(member);
123
- }
124
- if (prefix !== null){
125
- code.appendChild(document.createTextNode(prefix));
126
- // let span = a.appendChild(document.createElement('span'));
127
- // span.setAttribute("class", "prefix");
128
- // span.appendChild(document.createTextNode(prefix + ' '));
129
- }
130
- code.appendChild(a);
131
- let suffix = this.suffixForMember(member);
132
- if (suffix !== null){
133
- code.appendChild(document.createTextNode(suffix));
108
+ }
109
+ let list = div.appendChild(document.createElement("ul"));
110
+ list.setAttribute("class", "members");
111
+ for (let j = 0, k = topic.members.length; j < k; ++j){
112
+ let member = topic.members[j];
113
+ let item = list.appendChild(document.createElement("li"));
114
+ item.setAttribute("class", member.kind);
115
+ let a = document.createElement("a");
116
+ let url = this.urlForComponent(member);
117
+ a.setAttribute("href", url.encodedString);
118
+ if (url.isAbsolute){
119
+ a.setAttribute("target", "_blank");
120
+ a.setAttribute("rel", "noopener noreferrer");
121
+ }
122
+ if (member.kind == 'framework' || member.kind == 'document'){
123
+ item.appendChild(a);
124
+ }else{
125
+ let code = item.appendChild(document.createElement('code'));
126
+ let prefix = null;
127
+ if (member.kind == 'method' || member.kind == 'property'){
128
+ if (member.isStatic){
129
+ prefix = 'static ';
134
130
  }
135
131
  }
136
- a.appendChild(document.createTextNode(this.nameForMember(member)));
137
- if (member.summary){
138
- let markdown = this.createMarkdownWithString(member.summary);
139
- let children = markdown.htmlElementsForDocument(document);
140
- for (let j = 0, k = children.length; j < k; ++j){
141
- item.appendChild(children[j]);
142
- }
143
-
132
+ if (prefix === null){
133
+ prefix = this.prefixForMember(member);
134
+ }
135
+ if (prefix !== null){
136
+ code.appendChild(document.createTextNode(prefix));
137
+ // let span = a.appendChild(document.createElement('span'));
138
+ // span.setAttribute("class", "prefix");
139
+ // span.appendChild(document.createTextNode(prefix + ' '));
144
140
  }
141
+ code.appendChild(a);
142
+ let suffix = this.suffixForMember(member);
143
+ if (suffix !== null){
144
+ code.appendChild(document.createTextNode(suffix));
145
+ }
146
+ }
147
+ a.appendChild(document.createTextNode(this.nameForMember(member)));
148
+ if (member.summary){
149
+ let markdown = this.createMarkdownWithString(member.summary);
150
+ let children = markdown.htmlElementsForDocument(document);
151
+ for (let j = 0, k = children.length; j < k; ++j){
152
+ item.appendChild(children[j]);
153
+ }
154
+
145
155
  }
146
156
  }
147
157
  }
@@ -172,4 +182,4 @@
172
182
  return obj;
173
183
  }
174
184
 
175
- });
185
+ });
@@ -20,6 +20,7 @@
20
20
  // #import "DocIndex.js"
21
21
  // #import "DocFramework.js"
22
22
  // #import "DocClass.js"
23
+ // #import "DocExtension.js"
23
24
  // #import "DocProtocol.js"
24
25
  // #import "DocMethod.js"
25
26
  // #import "DocInit.js"
@@ -62,6 +63,7 @@ JSClass("Documentation", JSObject, {
62
63
  await this.copyStyles();
63
64
  let rootComponent = await this.loadSource(this.rootURL);
64
65
  rootComponent.outputURL = this.wwwURL.appendingPathComponent('index.html');
66
+ rootComponent.populateRelationships();
65
67
  await this.output([rootComponent]);
66
68
  await this.outputComponentsJSON(rootComponent);
67
69
  await this.outputManifestConfig(rootComponent);
@@ -210,12 +212,23 @@ JSClass("Documentation", JSObject, {
210
212
  },
211
213
 
212
214
  loadSource: async function(url){
213
- this.printer.setStatus("Reading %s...".sprintf(url.lastPathComponent));
214
- let exists = await this.fileManager.itemExistsAtURL(url);
215
- if (!exists){
215
+ if (url.scheme === "jskit"){
216
+ if (!this.hasAttemptedJSKitDownload){
217
+ await this.downloadJSKitDocumentation();
218
+ }
219
+ url = JSURL.initWithString(url.path + ".doc.yaml", this.jskitDocumenationLocalURL);
220
+ }
221
+ let contents = null;
222
+ if (url.scheme === JSFileManager.Scheme.file){
223
+ this.printer.setStatus("Reading %s...".sprintf(url.lastPathComponent));
224
+ let exists = await this.fileManager.itemExistsAtURL(url);
225
+ if (exists){
226
+ contents = await this.fileManager.contentsAtURL(url);
227
+ }
228
+ }
229
+ if (contents === null){
216
230
  return null;
217
231
  }
218
- let contents = await this.fileManager.contentsAtURL(url);
219
232
  let yaml = contents.stringByDecodingUTF8();
220
233
  let info = jsyaml.safeLoad(yaml);
221
234
  if (!info.name){
@@ -227,8 +240,64 @@ JSClass("Documentation", JSObject, {
227
240
  return component;
228
241
  },
229
242
 
243
+ jskitVersion: JSLazyInitProperty(() => JSBundle.mainBundle.info.JSBundleVersion),
244
+
245
+ jskitDocumenationRemoteURL: JSLazyInitProperty(function(){
246
+ let url = JSURL.initWithString("https://github.com/breakside/JSKit/archive/refs/tags/");
247
+ url.appendPathComponent("v" + this.jskitVersion + ".zip");
248
+ return url;
249
+ }),
250
+
251
+ jskitDocumenationLocalURL: JSLazyInitProperty(function(){
252
+ return JSURL.initWithString("JSKit", this.rootURL).appendingPathComponent(this.jskitVersion, true);
253
+ }),
254
+
255
+ hasAttemptedJSKitDownload: false,
256
+
257
+ downloadJSKitDocumentation: async function(){
258
+ if (!this.hasAttemptedJSKitDownload){
259
+ this.hasAttemptedJSKitDownload = true;
260
+ let exists = await this.fileManager.itemExistsAtURL(this.jskitDocumenationLocalURL);
261
+ if (!exists){
262
+ this.printer.setStatus("Downloading JSKit docs...");
263
+ let task = JSURLSession.shared.dataTaskWithURL(this.jskitDocumenationRemoteURL);
264
+ let response = await task.resume();
265
+ if (response.statusClass === JSURLResponse.StatusClass.success){
266
+ this.printer.setStatus("Unzipping JSKit docs...");
267
+ let zip = JSZip.initWithData(response.data);
268
+ if (zip !== null){
269
+ let docsPrefix = "JSKit-" + this.jskitVersion + "/Documentation/Code/";
270
+ let url;
271
+ let contents;
272
+ for (let filename of zip.filenames){
273
+ if (filename.startsWith(docsPrefix) && !filename.endsWith("/")){
274
+ contents = zip.dataForFilename(filename);
275
+ if (contents !== null){
276
+ filename = filename.substr(docsPrefix.length);
277
+ url = JSURL.initWithString(filename, this.jskitDocumenationLocalURL);
278
+ await this.fileManager.createFileAtURL(url, contents);
279
+ }else{
280
+ throw new Error("could not extract " + filename);
281
+ }
282
+ }
283
+ }
284
+ }else{
285
+ throw new Error("Could not read zip");
286
+ }
287
+ }else{
288
+ throw new Error("Response status is %d".sprintf(response.statusCode));
289
+ }
290
+ }
291
+ }
292
+ },
293
+
230
294
  createComponentFromInfo: async function(info, baseURL, defaultKind){
231
295
  if (typeof(info) === 'string'){
296
+ if (info.startsWith("jskit:")){
297
+ let url = JSURL.initWithString(info);
298
+ let component = await this.loadSource(url);
299
+ return component;
300
+ }
232
301
  let url = JSURL.initWithString(info + '.doc.yaml', baseURL);
233
302
  url.standardize();
234
303
  let component = await this.loadSource(url);
@@ -203,7 +203,7 @@ JSClass("HTMLProjectServer", JSObject, {
203
203
  let exists = await this.fileManager.itemExistsAtURL(fileURL);
204
204
  if (exists){
205
205
  let attributes = await this.fileManager.attributesOfItemAtURL(fileURL);
206
- headers["Content-Type"] = this.contentTypesByExtension[url.fileExtension] || "application/octet-stream";
206
+ headers["Content-Type"] = this.contentTypesByExtension[fileURL.fileExtension] || "application/octet-stream";
207
207
  headers["Content-Length"] = attributes.size;
208
208
  filePath = this.fileManager.pathForURL(fileURL);
209
209
  statusCode = 200;
package/Node/Markdown.js CHANGED
@@ -265,7 +265,7 @@ JSClass("Markdown", JSObject, {
265
265
  let line = lines[i];
266
266
  var trimmed = line.trim();
267
267
  if (inCodeBlock){
268
- if (line.match(/^````+$/)){
268
+ if (line.match(/^```+$/)){
269
269
  inCodeBlock = false;
270
270
  let code = document.createElement(options.codeBlockTagName);
271
271
  code.setAttribute("class", options.codeBlockClassName);
@@ -291,7 +291,7 @@ JSClass("Markdown", JSObject, {
291
291
  addHeader(options.secondLevelHeaderTagName);
292
292
  }else if (line.match(/^#{1,2}\s/)){
293
293
  addATXHeader(line);
294
- }else if (line.match(/^````+$/)){
294
+ }else if (line.match(/^```+$/)){
295
295
  finishBlock();
296
296
  inOrderedList = false;
297
297
  inUnorderedList = false;
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.jskit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "node",
5
5
  "JSBundleIdentifier": "io.breakside.jskit",
6
- "JSBundleVersion": "2026.10.0",
6
+ "JSBundleVersion": "2026.11.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": "4f9f54d7fd9b56bd8c893ac8689a8efee1958ee5"
13
+ "GitRevision": "812100aa4c3e5b1ec1d0d432be903bba4db01b0e"
14
14
  },
15
15
  "Resources": [
16
16
  {
@@ -18,7 +18,7 @@ JSBundle.bundles['io.breakside.jskit'] = {
18
18
  "ext": ".css",
19
19
  "byte_size": 10906,
20
20
  "mimetype": "text/css",
21
- "hash": "8e97b7b1e6c054c8490b19d2c4d64d14ad96cd3f",
21
+ "hash": "1649bda738e2e7e746e78641145cfc85380ea46c",
22
22
  "nodeBundlePath": "Resources/doc-default.css"
23
23
  },
24
24
  {
package/Node/jskit CHANGED
@@ -201,6 +201,7 @@ require("./Docs/DocTopicBasedComponent.js");
201
201
  require("./Docs/DocIndex.js");
202
202
  require("./Docs/DocFramework.js");
203
203
  require("./Docs/DocClass.js");
204
+ require("./Docs/DocExtension.js");
204
205
  require("./Docs/DocProtocol.js");
205
206
  require("./Docs/DocFunction.js");
206
207
  require("./Docs/DocMethod.js");
@@ -270,7 +270,7 @@ article.doc > section.topics > section.topic > header{
270
270
  margin-right: 20px;
271
271
  }
272
272
 
273
- article.doc > section.topics > section.topic > header > h1{
273
+ article.doc > section.topics > section.topic > header > h3{
274
274
  margin: 0;
275
275
  }
276
276
 
@@ -425,7 +425,7 @@ article.doc > footer > p {
425
425
  article.doc > section.topics > section.topic{
426
426
  display: block;
427
427
  }
428
- article.doc > section.topics > section.topic > header > h1{
428
+ article.doc > section.topics > section.topic > header > h3{
429
429
  margin-bottom: 10px;
430
430
  }
431
431
  }
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKit
3
- JSBundleVersion: 2026.10.0
3
+ JSBundleVersion: 2026.11.0
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: 2026.10.0
3
+ JSBundleVersion: 2026.11.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.AuthKit
3
- JSBundleVersion: 2026.10.0
3
+ JSBundleVersion: 2026.11.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.CSSOM
3
- JSBundleVersion: 2026.10.0
3
+ JSBundleVersion: 2026.11.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.ChartKit
3
- JSBundleVersion: 2026.10.0
3
+ JSBundleVersion: 2026.11.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2021 Breakside Inc.
6
6
  # JSBundleEnvironments: