@unvt/charites 0.1.4 → 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.
- package/.all-contributorsrc +63 -0
- package/.devcontainer/Dockerfile +29 -0
- package/.devcontainer/README.md +34 -0
- package/.devcontainer/devcontainer.json +36 -0
- package/.github/CONTRIBUTING.md +6 -4
- package/.github/PULL_REQUEST_TEMPLATE.md +1 -0
- package/.github/workflows/build.yml +1 -1
- package/README.md +8 -3
- package/dist/commands/serve.js +5 -0
- package/dist/lib/build-sprite.js +8 -62
- package/dist/lib/error.js +4 -1
- package/docs/source/install/recommended_environment.rst +1 -1
- package/package.json +7 -4
- package/provider/default/app.js +13 -0
- package/provider/default/index.html +2 -0
- package/provider/mapbox/app.js +14 -0
- package/provider/mapbox/index.html +2 -0
- package/src/commands/serve.ts +5 -0
- package/src/lib/build-sprite.ts +8 -71
- package/src/lib/error.ts +3 -1
- package/test/build-sprite.spec.ts +5 -5
- package/test/build.spec.ts +11 -11
- package/test/command.build.spec.ts +100 -0
- package/test/command.convert.spec.ts +24 -0
- package/test/command.init.spec.ts +45 -0
- package/test/util/charitesCmd.ts +3 -0
- package/test/util/copyFixtures.ts +14 -0
- package/test/util/execPromise.ts +14 -0
- package/test/util/makeTempDir.ts +6 -0
package/.all-contributorsrc
CHANGED
|
@@ -13,6 +13,69 @@
|
|
|
13
13
|
"contributions": [
|
|
14
14
|
"code"
|
|
15
15
|
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"login": "naogify",
|
|
19
|
+
"name": "Naoki Ohashi",
|
|
20
|
+
"avatar_url": "https://avatars.githubusercontent.com/u/8760841?v=4",
|
|
21
|
+
"profile": "https://naoki-is.me",
|
|
22
|
+
"contributions": [
|
|
23
|
+
"code"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"login": "ubukawa",
|
|
28
|
+
"name": "UBUKAWA Taro",
|
|
29
|
+
"avatar_url": "https://avatars.githubusercontent.com/u/59204379?v=4",
|
|
30
|
+
"profile": "https://github.com/ubukawa",
|
|
31
|
+
"contributions": [
|
|
32
|
+
"code"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"login": "miya0001",
|
|
37
|
+
"name": "Takayuki Miyauchi",
|
|
38
|
+
"avatar_url": "https://avatars.githubusercontent.com/u/309946?v=4",
|
|
39
|
+
"profile": "https://geolonia.com/",
|
|
40
|
+
"contributions": [
|
|
41
|
+
"code"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"login": "JinIgarashi",
|
|
46
|
+
"name": "Jin Igarashi",
|
|
47
|
+
"avatar_url": "https://avatars.githubusercontent.com/u/2639701?v=4",
|
|
48
|
+
"profile": "https://jin-igarashi.me",
|
|
49
|
+
"contributions": [
|
|
50
|
+
"code"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"login": "smellman",
|
|
55
|
+
"name": "Taro Matsuzawa aka. btm",
|
|
56
|
+
"avatar_url": "https://avatars.githubusercontent.com/u/135112?v=4",
|
|
57
|
+
"profile": "http://smellman.hatenablog.com/",
|
|
58
|
+
"contributions": [
|
|
59
|
+
"code"
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"login": "ShinichiNishikawa",
|
|
64
|
+
"name": "Shinichi Nishikawa",
|
|
65
|
+
"avatar_url": "https://avatars.githubusercontent.com/u/1124652?v=4",
|
|
66
|
+
"profile": "https://shinichi.blog",
|
|
67
|
+
"contributions": [
|
|
68
|
+
"doc"
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"login": "yuiseki",
|
|
73
|
+
"name": "yuiseki",
|
|
74
|
+
"avatar_url": "https://avatars.githubusercontent.com/u/25507?v=4",
|
|
75
|
+
"profile": "http://yuiseki.net/",
|
|
76
|
+
"contributions": [
|
|
77
|
+
"code"
|
|
78
|
+
]
|
|
16
79
|
}
|
|
17
80
|
],
|
|
18
81
|
"contributorsPerLine": 7,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
FROM ubuntu:22.04
|
|
2
|
+
|
|
3
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
4
|
+
RUN apt-get update && apt install -y --no-install-recommends \
|
|
5
|
+
git \
|
|
6
|
+
curl \
|
|
7
|
+
vim \
|
|
8
|
+
htop \
|
|
9
|
+
make \
|
|
10
|
+
jq
|
|
11
|
+
|
|
12
|
+
ENV DEBIAN_FRONTEND=dialog
|
|
13
|
+
|
|
14
|
+
RUN curl -Ls https://deb.nodesource.com/setup_18.x | bash
|
|
15
|
+
RUN apt update && apt install -y nodejs npm
|
|
16
|
+
RUN npm install npm@latest -g
|
|
17
|
+
|
|
18
|
+
RUN useradd -m user
|
|
19
|
+
USER user
|
|
20
|
+
|
|
21
|
+
ENV NPM_CONFIG_DIR="/home/user/.npm-global"
|
|
22
|
+
RUN mkdir -p "${NPM_CONFIG_DIR}"
|
|
23
|
+
RUN mkdir -p "${NPM_CONFIG_DIR}/bin"
|
|
24
|
+
RUN mkdir -p "${NPM_CONFIG_DIR}/lib"
|
|
25
|
+
ENV PATH="/home/user/.npm-global/bin:${PATH}"
|
|
26
|
+
|
|
27
|
+
EXPOSE 8080
|
|
28
|
+
|
|
29
|
+
CMD [ "sleep", "infinity" ]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Development Containers (DevContainer) for charites
|
|
2
|
+
|
|
3
|
+
## What is it?
|
|
4
|
+
|
|
5
|
+
- DevContainer is a Dockerfike and configuration file for remote development in Visual Studio Code or GitHub Codespaces
|
|
6
|
+
- DevContainer allows development environments to be written and maintained as code
|
|
7
|
+
- DevContainer allows everyone to develop in a common development environment
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
- Visual Studio Code
|
|
12
|
+
- Docker
|
|
13
|
+
|
|
14
|
+
## How to use it?
|
|
15
|
+
|
|
16
|
+
- Fork `charites` repository (If not yet)
|
|
17
|
+
- Sync your fork from upstream (If not yet)
|
|
18
|
+
- Clone `charites` repository (If not yet)
|
|
19
|
+
- Open cloned directory
|
|
20
|
+
- At this time, you should see a message `Reopen in container`, then click `Open` button
|
|
21
|
+
- DevContainer will be built...
|
|
22
|
+
- It take a while...
|
|
23
|
+
|
|
24
|
+
### Once the DevContainer has been built and started...
|
|
25
|
+
|
|
26
|
+
- Development can be done as usual
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
npm ci
|
|
30
|
+
npm run build
|
|
31
|
+
npm install -g .
|
|
32
|
+
charites help
|
|
33
|
+
charites serve test/data/style.yml
|
|
34
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Ubuntu 22.04 Node.js",
|
|
3
|
+
"dockerFile": "./Dockerfile",
|
|
4
|
+
"forwardPorts": [8080],
|
|
5
|
+
"remoteUser": "user",
|
|
6
|
+
"overrideCommand": false,
|
|
7
|
+
"customizations": {
|
|
8
|
+
"vscode": {
|
|
9
|
+
"settings": {
|
|
10
|
+
"terminal.integrated.profiles.linux": {
|
|
11
|
+
"bash": {
|
|
12
|
+
"path": "/bin/bash"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"terminal.integrated.defaultProfile.linux": "bash",
|
|
16
|
+
"files.autoSave": "afterDelay",
|
|
17
|
+
"files.autoSaveDelay": 1000,
|
|
18
|
+
"editor.formatOnSave": true
|
|
19
|
+
},
|
|
20
|
+
"extensions": [
|
|
21
|
+
"ms-vscode-remote.vscode-remote-extensionpack",
|
|
22
|
+
"ms-vscode.vscode-typescript-next",
|
|
23
|
+
"ms-vsliveshare.vsliveshare",
|
|
24
|
+
"esbenp.prettier-vscode",
|
|
25
|
+
"usernamehw.errorlens",
|
|
26
|
+
"VisualStudioExptTeam.vscodeintellicode",
|
|
27
|
+
"VisualStudioExptTeam.intellicode-api-usage-examples",
|
|
28
|
+
"wraith13.bracket-lens",
|
|
29
|
+
"oderwat.indent-rainbow",
|
|
30
|
+
"mosapride.zenkaku",
|
|
31
|
+
"vscode-icons-team.vscode-icons",
|
|
32
|
+
"nickdemayo.vscode-json-editor"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
package/.github/CONTRIBUTING.md
CHANGED
|
@@ -10,7 +10,9 @@ Submit a new issue only if you are sure it is a missing feature or a bug.
|
|
|
10
10
|
|
|
11
11
|
4. Run unit tests to ensure all features work well. Run: `npm test`
|
|
12
12
|
|
|
13
|
-
5.
|
|
13
|
+
5. Please add at least one unit test if you are going to add new feature.
|
|
14
|
+
|
|
15
|
+
6. Make sure `charites` command work well after installing globally. Run:
|
|
14
16
|
|
|
15
17
|
```bash
|
|
16
18
|
npm uninstall -g .
|
|
@@ -19,11 +21,11 @@ npm install -g
|
|
|
19
21
|
charites help
|
|
20
22
|
```
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
7. Make sure you submit a change specific to exactly one issue. If you have ideas for multiple changes please create separate pull requests.
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
8. Make sure update documentation under `docs` folder if your changes affect existing documents.
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
9. Push to your fork and [submit a pull request](https://help.github.com/articles/using-pull-requests). A button should appear on your fork its github page afterwards.
|
|
27
29
|
|
|
28
30
|
## Translation of charites documentation
|
|
29
31
|
|
|
@@ -19,6 +19,7 @@ Please describe what you changed briefly.
|
|
|
19
19
|
- [ ] No lint errors after `npm run lint`
|
|
20
20
|
- [ ] No errors on using `charites help` globally
|
|
21
21
|
- [ ] Make sure all the exsiting features working well
|
|
22
|
+
- [ ] Have you added at least one unit test if you are going to add new feature?
|
|
22
23
|
- [ ] Have you updated documentation?
|
|
23
24
|
<!-- ignore-task-list-end -->
|
|
24
25
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Charites
|
|
2
2
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
3
|
-
[](#contributors-)
|
|
4
4
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
5
5
|
|
|
6
6
|
An easy, intuitive, and efficient command-line tool for writing vector map styles compatible with the [Mapbox](https://docs.mapbox.com/mapbox-gl-js/style-spec/) and [MapLibre](https://maplibre.org/maplibre-gl-js-docs/style-spec/) Style Specification in YAML.
|
|
@@ -37,14 +37,19 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|
|
37
37
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
|
38
38
|
<!-- prettier-ignore-start -->
|
|
39
39
|
<!-- markdownlint-disable -->
|
|
40
|
-
|
|
41
40
|
<table>
|
|
42
41
|
<tr>
|
|
43
42
|
<td align="center"><a href="https://geolonia.com/"><img src="https://avatars.githubusercontent.com/u/42296593?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Geolonia</b></sub></a><br /><a href="https://github.com/unvt/charites/commits?author=geolonia" title="Code">💻</a></td>
|
|
43
|
+
<td align="center"><a href="https://naoki-is.me"><img src="https://avatars.githubusercontent.com/u/8760841?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Naoki Ohashi</b></sub></a><br /><a href="https://github.com/unvt/charites/commits?author=naogify" title="Code">💻</a></td>
|
|
44
|
+
<td align="center"><a href="https://github.com/ubukawa"><img src="https://avatars.githubusercontent.com/u/59204379?v=4?s=100" width="100px;" alt=""/><br /><sub><b>UBUKAWA Taro</b></sub></a><br /><a href="https://github.com/unvt/charites/commits?author=ubukawa" title="Code">💻</a></td>
|
|
45
|
+
<td align="center"><a href="https://geolonia.com/"><img src="https://avatars.githubusercontent.com/u/309946?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Takayuki Miyauchi</b></sub></a><br /><a href="https://github.com/unvt/charites/commits?author=miya0001" title="Code">💻</a></td>
|
|
46
|
+
<td align="center"><a href="https://jin-igarashi.me"><img src="https://avatars.githubusercontent.com/u/2639701?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jin Igarashi</b></sub></a><br /><a href="https://github.com/unvt/charites/commits?author=JinIgarashi" title="Code">💻</a></td>
|
|
47
|
+
<td align="center"><a href="http://smellman.hatenablog.com/"><img src="https://avatars.githubusercontent.com/u/135112?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Taro Matsuzawa aka. btm</b></sub></a><br /><a href="https://github.com/unvt/charites/commits?author=smellman" title="Code">💻</a></td>
|
|
48
|
+
<td align="center"><a href="https://shinichi.blog"><img src="https://avatars.githubusercontent.com/u/1124652?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shinichi Nishikawa</b></sub></a><br /><a href="https://github.com/unvt/charites/commits?author=ShinichiNishikawa" title="Documentation">📖</a></td>
|
|
49
|
+
<td align="center"><a href="http://yuiseki.net/"><img src="https://avatars.githubusercontent.com/u/25507?v=4?s=100" width="100px;" alt=""/><br /><sub><b>yuiseki</b></sub></a><br /><a href="https://github.com/unvt/charites/commits?author=yuiseki" title="Code">💻</a></td>
|
|
44
50
|
</tr>
|
|
45
51
|
</table>
|
|
46
52
|
|
|
47
|
-
|
|
48
53
|
<!-- markdownlint-restore -->
|
|
49
54
|
<!-- prettier-ignore-end -->
|
|
50
55
|
|
package/dist/commands/serve.js
CHANGED
|
@@ -73,6 +73,11 @@ function serve(source, options) {
|
|
|
73
73
|
throw `Invalid provider: ${provider}`;
|
|
74
74
|
}
|
|
75
75
|
break;
|
|
76
|
+
default:
|
|
77
|
+
res.statusCode = 404;
|
|
78
|
+
res.setHeader('Content-Type', 'text/plain; charset=UTF-8');
|
|
79
|
+
res.end('Not found');
|
|
80
|
+
break;
|
|
76
81
|
}
|
|
77
82
|
});
|
|
78
83
|
server.listen(port, () => {
|
package/dist/lib/build-sprite.js
CHANGED
|
@@ -1,71 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildSprite = void 0;
|
|
4
|
-
const
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const glob = require('glob');
|
|
4
|
+
const sprite_one_1 = require("@unvt/sprite-one");
|
|
7
5
|
const path = require('path');
|
|
8
|
-
function generateLayoutAsync(option) {
|
|
9
|
-
return new Promise((resolve, reject) => {
|
|
10
|
-
spritezero.generateLayout(option, (err, result) => {
|
|
11
|
-
if (err)
|
|
12
|
-
reject(err);
|
|
13
|
-
else
|
|
14
|
-
resolve(result);
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
function generateImageAsync(option) {
|
|
19
|
-
return new Promise((resolve, reject) => {
|
|
20
|
-
spritezero.generateImage(option, (err, result) => {
|
|
21
|
-
if (err)
|
|
22
|
-
reject(err);
|
|
23
|
-
else
|
|
24
|
-
resolve(result);
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
6
|
async function buildSprite(svgPath, publicPath, iconSlug) {
|
|
29
7
|
const pxRatios = [1, 2];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
svg: fs.readFileSync(iconPath),
|
|
37
|
-
id: path.basename(iconPath).replace('.svg', ''),
|
|
38
|
-
};
|
|
39
|
-
});
|
|
40
|
-
let file = '';
|
|
41
|
-
if (pxRatio > 1) {
|
|
42
|
-
file = `@${pxRatio}x`;
|
|
43
|
-
}
|
|
44
|
-
const pngPath = path.join(publicPath, `${iconSlug}${file}.png`);
|
|
45
|
-
const jsonPath = path.join(publicPath, `${iconSlug}${file}.json`);
|
|
46
|
-
try {
|
|
47
|
-
const dataLayout = await generateLayoutAsync({
|
|
48
|
-
imgs: svgFiles,
|
|
49
|
-
pixelRatio: pxRatio,
|
|
50
|
-
format: true,
|
|
51
|
-
});
|
|
52
|
-
fs.writeFileSync(jsonPath, JSON.stringify(dataLayout));
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
throw `${publicPath}: No such file or directory`;
|
|
56
|
-
}
|
|
57
|
-
try {
|
|
58
|
-
const imageLayout = await generateLayoutAsync({
|
|
59
|
-
imgs: svgFiles,
|
|
60
|
-
pixelRatio: pxRatio,
|
|
61
|
-
format: false,
|
|
62
|
-
});
|
|
63
|
-
const image = await generateImageAsync(imageLayout);
|
|
64
|
-
fs.writeFileSync(pngPath, image);
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
throw `${publicPath}: No such file or directory`;
|
|
68
|
-
}
|
|
8
|
+
const outPath = path.join(publicPath, iconSlug);
|
|
9
|
+
try {
|
|
10
|
+
await sprite_one_1.generateSprite(outPath, [svgPath], pxRatios);
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
throw error;
|
|
69
14
|
}
|
|
15
|
+
return;
|
|
70
16
|
}
|
|
71
17
|
exports.buildSprite = buildSprite;
|
package/dist/lib/error.js
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.error = void 0;
|
|
4
4
|
exports.error = (e) => {
|
|
5
|
-
if (e instanceof
|
|
5
|
+
if (e instanceof Error) {
|
|
6
6
|
console.error(e.message);
|
|
7
7
|
}
|
|
8
|
+
else {
|
|
9
|
+
console.error(String(e));
|
|
10
|
+
}
|
|
8
11
|
process.exit(1);
|
|
9
12
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Recommended environment
|
|
2
2
|
=======================
|
|
3
3
|
|
|
4
|
-
Chrities may work well on OSX, Ubuntu,
|
|
4
|
+
Chrities may work well on OSX, Ubuntu, and Raspberry Pi.
|
|
5
5
|
|
|
6
6
|
Docker can be the good environment in Windows while WSL might work well.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unvt/charites",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"bin": {
|
|
6
6
|
"charites": "dist/cli.js"
|
|
@@ -9,16 +9,16 @@
|
|
|
9
9
|
"build": "tsc -p .",
|
|
10
10
|
"watch": "tsc -w",
|
|
11
11
|
"lint": "eslint --fix .",
|
|
12
|
-
"test": "mocha -r ts-node/register test/*.ts",
|
|
12
|
+
"test": "npm run build && mocha -r ts-node/register test/*.ts",
|
|
13
13
|
"test:watch": "npm test -- --watch --watch-files src/**/*.ts --watch-files test/**/*.ts",
|
|
14
|
-
"command": "./node_modules/.bin/ts-node ./src/cli"
|
|
14
|
+
"command": "./node_modules/.bin/ts-node ./src/cli.ts"
|
|
15
15
|
},
|
|
16
16
|
"author": "",
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@mapbox/mapbox-gl-style-spec": "^13.22.0",
|
|
20
|
-
"@mapbox/spritezero": "^8.0.0",
|
|
21
20
|
"@maplibre/maplibre-gl-style-spec": "^14.0.2",
|
|
21
|
+
"@unvt/sprite-one": "^0.0.6",
|
|
22
22
|
"@types/jsonminify": "^0.4.1",
|
|
23
23
|
"axios": "^0.24.0",
|
|
24
24
|
"commander": "^8.2.0",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/chai": "^4.2.11",
|
|
35
|
+
"@types/fs-extra": "^9.0.13",
|
|
35
36
|
"@types/js-yaml": "^4.0.3",
|
|
36
37
|
"@types/mocha": "^7.0.2",
|
|
37
38
|
"@types/node": "^14.0.14",
|
|
@@ -42,6 +43,8 @@
|
|
|
42
43
|
"eslint": "^7.21.0",
|
|
43
44
|
"eslint-config-prettier": "^6.15.0",
|
|
44
45
|
"eslint-plugin-prettier": "^3.3.1",
|
|
46
|
+
"fs-extra": "^10.0.0",
|
|
47
|
+
"kill-port-process": "^3.0.1",
|
|
45
48
|
"mocha": "^8.0.1",
|
|
46
49
|
"prettier": "^2.5.0",
|
|
47
50
|
"ts-node": "^8.10.2",
|
package/provider/default/app.js
CHANGED
|
@@ -12,6 +12,19 @@ socket.addEventListener('message', (message) => {
|
|
|
12
12
|
|
|
13
13
|
map.addControl(new maplibregl.NavigationControl(), 'top-right')
|
|
14
14
|
|
|
15
|
+
map.addControl(
|
|
16
|
+
new watergis.MaplibreLegendControl(
|
|
17
|
+
{},
|
|
18
|
+
{
|
|
19
|
+
showDefault: true,
|
|
20
|
+
showCheckbox: true,
|
|
21
|
+
onlyRendered: true,
|
|
22
|
+
reverseOrder: true,
|
|
23
|
+
},
|
|
24
|
+
),
|
|
25
|
+
'bottom-left',
|
|
26
|
+
)
|
|
27
|
+
|
|
15
28
|
const showTileBoundaries = document.getElementById('showTileBoundaries')
|
|
16
29
|
const setShowTileBoundaries = function () {
|
|
17
30
|
const checked = showTileBoundaries.checked
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<link rel="stylesheet" href="/app.css" />
|
|
5
5
|
<link href='https://unpkg.com/maplibre-gl@1.15.2/dist/maplibre-gl.css' rel='stylesheet' />
|
|
6
|
+
<link href='https://watergis.github.io/maplibre-gl-legend/maplibre-gl-legend.css' rel='stylesheet' />
|
|
6
7
|
<title>Charites Live Preview</title>
|
|
7
8
|
<script src='https://unpkg.com/maplibre-gl@1.15.2/dist/maplibre-gl.js'></script>
|
|
9
|
+
<script src="https://watergis.github.io/maplibre-gl-legend/maplibre-gl-legend.js"></script>
|
|
8
10
|
</head>
|
|
9
11
|
<body>
|
|
10
12
|
<div class="overlay">
|
package/provider/mapbox/app.js
CHANGED
|
@@ -14,6 +14,20 @@ socket.addEventListener('message', (message) => {
|
|
|
14
14
|
|
|
15
15
|
map.addControl(new mapboxgl.NavigationControl(), 'top-right')
|
|
16
16
|
|
|
17
|
+
map.addControl(
|
|
18
|
+
new watergis.MapboxLegendControl(
|
|
19
|
+
{},
|
|
20
|
+
{
|
|
21
|
+
showDefault: true,
|
|
22
|
+
showCheckbox: true,
|
|
23
|
+
onlyRendered: true,
|
|
24
|
+
reverseOrder: true,
|
|
25
|
+
accesstoken: mapboxgl.accessToken,
|
|
26
|
+
},
|
|
27
|
+
),
|
|
28
|
+
'bottom-left',
|
|
29
|
+
)
|
|
30
|
+
|
|
17
31
|
const showTileBoundaries = document.getElementById('showTileBoundaries')
|
|
18
32
|
const setShowTileBoundaries = function () {
|
|
19
33
|
const checked = showTileBoundaries.checked
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<link rel="stylesheet" href="/app.css" />
|
|
5
5
|
<link href='https://api.mapbox.com/mapbox-gl-js/v2.5.0/mapbox-gl.css' rel='stylesheet' />
|
|
6
|
+
<link href='https://watergis.github.io/mapbox-gl-legend/mapbox-gl-legend.css' rel='stylesheet' />
|
|
6
7
|
<title>Charites Live Preview</title>
|
|
7
8
|
<script src='https://api.mapbox.com/mapbox-gl-js/v2.5.0/mapbox-gl.js'></script>
|
|
9
|
+
<script src="https://watergis.github.io/mapbox-gl-legend/mapbox-gl-legend.js"></script>
|
|
8
10
|
</head>
|
|
9
11
|
<body>
|
|
10
12
|
<div class="overlay">
|
package/src/commands/serve.ts
CHANGED
|
@@ -81,6 +81,11 @@ export function serve(source: string, options: serveOptions) {
|
|
|
81
81
|
throw `Invalid provider: ${provider}`
|
|
82
82
|
}
|
|
83
83
|
break
|
|
84
|
+
default:
|
|
85
|
+
res.statusCode = 404
|
|
86
|
+
res.setHeader('Content-Type', 'text/plain; charset=UTF-8')
|
|
87
|
+
res.end('Not found')
|
|
88
|
+
break
|
|
84
89
|
}
|
|
85
90
|
})
|
|
86
91
|
|
package/src/lib/build-sprite.ts
CHANGED
|
@@ -1,80 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
const fs = require('fs')
|
|
3
|
-
const glob = require('glob')
|
|
1
|
+
import { generateSprite } from '@unvt/sprite-one'
|
|
4
2
|
const path = require('path')
|
|
5
3
|
|
|
6
|
-
type spriteOption = {
|
|
7
|
-
imgs: string
|
|
8
|
-
pixelRatio: number
|
|
9
|
-
format: boolean
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function generateLayoutAsync(option: spriteOption): Promise<string> {
|
|
13
|
-
return new Promise((resolve, reject) => {
|
|
14
|
-
spritezero.generateLayout(option, (err: TypeError, result: string) => {
|
|
15
|
-
if (err) reject(err)
|
|
16
|
-
else resolve(result)
|
|
17
|
-
})
|
|
18
|
-
})
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function generateImageAsync(option: string): Promise<string> {
|
|
22
|
-
return new Promise((resolve, reject) => {
|
|
23
|
-
spritezero.generateImage(option, (err: TypeError, result: string) => {
|
|
24
|
-
if (err) reject(err)
|
|
25
|
-
else resolve(result)
|
|
26
|
-
})
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
4
|
export async function buildSprite(
|
|
31
5
|
svgPath: string,
|
|
32
6
|
publicPath: string,
|
|
33
7
|
iconSlug: string,
|
|
34
|
-
) {
|
|
8
|
+
): Promise<void> {
|
|
35
9
|
const pxRatios = [1, 2]
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
.sync(path.join(svgPath, `*.svg`))
|
|
42
|
-
.map(function (iconPath: string) {
|
|
43
|
-
return {
|
|
44
|
-
svg: fs.readFileSync(iconPath),
|
|
45
|
-
id: path.basename(iconPath).replace('.svg', ''),
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
let file = ''
|
|
50
|
-
if (pxRatio > 1) {
|
|
51
|
-
file = `@${pxRatio}x`
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const pngPath = path.join(publicPath, `${iconSlug}${file}.png`)
|
|
55
|
-
const jsonPath = path.join(publicPath, `${iconSlug}${file}.json`)
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
const dataLayout = await generateLayoutAsync({
|
|
59
|
-
imgs: svgFiles,
|
|
60
|
-
pixelRatio: pxRatio,
|
|
61
|
-
format: true,
|
|
62
|
-
})
|
|
63
|
-
fs.writeFileSync(jsonPath, JSON.stringify(dataLayout))
|
|
64
|
-
} catch (error) {
|
|
65
|
-
throw `${publicPath}: No such file or directory`
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const imageLayout = await generateLayoutAsync({
|
|
70
|
-
imgs: svgFiles,
|
|
71
|
-
pixelRatio: pxRatio,
|
|
72
|
-
format: false,
|
|
73
|
-
})
|
|
74
|
-
const image = await generateImageAsync(imageLayout)
|
|
75
|
-
fs.writeFileSync(pngPath, image)
|
|
76
|
-
} catch (error) {
|
|
77
|
-
throw `${publicPath}: No such file or directory`
|
|
78
|
-
}
|
|
10
|
+
const outPath = path.join(publicPath, iconSlug)
|
|
11
|
+
try {
|
|
12
|
+
await generateSprite(outPath, [svgPath], pxRatios)
|
|
13
|
+
} catch (error) {
|
|
14
|
+
throw error
|
|
79
15
|
}
|
|
16
|
+
return
|
|
80
17
|
}
|
package/src/lib/error.ts
CHANGED
|
@@ -12,13 +12,13 @@ describe('Test for the `build-sprite.ts`.', () => {
|
|
|
12
12
|
tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'charites-'))
|
|
13
13
|
})
|
|
14
14
|
|
|
15
|
-
it("should create icon's json/png at specified path and name ",
|
|
15
|
+
it("should create icon's json/png at specified path and name ", () => {
|
|
16
16
|
const expectedJsonPath = path.join(tmpdir, 'basic.json')
|
|
17
17
|
const expectedPngPath = path.join(tmpdir, 'basic.png')
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
buildSprite(iconsPath, tmpdir, `basic`).then(() => {
|
|
20
|
+
assert.deepEqual(true, !!fs.statSync(expectedJsonPath))
|
|
21
|
+
assert.deepEqual(true, !!fs.statSync(expectedPngPath))
|
|
22
|
+
})
|
|
23
23
|
})
|
|
24
24
|
})
|
package/test/build.spec.ts
CHANGED
|
@@ -69,36 +69,36 @@ describe('Test for the `build.ts`.', () => {
|
|
|
69
69
|
)
|
|
70
70
|
})
|
|
71
71
|
|
|
72
|
-
it('Should build icons with the option `--sprite-url`. Icon file name is set by spriteUrl',
|
|
72
|
+
it('Should build icons with the option `--sprite-url`. Icon file name is set by spriteUrl', () => {
|
|
73
73
|
const expectedIconName = 'dark'
|
|
74
74
|
const expectedPng = path.join(tmpdir, `${expectedIconName}.png`)
|
|
75
75
|
const expectedJson = path.join(tmpdir, `${expectedIconName}.json`)
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
build(styleYaml, styleJson, {
|
|
78
78
|
provider: defaultValues.provider,
|
|
79
79
|
spriteUrl: `http://localhost:8080/${expectedIconName}`,
|
|
80
80
|
spriteInput: iconSource,
|
|
81
81
|
spriteOutput: tmpdir,
|
|
82
|
+
}).then(() => {
|
|
83
|
+
assert.deepEqual(true, !!fs.statSync(expectedPng))
|
|
84
|
+
assert.deepEqual(true, !!fs.statSync(expectedJson))
|
|
82
85
|
})
|
|
83
|
-
|
|
84
|
-
assert.deepEqual(true, !!fs.statSync(expectedPng))
|
|
85
|
-
assert.deepEqual(true, !!fs.statSync(expectedJson))
|
|
86
86
|
})
|
|
87
87
|
|
|
88
|
-
it('Use sprite name that specified in style.json with no --sprite-url option',
|
|
88
|
+
it('Use sprite name that specified in style.json with no --sprite-url option', () => {
|
|
89
89
|
const expectedIconName = 'basic-white' // from test/data/style.yml
|
|
90
90
|
const expectedPng = path.join(tmpdir, `${expectedIconName}.png`)
|
|
91
91
|
const expectedJson = path.join(tmpdir, `${expectedIconName}.json`)
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
build(styleYaml, styleJson, {
|
|
94
94
|
provider: defaultValues.provider,
|
|
95
95
|
spriteInput: iconSource,
|
|
96
96
|
spriteOutput: tmpdir,
|
|
97
|
+
}).then(() => {
|
|
98
|
+
// The file should exists.
|
|
99
|
+
assert.deepEqual(true, !!fs.statSync(expectedPng))
|
|
100
|
+
assert.deepEqual(true, !!fs.statSync(expectedJson))
|
|
97
101
|
})
|
|
98
|
-
|
|
99
|
-
// The file should exists.
|
|
100
|
-
assert.deepEqual(true, !!fs.statSync(expectedPng))
|
|
101
|
-
assert.deepEqual(true, !!fs.statSync(expectedJson))
|
|
102
102
|
})
|
|
103
103
|
|
|
104
104
|
it('Should not create sprite when input directory is not exist.', async () => {
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { assert } from 'chai'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import { copyFixturesFile, copyFixturesDir } from './util/copyFixtures'
|
|
5
|
+
import { exec } from './util/execPromise'
|
|
6
|
+
import { makeTempDir } from './util/makeTempDir'
|
|
7
|
+
import charites from './util/charitesCmd'
|
|
8
|
+
|
|
9
|
+
let tmpdir = ''
|
|
10
|
+
|
|
11
|
+
describe('Test for the `charites build`', () => {
|
|
12
|
+
beforeEach(async function () {
|
|
13
|
+
tmpdir = makeTempDir()
|
|
14
|
+
copyFixturesFile('style.yml', tmpdir)
|
|
15
|
+
copyFixturesDir('layers', tmpdir)
|
|
16
|
+
copyFixturesDir('icons', tmpdir)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('charites build style.yml', async () => {
|
|
20
|
+
// prettier-ignore
|
|
21
|
+
const { stdout, stderr } = await exec(`${charites} build style.yml`, tmpdir)
|
|
22
|
+
assert.deepEqual(stdout, '')
|
|
23
|
+
assert.deepEqual(stderr, '')
|
|
24
|
+
assert.isTrue(fs.existsSync(path.join(tmpdir, 'style.json')))
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('charites build style.yml custom.json', async () => {
|
|
28
|
+
// prettier-ignore
|
|
29
|
+
const { stdout, stderr } = await exec(`${charites} build style.yml custom.json`, tmpdir)
|
|
30
|
+
assert.deepEqual(stdout, '')
|
|
31
|
+
assert.deepEqual(stderr, '')
|
|
32
|
+
assert.isTrue(fs.existsSync(path.join(tmpdir, 'custom.json')))
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('charites build style.yml --compact-output', async () => {
|
|
36
|
+
// prettier-ignore
|
|
37
|
+
const { stdout, stderr } = await exec(`${charites} build style.yml --compact-output`, tmpdir)
|
|
38
|
+
assert.deepEqual(stdout, '')
|
|
39
|
+
assert.deepEqual(stderr, '')
|
|
40
|
+
|
|
41
|
+
const contents = fs.readFileSync(path.join(tmpdir, 'style.json'), 'utf-8')
|
|
42
|
+
assert.isNull(contents.match(/\\n/))
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('charites build style.yml style.json --sprite-url http://localhost:8080/icons', async () => {
|
|
46
|
+
// prettier-ignore
|
|
47
|
+
const { stdout, stderr } = await exec(`${charites} build style.yml style.json --sprite-url http://localhost:8080/icons`, tmpdir)
|
|
48
|
+
assert.deepEqual(stdout, '')
|
|
49
|
+
assert.deepEqual(stderr, '')
|
|
50
|
+
|
|
51
|
+
const contents = fs.readFileSync(path.join(tmpdir, 'style.json'), 'utf-8')
|
|
52
|
+
assert.deepEqual('http://localhost:8080/icons', JSON.parse(contents).sprite)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('charites build style.yml style.json --sprite-input icons --sprite-output .', async () => {
|
|
56
|
+
// prettier-ignore
|
|
57
|
+
const { stdout, stderr } = await exec(`${charites} build style.yml style.json --sprite-input icons --sprite-output .`, tmpdir)
|
|
58
|
+
assert.deepEqual(stdout, '')
|
|
59
|
+
assert.deepEqual(stderr, '')
|
|
60
|
+
|
|
61
|
+
assert.isTrue(fs.existsSync(path.join(tmpdir, 'basic-white.png')))
|
|
62
|
+
assert.isTrue(fs.existsSync(path.join(tmpdir, 'basic-white.json')))
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('charites build style.yml style.json --sprite-url http://localhost:8080', async () => {
|
|
66
|
+
try {
|
|
67
|
+
// prettier-ignore
|
|
68
|
+
await exec(`${charites} build style.yml style.json --sprite-url http://localhost:8080`, tmpdir)
|
|
69
|
+
} catch (error) {
|
|
70
|
+
assert.deepEqual(error.stdout, '')
|
|
71
|
+
assert.deepEqual(error.stderr, 'Invalid sprite url format.\n')
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('charites build style.yml style.json --sprite-input noExistDirname', async () => {
|
|
76
|
+
try {
|
|
77
|
+
// prettier-ignore
|
|
78
|
+
await exec(`${charites} build style.yml style.json --sprite-input noExistDirname`, tmpdir)
|
|
79
|
+
} catch (error) {
|
|
80
|
+
assert.deepEqual(error.stdout, '')
|
|
81
|
+
assert.deepEqual(
|
|
82
|
+
error.stderr,
|
|
83
|
+
'noExistDirname: No such directory. Please specify valid icon input directory. For more help run charites build --help\n',
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('charites build style.yml style.json --sprite-output noExistDirname', async () => {
|
|
89
|
+
try {
|
|
90
|
+
// prettier-ignore
|
|
91
|
+
await exec(`${charites} build style.yml style.json --sprite-output noExistDirname`, tmpdir)
|
|
92
|
+
} catch (error) {
|
|
93
|
+
assert.deepEqual(error.stdout, '')
|
|
94
|
+
assert.deepEqual(
|
|
95
|
+
error.stderr,
|
|
96
|
+
'noExistDirname: No such directory. Please specify valid icon output directory. For more help run charites build --help\n',
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { assert } from 'chai'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import { copyFixturesFile } from './util/copyFixtures'
|
|
5
|
+
import { exec } from './util/execPromise'
|
|
6
|
+
import { makeTempDir } from './util/makeTempDir'
|
|
7
|
+
import charites from './util/charitesCmd'
|
|
8
|
+
|
|
9
|
+
let tmpdir = ''
|
|
10
|
+
|
|
11
|
+
describe('Test for the `charites convert`', () => {
|
|
12
|
+
beforeEach(async function () {
|
|
13
|
+
tmpdir = makeTempDir()
|
|
14
|
+
copyFixturesFile('style.json', tmpdir)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('charites convert style.json style.yml', async () => {
|
|
18
|
+
// prettier-ignore
|
|
19
|
+
const { stdout, stderr } = await exec(`${charites} convert style.json style.yml`, tmpdir)
|
|
20
|
+
assert.deepEqual(stdout, '')
|
|
21
|
+
assert.deepEqual(stderr, '')
|
|
22
|
+
assert.isTrue(fs.existsSync(path.join(tmpdir, 'style.yml')))
|
|
23
|
+
})
|
|
24
|
+
})
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { assert } from 'chai'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import { exec } from './util/execPromise'
|
|
5
|
+
import { makeTempDir } from './util/makeTempDir'
|
|
6
|
+
import charites from './util/charitesCmd'
|
|
7
|
+
|
|
8
|
+
const tileJsonUrl =
|
|
9
|
+
'https://raw.githubusercontent.com/mapbox/tilejson-spec/master/3.0.0/example/osm.json'
|
|
10
|
+
const metadataJsonUrl = 'https://optgeo.github.io/kokoromi-rw/zxy/metadata.json'
|
|
11
|
+
|
|
12
|
+
let tmpdir = ''
|
|
13
|
+
|
|
14
|
+
describe('Test for the `charites convert`', () => {
|
|
15
|
+
beforeEach(async function () {
|
|
16
|
+
tmpdir = makeTempDir()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('charites init style.yml --tilejson-urls ${tileJsonUrl}', async () => {
|
|
20
|
+
// prettier-ignore
|
|
21
|
+
const { stdout, stderr } = await exec(`${charites} init style.yml --tilejson-urls ${tileJsonUrl}`, tmpdir)
|
|
22
|
+
assert.deepEqual(stdout, '')
|
|
23
|
+
assert.deepEqual(stderr, '')
|
|
24
|
+
assert.isTrue(fs.existsSync(path.join(tmpdir, 'style.yml')))
|
|
25
|
+
assert.isTrue(fs.existsSync(path.join(tmpdir, 'layers')))
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('charites init style.yml --metadatajson-urls ${metadataJsonUrl}', async () => {
|
|
29
|
+
// prettier-ignore
|
|
30
|
+
const { stdout, stderr } = await exec(`${charites} init style.yml --metadatajson-urls ${metadataJsonUrl}`, tmpdir)
|
|
31
|
+
assert.deepEqual(stdout, '')
|
|
32
|
+
assert.deepEqual(stderr, '')
|
|
33
|
+
assert.isTrue(fs.existsSync(path.join(tmpdir, 'style.yml')))
|
|
34
|
+
assert.isTrue(fs.existsSync(path.join(tmpdir, 'layers')))
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('charites init style.yml --tilejson-urls ${tileJsonUrl} --composite-layers', async () => {
|
|
38
|
+
// prettier-ignore
|
|
39
|
+
const { stdout, stderr } = await exec(`${charites} init style.yml --tilejson-urls ${tileJsonUrl} --composite-layers`, tmpdir)
|
|
40
|
+
assert.deepEqual(stdout, '')
|
|
41
|
+
assert.deepEqual(stderr, '')
|
|
42
|
+
assert.isTrue(fs.existsSync(path.join(tmpdir, 'style.yml')))
|
|
43
|
+
assert.isFalse(fs.existsSync(path.join(tmpdir, 'layers')))
|
|
44
|
+
})
|
|
45
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import fse from 'fs-extra'
|
|
4
|
+
|
|
5
|
+
export const copyFixturesFile = (file: string, destDir: string) => {
|
|
6
|
+
fs.copyFileSync(
|
|
7
|
+
path.join(__dirname, '..', 'data', file),
|
|
8
|
+
path.join(destDir, file),
|
|
9
|
+
)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const copyFixturesDir = (dir: string, destDir: string) => {
|
|
13
|
+
fse.copySync(path.join(__dirname, '..', 'data', dir), path.join(destDir, dir))
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import child_process from 'child_process'
|
|
2
|
+
import util from 'util'
|
|
3
|
+
import { makeTempDir } from './makeTempDir'
|
|
4
|
+
const execSync = util.promisify(child_process.exec)
|
|
5
|
+
|
|
6
|
+
export const exec = async (cmd: string, cwd?: string) => {
|
|
7
|
+
const temp = cwd ? cwd : makeTempDir()
|
|
8
|
+
const { stdout, stderr } = await execSync(cmd, {
|
|
9
|
+
encoding: 'utf8',
|
|
10
|
+
cwd: temp,
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
return { stdout, stderr, cwd: temp }
|
|
14
|
+
}
|