functionalscript 0.0.341 → 0.0.344

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.
@@ -1,8 +1,10 @@
1
1
  # Common.js
2
2
 
3
- ```ts
4
- // package/index.js
3
+ ## Package
4
+
5
+ [package/index.js](package/index.js)
5
6
 
7
+ ```ts
6
8
  // A dictionary of packages.
7
9
  //
8
10
  // A package contains a dictionary of dependencies and a dictionary of files.
@@ -25,9 +27,13 @@ type Package = {
25
27
  // returns source of the file.
26
28
  readonly file: (localFileId: string) => string | undefined
27
29
  }
30
+ ```
28
31
 
29
- // module/index.js
32
+ ## Module
30
33
 
34
+ [module/index.js](module/index.js)
35
+
36
+ ```ts
31
37
  // A module map is a dictionary of modules.
32
38
  //
33
39
  // A module is a compiled and initialized source file.
@@ -62,9 +68,13 @@ type ModuleId = {
62
68
  }
63
69
 
64
70
  const moduleIdToString: (moduleId: ModuleId) => string;
71
+ ```
65
72
 
66
- // build/index.js
73
+ ## Build
67
74
 
75
+ [build/index.js](build/index.js)
76
+
77
+ ```ts
68
78
  type BuildConfig<M> = {
69
79
  readonly packageGet: PackageGet
70
80
  readonly moduleMapInterface: ModuleMapInterface<M>
@@ -81,8 +91,4 @@ type BuildState<M> = {
81
91
  }
82
92
 
83
93
  const getOrBuild: <M>(buildConfig: BuildConfig<M>) => readonly[ModuleState, M];
84
-
85
- //
86
-
87
-
88
94
  ```
@@ -36,7 +36,13 @@ const notFound = moduleMap => [['error', ['file not found']], moduleMap]
36
36
  const getOrBuild = compile => packageGet => moduleMapInterface => {
37
37
  /** @typedef {typeof moduleMapInterface extends module_.MapInterface<infer M> ? M : never} M */
38
38
 
39
- /** @type {(buildSet: stringSet.StringSet) => (moduleId: module_.Id) => (source: string) => (moduleMap: M) => Result<M>} */
39
+ /**
40
+ * @type {(buildSet: stringSet.StringSet) =>
41
+ * (moduleId: module_.Id) =>
42
+ * (source: string) =>
43
+ * (moduleMap: M) =>
44
+ * Result<M>}
45
+ */
40
46
  const build = buildSet => moduleId => {
41
47
  const moduleIdStr = module_.idToString(moduleId)
42
48
  const buildSet1 = stringSet.set(moduleIdStr)(buildSet)
@@ -25,7 +25,10 @@ const isPackageJson = j => {
25
25
  * }} Package
26
26
  */
27
27
 
28
- /** @typedef {(packageId: string) => Package | undefined} Get */
28
+ /**
29
+ * @note Current package has an empty string '' as a packageId.
30
+ * @typedef {(packageId: string) => Package | undefined} Get
31
+ */
29
32
 
30
33
  module.exports = {
31
34
  /** @readonly */
package/html/index.js ADDED
@@ -0,0 +1,121 @@
1
+ const list = require('../types/list/index.js')
2
+ const object = require('../types/object/index.js')
3
+ const operator = require('../types/function/operator/index.js')
4
+ const { compose } = require('../types/function/index.js')
5
+
6
+ /**
7
+ * @typedef {|
8
+ * 'a' |
9
+ * 'b' |
10
+ * 'body' |
11
+ * 'canvas' |
12
+ * 'div' |
13
+ * 'h1' |
14
+ * 'h2' |
15
+ * 'h3' |
16
+ * 'h4' |
17
+ * 'h5' |
18
+ * 'h6' |
19
+ * 'head' |
20
+ * 'html' |
21
+ * 'label' |
22
+ * 'p' |
23
+ * 'pre' |
24
+ * 'script' |
25
+ * 'table' |
26
+ * 'td' |
27
+ * 'th' |
28
+ * 'title' |
29
+ * 'tr'
30
+ * } Tag
31
+ */
32
+
33
+ /**
34
+ * @typedef {|
35
+ * 'img' |
36
+ * 'input' |
37
+ * 'link' |
38
+ * 'meta'
39
+ * } ShortTag
40
+ */
41
+
42
+ /** @typedef {readonly[ShortTag]} ShortElement1*/
43
+
44
+ /** @typedef {readonly[ShortTag, Attributes]} ShortElement2 */
45
+
46
+ /** @typedef {readonly[Tag, readonly Node[]]} Element2 */
47
+
48
+ /** @typedef {readonly[Tag, Attributes, Nodes]} Element3*/
49
+
50
+ /** @typedef {ShortElement1 | ShortElement2 | Element2 | Element3} Element */
51
+
52
+ /**
53
+ * @typedef {{
54
+ * readonly[k in string]: string
55
+ * }} Attributes
56
+ */
57
+
58
+ /** @typedef {list.List<Node>} Nodes */
59
+
60
+ /** @typedef {Element | string} Node */
61
+
62
+ /**
63
+ * https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-in-html
64
+ *
65
+ * @type {(code: number) => string}
66
+ */
67
+ const escapeCharCode = code => {
68
+ switch (code) {
69
+ case 0x22: return '&quot;'
70
+ case 0x26: return '&amp;'
71
+ case 0x3C: return '&lt;'
72
+ case 0x3E: return '&gt;'
73
+ default: return String.fromCharCode(code)
74
+ }
75
+ }
76
+
77
+ const escape = compose(list.toCharCodes)(list.map(escapeCharCode))
78
+
79
+ /** @type {(n: Node) => list.List<string>} */
80
+ const node = n => typeof n === 'string' ? escape(n) : element(n)
81
+
82
+ const nodes = list.flatMap(node)
83
+
84
+ /** @type {(a: object.Entry<string>) => list.List<string>} */
85
+ const attribute = ([name, value]) => list.flat([[' ', name, '="'], escape(value), ['"']])
86
+
87
+ /** @type {(a: Attributes) => list.List<string>} */
88
+ const attributes = compose(Object.entries)(list.flatMap(attribute))
89
+
90
+ /** @type {(element: Element) => list.List<string>} */
91
+ const element = e => {
92
+ const f = () => {
93
+ switch (e.length) {
94
+ case 1: { return [[`<`, e[0], '/>']] }
95
+ case 2: {
96
+ const [tag, a] = e
97
+ return a instanceof Array ?
98
+ [['<', tag, '>'], nodes(a), ['</', tag, '>']] :
99
+ [[`<`, tag], attributes(a), [`/>`]]
100
+ }
101
+ default: {
102
+ const [tag, a, ns] = e
103
+ return [['<', tag], attributes(a), ['>'], nodes(ns), ['</', tag, '>']]
104
+ }
105
+ }
106
+ }
107
+ return list.flat(f())
108
+ }
109
+
110
+ const html = compose(element)(list.concat(['<!DOCTYPE html>']))
111
+
112
+ const htmlToString = compose(html)(list.fold(operator.concat)(''))
113
+
114
+ module.exports = {
115
+ /** @readonly */
116
+ element,
117
+ /** @readonly */
118
+ html,
119
+ /** @readonly */
120
+ htmlToString,
121
+ }
package/html/test.js ADDED
@@ -0,0 +1,13 @@
1
+ const _ = require('./index.js')
2
+
3
+ {
4
+ const r = _.htmlToString(['html', []])
5
+ if (r !== '<!DOCTYPE html><html></html>') { throw r }
6
+ }
7
+
8
+ {
9
+ /** @type {_.Element} */
10
+ const x = ['div', {}, ['<div>&amp;</div>', ['a', { href: 'hello"' }, []]]]
11
+ const s = _.htmlToString(x)
12
+ if (s !== '<!DOCTYPE html><div>&lt;div&gt;&amp;amp;&lt;/div&gt;<a href="hello&quot;"></a></div>') { throw s }
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.341",
3
+ "version": "0.0.344",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "homepage": "https://github.com/functionalscript/functionalscript#readme",
30
30
  "devDependencies": {
31
- "@types/node": "^17.0.35",
32
- "typescript": "^4.7.2"
31
+ "@types/node": "^17.0.42",
32
+ "typescript": "^4.7.3"
33
33
  }
34
34
  }
package/test.js CHANGED
@@ -1,4 +1,4 @@
1
- const i = require('./index.js')
1
+ // const i = require('./index.js')
2
2
 
3
3
  require('./types/list/test.js')
4
4
  require('./types/array/test.js')
@@ -15,6 +15,7 @@ require('./types/function/compare/test.js')
15
15
  require('./types/stringSet/test.js')
16
16
  require('./commonjs/build/test.js')
17
17
  require('./types/range/test.js')
18
+ require('./html/test.js')
18
19
 
19
20
  /** @type {() => never} */
20
21
  const assert = () => { throw 'assert' }
@@ -22,53 +23,6 @@ const assert = () => { throw 'assert' }
22
23
  /** @type {(_: boolean) => void} */
23
24
  const assert_if = c => { if (c) { throw 'assert_if' } }
24
25
 
25
- {
26
- i.parseModuleUrl('')(
27
- assert,
28
- e => assert_if(e.id !== 'expected' || e.params[0] !== ':'))
29
- }
30
-
31
- {
32
- i.parseModuleUrl(':')(
33
- assert,
34
- e => assert_if(e.id !== 'unknownProtocol'))
35
- }
36
-
37
- {
38
- i.parseModuleUrl('github:r')(
39
- assert,
40
- e => assert_if(e.id !== 'expected'))
41
- }
42
-
43
- {
44
- i.parseModuleUrl('github:functionalscript/node-example')(
45
- v => assert_if(
46
- v.repo.org !== 'functionalscript' ||
47
- v.repo.name !== 'node-example' ||
48
- 'branch' in v),
49
- assert)
50
- }
51
-
52
- {
53
- i.parseModuleUrl('github:functionalscript/node-example#main')(
54
- v => assert_if(
55
- v.repo.org !== 'functionalscript' ||
56
- v.repo.name !== 'node-example' ||
57
- !('branch' in v) ||
58
- v.branch !== 'main'),
59
- assert)
60
- }
61
-
62
- {
63
- i.parseModuleUrl('github:functionalscript/node-example#4b14a7a2b11cf53f037931eb7bef240f96dcea64')(
64
- v => assert_if(
65
- v.repo.org !== 'functionalscript' ||
66
- v.repo.name !== 'node-example' ||
67
- !('commit' in v) ||
68
- v.commit !== '4b14a7a2b11cf53f037931eb7bef240f96dcea64'),
69
- assert)
70
- }
71
-
72
26
  {
73
27
  const c = (()=>{})['constructor']
74
28
  const f = c('return 5')
package/index.js DELETED
@@ -1,76 +0,0 @@
1
- /** @type {<F>(c: string, found: (before: string, after: string) => F, notFound: (c: string, source: string) => F) => (source: string) => F} */
2
- const splitOne = (c, found, notFound) => source => {
3
- const i = source.indexOf(c)
4
- return i !== -1 ? found(source.substring(0, i), source.substring(i + 1)) : notFound(c, source)
5
- }
6
-
7
- /** @type {<T>(f: (_: T) => boolean) => (_: Iterable<T>) => boolean} */
8
- const every = f => i => {
9
- for (let e of i) {
10
- if (!f(e)) {
11
- return false
12
- }
13
- }
14
- return true
15
- }
16
-
17
- /** @typedef {{org: string, name: string}} RepoId */
18
- /** @typedef {{repo: RepoId}} ModuleRepoId */
19
- /** @typedef {{repo: RepoId, branch: string}} ModuleRepoBranchId */
20
- /** @typedef {{repo: RepoId, commit: string}} ModuleRepoCommitId */
21
- /** @typedef {ModuleRepoId|ModuleRepoBranchId|ModuleRepoCommitId} ModuleId */
22
-
23
- /** @typedef {(..._: string[]) => string} GetMsg */
24
- /** @typedef {'expected'|'unknownProtocol'} ErrorId */
25
- /** @typedef {{[_ in ErrorId]: GetMsg}} ErrorMap */
26
- /** @typedef {{ id: ErrorId, params: string[]}} ErrorValue */
27
-
28
- /**
29
- * @template T
30
- * @typedef {<R>(v: (_: T) => R, e: (_: ErrorValue) => R) => R} Result
31
- */
32
-
33
- /** @type {<T>(_: T) => Result<T>} */
34
- const value = v => vf => vf(v)
35
-
36
- /**
37
- * @typedef {<R, T>(_: (_: T) => R, e: (_: ErrorValue) => R) => R} ErrorResult
38
- */
39
-
40
- /** @type {(e: ErrorValue) => ErrorResult} */
41
- const error = e => (_, ef) => ef(e)
42
-
43
- /** @type {(id: ErrorId) => (...params: string[]) => ErrorResult} */
44
- const createError = id => (...params) => error({ id, params })
45
-
46
- /** @type {(_: string) => Result<ModuleId>} */
47
- const parseRepo = repo => {
48
- const s = repo.split('/')
49
- return s.length === 2 ? value({ repo: { org: s[0], name: s[1] } }) : createError('expected')('/', repo)
50
- }
51
-
52
- /** @type {(_: string) => boolean} */
53
- const isCommit = name => name.length === 40 && every(c => "0123456789ABCDEFabcdef".includes(c))(name)
54
-
55
- /** @type {(repo: string, branch: string) => Result<ModuleId>} */
56
- const parseRepoAndBranchCommit = (repo, branchCommit) =>
57
- parseRepo(repo)(
58
- ({repo}) => value(isCommit(branchCommit) ? { repo, commit: branchCommit } : { repo, branch: branchCommit }),
59
- error)
60
-
61
- const parseGitHubId = splitOne('#', parseRepoAndBranchCommit, (_, repo) => parseRepo(repo))
62
-
63
- /** @type {(protocol: string, id: string) => Result<ModuleId>} */
64
- const parseProtocolAndId = (protocol, id) => protocol === 'github'
65
- ? parseGitHubId(id) : createError('unknownProtocol')(protocol)
66
-
67
- module.exports = {
68
- every,
69
- isCommit,
70
- parseModuleUrl: splitOne(':', parseProtocolAndId, createError('expected')),
71
- /** @type {ErrorMap} */
72
- errorMap: {
73
- expected: (c, s) => `expected '${c}' in '${s}'`,
74
- unknownProtocol: protocol => `unknown protocol '${protocol}'`,
75
- },
76
- }