nsp-server-pages 0.1.1 → 0.2.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 (40) hide show
  1. package/cjs/index.js +6 -1
  2. package/cjs/package.json +1 -0
  3. package/cjs/src/app.js +20 -20
  4. package/cjs/src/catch.js +10 -9
  5. package/cjs/src/loaders.js +1 -1
  6. package/cjs/src/mount.js +6 -6
  7. package/cjs/src/parser/attr.js +92 -0
  8. package/{src/parse-el.js → cjs/src/parser/el.js} +15 -28
  9. package/cjs/src/parser/jsp.js +88 -0
  10. package/cjs/src/parser/scriptlet.js +47 -0
  11. package/cjs/src/parser/tag.js +130 -0
  12. package/{src/parse-text.js → cjs/src/parser/text.js} +13 -25
  13. package/cjs/src/stack-store.js +31 -0
  14. package/cjs/src/taglib.js +7 -7
  15. package/esm/index.js +2 -0
  16. package/esm/package.json +4 -0
  17. package/{src → esm/src}/app.js +19 -19
  18. package/{src → esm/src}/catch.js +10 -9
  19. package/{src → esm/src}/mount.js +6 -6
  20. package/esm/src/parser/attr.js +88 -0
  21. package/{cjs/src/parse-el.js → esm/src/parser/el.js} +11 -32
  22. package/esm/src/parser/jsp.js +83 -0
  23. package/esm/src/parser/scriptlet.js +43 -0
  24. package/esm/src/parser/tag.js +126 -0
  25. package/{cjs/src/parse-text.js → esm/src/parser/text.js} +9 -29
  26. package/esm/src/stack-store.js +27 -0
  27. package/{src → esm/src}/taglib.js +7 -7
  28. package/package.json +14 -13
  29. package/types/hooks.d.ts +103 -0
  30. package/{index.d.ts → types/index.d.ts} +62 -40
  31. package/cjs/src/parse-attr.js +0 -91
  32. package/cjs/src/parse-jsp.js +0 -206
  33. package/cjs/src/parse-scriptlet.js +0 -71
  34. package/index.js +0 -1
  35. package/src/parse-attr.js +0 -87
  36. package/src/parse-jsp.js +0 -201
  37. package/src/parse-scriptlet.js +0 -67
  38. /package/{src → esm/src}/bundle.js +0 -0
  39. /package/{src → esm/src}/concat.js +0 -0
  40. /package/{src → esm/src}/loaders.js +0 -0
@@ -1,5 +1,8 @@
1
- import { parseEL } from "./parse-el.js";
2
- import { parseScriptlet } from "./parse-scriptlet.js";
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Text = void 0;
4
+ const el_js_1 = require("./el.js");
5
+ const scriptlet_js_1 = require("./scriptlet.js");
3
6
  /**
4
7
  * escape special characters in Template Literal
5
8
  */
@@ -16,36 +19,21 @@ const bodyRegExp = new RegExp(bodyRE, "s");
16
19
  /**
17
20
  * Parser for: text content
18
21
  */
19
- export const parseText = (app, src) => new TextParser(app, src);
20
- class TextParser {
22
+ class Text {
21
23
  constructor(app, src) {
22
24
  this.app = app;
23
- this.src = src;
24
- //
25
+ this.src = app.process("before.parse.text", src) ?? src;
25
26
  }
26
27
  /**
27
28
  * Transpile ${expression} and <% scriptlet %> to JavaScript source code
28
29
  */
29
30
  toJS(option) {
30
- return textToJS(this.app, this.src, option);
31
- }
32
- /**
33
- * Compile ${expression} and <% scriptlet %> to JavaScript function instance
34
- */
35
- toFn() {
36
- const { app } = this;
37
- const { nspName, vName } = app.options;
38
- const js = this.toJS();
39
- try {
40
- const fn = Function(nspName, vName, `return ${js}`);
41
- return (context) => fn(app, context);
42
- }
43
- catch (e) {
44
- app.log("TextParser: " + js?.substring(0, 1000));
45
- throw e;
46
- }
31
+ const { app, src } = this;
32
+ const js = app.process("parse.text", src) ?? textToJS(app, src, option);
33
+ return app.process("after.parse.text", js) ?? js;
47
34
  }
48
35
  }
36
+ exports.Text = Text;
49
37
  /**
50
38
  * Transpile ${expression}, #{async expression} and <% scriptlet %> to JavaScript source code
51
39
  */
@@ -62,7 +50,7 @@ const textToJS = (app, src, option) => {
62
50
  const isAsync = /^#/s.test(value);
63
51
  value = value.replace(/^[$#]\{\s*/s, "");
64
52
  value = value.replace(/\s*}$/s, "");
65
- const item = parseEL(app, value);
53
+ const item = new el_js_1.EL(app, value);
66
54
  if (isAsync) {
67
55
  items.push({ toJS: (option) => `await ${item.toJS(option)}` });
68
56
  }
@@ -72,7 +60,7 @@ const textToJS = (app, src, option) => {
72
60
  }
73
61
  else if (i3 === 2) {
74
62
  // <% scriptlet %>
75
- const item = parseScriptlet(app, value);
63
+ const item = new scriptlet_js_1.Scriptlet(app, value);
76
64
  items.push(item);
77
65
  }
78
66
  else {
@@ -0,0 +1,31 @@
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;
package/cjs/src/taglib.js CHANGED
@@ -2,8 +2,8 @@
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 addTagLib = (app, tagLibDef) => {
6
- const { fnMap, tagMap } = app;
5
+ function addTagLib(tagLibDef) {
6
+ const { fnMap, tagMap } = this;
7
7
  const { ns, fn, tag } = tagLibDef;
8
8
  if (fn) {
9
9
  for (const name in fn) {
@@ -15,15 +15,15 @@ const addTagLib = (app, tagLibDef) => {
15
15
  tagMap.set(`${ns}:${name}`, tag[name]);
16
16
  }
17
17
  }
18
- };
18
+ }
19
19
  exports.addTagLib = addTagLib;
20
- const prepareTag = (app, name, attr, body) => {
21
- const { tagMap } = app;
20
+ function prepareTag(name, attr, body) {
21
+ const { tagMap } = this;
22
22
  const tagFn = tagMap.get(name) || defaultTagFn;
23
23
  const attrFn = !attr ? () => ({}) : (typeof attr !== "function") ? () => attr : attr;
24
- const tagDef = { name, app, attr: attrFn, body };
24
+ const tagDef = { name, app: this, attr: attrFn, body };
25
25
  return tagFn(tagDef);
26
- };
26
+ }
27
27
  exports.prepareTag = prepareTag;
28
28
  const defaultTagFn = (tagDef) => {
29
29
  const { name } = tagDef;
package/esm/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import { App } from "./src/app.js";
2
+ export const createNSP = (options) => new App(options);
@@ -0,0 +1,4 @@
1
+ {
2
+ "main": "./index.js",
3
+ "type": "module"
4
+ }
@@ -1,17 +1,17 @@
1
1
  import { load, mount } from "./mount.js";
2
2
  import { FileLoader, JsLoader, JspLoader } from "./loaders.js";
3
- import { parseJSP } from "./parse-jsp.js";
3
+ import { JSP } from "./parser/jsp.js";
4
4
  import { catchFn } from "./catch.js";
5
5
  import { bundle } from "./bundle.js";
6
6
  import { addTagLib, prepareTag } from "./taglib.js";
7
7
  import { concat } from "./concat.js";
8
- export const createNSP = (options) => new App(options);
9
- class App {
8
+ import { StackStore } from "./stack-store.js";
9
+ export class App {
10
10
  constructor(options) {
11
11
  this.loaders = [];
12
12
  this.tagMap = new Map();
13
13
  this.fnMap = new Map();
14
- this.listeners = new Map;
14
+ this.hooks = new Map();
15
15
  this.options = options = Object.create(options || null);
16
16
  if (!options.vName)
17
17
  options.vName = "v";
@@ -21,12 +21,12 @@ class App {
21
21
  options.storeKey = "#nsp";
22
22
  }
23
23
  hook(type, fn) {
24
- this.listeners.set(type, fn);
24
+ this.hooks.set(type, fn);
25
25
  }
26
- process(type, arg) {
27
- const fn = this.listeners.get(type);
26
+ process(type, ...args) {
27
+ const fn = this.hooks.get(type);
28
28
  if (fn)
29
- return fn(arg);
29
+ return fn.apply(this, args);
30
30
  }
31
31
  log(message) {
32
32
  const logger = this.options.logger || console;
@@ -42,11 +42,11 @@ class App {
42
42
  return fn;
43
43
  }
44
44
  addTagLib(tagLibDef) {
45
- addTagLib(this, tagLibDef);
45
+ addTagLib.call(this, tagLibDef);
46
46
  }
47
47
  tag(name, attr, ..._) {
48
48
  const bodyFn = bundle(arguments, 2);
49
- const tagFn = prepareTag(this, name, attr, bodyFn);
49
+ const tagFn = prepareTag.call(this, name, attr, bodyFn);
50
50
  return catchFn(this, tagFn);
51
51
  }
52
52
  bundle(..._) {
@@ -54,35 +54,35 @@ class App {
54
54
  return catchFn(this, fn);
55
55
  }
56
56
  parse(src) {
57
- return parseJSP(this, src);
57
+ return new JSP(this, src);
58
58
  }
59
59
  mount(path, fn) {
60
- return mount(this, path, fn);
60
+ return mount.call(this, path, fn);
61
61
  }
62
62
  load(path) {
63
- return load(this, path);
63
+ return load.call(this, path);
64
64
  }
65
65
  loadJS(file) {
66
- const loader = this.jsLoader || (this.jsLoader = new JsLoader(this));
66
+ const loader = (this.jsLoader ??= new JsLoader(this));
67
67
  return loader.load(file);
68
68
  }
69
69
  loadJSP(file) {
70
- const loader = this.jspLoader || (this.jspLoader = new JspLoader(this));
70
+ const loader = (this.jspLoader ??= new JspLoader(this));
71
71
  return loader.load(file);
72
72
  }
73
73
  loadFile(file) {
74
- const loader = this.fileLoader || (this.fileLoader = new FileLoader(this));
74
+ const loader = (this.fileLoader ??= new FileLoader(this));
75
75
  return loader.load(file);
76
76
  }
77
- store(context, key, initFn) {
77
+ store(context, key) {
78
78
  if ("object" !== typeof context && context == null) {
79
79
  throw new Error("Context must be an object");
80
80
  }
81
81
  const { storeKey } = this.options;
82
- const map = context[storeKey] || (context[storeKey] = new Map());
82
+ const map = (context[storeKey] ??= new Map());
83
83
  let value = map.get(key);
84
84
  if (value == null) {
85
- value = initFn();
85
+ value = new StackStore();
86
86
  map.set(key, value);
87
87
  }
88
88
  return value;
@@ -1,6 +1,4 @@
1
- import { toXML } from "to-xml";
2
1
  const isPromise = (v) => v && (typeof v.catch === "function");
3
- const escapeError = (e) => toXML({ "#": (e?.message || String(e)) });
4
2
  export const catchFn = (app, fn) => {
5
3
  return context => {
6
4
  try {
@@ -18,16 +16,19 @@ export const catchFn = (app, fn) => {
18
16
  function errorHandler(e) {
19
17
  // just throw the error if it's already handled
20
18
  if (context != null) {
21
- const data = app.store(context, "error", () => ({}));
22
- if (data.error === e)
19
+ const store = app.store(context, "error");
20
+ if (store.find(err => (err === e))) {
23
21
  throw e;
24
- data.error = e;
22
+ }
23
+ store.open(e);
25
24
  }
26
- // call the error handler
25
+ // call the error hook
27
26
  const result = app.process("error", e, context);
28
- if (result != null)
29
- return result;
30
- return `<!--\n[ERR] ${escapeError(e)}\n-->`;
27
+ // if the hook returns nothing, throw the error
28
+ if (result == null)
29
+ throw e;
30
+ // if the hook returns a string, show it
31
+ return result;
31
32
  }
32
33
  };
33
34
  };
@@ -1,14 +1,14 @@
1
- export const mount = (app, match, fn) => {
1
+ export function mount(match, fn) {
2
2
  const test = ("string" !== typeof match) ? match : {
3
3
  test: ((path) => path.startsWith(match))
4
4
  };
5
- app.loaders.push(!test ? fn : path => {
5
+ this.loaders.push(!test ? fn : path => {
6
6
  if (test.test(path))
7
7
  return fn(path);
8
8
  });
9
- };
10
- export const load = async (app, path) => {
11
- const { loaders } = app;
9
+ }
10
+ export async function load(path) {
11
+ const { loaders } = this;
12
12
  const search = path.replace(/^[^?]*\??/, "");
13
13
  path = path.replace(/\?.*$/, "");
14
14
  path = path.replace(/^\/*/, "/");
@@ -26,4 +26,4 @@ export const load = async (app, path) => {
26
26
  }
27
27
  return fn(context);
28
28
  };
29
- };
29
+ }
@@ -0,0 +1,88 @@
1
+ import { Text } from "./text.js";
2
+ const isSafeKey = (key) => /^[A-Za-z_]\w+$/.test(key);
3
+ /**
4
+ * Parser for HTML tag attributes <tagName attr="value"/>
5
+ */
6
+ export class Attr {
7
+ constructor(app, src) {
8
+ this.app = app;
9
+ this.src = app.process("before.parse.attr", src) ?? src;
10
+ }
11
+ /**
12
+ * Transpile HTML tag attributes to JavaScript source code
13
+ */
14
+ toJS(option) {
15
+ const { app, src } = this;
16
+ const js = app.process("parse.attr", src) ?? this._toJS(option);
17
+ return app.process("after.parse.attr", js) ?? js;
18
+ }
19
+ keys() {
20
+ return Object.keys(this.getIndex());
21
+ }
22
+ get(key) {
23
+ return this.getIndex()[key];
24
+ }
25
+ getIndex() {
26
+ let { index, src } = this;
27
+ if (index)
28
+ return index;
29
+ index = this.index = {};
30
+ if (!src)
31
+ return index;
32
+ src = src.replace(/^\s*<\S+\s*/s, "");
33
+ src = src.replace(/\s*\/?>\s*$/s, "");
34
+ src.replace(/([^\s='"]+)(\s*=(?:\s*"([^"]*)"|\s*'([^']*)'|([^\s='"]*)))?/g, (_, key, eq, v1, v2, v3) => {
35
+ if (eq) {
36
+ const value = unescapeXML(v1 || v2 || v3 || "");
37
+ index[key] = new Text(this.app, value).toJS({});
38
+ }
39
+ else {
40
+ const value = true;
41
+ index[key] = String(value);
42
+ }
43
+ return "";
44
+ });
45
+ return index;
46
+ }
47
+ /**
48
+ * Transpile HTML tag attributes to JavaScript source code
49
+ */
50
+ _toJS(option) {
51
+ const { app } = this;
52
+ const { indent } = app.options;
53
+ const spaces = +indent ? " ".repeat(+indent) : (indent ?? "");
54
+ const currentLF = option?.LF ?? "\n";
55
+ const nextLF = currentLF + spaces;
56
+ const keys = this.keys();
57
+ const items = keys.map(key => {
58
+ if (!isSafeKey(key)) {
59
+ key = JSON.stringify(key);
60
+ }
61
+ const value = this.get(key);
62
+ return `${key}: ${value}`;
63
+ });
64
+ // no arguments
65
+ if (!keys.length)
66
+ return 'null';
67
+ const js = items.join(`,${nextLF}`);
68
+ const trailingComma = (keys.length > 1) ? "," : "";
69
+ return `{${nextLF}${js}${trailingComma}${currentLF}}`;
70
+ }
71
+ }
72
+ const UNESCAPE = {
73
+ "&amp;": "&",
74
+ "&lt;": "<",
75
+ "&gt;": ">",
76
+ "&apos;": "'",
77
+ "&quot;": '"'
78
+ };
79
+ const unescapeXML = (str) => {
80
+ return str?.replace(/(&(?:lt|gt|amp|apos|quot|#(?:\d{1,6}|x[0-9a-fA-F]{1,5}));)/g, (str) => {
81
+ if (str[1] === "#") {
82
+ const code = (str[2] === "x") ? parseInt(str.substring(3), 16) : parseInt(str.substr(2), 10);
83
+ if (code > -1)
84
+ return String.fromCharCode(code);
85
+ }
86
+ return UNESCAPE[str] || str;
87
+ });
88
+ };
@@ -1,6 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseEL = void 0;
4
1
  const trim = (str) => str.replace(/^\s+/s, "").replace(/\s+$/s, "");
5
2
  const wordMap = {
6
3
  and: "&&",
@@ -33,39 +30,23 @@ const itemRegExp = new RegExp(`(${itemRE})`, "s");
33
30
  /**
34
31
  * Simplified transformer for expression language
35
32
  */
36
- const parseEL = (app, src) => new ElParser(app, src);
37
- exports.parseEL = parseEL;
38
- class ElParser {
33
+ export class EL {
39
34
  constructor(app, src) {
40
35
  this.app = app;
41
- this.src = src;
42
- //
43
- }
44
- /**
45
- * Compile ${EL} to JavaScript function instance
46
- */
47
- toFn() {
48
- const { app } = this;
49
- const { nspName, vName } = app.options;
50
- const js = this.toJS();
51
- try {
52
- const fn = Function(nspName, vName, `return ${js}`);
53
- return (context) => fn(app, context);
54
- }
55
- catch (e) {
56
- app.log("ElParser: " + js?.substring(0, 1000));
57
- throw e;
58
- }
36
+ src = trim(src);
37
+ this.src = app.process("before.parse.el", src) ?? src;
59
38
  }
60
39
  /**
61
40
  * Transpile ${EL} to JavaScript source code
62
41
  */
63
- toJS(_) {
64
- const { app } = this;
65
- const { nullish, prefilter, postfilter } = app.options;
66
- let src = trim(this.src);
67
- if (prefilter)
68
- src = prefilter(src);
42
+ toJS(option) {
43
+ const { app, src } = this;
44
+ const js = app.process("parse.el", src) ?? this._toJS(option);
45
+ return app.process("after.parse.el", js) ?? js;
46
+ }
47
+ _toJS(_) {
48
+ const { app, src } = this;
49
+ const { nullish } = app.options;
69
50
  if (src == null)
70
51
  return 'null';
71
52
  const array = src.split(itemRegExp);
@@ -102,8 +83,6 @@ class ElParser {
102
83
  }
103
84
  js = `${js} ?? ""`;
104
85
  }
105
- if (postfilter)
106
- js = postfilter(js);
107
86
  return js;
108
87
  }
109
88
  }
@@ -0,0 +1,83 @@
1
+ import { Scriptlet } from "./scriptlet.js";
2
+ import { StackStore } from "../stack-store.js";
3
+ import { Tag } from "./tag.js";
4
+ /**
5
+ * Parser for JSP document
6
+ */
7
+ export class JSP {
8
+ constructor(app, src) {
9
+ this.app = app;
10
+ this.src = app.process("before.parse.jsp", src) ?? src;
11
+ }
12
+ /**
13
+ * Transpile JSP document to JavaScript source code
14
+ */
15
+ toJS(option) {
16
+ const { app, src } = this;
17
+ const js = app.process("parse.jsp", src) ?? jspToJS(app, src, option);
18
+ return app.process("after.parse.jsp", js) ?? js;
19
+ }
20
+ /**
21
+ * Compile JSP document to JavaScript function
22
+ */
23
+ toFn() {
24
+ const { app } = this;
25
+ const { nspName } = app.options;
26
+ const js = this.toJS();
27
+ try {
28
+ const fn = Function(nspName, `return ${js}`);
29
+ return fn(app);
30
+ }
31
+ catch (e) {
32
+ app.log("JspParser: " + js?.substring(0, 1000));
33
+ throw e;
34
+ }
35
+ }
36
+ }
37
+ const nameRE = `[A-Za-z][A-Za-z0-9]*`;
38
+ const stringRE = `"(?:\\\\[.]|[^\\\\"])*"|'(?:\\\\[.]|[^\\\\'])*'`;
39
+ const insideRE = `[^"']|${stringRE}`;
40
+ const tagRegExp = new RegExp(`(</?${nameRE}:(?:${insideRE})*?>)|(<%(?:${insideRE})*?%>)`, "s");
41
+ export const jspToJS = (app, src, option) => {
42
+ const root = new Tag(app);
43
+ const tree = new StackStore(root);
44
+ const array = src.split(tagRegExp);
45
+ for (let i = 0; i < array.length; i++) {
46
+ const i3 = i % 3;
47
+ let str = array[i];
48
+ if (i3 === 1 && str) {
49
+ // taglib
50
+ const tag = new Tag(app, str);
51
+ // close-tag
52
+ if (tag.isClose()) {
53
+ const closed = tree.close();
54
+ if (!closed) {
55
+ throw new Error(`invalid closing tag: </${tag.tagName}>`);
56
+ }
57
+ if (closed.tagName !== tag.tagName) {
58
+ throw new Error(`invalid closing tag: <${closed.tagName}></${tag.tagName}>`);
59
+ }
60
+ continue;
61
+ }
62
+ tree.get().append(tag);
63
+ // open-tag
64
+ if (tag.isOpen()) {
65
+ tree.open(tag);
66
+ }
67
+ }
68
+ else if (i3 === 2 && str) {
69
+ // <% scriptlet %>
70
+ const item = new Scriptlet(app, str);
71
+ tree.get().append(item);
72
+ }
73
+ else if (i3 === 0) {
74
+ // text node
75
+ tree.get().append(str);
76
+ }
77
+ }
78
+ const closed = tree.close();
79
+ if (closed !== root) {
80
+ throw new Error(`invalid closing tag: </${closed?.tagName}>`);
81
+ }
82
+ return root.toJS(option);
83
+ };
@@ -0,0 +1,43 @@
1
+ const typeMap = {
2
+ "<%-": "comment",
3
+ "<%@": "directive",
4
+ "<%!": "declaration",
5
+ "<%=": "expression",
6
+ };
7
+ /**
8
+ * Parser for Directive, Declaration, Scriptlet
9
+ * <%-- comment --%>
10
+ * <%@ directive %>
11
+ * <%! declaration(s) %>
12
+ * <% scriptlet %>
13
+ * <%= expression %>
14
+ */
15
+ export class Scriptlet {
16
+ constructor(app, src) {
17
+ this.app = app;
18
+ const type = this.type = typeMap[src.substring(0, 3)] || "scriptlet";
19
+ this.src = app.process(`before.parse.${type}`, src) ?? src;
20
+ }
21
+ /**
22
+ * Transpile <% scriptlet %> to JavaScript source code
23
+ */
24
+ toJS(option) {
25
+ const { app, src, type } = this;
26
+ const js = app.process(`parse.${type}`, src) ?? this._toJS(option);
27
+ return app.process(`after.parse.${type}`, js) ?? js;
28
+ }
29
+ _toJS(option) {
30
+ const { app, type } = this;
31
+ const { nspName, vName } = app.options;
32
+ const currentLF = option?.LF ?? "\n";
33
+ let { src } = this;
34
+ if (type === "comment") {
35
+ src = src.replace(/[ \t]*[\r\n]+/sg, `${currentLF}// `);
36
+ return `// ${src}`;
37
+ }
38
+ app.log(`${type} found: ${src?.substring(0, 1000)}`);
39
+ src = /`|\$\{/.test(src) ? JSON.stringify(src) : "`" + src + "`";
40
+ src = `${vName} => ${nspName}.process("${type}", ${src}, ${vName})`;
41
+ return src;
42
+ }
43
+ }