chemicaljs 1.7.1 → 1.7.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.
package/README.md CHANGED
@@ -49,7 +49,7 @@ const [app, listen] = new ChemicalServer({
49
49
  3. Use `app` which is an express app. You may need to import express for certain APIs.
50
50
 
51
51
  ```js
52
- chemical.get("/", function(req, res){
52
+ app.get("/", function(req, res){
53
53
  res.send("Hello World");
54
54
  });
55
55
  ```
@@ -170,6 +170,13 @@ await chemical.encode("https://example.com", {
170
170
  })
171
171
  ```
172
172
 
173
+ 3. To decode a URL use `chemical.decode`
174
+
175
+ ```js
176
+ const encodedURL = await chemical.encode("https://example.com")
177
+ const decodedURL = await chemical.decode(encodedURL)
178
+ ```
179
+
173
180
  4. Set `autoHttps` to make `example.com` > `https://example.com`
174
181
 
175
182
  ```js
@@ -287,9 +294,11 @@ Setup a proxy site with easy HTML components.
287
294
  An anchor link but it automatically encodes the URL.
288
295
 
289
296
  ```html
290
- <a href="https://example.com" is="chemical-link">Link</a>
297
+ <a data-href="https://example.com" is="chemical-link">Link</a>
291
298
  ```
292
299
 
300
+ You can also add `data-service="uv"`, `data-autoHttps`, and `data-search-engine="https://www.google.com/search?q=%s"`
301
+
293
302
  You can style the link as chemical is loading.
294
303
 
295
304
  ```css
@@ -303,19 +312,21 @@ a[data-chemical-loading="true"] {
303
312
  Opens in the current tab when the enter key is pressed.
304
313
 
305
314
  ```html
306
- <input target="_self" placeholder="Enter URL" is="chemical-input">
315
+ <input data-target="_self" placeholder="Enter URL" is="chemical-input">
307
316
  ```
308
317
 
318
+ You can also add `data-service="uv"`, `data-autoHttps`, and `data-search-engine="https://www.google.com/search?q=%s"`
319
+
309
320
  Opens in current tab when the enter key is pressed.
310
321
 
311
322
  ```html
312
- <input target="_blank" placeholder="Enter URL" is="chemical-input">
323
+ <input data-target="_blank" placeholder="Enter URL" is="chemical-input">
313
324
  ```
314
325
 
315
- Custom action when the enter key is pressed. Change `action` to your function name. The first parameter of the action will be the encoded URL.
326
+ Custom action when the enter key is pressed. Change `data-action` to your function name. The first parameter of the action will be the encoded URL.
316
327
 
317
328
  ```html
318
- <input action="logURL" placeholder="Enter URL" is="chemical-input">
329
+ <input data-action="logURL" placeholder="Enter URL" is="chemical-input">
319
330
  <script>
320
331
  function logURL(url) {
321
332
  console.log(url)
@@ -328,8 +339,8 @@ Custom action when the enter key is pressed. Change `action` to your function na
328
339
  Opens when the enter key is pressed or button is clicked. Set the `for` attribute to the `id` of the button.
329
340
 
330
341
  ```html
331
- <input id="my-input" target="_blank" placeholder="Enter URL" is="chemical-input">
332
- <button for="my-input" is="chemical-button">Go!</button>
342
+ <input id="my-input" data-target="_blank" placeholder="Enter URL" is="chemical-input">
343
+ <button data-for="my-input" is="chemical-button">Go!</button>
333
344
  ```
334
345
 
335
346
  ### With iframe
@@ -337,7 +348,7 @@ Opens when the enter key is pressed or button is clicked. Set the `for` attribut
337
348
  A hidden iframe that is shown when the enter key is pressed. Set the `frame` attribute to the `id` of the iframe.
338
349
 
339
350
  ```html
340
- <input frame="my-iframe" placeholder="Enter URL" is="chemical-input">
351
+ <input data-frame="my-iframe" placeholder="Enter URL" is="chemical-input">
341
352
  <iframe id="my-iframe" is="chemical-iframe"></iframe>
342
353
  ```
343
354
 
@@ -349,14 +360,14 @@ Set the `controls` attribute to the `id` of the controls.
349
360
  Set the second parameter of `chemicalAction` to the `id` of the iframe.
350
361
 
351
362
  ```html
352
- <input frame="my-iframe-2" placeholder="Enter URL" is="chemical-input">
363
+ <input data-frame="my-iframe-2" placeholder="Enter URL" is="chemical-input">
353
364
  <section id="my-controls-2" is="chemical-controls">
354
365
  <button onclick="chemicalAction('back', 'my-iframe-2')">←</button>
355
366
  <button onclick="chemicalAction('forward', 'my-iframe-2')">→</button>
356
367
  <button onclick="chemicalAction('reload', 'my-iframe-2')">⟳</button>
357
368
  <button onclick="chemicalAction('close', 'my-iframe-2')">🗙</button>
358
369
  </section>
359
- <iframe controls="my-controls-2" id="my-iframe-2" is="chemical-iframe"></iframe>
370
+ <iframe data-controls="my-controls-2" id="my-iframe-2" is="chemical-iframe"></iframe>
360
371
  ```
361
372
 
362
373
  ## License
@@ -4,16 +4,23 @@ class ChemicalInput extends HTMLInputElement {
4
4
  }
5
5
  connectedCallback() {
6
6
  this.addEventListener("keydown", async function (e) {
7
- if (e.key == "Enter" && window.chemicalLoaded && e.target.value) {
8
- let encodedURL = await window.chemicalEncode(e.target.value)
9
- let action = this.getAttribute("action")
10
- let target = this.getAttribute("target")
11
- let frame = this.getAttribute("frame")
7
+ if (e.key == "Enter" && window.chemical.loaded && e.target.value) {
8
+ let service = this.dataset.service || "uv";
9
+ let autoHttps = this.dataset.autoHttps !== undefined ? true : false;
10
+ let searchEngine = this.dataset.searchEngine;
11
+ let action = this.dataset.action
12
+ let target = this.dataset.target
13
+ let frame = this.dataset.frame
14
+ let encodedURL = await chemical.encode(e.target.value, {
15
+ service,
16
+ autoHttps,
17
+ searchEngine
18
+ })
12
19
 
13
20
  if (frame) {
14
- let forFrame = document.getElementById(this.getAttribute("frame"))
15
- forFrame.src = encodedURL
16
- forFrame.setAttribute("open", "true")
21
+ let forFrame = document.getElementById(frame)
22
+ forFrame.src = encodedURL;
23
+ forFrame.setAttribute("data-open", "true")
17
24
  }
18
25
 
19
26
  if (action) {
@@ -38,7 +45,7 @@ class ChemicalButton extends HTMLButtonElement {
38
45
  }
39
46
  connectedCallback() {
40
47
  this.addEventListener("click", function (e) {
41
- let forInput = document.getElementById(this.getAttribute("for"))
48
+ let forInput = document.getElementById(this.dataset.for)
42
49
 
43
50
  if (forInput) {
44
51
  forInput.dispatchEvent(new KeyboardEvent("keydown", {
@@ -50,40 +57,40 @@ class ChemicalButton extends HTMLButtonElement {
50
57
  }
51
58
 
52
59
  class ChemicalIFrame extends HTMLIFrameElement {
53
- static observedAttributes = ["open"];
60
+ static observedAttributes = ["data-open"];
54
61
  constructor() {
55
62
  super();
56
63
  }
57
64
  connectedCallback() {
58
- let open = this.getAttribute("open")
65
+ let open = this.dataset.open
59
66
  this.style.display = open == "true" ? "" : "none"
60
67
  }
61
68
  attributeChangedCallback(name, oldValue, newValue) {
62
- if (name == "open") {
63
- let open = this.getAttribute("open")
69
+ if (name == "data-open") {
70
+ let open = this.dataset.open
64
71
  this.style.display = open == "true" ? "" : "none"
65
72
 
66
- let controls = document.getElementById(this.getAttribute("controls"))
73
+ let controls = document.getElementById(this.dataset.controls)
67
74
 
68
75
  if (controls) {
69
- controls.setAttribute("open", open)
76
+ controls.dataset.open = open
70
77
  }
71
78
  }
72
79
  }
73
80
  }
74
81
 
75
82
  class ChemicalControls extends HTMLElement {
76
- static observedAttributes = ["open"];
83
+ static observedAttributes = ["data-open"];
77
84
  constructor() {
78
85
  super();
79
86
  }
80
87
  connectedCallback() {
81
- let open = this.getAttribute("open")
88
+ let open = this.dataset.open
82
89
  this.style.display = open == "true" ? "" : "none"
83
90
  }
84
91
  attributeChangedCallback(name, oldValue, newValue) {
85
- if (name == "open") {
86
- let open = this.getAttribute("open")
92
+ if (name == "data-open") {
93
+ let open = this.dataset.open
87
94
  this.style.display = open == "true" ? "" : "none"
88
95
  }
89
96
  }
@@ -94,16 +101,26 @@ class ChemicalLink extends HTMLAnchorElement {
94
101
  super();
95
102
  }
96
103
  async connectedCallback() {
97
- let href = this.getAttribute("href");
98
- this.removeAttribute("href");
104
+ let href = this.dataset.href;
105
+ let service = this.dataset.service || "uv";
106
+ let autoHttps = this.dataset.autoHttps !== undefined ? true : false;
107
+ let searchEngine = this.dataset.searchEngine;
99
108
  this.dataset.chemicalLoading = "true";
100
109
 
101
- if (window.chemicalLoaded) {
102
- this.setAttribute("href", await chemicalEncode(href))
110
+ if (window.chemical.loaded) {
111
+ this.setAttribute("href", await chemical.encode(href, {
112
+ service,
113
+ autoHttps,
114
+ searchEngine
115
+ }))
103
116
  this.dataset.chemicalLoading = "false";
104
117
  } else {
105
118
  window.addEventListener("chemicalLoaded", async () => {
106
- this.setAttribute("href", await chemicalEncode(href))
119
+ this.setAttribute("href", await chemical.encode(href, {
120
+ service,
121
+ autoHttps,
122
+ searchEngine
123
+ }))
107
124
  this.dataset.chemicalLoading = "false";
108
125
  })
109
126
  }
@@ -131,7 +148,7 @@ function chemicalAction(action, frameID) {
131
148
  frame.contentWindow.location.reload()
132
149
  break;
133
150
  case "close":
134
- frame.setAttribute("open", "false")
151
+ frame.dataset.open = "false"
135
152
  frame.src = ""
136
153
  }
137
154
  }
@@ -4,178 +4,192 @@ window.chemical = {
4
4
  wisp: document.currentScript.dataset.wisp || (location.protocol === "https:" ? "wss" : "ws") + "://" + location.host + "/wisp/"
5
5
  }
6
6
 
7
- function rammerheadEncode(baseUrl) {
8
- const mod = (n, m) => ((n % m) + m) % m
7
+ function rammerheadEncode(baseUrl, decode = false) {
8
+ const mod = (n, m) => ((n % m) + m) % m;
9
9
  const baseDictionary =
10
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~-"
11
- const shuffledIndicator = "_rhs"
10
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~-";
11
+ const shuffledIndicator = "_rhs";
12
+
12
13
  const generateDictionary = function () {
13
- let str = ""
14
- const split = baseDictionary.split("")
14
+ let str = "";
15
+ const split = baseDictionary.split("");
15
16
  while (split.length > 0) {
16
- str += split.splice(Math.floor(Math.random() * split.length), 1)[0]
17
+ str += split.splice(Math.floor(Math.random() * split.length), 1)[0];
17
18
  }
18
- return str
19
- }
19
+ return str;
20
+ };
21
+
20
22
  class StrShuffler {
21
23
  constructor(dictionary = generateDictionary()) {
22
- this.dictionary = dictionary
24
+ this.dictionary = dictionary;
23
25
  }
26
+
24
27
  shuffle(str) {
25
28
  if (str.startsWith(shuffledIndicator)) {
26
- return str
29
+ return str;
27
30
  }
28
- let shuffledStr = ""
31
+ let shuffledStr = "";
29
32
  for (let i = 0; i < str.length; i++) {
30
- const char = str.charAt(i)
31
- const idx = baseDictionary.indexOf(char)
33
+ const char = str.charAt(i);
34
+ const idx = baseDictionary.indexOf(char);
32
35
  if (char === "%" && str.length - i >= 3) {
33
- shuffledStr += char
34
- shuffledStr += str.charAt(++i)
35
- shuffledStr += str.charAt(++i)
36
+ shuffledStr += char;
37
+ shuffledStr += str.charAt(++i);
38
+ shuffledStr += str.charAt(++i);
36
39
  } else if (idx === -1) {
37
- shuffledStr += char
40
+ shuffledStr += char;
38
41
  } else {
39
42
  shuffledStr += this.dictionary.charAt(
40
43
  mod(idx + i, baseDictionary.length)
41
- )
44
+ );
42
45
  }
43
46
  }
44
- return shuffledIndicator + shuffledStr
47
+ return shuffledIndicator + shuffledStr;
45
48
  }
49
+
46
50
  unshuffle(str) {
47
51
  if (!str.startsWith(shuffledIndicator)) {
48
- return str
52
+ return str;
49
53
  }
50
54
 
51
- str = str.slice(shuffledIndicator.length)
55
+ str = str.slice(shuffledIndicator.length);
52
56
 
53
- let unshuffledStr = ""
57
+ let unshuffledStr = "";
54
58
  for (let i = 0; i < str.length; i++) {
55
- const char = str.charAt(i)
56
- const idx = this.dictionary.indexOf(char)
59
+ const char = str.charAt(i);
60
+ const idx = this.dictionary.indexOf(char);
57
61
  if (char === "%" && str.length - i >= 3) {
58
- unshuffledStr += char
59
- unshuffledStr += str.charAt(++i)
60
- unshuffledStr += str.charAt(++i)
62
+ unshuffledStr += char;
63
+ unshuffledStr += str.charAt(++i);
64
+ unshuffledStr += str.charAt(++i);
61
65
  } else if (idx === -1) {
62
- unshuffledStr += char
66
+ unshuffledStr += char;
63
67
  } else {
64
68
  unshuffledStr += baseDictionary.charAt(
65
69
  mod(idx - i, baseDictionary.length)
66
- )
70
+ );
67
71
  }
68
72
  }
69
- return unshuffledStr
73
+ return unshuffledStr;
70
74
  }
71
75
  }
76
+
72
77
  function get(url, callback, shush = false) {
73
- var request = new XMLHttpRequest()
74
- request.open("GET", url, true)
75
- request.send()
78
+ var request = new XMLHttpRequest();
79
+ request.open("GET", url, true);
80
+ request.send();
76
81
 
77
82
  request.onerror = function () {
78
- if (!shush) console.log("Cannot communicate with the server")
79
- }
83
+ if (!shush) console.log("Cannot communicate with the server");
84
+ };
80
85
  request.onload = function () {
81
86
  if (request.status === 200) {
82
- callback(request.responseText)
87
+ callback(request.responseText);
83
88
  } else {
84
89
  if (!shush)
85
90
  console.log(
86
91
  'unexpected server response to not match "200". Server says "' +
87
92
  request.responseText +
88
93
  '"'
89
- )
94
+ );
90
95
  }
91
- }
96
+ };
92
97
  }
98
+
93
99
  var api = {
94
100
  newsession(callback) {
95
- get("/newsession", callback)
101
+ get("/newsession", callback);
96
102
  },
97
103
  sessionexists(id, callback) {
98
104
  get("/sessionexists?id=" + encodeURIComponent(id), function (res) {
99
- if (res === "exists") return callback(true)
100
- if (res === "not found") return callback(false)
101
- console.log("unexpected response from server. received" + res)
102
- })
105
+ if (res === "exists") return callback(true);
106
+ if (res === "not found") return callback(false);
107
+ console.log("unexpected response from server. received" + res);
108
+ });
103
109
  },
104
110
  shuffleDict(id, callback) {
105
- console.log("Shuffling", id)
111
+ console.log("Shuffling", id);
106
112
  get("/api/shuffleDict?id=" + encodeURIComponent(id), function (res) {
107
- callback(JSON.parse(res))
108
- })
113
+ callback(JSON.parse(res));
114
+ });
109
115
  }
110
- }
111
- var localStorageKey = "rammerhead_sessionids"
112
- var localStorageKeyDefault = "rammerhead_default_sessionid"
116
+ };
117
+
118
+ var localStorageKey = "rammerhead_sessionids";
119
+ var localStorageKeyDefault = "rammerhead_default_sessionid";
113
120
  var sessionIdsStore = {
114
121
  get() {
115
- var rawData = localStorage.getItem(localStorageKey)
116
- if (!rawData) return []
122
+ var rawData = localStorage.getItem(localStorageKey);
123
+ if (!rawData) return [];
117
124
  try {
118
- var data = JSON.parse(rawData)
119
- if (!Array.isArray(data)) throw "getout"
120
- return data
125
+ var data = JSON.parse(rawData);
126
+ if (!Array.isArray(data)) throw "getout";
127
+ return data;
121
128
  } catch (e) {
122
- return []
129
+ return [];
123
130
  }
124
131
  },
125
132
  set(data) {
126
- if (!data || !Array.isArray(data)) throw new TypeError("must be array")
127
- localStorage.setItem(localStorageKey, JSON.stringify(data))
133
+ if (!data || !Array.isArray(data)) throw new TypeError("must be array");
134
+ localStorage.setItem(localStorageKey, JSON.stringify(data));
128
135
  },
129
136
  getDefault() {
130
- var sessionId = localStorage.getItem(localStorageKeyDefault)
137
+ var sessionId = localStorage.getItem(localStorageKeyDefault);
131
138
  if (sessionId) {
132
- var data = sessionIdsStore.get()
139
+ var data = sessionIdsStore.get();
133
140
  data.filter(function (e) {
134
- return e.id === sessionId
135
- })
136
- if (data.length) return data[0]
141
+ return e.id === sessionId;
142
+ });
143
+ if (data.length) return data[0];
137
144
  }
138
- return null
145
+ return null;
139
146
  },
140
147
  setDefault(id) {
141
- localStorage.setItem(localStorageKeyDefault, id)
148
+ localStorage.setItem(localStorageKeyDefault, id);
142
149
  }
143
- }
150
+ };
151
+
144
152
  function addSession(id) {
145
- var data = sessionIdsStore.get()
146
- data.unshift({ id: id, createdOn: new Date().toLocaleString() })
147
- sessionIdsStore.set(data)
153
+ var data = sessionIdsStore.get();
154
+ data.unshift({ id: id, createdOn: new Date().toLocaleString() });
155
+ sessionIdsStore.set(data);
148
156
  }
157
+
149
158
  function getSessionId() {
150
159
  return new Promise(resolve => {
151
- var id = localStorage.getItem("session-string")
160
+ var id = localStorage.getItem("session-string");
152
161
  api.sessionexists(id, function (value) {
153
162
  if (!value) {
154
- console.log("Session validation failed")
163
+ console.log("Session validation failed");
155
164
  api.newsession(function (id) {
156
- addSession(id)
157
- localStorage.setItem("session-string", id)
158
- console.log(id)
159
- console.log("^ new id")
160
- resolve(id)
161
- })
165
+ addSession(id);
166
+ localStorage.setItem("session-string", id);
167
+ console.log(id);
168
+ console.log("^ new id");
169
+ resolve(id);
170
+ });
162
171
  } else {
163
- resolve(id)
172
+ resolve(id);
164
173
  }
165
- })
166
- })
174
+ });
175
+ });
167
176
  }
168
- var ProxyHref
177
+
178
+ var ProxyHref;
169
179
 
170
180
  return getSessionId().then(id => {
171
181
  return new Promise(resolve => {
172
182
  api.shuffleDict(id, function (shuffleDict) {
173
- var shuffler = new StrShuffler(shuffleDict)
174
- ProxyHref = "/" + id + "/" + shuffler.shuffle(baseUrl)
175
- resolve(ProxyHref)
176
- })
177
- })
178
- })
183
+ var shuffler = new StrShuffler(shuffleDict);
184
+ if (decode) {
185
+ ProxyHref = shuffler.unshuffle(baseUrl.split(id + "/")[1]);
186
+ } else {
187
+ ProxyHref = "/" + id + "/" + shuffler.shuffle(baseUrl);
188
+ }
189
+ resolve(ProxyHref);
190
+ });
191
+ });
192
+ });
179
193
  }
180
194
 
181
195
  async function encodeService(url, service) {
@@ -214,6 +228,14 @@ window.chemical.encode = async function (url, config) {
214
228
  }
215
229
  }
216
230
 
231
+ if (config.service == undefined) {
232
+ config.service = defaultService;
233
+ }
234
+
235
+ if (config.autoHttps == undefined) {
236
+ config.autoHttps = false;
237
+ }
238
+
217
239
  if (url.match(/^https?:\/\//)) {
218
240
  return await encodeService(url, config.service);
219
241
  } else if (config.autoHttps == true && (url.includes(".") && !url.includes(" "))) {
@@ -225,6 +247,32 @@ window.chemical.encode = async function (url, config) {
225
247
  }
226
248
  }
227
249
 
250
+ window.chemical.decode = async function (url, config) {
251
+ if (!config || typeof config !== "object" || Array.isArray(config)) {
252
+ config = {
253
+ service: defaultService,
254
+ }
255
+ }
256
+
257
+ switch (config.service) {
258
+ case "uv":
259
+ if (uvEnabled) {
260
+ return __uv$config.decodeUrl(url.split(__uv$config.prefix)[1]);
261
+ }
262
+ break;
263
+ case "rammerhead":
264
+ if (rammerheadEnabled) {
265
+ return await rammerheadEncode(url.split(window.location.origin)[1], true);
266
+ }
267
+ break;
268
+ case "scramjet":
269
+ if (scramjetEnabled) {
270
+ return __scramjet$config.codec.decode(url.split(__scramjet$config.prefix)[1]);
271
+ }
272
+ break;
273
+ }
274
+ }
275
+
228
276
  function getTransport(transport) {
229
277
  switch (transport) {
230
278
  default:
@@ -291,20 +339,18 @@ function setupFetch() {
291
339
  }
292
340
  }
293
341
 
294
- (async () => {
295
- await loadScript("/baremux/index.js");
296
- if (uvEnabled) {
297
- await loadScript("/uv/uv.bundle.js");
298
- await loadScript("/uv/uv.config.js");
299
- }
300
- if (scramjetEnabled) {
301
- await loadScript("/scramjet/scramjet.codecs.js");
302
- await loadScript("/scramjet/scramjet.config.js");
303
- }
304
- window.chemical.connection = new window.BareMux.BareMuxConnection("/baremux/worker.js");
305
- await window.chemical.setTransport();
306
- setupFetch();
307
- await registerSW();
308
- window.chemical.loaded = true;
309
- window.dispatchEvent(new Event("chemicalLoaded"));
310
- })();
342
+ await loadScript("/baremux/index.js");
343
+ if (uvEnabled) {
344
+ await loadScript("/uv/uv.bundle.js");
345
+ await loadScript("/uv/uv.config.js");
346
+ }
347
+ if (scramjetEnabled) {
348
+ await loadScript("/scramjet/scramjet.codecs.js");
349
+ await loadScript("/scramjet/scramjet.config.js");
350
+ }
351
+ window.chemical.connection = new window.BareMux.BareMuxConnection("/baremux/worker.js");
352
+ await window.chemical.setTransport();
353
+ setupFetch();
354
+ await registerSW();
355
+ window.chemical.loaded = true;
356
+ window.dispatchEvent(new Event("chemicalLoaded"));