ventojs 0.6.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.
- package/LICENSE +21 -0
- package/README.md +138 -0
- package/esm/_dnt.shims.d.ts +5 -0
- package/esm/_dnt.shims.js +62 -0
- package/esm/_dnt.test_polyfills.d.ts +11 -0
- package/esm/_dnt.test_shims.d.ts +5 -0
- package/esm/deps/deno.land/std@0.178.0/_util/asserts.d.ts +10 -0
- package/esm/deps/deno.land/std@0.178.0/_util/asserts.js +21 -0
- package/esm/deps/deno.land/std@0.178.0/_util/os.d.ts +4 -0
- package/esm/deps/deno.land/std@0.178.0/_util/os.js +18 -0
- package/esm/deps/deno.land/std@0.178.0/path/_constants.d.ts +39 -0
- package/esm/deps/deno.land/std@0.178.0/path/_constants.js +46 -0
- package/esm/deps/deno.land/std@0.178.0/path/_interface.d.ts +26 -0
- package/esm/deps/deno.land/std@0.178.0/path/_interface.js +3 -0
- package/esm/deps/deno.land/std@0.178.0/path/_util.d.ts +11 -0
- package/esm/deps/deno.land/std@0.178.0/path/_util.js +161 -0
- package/esm/deps/deno.land/std@0.178.0/path/common.d.ts +13 -0
- package/esm/deps/deno.land/std@0.178.0/path/common.js +36 -0
- package/esm/deps/deno.land/std@0.178.0/path/glob.d.ts +83 -0
- package/esm/deps/deno.land/std@0.178.0/path/glob.js +361 -0
- package/esm/deps/deno.land/std@0.178.0/path/mod.d.ts +9 -0
- package/esm/deps/deno.land/std@0.178.0/path/mod.js +32 -0
- package/esm/deps/deno.land/std@0.178.0/path/posix.d.ts +86 -0
- package/esm/deps/deno.land/std@0.178.0/path/posix.js +442 -0
- package/esm/deps/deno.land/std@0.178.0/path/separator.d.ts +2 -0
- package/esm/deps/deno.land/std@0.178.0/path/separator.js +5 -0
- package/esm/deps/deno.land/std@0.178.0/path/win32.d.ts +91 -0
- package/esm/deps/deno.land/std@0.178.0/path/win32.js +909 -0
- package/esm/deps/deno.land/std@0.190.0/_util/asserts.d.ts +10 -0
- package/esm/deps/deno.land/std@0.190.0/bytes/copy.d.ts +27 -0
- package/esm/deps/deno.land/std@0.190.0/fmt/colors.d.ts +270 -0
- package/esm/deps/deno.land/std@0.190.0/front_matter/mod.d.ts +78 -0
- package/esm/deps/deno.land/std@0.190.0/front_matter/yaml.d.ts +4 -0
- package/esm/deps/deno.land/std@0.190.0/io/buffer.d.ts +81 -0
- package/esm/deps/deno.land/std@0.190.0/testing/_diff.d.ts +26 -0
- package/esm/deps/deno.land/std@0.190.0/testing/_format.d.ts +1 -0
- package/esm/deps/deno.land/std@0.190.0/testing/asserts.d.ts +284 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_error.d.ts +6 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_loader/loader.d.ts +4 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_loader/loader_state.d.ts +43 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_mark.d.ts +10 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_state.d.ts +5 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/binary.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/bool.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/float.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/function.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/int.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/map.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/merge.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/mod.d.ts +16 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/nil.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/omap.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/pairs.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/regexp.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/seq.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/set.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/str.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/timestamp.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_type/undefined.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/_utils.d.ts +19 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/parse.d.ts +35 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/schema/core.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/schema/default.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/schema/extended.d.ts +30 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/schema/failsafe.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/schema/json.d.ts +2 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/schema/mod.d.ts +5 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/schema.d.ts +22 -0
- package/esm/deps/deno.land/std@0.190.0/yaml/type.d.ts +28 -0
- package/esm/deps.d.ts +1 -0
- package/esm/deps.js +1 -0
- package/esm/mod.d.ts +7 -0
- package/esm/mod.js +28 -0
- package/esm/package.json +3 -0
- package/esm/plugins/escape.d.ts +2 -0
- package/esm/plugins/escape.js +16 -0
- package/esm/plugins/for.d.ts +2 -0
- package/esm/plugins/for.js +48 -0
- package/esm/plugins/if.d.ts +2 -0
- package/esm/plugins/if.js +32 -0
- package/esm/plugins/include.d.ts +2 -0
- package/esm/plugins/include.js +16 -0
- package/esm/plugins/js.d.ts +2 -0
- package/esm/plugins/js.js +11 -0
- package/esm/plugins/layout.d.ts +2 -0
- package/esm/plugins/layout.js +29 -0
- package/esm/plugins/set.d.ts +2 -0
- package/esm/plugins/set.js +44 -0
- package/esm/src/environment.d.ts +29 -0
- package/esm/src/environment.js +136 -0
- package/esm/src/loader.d.ts +14 -0
- package/esm/src/loader.js +19 -0
- package/esm/src/tokenizer.d.ts +8 -0
- package/esm/src/tokenizer.js +197 -0
- package/esm/test/comment.test.d.ts +1 -0
- package/esm/test/escape.test.d.ts +1 -0
- package/esm/test/for.test.d.ts +1 -0
- package/esm/test/if.test.d.ts +1 -0
- package/esm/test/include.test.d.ts +1 -0
- package/esm/test/js.test.d.ts +1 -0
- package/esm/test/layout.test.d.ts +1 -0
- package/esm/test/print.test.d.ts +1 -0
- package/esm/test/raw.test.d.ts +1 -0
- package/esm/test/set.test.d.ts +1 -0
- package/esm/test/tokenizer.test.d.ts +1 -0
- package/esm/test/utils.d.ts +23 -0
- package/package.json +25 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Óscar Otero
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# VENTO
|
|
2
|
+
|
|
3
|
+
This is a minimal template engine inspired by other great engines like Nunjucks,
|
|
4
|
+
Liquid, Mustache or EJS.
|
|
5
|
+
|
|
6
|
+
## Why another template engine?
|
|
7
|
+
|
|
8
|
+
Because I couldn't find the "perfect" template engine for me (probably this one
|
|
9
|
+
neither is). The issues I found in existing template engines:
|
|
10
|
+
|
|
11
|
+
### Nunjucks
|
|
12
|
+
|
|
13
|
+
(It's my favorite template engine so far).
|
|
14
|
+
|
|
15
|
+
- I like:
|
|
16
|
+
- I can invoke functions like `{{ user.getName() }}`.
|
|
17
|
+
- Very flexible, with many built-in filters and features
|
|
18
|
+
- I don't like:
|
|
19
|
+
- It's not well maintained. The last version was released in Jun 2022. And the
|
|
20
|
+
previous version in 2020.
|
|
21
|
+
- It's not async-friendly. For example, you have some tags to work with sync
|
|
22
|
+
values (like `for` and `if`) and others for async values (like `asyncEach`
|
|
23
|
+
and `ifAysnc`). Some features don't work in async contexts.
|
|
24
|
+
- To me, it's very uncomfortable to have to type the delimiters `{%` and `%}`
|
|
25
|
+
all the time (especially the `%` character).
|
|
26
|
+
- By default, all variables are escaped, so you have to remember to use the
|
|
27
|
+
`safe` filter everywhere. This is not very convenient for my use case
|
|
28
|
+
(static site generators), where I can control all the content and the HTML
|
|
29
|
+
generated.
|
|
30
|
+
- Some filters are too specific.
|
|
31
|
+
|
|
32
|
+
### Liquid
|
|
33
|
+
|
|
34
|
+
- I like:
|
|
35
|
+
- The support for async evaluation is less hacky than Nunjucks.
|
|
36
|
+
- The variables are not escaped by default, there's an `escape` filter for
|
|
37
|
+
that.
|
|
38
|
+
|
|
39
|
+
- I don't like:
|
|
40
|
+
- It's not possible to invoke functions in a liquid template. For example
|
|
41
|
+
`{{ user.getName() }}` fails.
|
|
42
|
+
- It has the same problem as Nunjucks with the `%` character in the
|
|
43
|
+
delimiters.
|
|
44
|
+
|
|
45
|
+
### EJS/Eta
|
|
46
|
+
|
|
47
|
+
- I like:
|
|
48
|
+
- It allows running any javascript code in the template.
|
|
49
|
+
- I don't like:
|
|
50
|
+
- It has the same problem with the `%` character. And I don't like the opening
|
|
51
|
+
and closing delimiters (`<%` and `%>`).
|
|
52
|
+
- Because it runs javascript, it's very verbose to do a simple `forEach` or
|
|
53
|
+
`if`.
|
|
54
|
+
|
|
55
|
+
### Mustache
|
|
56
|
+
|
|
57
|
+
- I like:
|
|
58
|
+
- Very simple, everything is inside `{{` and `}}`.
|
|
59
|
+
- The closing tag is `{{/tagname}}`, very nice!
|
|
60
|
+
- I don't like:
|
|
61
|
+
- Perhaps too simple and the syntax can be a bit confusing.
|
|
62
|
+
- Partials. It's not easy to include them dynamically.
|
|
63
|
+
- The data context is a bit confusing to me.
|
|
64
|
+
- Very uncomfortable to work with filters.
|
|
65
|
+
|
|
66
|
+
### What this new template engine has to offer?
|
|
67
|
+
|
|
68
|
+
First, let's take a look at this syntax example:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
{{ if printName }}
|
|
72
|
+
{{ await user.getName("full") |> toUpperCase }}
|
|
73
|
+
{{ /if }}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- Everything is between `{{` and `}}` tags. Unlike Nunjucks or Liquid, there's
|
|
77
|
+
no distinction between tags `{% tag %}` and printing variables `{{ var }}`.
|
|
78
|
+
- The closed tag is done by prepending the `/` character (like Mustache).
|
|
79
|
+
- Async friendly.
|
|
80
|
+
- Like EJS, you can use real JavaScript code everywhere.
|
|
81
|
+
`await user.getName("full")` is real JS code that will be executed at runtime.
|
|
82
|
+
- Filters are applied using the
|
|
83
|
+
[pipeline operator](https://github.com/tc39/proposal-pipeline-operator)
|
|
84
|
+
(`|>`). Note: this is not exactly like the last proposal for JavaScript, it's
|
|
85
|
+
inspired by
|
|
86
|
+
([the previous proposal](https://github.com/valtech-nyc/proposal-fsharp-pipelines)
|
|
87
|
+
that was rejected but it's way more simple and fits better for filters.
|
|
88
|
+
- Filters can run prototype methods. In this example `users.getName("full")`
|
|
89
|
+
returns a string, so the `toUpperCase` is a method of the `String` object.
|
|
90
|
+
It's the same as `users.getName("full").toUpperCase()`.
|
|
91
|
+
|
|
92
|
+
## Getting started
|
|
93
|
+
|
|
94
|
+
This is a library for Deno. I'm planning to release an NPM version in the
|
|
95
|
+
future.
|
|
96
|
+
|
|
97
|
+
First, you need to import the library and create an instance:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import vento from "https://deno.land/x/vento@v0.2.0/mod.ts";
|
|
101
|
+
|
|
102
|
+
const vto = vento({
|
|
103
|
+
// Resolve the non-relative includes paths
|
|
104
|
+
includes: "./path/to/includes",
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
There are different ways to load, compile and run a template. For example, you
|
|
109
|
+
can use `load` to load and compile a template file and return it.
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
// Load and return a template
|
|
113
|
+
const template = vto.load("my-template.vto");
|
|
114
|
+
|
|
115
|
+
// Now you can use it passing the data
|
|
116
|
+
template({ title: "Hello world" });
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Alternatively, you can load and run the template file in a single call:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
vto.run("my-template.vto", { title: "Hello world" });
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
If the template code is not a file, you can run it directly:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
vto.runString("<h1>{{ title }}</h1>", { title: "Hello world" });
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Visual Studio Code Support
|
|
132
|
+
|
|
133
|
+
[The Vento extension for VS Code](https://marketplace.visualstudio.com/items?itemName=oscarotero.vento-syntax)
|
|
134
|
+
enables syntax highlight and provides some useful snippets.
|
|
135
|
+
|
|
136
|
+
## API
|
|
137
|
+
|
|
138
|
+
[Read the docs](https://oscarotero.github.io/vento/)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Deno } from "@deno/shim-deno";
|
|
2
|
+
export { Deno } from "@deno/shim-deno";
|
|
3
|
+
const dntGlobals = {
|
|
4
|
+
Deno,
|
|
5
|
+
};
|
|
6
|
+
export const dntGlobalThis = createMergeProxy(globalThis, dntGlobals);
|
|
7
|
+
// deno-lint-ignore ban-types
|
|
8
|
+
function createMergeProxy(baseObj, extObj) {
|
|
9
|
+
return new Proxy(baseObj, {
|
|
10
|
+
get(_target, prop, _receiver) {
|
|
11
|
+
if (prop in extObj) {
|
|
12
|
+
return extObj[prop];
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return baseObj[prop];
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
set(_target, prop, value) {
|
|
19
|
+
if (prop in extObj) {
|
|
20
|
+
delete extObj[prop];
|
|
21
|
+
}
|
|
22
|
+
baseObj[prop] = value;
|
|
23
|
+
return true;
|
|
24
|
+
},
|
|
25
|
+
deleteProperty(_target, prop) {
|
|
26
|
+
let success = false;
|
|
27
|
+
if (prop in extObj) {
|
|
28
|
+
delete extObj[prop];
|
|
29
|
+
success = true;
|
|
30
|
+
}
|
|
31
|
+
if (prop in baseObj) {
|
|
32
|
+
delete baseObj[prop];
|
|
33
|
+
success = true;
|
|
34
|
+
}
|
|
35
|
+
return success;
|
|
36
|
+
},
|
|
37
|
+
ownKeys(_target) {
|
|
38
|
+
const baseKeys = Reflect.ownKeys(baseObj);
|
|
39
|
+
const extKeys = Reflect.ownKeys(extObj);
|
|
40
|
+
const extKeysSet = new Set(extKeys);
|
|
41
|
+
return [...baseKeys.filter((k) => !extKeysSet.has(k)), ...extKeys];
|
|
42
|
+
},
|
|
43
|
+
defineProperty(_target, prop, desc) {
|
|
44
|
+
if (prop in extObj) {
|
|
45
|
+
delete extObj[prop];
|
|
46
|
+
}
|
|
47
|
+
Reflect.defineProperty(baseObj, prop, desc);
|
|
48
|
+
return true;
|
|
49
|
+
},
|
|
50
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
51
|
+
if (prop in extObj) {
|
|
52
|
+
return Reflect.getOwnPropertyDescriptor(extObj, prop);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
return Reflect.getOwnPropertyDescriptor(baseObj, prop);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
has(_target, prop) {
|
|
59
|
+
return prop in extObj || prop in baseObj;
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* All internal non-test code, that is files that do not have `test` or `bench` in the name, must use the assertion functions within `_utils/asserts.ts` and not `testing/asserts.ts`. This is to create a separation of concerns between internal and testing assertions.
|
|
3
|
+
*/
|
|
4
|
+
export declare class DenoStdInternalError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
/** Make an assertion, if not `true`, then throw. */
|
|
8
|
+
export declare function assert(expr: unknown, msg?: string): asserts expr;
|
|
9
|
+
/** Use this to assert unreachable code. */
|
|
10
|
+
export declare function unreachable(): never;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
2
|
+
// This module is browser compatible.
|
|
3
|
+
/**
|
|
4
|
+
* All internal non-test code, that is files that do not have `test` or `bench` in the name, must use the assertion functions within `_utils/asserts.ts` and not `testing/asserts.ts`. This is to create a separation of concerns between internal and testing assertions.
|
|
5
|
+
*/
|
|
6
|
+
export class DenoStdInternalError extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "DenoStdInternalError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Make an assertion, if not `true`, then throw. */
|
|
13
|
+
export function assert(expr, msg = "") {
|
|
14
|
+
if (!expr) {
|
|
15
|
+
throw new DenoStdInternalError(msg);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** Use this to assert unreachable code. */
|
|
19
|
+
export function unreachable() {
|
|
20
|
+
throw new DenoStdInternalError("unreachable");
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
2
|
+
// This module is browser compatible.
|
|
3
|
+
import * as dntShim from "../../../../_dnt.shims.js";
|
|
4
|
+
export const osType = (() => {
|
|
5
|
+
// deno-lint-ignore no-explicit-any
|
|
6
|
+
const { Deno } = dntShim.dntGlobalThis;
|
|
7
|
+
if (typeof Deno?.build?.os === "string") {
|
|
8
|
+
return Deno.build.os;
|
|
9
|
+
}
|
|
10
|
+
// deno-lint-ignore no-explicit-any
|
|
11
|
+
const { navigator } = dntShim.dntGlobalThis;
|
|
12
|
+
if (navigator?.appVersion?.includes?.("Win")) {
|
|
13
|
+
return "windows";
|
|
14
|
+
}
|
|
15
|
+
return "linux";
|
|
16
|
+
})();
|
|
17
|
+
export const isWindows = osType === "windows";
|
|
18
|
+
export const isLinux = osType === "linux";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare const CHAR_UPPERCASE_A = 65;
|
|
2
|
+
export declare const CHAR_LOWERCASE_A = 97;
|
|
3
|
+
export declare const CHAR_UPPERCASE_Z = 90;
|
|
4
|
+
export declare const CHAR_LOWERCASE_Z = 122;
|
|
5
|
+
export declare const CHAR_DOT = 46;
|
|
6
|
+
export declare const CHAR_FORWARD_SLASH = 47;
|
|
7
|
+
export declare const CHAR_BACKWARD_SLASH = 92;
|
|
8
|
+
export declare const CHAR_VERTICAL_LINE = 124;
|
|
9
|
+
export declare const CHAR_COLON = 58;
|
|
10
|
+
export declare const CHAR_QUESTION_MARK = 63;
|
|
11
|
+
export declare const CHAR_UNDERSCORE = 95;
|
|
12
|
+
export declare const CHAR_LINE_FEED = 10;
|
|
13
|
+
export declare const CHAR_CARRIAGE_RETURN = 13;
|
|
14
|
+
export declare const CHAR_TAB = 9;
|
|
15
|
+
export declare const CHAR_FORM_FEED = 12;
|
|
16
|
+
export declare const CHAR_EXCLAMATION_MARK = 33;
|
|
17
|
+
export declare const CHAR_HASH = 35;
|
|
18
|
+
export declare const CHAR_SPACE = 32;
|
|
19
|
+
export declare const CHAR_NO_BREAK_SPACE = 160;
|
|
20
|
+
export declare const CHAR_ZERO_WIDTH_NOBREAK_SPACE = 65279;
|
|
21
|
+
export declare const CHAR_LEFT_SQUARE_BRACKET = 91;
|
|
22
|
+
export declare const CHAR_RIGHT_SQUARE_BRACKET = 93;
|
|
23
|
+
export declare const CHAR_LEFT_ANGLE_BRACKET = 60;
|
|
24
|
+
export declare const CHAR_RIGHT_ANGLE_BRACKET = 62;
|
|
25
|
+
export declare const CHAR_LEFT_CURLY_BRACKET = 123;
|
|
26
|
+
export declare const CHAR_RIGHT_CURLY_BRACKET = 125;
|
|
27
|
+
export declare const CHAR_HYPHEN_MINUS = 45;
|
|
28
|
+
export declare const CHAR_PLUS = 43;
|
|
29
|
+
export declare const CHAR_DOUBLE_QUOTE = 34;
|
|
30
|
+
export declare const CHAR_SINGLE_QUOTE = 39;
|
|
31
|
+
export declare const CHAR_PERCENT = 37;
|
|
32
|
+
export declare const CHAR_SEMICOLON = 59;
|
|
33
|
+
export declare const CHAR_CIRCUMFLEX_ACCENT = 94;
|
|
34
|
+
export declare const CHAR_GRAVE_ACCENT = 96;
|
|
35
|
+
export declare const CHAR_AT = 64;
|
|
36
|
+
export declare const CHAR_AMPERSAND = 38;
|
|
37
|
+
export declare const CHAR_EQUAL = 61;
|
|
38
|
+
export declare const CHAR_0 = 48;
|
|
39
|
+
export declare const CHAR_9 = 57;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
2
|
+
// Copyright the Browserify authors. MIT License.
|
|
3
|
+
// Ported from https://github.com/browserify/path-browserify/
|
|
4
|
+
// This module is browser compatible.
|
|
5
|
+
// Alphabet chars.
|
|
6
|
+
export const CHAR_UPPERCASE_A = 65; /* A */
|
|
7
|
+
export const CHAR_LOWERCASE_A = 97; /* a */
|
|
8
|
+
export const CHAR_UPPERCASE_Z = 90; /* Z */
|
|
9
|
+
export const CHAR_LOWERCASE_Z = 122; /* z */
|
|
10
|
+
// Non-alphabetic chars.
|
|
11
|
+
export const CHAR_DOT = 46; /* . */
|
|
12
|
+
export const CHAR_FORWARD_SLASH = 47; /* / */
|
|
13
|
+
export const CHAR_BACKWARD_SLASH = 92; /* \ */
|
|
14
|
+
export const CHAR_VERTICAL_LINE = 124; /* | */
|
|
15
|
+
export const CHAR_COLON = 58; /* : */
|
|
16
|
+
export const CHAR_QUESTION_MARK = 63; /* ? */
|
|
17
|
+
export const CHAR_UNDERSCORE = 95; /* _ */
|
|
18
|
+
export const CHAR_LINE_FEED = 10; /* \n */
|
|
19
|
+
export const CHAR_CARRIAGE_RETURN = 13; /* \r */
|
|
20
|
+
export const CHAR_TAB = 9; /* \t */
|
|
21
|
+
export const CHAR_FORM_FEED = 12; /* \f */
|
|
22
|
+
export const CHAR_EXCLAMATION_MARK = 33; /* ! */
|
|
23
|
+
export const CHAR_HASH = 35; /* # */
|
|
24
|
+
export const CHAR_SPACE = 32; /* */
|
|
25
|
+
export const CHAR_NO_BREAK_SPACE = 160; /* \u00A0 */
|
|
26
|
+
export const CHAR_ZERO_WIDTH_NOBREAK_SPACE = 65279; /* \uFEFF */
|
|
27
|
+
export const CHAR_LEFT_SQUARE_BRACKET = 91; /* [ */
|
|
28
|
+
export const CHAR_RIGHT_SQUARE_BRACKET = 93; /* ] */
|
|
29
|
+
export const CHAR_LEFT_ANGLE_BRACKET = 60; /* < */
|
|
30
|
+
export const CHAR_RIGHT_ANGLE_BRACKET = 62; /* > */
|
|
31
|
+
export const CHAR_LEFT_CURLY_BRACKET = 123; /* { */
|
|
32
|
+
export const CHAR_RIGHT_CURLY_BRACKET = 125; /* } */
|
|
33
|
+
export const CHAR_HYPHEN_MINUS = 45; /* - */
|
|
34
|
+
export const CHAR_PLUS = 43; /* + */
|
|
35
|
+
export const CHAR_DOUBLE_QUOTE = 34; /* " */
|
|
36
|
+
export const CHAR_SINGLE_QUOTE = 39; /* ' */
|
|
37
|
+
export const CHAR_PERCENT = 37; /* % */
|
|
38
|
+
export const CHAR_SEMICOLON = 59; /* ; */
|
|
39
|
+
export const CHAR_CIRCUMFLEX_ACCENT = 94; /* ^ */
|
|
40
|
+
export const CHAR_GRAVE_ACCENT = 96; /* ` */
|
|
41
|
+
export const CHAR_AT = 64; /* @ */
|
|
42
|
+
export const CHAR_AMPERSAND = 38; /* & */
|
|
43
|
+
export const CHAR_EQUAL = 61; /* = */
|
|
44
|
+
// Digits
|
|
45
|
+
export const CHAR_0 = 48; /* 0 */
|
|
46
|
+
export const CHAR_9 = 57; /* 9 */
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A parsed path object generated by path.parse() or consumed by path.format().
|
|
3
|
+
*/
|
|
4
|
+
export interface ParsedPath {
|
|
5
|
+
/**
|
|
6
|
+
* The root of the path such as '/' or 'c:\'
|
|
7
|
+
*/
|
|
8
|
+
root: string;
|
|
9
|
+
/**
|
|
10
|
+
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
|
|
11
|
+
*/
|
|
12
|
+
dir: string;
|
|
13
|
+
/**
|
|
14
|
+
* The file name including extension (if any) such as 'index.html'
|
|
15
|
+
*/
|
|
16
|
+
base: string;
|
|
17
|
+
/**
|
|
18
|
+
* The file extension (if any) such as '.html'
|
|
19
|
+
*/
|
|
20
|
+
ext: string;
|
|
21
|
+
/**
|
|
22
|
+
* The file name without extension (if any) such as 'index'
|
|
23
|
+
*/
|
|
24
|
+
name: string;
|
|
25
|
+
}
|
|
26
|
+
export type FormatInputPathObject = Partial<ParsedPath>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FormatInputPathObject } from "./_interface.js";
|
|
2
|
+
export declare function assertPath(path: string): void;
|
|
3
|
+
export declare function isPosixPathSeparator(code: number): boolean;
|
|
4
|
+
export declare function isPathSeparator(code: number): boolean;
|
|
5
|
+
export declare function isWindowsDeviceRoot(code: number): boolean;
|
|
6
|
+
export declare function normalizeString(path: string, allowAboveRoot: boolean, separator: string, isPathSeparator: (code: number) => boolean): string;
|
|
7
|
+
export declare function _format(sep: string, pathObject: FormatInputPathObject): string;
|
|
8
|
+
export declare function encodeWhitespace(string: string): string;
|
|
9
|
+
export declare function lastPathSegment(path: string, isSep: (char: number) => boolean, start?: number): string;
|
|
10
|
+
export declare function stripTrailingSeparators(segment: string, isSep: (char: number) => boolean): string;
|
|
11
|
+
export declare function stripSuffix(name: string, suffix: string): string;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
2
|
+
// Copyright the Browserify authors. MIT License.
|
|
3
|
+
// Ported from https://github.com/browserify/path-browserify/
|
|
4
|
+
// This module is browser compatible.
|
|
5
|
+
import { CHAR_BACKWARD_SLASH, CHAR_DOT, CHAR_FORWARD_SLASH, CHAR_LOWERCASE_A, CHAR_LOWERCASE_Z, CHAR_UPPERCASE_A, CHAR_UPPERCASE_Z, } from "./_constants.js";
|
|
6
|
+
export function assertPath(path) {
|
|
7
|
+
if (typeof path !== "string") {
|
|
8
|
+
throw new TypeError(`Path must be a string. Received ${JSON.stringify(path)}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function isPosixPathSeparator(code) {
|
|
12
|
+
return code === CHAR_FORWARD_SLASH;
|
|
13
|
+
}
|
|
14
|
+
export function isPathSeparator(code) {
|
|
15
|
+
return isPosixPathSeparator(code) || code === CHAR_BACKWARD_SLASH;
|
|
16
|
+
}
|
|
17
|
+
export function isWindowsDeviceRoot(code) {
|
|
18
|
+
return ((code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z) ||
|
|
19
|
+
(code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z));
|
|
20
|
+
}
|
|
21
|
+
// Resolves . and .. elements in a path with directory names
|
|
22
|
+
export function normalizeString(path, allowAboveRoot, separator, isPathSeparator) {
|
|
23
|
+
let res = "";
|
|
24
|
+
let lastSegmentLength = 0;
|
|
25
|
+
let lastSlash = -1;
|
|
26
|
+
let dots = 0;
|
|
27
|
+
let code;
|
|
28
|
+
for (let i = 0, len = path.length; i <= len; ++i) {
|
|
29
|
+
if (i < len)
|
|
30
|
+
code = path.charCodeAt(i);
|
|
31
|
+
else if (isPathSeparator(code))
|
|
32
|
+
break;
|
|
33
|
+
else
|
|
34
|
+
code = CHAR_FORWARD_SLASH;
|
|
35
|
+
if (isPathSeparator(code)) {
|
|
36
|
+
if (lastSlash === i - 1 || dots === 1) {
|
|
37
|
+
// NOOP
|
|
38
|
+
}
|
|
39
|
+
else if (lastSlash !== i - 1 && dots === 2) {
|
|
40
|
+
if (res.length < 2 ||
|
|
41
|
+
lastSegmentLength !== 2 ||
|
|
42
|
+
res.charCodeAt(res.length - 1) !== CHAR_DOT ||
|
|
43
|
+
res.charCodeAt(res.length - 2) !== CHAR_DOT) {
|
|
44
|
+
if (res.length > 2) {
|
|
45
|
+
const lastSlashIndex = res.lastIndexOf(separator);
|
|
46
|
+
if (lastSlashIndex === -1) {
|
|
47
|
+
res = "";
|
|
48
|
+
lastSegmentLength = 0;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
res = res.slice(0, lastSlashIndex);
|
|
52
|
+
lastSegmentLength = res.length - 1 - res.lastIndexOf(separator);
|
|
53
|
+
}
|
|
54
|
+
lastSlash = i;
|
|
55
|
+
dots = 0;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
else if (res.length === 2 || res.length === 1) {
|
|
59
|
+
res = "";
|
|
60
|
+
lastSegmentLength = 0;
|
|
61
|
+
lastSlash = i;
|
|
62
|
+
dots = 0;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (allowAboveRoot) {
|
|
67
|
+
if (res.length > 0)
|
|
68
|
+
res += `${separator}..`;
|
|
69
|
+
else
|
|
70
|
+
res = "..";
|
|
71
|
+
lastSegmentLength = 2;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
if (res.length > 0)
|
|
76
|
+
res += separator + path.slice(lastSlash + 1, i);
|
|
77
|
+
else
|
|
78
|
+
res = path.slice(lastSlash + 1, i);
|
|
79
|
+
lastSegmentLength = i - lastSlash - 1;
|
|
80
|
+
}
|
|
81
|
+
lastSlash = i;
|
|
82
|
+
dots = 0;
|
|
83
|
+
}
|
|
84
|
+
else if (code === CHAR_DOT && dots !== -1) {
|
|
85
|
+
++dots;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
dots = -1;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return res;
|
|
92
|
+
}
|
|
93
|
+
export function _format(sep, pathObject) {
|
|
94
|
+
const dir = pathObject.dir || pathObject.root;
|
|
95
|
+
const base = pathObject.base ||
|
|
96
|
+
(pathObject.name || "") + (pathObject.ext || "");
|
|
97
|
+
if (!dir)
|
|
98
|
+
return base;
|
|
99
|
+
if (base === sep)
|
|
100
|
+
return dir;
|
|
101
|
+
if (dir === pathObject.root)
|
|
102
|
+
return dir + base;
|
|
103
|
+
return dir + sep + base;
|
|
104
|
+
}
|
|
105
|
+
const WHITESPACE_ENCODINGS = {
|
|
106
|
+
"\u0009": "%09",
|
|
107
|
+
"\u000A": "%0A",
|
|
108
|
+
"\u000B": "%0B",
|
|
109
|
+
"\u000C": "%0C",
|
|
110
|
+
"\u000D": "%0D",
|
|
111
|
+
"\u0020": "%20",
|
|
112
|
+
};
|
|
113
|
+
export function encodeWhitespace(string) {
|
|
114
|
+
return string.replaceAll(/[\s]/g, (c) => {
|
|
115
|
+
return WHITESPACE_ENCODINGS[c] ?? c;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
export function lastPathSegment(path, isSep, start = 0) {
|
|
119
|
+
let matchedNonSeparator = false;
|
|
120
|
+
let end = path.length;
|
|
121
|
+
for (let i = path.length - 1; i >= start; --i) {
|
|
122
|
+
if (isSep(path.charCodeAt(i))) {
|
|
123
|
+
if (matchedNonSeparator) {
|
|
124
|
+
start = i + 1;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else if (!matchedNonSeparator) {
|
|
129
|
+
matchedNonSeparator = true;
|
|
130
|
+
end = i + 1;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return path.slice(start, end);
|
|
134
|
+
}
|
|
135
|
+
export function stripTrailingSeparators(segment, isSep) {
|
|
136
|
+
if (segment.length <= 1) {
|
|
137
|
+
return segment;
|
|
138
|
+
}
|
|
139
|
+
let end = segment.length;
|
|
140
|
+
for (let i = segment.length - 1; i > 0; i--) {
|
|
141
|
+
if (isSep(segment.charCodeAt(i))) {
|
|
142
|
+
end = i;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return segment.slice(0, end);
|
|
149
|
+
}
|
|
150
|
+
export function stripSuffix(name, suffix) {
|
|
151
|
+
if (suffix.length >= name.length) {
|
|
152
|
+
return name;
|
|
153
|
+
}
|
|
154
|
+
const lenDiff = name.length - suffix.length;
|
|
155
|
+
for (let i = suffix.length - 1; i >= 0; --i) {
|
|
156
|
+
if (name.charCodeAt(lenDiff + i) !== suffix.charCodeAt(i)) {
|
|
157
|
+
return name;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return name.slice(0, -suffix.length);
|
|
161
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Determines the common path from a set of paths, using an optional separator,
|
|
2
|
+
* which defaults to the OS default separator.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import { common } from "https://deno.land/std@$STD_VERSION/path/mod.ts";
|
|
6
|
+
* const p = common([
|
|
7
|
+
* "./deno/std/path/mod.ts",
|
|
8
|
+
* "./deno/std/fs/mod.ts",
|
|
9
|
+
* ]);
|
|
10
|
+
* console.log(p); // "./deno/std/"
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function common(paths: string[], sep?: string): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
2
|
+
// This module is browser compatible.
|
|
3
|
+
import { SEP } from "./separator.js";
|
|
4
|
+
/** Determines the common path from a set of paths, using an optional separator,
|
|
5
|
+
* which defaults to the OS default separator.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { common } from "https://deno.land/std@$STD_VERSION/path/mod.ts";
|
|
9
|
+
* const p = common([
|
|
10
|
+
* "./deno/std/path/mod.ts",
|
|
11
|
+
* "./deno/std/fs/mod.ts",
|
|
12
|
+
* ]);
|
|
13
|
+
* console.log(p); // "./deno/std/"
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function common(paths, sep = SEP) {
|
|
17
|
+
const [first = "", ...remaining] = paths;
|
|
18
|
+
if (first === "" || remaining.length === 0) {
|
|
19
|
+
return first.substring(0, first.lastIndexOf(sep) + 1);
|
|
20
|
+
}
|
|
21
|
+
const parts = first.split(sep);
|
|
22
|
+
let endOfPrefix = parts.length;
|
|
23
|
+
for (const path of remaining) {
|
|
24
|
+
const compare = path.split(sep);
|
|
25
|
+
for (let i = 0; i < endOfPrefix; i++) {
|
|
26
|
+
if (compare[i] !== parts[i]) {
|
|
27
|
+
endOfPrefix = i;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (endOfPrefix === 0) {
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const prefix = parts.slice(0, endOfPrefix).join(sep);
|
|
35
|
+
return prefix.endsWith(sep) ? prefix : `${prefix}${sep}`;
|
|
36
|
+
}
|