@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.
@@ -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
+ }
@@ -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. Make sure `charites` command work well after installing globally. Run:
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
- 6. Make sure you submit a change specific to exactly one issue. If you have ideas for multiple changes please create separate pull requests.
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
- 7. Make sure update documentation under `docs` folder if your changes affect existing documents.
26
+ 8. Make sure update documentation under `docs` folder if your changes affect existing documents.
25
27
 
26
- 8. 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.
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
 
@@ -18,7 +18,7 @@ jobs:
18
18
 
19
19
  strategy:
20
20
  matrix:
21
- node-version: [14.x, 16.x]
21
+ node-version: [14.x, 16.x, 18.x]
22
22
 
23
23
  steps:
24
24
  - uses: actions/checkout@v2
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
- [![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)
3
+ [![All Contributors](https://img.shields.io/badge/all_contributors-8-orange.svg?style=flat-square)](#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
 
@@ -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, () => {
@@ -1,71 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildSprite = void 0;
4
- const spritezero = require('@mapbox/spritezero');
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
- for (let i = 0; i < pxRatios.length; i++) {
31
- const pxRatio = pxRatios[i];
32
- const svgFiles = glob
33
- .sync(path.join(svgPath, `*.svg`))
34
- .map(function (iconPath) {
35
- return {
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 TypeError) {
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, but it might not work well in some envrionment such as arm64 (eg., M1 Mac) because some of NPM packages like sprite-zero uses mapnik.
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.1.4",
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",
@@ -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">
@@ -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">
@@ -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
 
@@ -1,80 +1,17 @@
1
- const spritezero = require('@mapbox/spritezero')
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
- for (let i = 0; i < pxRatios.length; i++) {
38
- const pxRatio = pxRatios[i]
39
-
40
- const svgFiles = glob
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
@@ -1,6 +1,8 @@
1
1
  export const error = (e: unknown) => {
2
- if (e instanceof TypeError) {
2
+ if (e instanceof Error) {
3
3
  console.error(e.message)
4
+ } else {
5
+ console.error(String(e))
4
6
  }
5
7
  process.exit(1)
6
8
  }
@@ -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 ", async () => {
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
- await buildSprite(iconsPath, tmpdir, `basic`)
20
-
21
- assert.deepEqual(true, !!fs.statSync(expectedJsonPath))
22
- assert.deepEqual(true, !!fs.statSync(expectedPngPath))
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
  })
@@ -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', async () => {
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
- await build(styleYaml, styleJson, {
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', async () => {
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
- await build(styleYaml, styleJson, {
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,3 @@
1
+ import path from 'path'
2
+
3
+ export default `node ${path.join(__dirname, '..', '..', 'dist', 'cli.js')}`
@@ -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
+ }
@@ -0,0 +1,6 @@
1
+ import path from 'path'
2
+ import fs from 'fs'
3
+ import os from 'os'
4
+
5
+ export const makeTempDir = () =>
6
+ fs.mkdtempSync(path.join(os.tmpdir(), 'charites-'))