nsp-server-pages 0.2.0 → 0.2.2

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
@@ -11,7 +11,7 @@ NSP JavaScript Server Pages for Node.js
11
11
  - `${ f:h("tag") }` - custom taglib static function call
12
12
  - `<ns:tag attr="${ expression }"/>` - custom taglib action tag
13
13
  - `<%-- comments --%>` - comments in JSP just ignored
14
- - See TypeScript declaration [index.d.ts](https://github.com/kawanet/nsp-server-pages/blob/main/index.d.ts) for API detail.
14
+ - See [TypeScript declaration files](https://github.com/kawanet/nsp-server-pages/tree/main/types/) for API detail.
15
15
 
16
16
  ## SYNOPSIS
17
17
 
@@ -156,6 +156,7 @@ app.use("/", async (req, res, next) => {
156
156
  - https://github.com/kawanet/nsp-server-pages
157
157
  - https://github.com/kawanet/nsp-jstl-taglib
158
158
  - https://github.com/kawanet/nsp-struts1-taglib
159
+ - https://github.com/kawanet/nsp-seasar2-taglib
159
160
  - https://github.com/apache/tomcat
160
161
 
161
162
  ## LICENSE
package/cjs/src/app.js CHANGED
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.App = void 0;
4
- const mount_js_1 = require("./mount.js");
4
+ const bundle_js_1 = require("./bundle.js");
5
+ const catch_js_1 = require("./catch.js");
6
+ const concat_js_1 = require("./concat.js");
5
7
  const loaders_js_1 = require("./loaders.js");
8
+ const mount_js_1 = require("./mount.js");
6
9
  const jsp_js_1 = require("./parser/jsp.js");
7
- const catch_js_1 = require("./catch.js");
8
- const bundle_js_1 = require("./bundle.js");
10
+ const store_js_1 = require("./store.js");
9
11
  const taglib_js_1 = require("./taglib.js");
10
- const concat_js_1 = require("./concat.js");
11
- const stack_store_js_1 = require("./stack-store.js");
12
12
  class App {
13
13
  constructor(options) {
14
14
  this.loaders = [];
@@ -85,7 +85,7 @@ class App {
85
85
  const map = (context[storeKey] ??= new Map());
86
86
  let value = map.get(key);
87
87
  if (value == null) {
88
- value = new stack_store_js_1.StackStore();
88
+ value = new store_js_1.Store();
89
89
  map.set(key, value);
90
90
  }
91
91
  return value;
@@ -53,9 +53,9 @@ class Attr {
53
53
  _toJS(option) {
54
54
  const { app } = this;
55
55
  const { indent } = app.options;
56
- const spaces = +indent ? " ".repeat(+indent) : (indent ?? "");
57
- const currentLF = option?.LF ?? "\n";
58
- const nextLF = currentLF + spaces;
56
+ const SP = option?.SP ?? (("string" === typeof indent) ? indent : (+indent ? " ".repeat(+indent) : ""));
57
+ const LF = option?.LF ?? "\n";
58
+ const nextLF = LF + SP;
59
59
  const keys = this.keys();
60
60
  const items = keys.map(key => {
61
61
  if (!isSafeKey(key)) {
@@ -69,7 +69,7 @@ class Attr {
69
69
  return 'null';
70
70
  const js = items.join(`,${nextLF}`);
71
71
  const trailingComma = (keys.length > 1) ? "," : "";
72
- return `{${nextLF}${js}${trailingComma}${currentLF}}`;
72
+ return `{${nextLF}${js}${trailingComma}${LF}}`;
73
73
  }
74
74
  }
75
75
  exports.Attr = Attr;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.jspToJS = exports.JSP = void 0;
4
+ const store_js_1 = require("../store.js");
4
5
  const scriptlet_js_1 = require("./scriptlet.js");
5
- const stack_store_js_1 = require("../stack-store.js");
6
6
  const tag_js_1 = require("./tag.js");
7
7
  /**
8
8
  * Parser for JSP document
@@ -44,7 +44,7 @@ const insideRE = `[^"']|${stringRE}`;
44
44
  const tagRegExp = new RegExp(`(</?${nameRE}:(?:${insideRE})*?>)|(<%(?:${insideRE})*?%>)`, "s");
45
45
  const jspToJS = (app, src, option) => {
46
46
  const root = new tag_js_1.Tag(app);
47
- const tree = new stack_store_js_1.StackStore(root);
47
+ const tree = new store_js_1.Store(root);
48
48
  const array = src.split(tagRegExp);
49
49
  for (let i = 0; i < array.length; i++) {
50
50
  const i3 = i % 3;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Tag = void 0;
4
- const text_js_1 = require("./text.js");
5
4
  const attr_js_1 = require("./attr.js");
5
+ const text_js_1 = require("./text.js");
6
6
  const emptyText = {
7
7
  '""': true,
8
8
  "''": true,
@@ -34,13 +34,14 @@ class Tag {
34
34
  getBodyJS(option) {
35
35
  const { app } = this;
36
36
  const { indent, trimSpaces, vName } = app.options;
37
- const spaces = +indent ? " ".repeat(+indent) : (indent ?? "");
38
- const currentLF = option?.LF ?? "\n";
39
- const nextLF = currentLF + spaces;
37
+ const SP = option?.SP ?? (("string" === typeof indent) ? indent : (+indent ? " ".repeat(+indent) : ""));
38
+ const LF = option?.LF ?? "\n";
39
+ const nextLF = LF + SP;
40
+ const nextOption = { SP, LF: nextLF };
40
41
  const { children } = this;
41
42
  const args = children.map(item => {
42
43
  if (isTranspiler(item)) {
43
- return item.toJS({ LF: nextLF });
44
+ return item.toJS(nextOption);
44
45
  }
45
46
  else if (!/\S/.test(item)) {
46
47
  // item with only whitespace
@@ -53,7 +54,7 @@ class Tag {
53
54
  item = item.replace(/^[ \t]+/s, " ");
54
55
  item = item.replace(/[ \t]+$/s, " ");
55
56
  }
56
- let js = new text_js_1.Text(app, item).toJS({ LF: nextLF });
57
+ let js = new text_js_1.Text(app, item).toJS(nextOption);
57
58
  if (/\(.+?\)|\$\{.+?}/s.test(js)) {
58
59
  js = `${vName} => ${js}`; // array function
59
60
  }
@@ -75,11 +76,11 @@ class Tag {
75
76
  args[idx] += ",";
76
77
  }
77
78
  else if (idx === last && isComment) {
78
- args[idx] += currentLF;
79
+ args[idx] += LF;
79
80
  }
80
81
  });
81
82
  const bodyL = /^`\n/s.test(args.at(0)) ? "" : nextLF;
82
- const bodyR = /(\n`|[)\s])$/s.test(args.at(-1)) ? "" : currentLF;
83
+ const bodyR = /(\n`|[)\s])$/s.test(args.at(-1)) ? "" : LF;
83
84
  return bodyL + args.join(nextLF) + bodyR;
84
85
  }
85
86
  /**
@@ -98,13 +99,13 @@ class Tag {
98
99
  const commentJS = this.getCommentJS(option);
99
100
  const attr = new attr_js_1.Attr(app, this.src);
100
101
  const body = this.getBodyJS(option);
101
- const spaces = +indent ? " ".repeat(+indent) : (indent ?? "");
102
- const currentLF = option?.LF ?? "\n";
103
- const nextLF = currentLF + spaces;
104
- const tagOption = { LF: (body ? nextLF : currentLF) };
102
+ const SP = option?.SP ?? (("string" === typeof indent) ? indent : (+indent ? " ".repeat(+indent) : ""));
103
+ const LF = option?.LF ?? "\n";
104
+ const nextLF = LF + SP;
105
+ const nextOption = { SP, LF: (body ? nextLF : LF) };
105
106
  const type = `parse.tag.${tagName}`;
106
- const def = { app, name: tagName, attr, body, LF: currentLF, nextLF };
107
- const tagJS = app.process(type, def) ?? this.getTagJS(def, tagOption);
107
+ const def = { app, name: tagName, attr, body, LF: LF, nextLF };
108
+ const tagJS = app.process(type, def) ?? this.getTagJS(def, nextOption);
108
109
  return commentJS ? commentJS + tagJS : tagJS;
109
110
  }
110
111
  getCommentJS(option) {
@@ -120,10 +121,13 @@ class Tag {
120
121
  const attrRaw = def.attr.toJS(option);
121
122
  // transpile attributes to array function if they include variables
122
123
  const hasVars = /\(.+?\)|\$\{.+?}/s.test(attrRaw);
123
- const attrJS = hasVars ? `${vName} => (${attrRaw})` : attrRaw;
124
+ const attrArg = hasVars ? `, ${vName} => (${attrRaw})` : `, ${attrRaw}`;
124
125
  const nameJS = JSON.stringify(tagName);
125
126
  const hasAttr = /:/.test(attrRaw);
126
- const restJS = def.body ? (`, ${attrJS}, ${def.body}`) : (hasAttr ? `, ${attrJS}` : "");
127
+ let bodyArg = def.body;
128
+ if (bodyArg)
129
+ bodyArg = ((/^\n/.test(bodyArg)) ? "," : ", ") + bodyArg;
130
+ const restJS = bodyArg ? (attrArg + bodyArg) : (hasAttr ? attrArg : "");
127
131
  return `${nspName}.tag(${nameJS}${restJS})`;
128
132
  }
129
133
  }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Store = void 0;
4
+ /**
5
+ * The Store class was implemented using a stack {stack: P[]} at first.
6
+ * Now it was changed to a linked list to allow access to the parent.
7
+ */
8
+ class Store {
9
+ constructor(value) {
10
+ this.item = { value };
11
+ }
12
+ open(value) {
13
+ this.item = { parent: this.item, value };
14
+ }
15
+ close() {
16
+ const item = this.item;
17
+ this.item = item.parent;
18
+ return item.value;
19
+ }
20
+ get() {
21
+ return this.item.value;
22
+ }
23
+ set(value) {
24
+ this.item.value = value;
25
+ }
26
+ find(test) {
27
+ let item = this.item;
28
+ while (item) {
29
+ if (test(item.value)) {
30
+ return item.value;
31
+ }
32
+ item = item.parent;
33
+ }
34
+ }
35
+ }
36
+ exports.Store = Store;
package/cjs/src/taglib.js CHANGED
@@ -2,17 +2,45 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.prepareTag = exports.addTagLib = void 0;
4
4
  const to_xml_1 = require("to-xml");
5
+ const isTagCon = (v) => ("function" === typeof v?.prototype?.render);
6
+ const tagConToTagFn = (Tag) => {
7
+ return (tag) => {
8
+ return (context) => {
9
+ const result = new Tag(tag, context).render();
10
+ if (result)
11
+ return result;
12
+ };
13
+ };
14
+ };
5
15
  function addTagLib(tagLibDef) {
6
16
  const { fnMap, tagMap } = this;
7
17
  const { ns, fn, tag } = tagLibDef;
8
18
  if (fn) {
9
19
  for (const name in fn) {
10
- fnMap.set(`${ns}:${name}`, fn[name]);
20
+ const impl = fn[name];
21
+ if (typeof impl === "function") {
22
+ // FnFn is called with App instance as this
23
+ fnMap.set(`${ns}:${name}`, impl.bind(this));
24
+ }
25
+ else if (impl != null) {
26
+ throw new Error(`Invalid taglib implementation: \${${ns}:${name}()}`);
27
+ }
11
28
  }
12
29
  }
13
30
  if (tag) {
14
31
  for (const name in tag) {
15
- tagMap.set(`${ns}:${name}`, tag[name]);
32
+ const impl = tag[name];
33
+ if (isTagCon(impl)) {
34
+ // NSP.TagCon
35
+ tagMap.set(`${ns}:${name}`, tagConToTagFn(impl));
36
+ }
37
+ else if (typeof impl === "function") {
38
+ // NSP.TagFn
39
+ tagMap.set(`${ns}:${name}`, impl);
40
+ }
41
+ else if (impl != null) {
42
+ throw new Error(`Invalid taglib implementation: <${ns}:${name}>`);
43
+ }
16
44
  }
17
45
  }
18
46
  }
package/esm/src/app.js CHANGED
@@ -1,11 +1,11 @@
1
- import { load, mount } from "./mount.js";
1
+ import { bundle } from "./bundle.js";
2
+ import { catchFn } from "./catch.js";
3
+ import { concat } from "./concat.js";
2
4
  import { FileLoader, JsLoader, JspLoader } from "./loaders.js";
5
+ import { load, mount } from "./mount.js";
3
6
  import { JSP } from "./parser/jsp.js";
4
- import { catchFn } from "./catch.js";
5
- import { bundle } from "./bundle.js";
7
+ import { Store } from "./store.js";
6
8
  import { addTagLib, prepareTag } from "./taglib.js";
7
- import { concat } from "./concat.js";
8
- import { StackStore } from "./stack-store.js";
9
9
  export class App {
10
10
  constructor(options) {
11
11
  this.loaders = [];
@@ -82,7 +82,7 @@ export class App {
82
82
  const map = (context[storeKey] ??= new Map());
83
83
  let value = map.get(key);
84
84
  if (value == null) {
85
- value = new StackStore();
85
+ value = new Store();
86
86
  map.set(key, value);
87
87
  }
88
88
  return value;
@@ -50,9 +50,9 @@ export class Attr {
50
50
  _toJS(option) {
51
51
  const { app } = this;
52
52
  const { indent } = app.options;
53
- const spaces = +indent ? " ".repeat(+indent) : (indent ?? "");
54
- const currentLF = option?.LF ?? "\n";
55
- const nextLF = currentLF + spaces;
53
+ const SP = option?.SP ?? (("string" === typeof indent) ? indent : (+indent ? " ".repeat(+indent) : ""));
54
+ const LF = option?.LF ?? "\n";
55
+ const nextLF = LF + SP;
56
56
  const keys = this.keys();
57
57
  const items = keys.map(key => {
58
58
  if (!isSafeKey(key)) {
@@ -66,7 +66,7 @@ export class Attr {
66
66
  return 'null';
67
67
  const js = items.join(`,${nextLF}`);
68
68
  const trailingComma = (keys.length > 1) ? "," : "";
69
- return `{${nextLF}${js}${trailingComma}${currentLF}}`;
69
+ return `{${nextLF}${js}${trailingComma}${LF}}`;
70
70
  }
71
71
  }
72
72
  const UNESCAPE = {
@@ -1,5 +1,5 @@
1
+ import { Store } from "../store.js";
1
2
  import { Scriptlet } from "./scriptlet.js";
2
- import { StackStore } from "../stack-store.js";
3
3
  import { Tag } from "./tag.js";
4
4
  /**
5
5
  * Parser for JSP document
@@ -40,7 +40,7 @@ const insideRE = `[^"']|${stringRE}`;
40
40
  const tagRegExp = new RegExp(`(</?${nameRE}:(?:${insideRE})*?>)|(<%(?:${insideRE})*?%>)`, "s");
41
41
  export const jspToJS = (app, src, option) => {
42
42
  const root = new Tag(app);
43
- const tree = new StackStore(root);
43
+ const tree = new Store(root);
44
44
  const array = src.split(tagRegExp);
45
45
  for (let i = 0; i < array.length; i++) {
46
46
  const i3 = i % 3;
@@ -1,5 +1,5 @@
1
- import { Text } from "./text.js";
2
1
  import { Attr } from "./attr.js";
2
+ import { Text } from "./text.js";
3
3
  const emptyText = {
4
4
  '""': true,
5
5
  "''": true,
@@ -31,13 +31,14 @@ export class Tag {
31
31
  getBodyJS(option) {
32
32
  const { app } = this;
33
33
  const { indent, trimSpaces, vName } = app.options;
34
- const spaces = +indent ? " ".repeat(+indent) : (indent ?? "");
35
- const currentLF = option?.LF ?? "\n";
36
- const nextLF = currentLF + spaces;
34
+ const SP = option?.SP ?? (("string" === typeof indent) ? indent : (+indent ? " ".repeat(+indent) : ""));
35
+ const LF = option?.LF ?? "\n";
36
+ const nextLF = LF + SP;
37
+ const nextOption = { SP, LF: nextLF };
37
38
  const { children } = this;
38
39
  const args = children.map(item => {
39
40
  if (isTranspiler(item)) {
40
- return item.toJS({ LF: nextLF });
41
+ return item.toJS(nextOption);
41
42
  }
42
43
  else if (!/\S/.test(item)) {
43
44
  // item with only whitespace
@@ -50,7 +51,7 @@ export class Tag {
50
51
  item = item.replace(/^[ \t]+/s, " ");
51
52
  item = item.replace(/[ \t]+$/s, " ");
52
53
  }
53
- let js = new Text(app, item).toJS({ LF: nextLF });
54
+ let js = new Text(app, item).toJS(nextOption);
54
55
  if (/\(.+?\)|\$\{.+?}/s.test(js)) {
55
56
  js = `${vName} => ${js}`; // array function
56
57
  }
@@ -72,11 +73,11 @@ export class Tag {
72
73
  args[idx] += ",";
73
74
  }
74
75
  else if (idx === last && isComment) {
75
- args[idx] += currentLF;
76
+ args[idx] += LF;
76
77
  }
77
78
  });
78
79
  const bodyL = /^`\n/s.test(args.at(0)) ? "" : nextLF;
79
- const bodyR = /(\n`|[)\s])$/s.test(args.at(-1)) ? "" : currentLF;
80
+ const bodyR = /(\n`|[)\s])$/s.test(args.at(-1)) ? "" : LF;
80
81
  return bodyL + args.join(nextLF) + bodyR;
81
82
  }
82
83
  /**
@@ -95,13 +96,13 @@ export class Tag {
95
96
  const commentJS = this.getCommentJS(option);
96
97
  const attr = new Attr(app, this.src);
97
98
  const body = this.getBodyJS(option);
98
- const spaces = +indent ? " ".repeat(+indent) : (indent ?? "");
99
- const currentLF = option?.LF ?? "\n";
100
- const nextLF = currentLF + spaces;
101
- const tagOption = { LF: (body ? nextLF : currentLF) };
99
+ const SP = option?.SP ?? (("string" === typeof indent) ? indent : (+indent ? " ".repeat(+indent) : ""));
100
+ const LF = option?.LF ?? "\n";
101
+ const nextLF = LF + SP;
102
+ const nextOption = { SP, LF: (body ? nextLF : LF) };
102
103
  const type = `parse.tag.${tagName}`;
103
- const def = { app, name: tagName, attr, body, LF: currentLF, nextLF };
104
- const tagJS = app.process(type, def) ?? this.getTagJS(def, tagOption);
104
+ const def = { app, name: tagName, attr, body, LF: LF, nextLF };
105
+ const tagJS = app.process(type, def) ?? this.getTagJS(def, nextOption);
105
106
  return commentJS ? commentJS + tagJS : tagJS;
106
107
  }
107
108
  getCommentJS(option) {
@@ -117,10 +118,13 @@ export class Tag {
117
118
  const attrRaw = def.attr.toJS(option);
118
119
  // transpile attributes to array function if they include variables
119
120
  const hasVars = /\(.+?\)|\$\{.+?}/s.test(attrRaw);
120
- const attrJS = hasVars ? `${vName} => (${attrRaw})` : attrRaw;
121
+ const attrArg = hasVars ? `, ${vName} => (${attrRaw})` : `, ${attrRaw}`;
121
122
  const nameJS = JSON.stringify(tagName);
122
123
  const hasAttr = /:/.test(attrRaw);
123
- const restJS = def.body ? (`, ${attrJS}, ${def.body}`) : (hasAttr ? `, ${attrJS}` : "");
124
+ let bodyArg = def.body;
125
+ if (bodyArg)
126
+ bodyArg = ((/^\n/.test(bodyArg)) ? "," : ", ") + bodyArg;
127
+ const restJS = bodyArg ? (attrArg + bodyArg) : (hasAttr ? attrArg : "");
124
128
  return `${nspName}.tag(${nameJS}${restJS})`;
125
129
  }
126
130
  }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The Store class was implemented using a stack {stack: P[]} at first.
3
+ * Now it was changed to a linked list to allow access to the parent.
4
+ */
5
+ export class Store {
6
+ constructor(value) {
7
+ this.item = { value };
8
+ }
9
+ open(value) {
10
+ this.item = { parent: this.item, value };
11
+ }
12
+ close() {
13
+ const item = this.item;
14
+ this.item = item.parent;
15
+ return item.value;
16
+ }
17
+ get() {
18
+ return this.item.value;
19
+ }
20
+ set(value) {
21
+ this.item.value = value;
22
+ }
23
+ find(test) {
24
+ let item = this.item;
25
+ while (item) {
26
+ if (test(item.value)) {
27
+ return item.value;
28
+ }
29
+ item = item.parent;
30
+ }
31
+ }
32
+ }
package/esm/src/taglib.js CHANGED
@@ -1,15 +1,43 @@
1
1
  import { toXML } from "to-xml";
2
+ const isTagCon = (v) => ("function" === typeof v?.prototype?.render);
3
+ const tagConToTagFn = (Tag) => {
4
+ return (tag) => {
5
+ return (context) => {
6
+ const result = new Tag(tag, context).render();
7
+ if (result)
8
+ return result;
9
+ };
10
+ };
11
+ };
2
12
  export function addTagLib(tagLibDef) {
3
13
  const { fnMap, tagMap } = this;
4
14
  const { ns, fn, tag } = tagLibDef;
5
15
  if (fn) {
6
16
  for (const name in fn) {
7
- fnMap.set(`${ns}:${name}`, fn[name]);
17
+ const impl = fn[name];
18
+ if (typeof impl === "function") {
19
+ // FnFn is called with App instance as this
20
+ fnMap.set(`${ns}:${name}`, impl.bind(this));
21
+ }
22
+ else if (impl != null) {
23
+ throw new Error(`Invalid taglib implementation: \${${ns}:${name}()}`);
24
+ }
8
25
  }
9
26
  }
10
27
  if (tag) {
11
28
  for (const name in tag) {
12
- tagMap.set(`${ns}:${name}`, tag[name]);
29
+ const impl = tag[name];
30
+ if (isTagCon(impl)) {
31
+ // NSP.TagCon
32
+ tagMap.set(`${ns}:${name}`, tagConToTagFn(impl));
33
+ }
34
+ else if (typeof impl === "function") {
35
+ // NSP.TagFn
36
+ tagMap.set(`${ns}:${name}`, impl);
37
+ }
38
+ else if (impl != null) {
39
+ throw new Error(`Invalid taglib implementation: <${ns}:${name}>`);
40
+ }
13
41
  }
14
42
  }
15
43
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nsp-server-pages",
3
3
  "description": "NSP JavaScript Server Pages for Node.js",
4
- "version": "0.2.0",
4
+ "version": "0.2.2",
5
5
  "author": "@kawanet",
6
6
  "bugs": {
7
7
  "url": "https://github.com/kawanet/nsp-server-pages/issues"
@@ -13,7 +13,7 @@
13
13
  "devDependencies": {
14
14
  "@rollup/plugin-node-resolve": "^15.2.1",
15
15
  "@types/mocha": "^10.0.1",
16
- "@types/node": "^20.5.6",
16
+ "@types/node": "^20.5.7",
17
17
  "mocha": "^10.2.0",
18
18
  "typescript": "^5.2.2"
19
19
  },
package/types/index.d.ts CHANGED
@@ -19,6 +19,8 @@ export declare namespace NSP {
19
19
 
20
20
  type TagFn<A, T = any> = (tag: TagDef<A, T>) => (NodeFn<T> | VoidFn<T>);
21
21
 
22
+ type TagCon<A, T = any> = { new(tag: NSP.TagDef<A>, context: T): TagClass };
23
+
22
24
  type LoaderFn = (path: string) => Promise<NodeFn<any> | undefined>;
23
25
 
24
26
  type Strings = string | Promise<string> | Strings[];
@@ -166,7 +168,11 @@ export declare namespace NSP {
166
168
  /**
167
169
  * tags
168
170
  */
169
- tag?: { [name: string]: TagFn<any> };
171
+ tag?: { [name: string]: TagFn<any> | TagCon<any> };
172
+ }
173
+
174
+ interface TagClass {
175
+ render(): string | Promise<string> | void | Promise<void>;
170
176
  }
171
177
 
172
178
  interface StackStore<P> {
@@ -198,6 +204,7 @@ export declare namespace NSP {
198
204
 
199
205
  interface ToJSOption {
200
206
  LF?: string;
207
+ SP?: string;
201
208
  }
202
209
 
203
210
  interface Transpiler {
@@ -1,31 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StackStore = void 0;
4
- class StackStore {
5
- constructor(value) {
6
- this.stack = [];
7
- if (arguments.length) {
8
- this.set(value);
9
- }
10
- }
11
- open(value) {
12
- this.stack.unshift(value);
13
- }
14
- close() {
15
- return this.stack.shift();
16
- }
17
- get() {
18
- return this.stack[0];
19
- }
20
- set(value) {
21
- this.stack[0] = value;
22
- }
23
- find(test) {
24
- for (const data of this.stack) {
25
- if (test(data)) {
26
- return data;
27
- }
28
- }
29
- }
30
- }
31
- exports.StackStore = StackStore;
@@ -1,27 +0,0 @@
1
- export class StackStore {
2
- constructor(value) {
3
- this.stack = [];
4
- if (arguments.length) {
5
- this.set(value);
6
- }
7
- }
8
- open(value) {
9
- this.stack.unshift(value);
10
- }
11
- close() {
12
- return this.stack.shift();
13
- }
14
- get() {
15
- return this.stack[0];
16
- }
17
- set(value) {
18
- this.stack[0] = value;
19
- }
20
- find(test) {
21
- for (const data of this.stack) {
22
- if (test(data)) {
23
- return data;
24
- }
25
- }
26
- }
27
- }