@iconify/tools 2.0.0-dev.3 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -0
- package/lib/colors/parse.d.ts +1 -1
- package/lib/colors/parse.js +3 -1
- package/lib/colors/parse.mjs +2 -1
- package/lib/colors/validate.d.ts +11 -0
- package/lib/colors/validate.js +45 -0
- package/lib/colors/validate.mjs +33 -0
- package/lib/css/parser/text.js +3 -6
- package/lib/css/parser/text.mjs +3 -3
- package/lib/{api → download/api}/cache.d.ts +0 -0
- package/lib/{api → download/api}/cache.js +1 -1
- package/lib/{api → download/api}/cache.mjs +2 -2
- package/lib/download/api/download.d.ts +5 -0
- package/lib/download/api/download.js +27 -0
- package/lib/download/api/download.mjs +21 -0
- package/lib/{api → download/api}/index.d.ts +0 -0
- package/lib/{api → download/api}/index.js +2 -2
- package/lib/{api → download/api}/index.mjs +3 -3
- package/lib/{api → download/api}/types.d.ts +0 -0
- package/lib/{api → download/api}/types.js +0 -0
- package/lib/{api → download/api}/types.mjs +0 -0
- package/lib/download/git/hash.d.ts +5 -0
- package/lib/download/git/hash.js +14 -0
- package/lib/download/git/hash.mjs +11 -0
- package/lib/download/git/index.d.ts +26 -0
- package/lib/download/git/index.js +52 -0
- package/lib/download/git/index.mjs +44 -0
- package/lib/download/github/hash.d.ts +5 -0
- package/lib/download/github/hash.js +28 -0
- package/lib/download/github/hash.mjs +25 -0
- package/lib/download/github/index.d.ts +28 -0
- package/lib/download/github/index.js +105 -0
- package/lib/download/github/index.mjs +83 -0
- package/lib/download/github/types.d.ts +9 -0
- package/lib/download/github/types.js +2 -0
- package/lib/download/github/types.mjs +0 -0
- package/lib/download/helpers/untar.d.ts +4 -0
- package/lib/download/helpers/untar.js +14 -0
- package/lib/download/helpers/untar.mjs +11 -0
- package/lib/download/helpers/unzip.d.ts +4 -0
- package/lib/download/helpers/unzip.js +18 -0
- package/lib/download/helpers/unzip.mjs +12 -0
- package/lib/download/npm/index.d.ts +27 -0
- package/lib/download/npm/index.js +73 -0
- package/lib/download/npm/index.mjs +63 -0
- package/lib/download/npm/types.d.ts +7 -0
- package/lib/download/npm/types.js +2 -0
- package/lib/download/npm/types.mjs +0 -0
- package/lib/download/npm/version.d.ts +13 -0
- package/lib/download/npm/version.js +27 -0
- package/lib/download/npm/version.mjs +20 -0
- package/lib/download/types/modified.d.ts +4 -0
- package/lib/download/types/modified.js +2 -0
- package/lib/download/types/modified.mjs +0 -0
- package/lib/export/directory.d.ts +2 -2
- package/lib/export/directory.js +2 -2
- package/lib/export/directory.mjs +2 -2
- package/lib/export/helpers/custom-files.d.ts +10 -0
- package/lib/export/helpers/custom-files.js +32 -0
- package/lib/export/helpers/custom-files.mjs +25 -0
- package/lib/export/{prepare.d.ts → helpers/prepare.d.ts} +4 -0
- package/lib/export/{prepare.js → helpers/prepare.js} +14 -5
- package/lib/export/{prepare.mjs → helpers/prepare.mjs} +9 -4
- package/lib/export/helpers/types-version.d.ts +4 -0
- package/lib/export/helpers/types-version.js +12 -0
- package/lib/export/helpers/types-version.mjs +40 -0
- package/lib/export/icon-package.d.ts +17 -0
- package/lib/export/icon-package.js +77 -0
- package/lib/export/icon-package.mjs +56 -0
- package/lib/export/json-package.d.ts +15 -0
- package/lib/export/json-package.js +151 -0
- package/lib/export/json-package.mjs +127 -0
- package/lib/icon-set/index.js +1 -2
- package/lib/icon-set/index.mjs +1 -1
- package/lib/import/figma/index.d.ts +5 -3
- package/lib/import/figma/index.js +0 -3
- package/lib/import/figma/query.d.ts +6 -4
- package/lib/import/figma/query.js +2 -5
- package/lib/import/figma/query.mjs +6 -2
- package/lib/import/figma/types/options.d.ts +4 -2
- package/lib/import/figma/types/result.d.ts +0 -4
- package/lib/index.d.ts +37 -0
- package/lib/index.js +89 -0
- package/lib/index.mjs +80 -0
- package/lib/misc/bump-version.d.ts +4 -0
- package/lib/misc/bump-version.js +19 -0
- package/lib/misc/bump-version.mjs +15 -0
- package/lib/misc/compare-dirs.d.ts +9 -0
- package/lib/misc/compare-dirs.js +84 -0
- package/lib/misc/compare-dirs.mjs +71 -0
- package/lib/misc/exec.d.ts +10 -0
- package/lib/misc/exec.js +26 -0
- package/lib/misc/exec.mjs +22 -0
- package/lib/misc/keyword.js +1 -1
- package/lib/misc/keyword.mjs +1 -1
- package/lib/misc/scan.d.ts +1 -1
- package/lib/misc/scan.js +14 -8
- package/lib/misc/scan.mjs +11 -6
- package/lib/misc/write-json.d.ts +4 -0
- package/lib/misc/write-json.js +11 -0
- package/lib/misc/write-json.mjs +8 -0
- package/lib/optimise/svgo.js +3 -1
- package/lib/optimise/svgo.mjs +2 -1
- package/lib/svg/index.d.ts +3 -0
- package/lib/svg/index.js +3 -0
- package/license.txt +21 -0
- package/package.json +138 -27
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Iconify Tools
|
|
2
|
+
|
|
3
|
+
This library is a collection of tools for importing, exporting and processing SVG images.
|
|
4
|
+
|
|
5
|
+
Its main purpose is to convert icon sets and fonts to Iconify JSON collections, but it can be used for other purposes.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
First install it by running this command:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
npm install @iconify/tools --save
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Example
|
|
16
|
+
|
|
17
|
+
The following code example does the following:
|
|
18
|
+
|
|
19
|
+
- Imports set of SVG from directory.
|
|
20
|
+
- Cleans up all icons.
|
|
21
|
+
- Changes colors in all icons to `currentColor`.
|
|
22
|
+
- Optimises icons.
|
|
23
|
+
- Exports icons as `IconifyJSON` icon set.
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
import { promises as fs } from 'fs';
|
|
27
|
+
import { importDirectory } from '@iconify/tools/lib/import/directory';
|
|
28
|
+
import { cleanupSVG } from '@iconify/tools/lib/svg/cleanup';
|
|
29
|
+
import { runSVGO } from '@iconify/tools/lib/optimise/svgo';
|
|
30
|
+
import { parseColors, isEmptyColor } from '@iconify/tools/lib/colors/parse';
|
|
31
|
+
|
|
32
|
+
(async () => {
|
|
33
|
+
// Import icons
|
|
34
|
+
const iconSet = await importDirectory('svg/test', {
|
|
35
|
+
prefix: 'test',
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Validate, clean up, fix palette and optimise
|
|
39
|
+
await iconSet.forEach(async (name, type) => {
|
|
40
|
+
if (type !== 'icon') {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const svg = iconSet.toSVG(name);
|
|
45
|
+
if (!svg) {
|
|
46
|
+
// Invalid icon
|
|
47
|
+
iconSet.remove(name);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Clean up and optimise icons
|
|
52
|
+
try {
|
|
53
|
+
await cleanupSVG(svg);
|
|
54
|
+
await parseColors(svg, {
|
|
55
|
+
defaultColor: 'currentColor',
|
|
56
|
+
callback: (attr, colorStr, color) => {
|
|
57
|
+
return !color || isEmptyColor(color)
|
|
58
|
+
? colorStr
|
|
59
|
+
: 'currentColor';
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
await runSVGO(svg);
|
|
63
|
+
} catch (err) {
|
|
64
|
+
// Invalid icon
|
|
65
|
+
console.error(`Error parsing ${name}:`, err);
|
|
66
|
+
iconSet.remove(name);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Update icon
|
|
71
|
+
iconSet.fromSVG(name, svg);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Export as IconifyJSON
|
|
75
|
+
const exported = JSON.stringify(iconSet.export(), null, '\t') + '\n';
|
|
76
|
+
|
|
77
|
+
// Save to file
|
|
78
|
+
await fs.writeFile(`output/${iconSet.prefix}.json`, exported, 'utf8');
|
|
79
|
+
})();
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Documentation
|
|
83
|
+
|
|
84
|
+
Full documentation is too big for simple README file. See [Iconify Tools documentation](https://docs.iconify.design/tools/tools2/) for detailed documentation with code samples.
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
Library is released with MIT license.
|
|
89
|
+
|
|
90
|
+
© 2021 Vjacheslav Trushkin
|
package/lib/colors/parse.d.ts
CHANGED
package/lib/colors/parse.js
CHANGED
|
@@ -245,13 +245,15 @@ async function parseColors(svg, options = {}) {
|
|
|
245
245
|
const color = getElementColor(prop, item);
|
|
246
246
|
if (color === attribs_1.defaultBlackColor) {
|
|
247
247
|
// Default black color: change it
|
|
248
|
-
result.hasUnsetColor = true;
|
|
249
248
|
if (defaultColor) {
|
|
250
249
|
// Add color to results and change attribute
|
|
251
250
|
findColor(defaultColor, true);
|
|
252
251
|
$element.attr(prop, (0, colors_1.colorToString)(defaultColor));
|
|
253
252
|
itemColors[prop] = defaultColor;
|
|
254
253
|
}
|
|
254
|
+
else {
|
|
255
|
+
result.hasUnsetColor = true;
|
|
256
|
+
}
|
|
255
257
|
}
|
|
256
258
|
}
|
|
257
259
|
}
|
package/lib/colors/parse.mjs
CHANGED
|
@@ -197,11 +197,12 @@ async function parseColors(svg, options = {}) {
|
|
|
197
197
|
const prop = requiredProps[i];
|
|
198
198
|
const color = getElementColor(prop, item);
|
|
199
199
|
if (color === defaultBlackColor) {
|
|
200
|
-
result.hasUnsetColor = true;
|
|
201
200
|
if (defaultColor) {
|
|
202
201
|
findColor(defaultColor, true);
|
|
203
202
|
$element.attr(prop, colorToString(defaultColor));
|
|
204
203
|
itemColors[prop] = defaultColor;
|
|
204
|
+
} else {
|
|
205
|
+
result.hasUnsetColor = true;
|
|
205
206
|
}
|
|
206
207
|
}
|
|
207
208
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SVG } from '../svg/index';
|
|
2
|
+
import { ParseColorsOptions } from './parse';
|
|
3
|
+
import type { FindColorsResult } from './parse';
|
|
4
|
+
/**
|
|
5
|
+
* Validate colors in icon
|
|
6
|
+
*
|
|
7
|
+
* If icon is monotone,
|
|
8
|
+
*
|
|
9
|
+
* Throws exception on error
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateColors(svg: SVG, expectMonotone: boolean, options?: ParseColorsOptions): Promise<FindColorsResult>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateColors = void 0;
|
|
4
|
+
const colors_1 = require("@iconify/utils/lib/colors");
|
|
5
|
+
const parse_1 = require("./parse");
|
|
6
|
+
/**
|
|
7
|
+
* Validate colors in icon
|
|
8
|
+
*
|
|
9
|
+
* If icon is monotone,
|
|
10
|
+
*
|
|
11
|
+
* Throws exception on error
|
|
12
|
+
*/
|
|
13
|
+
async function validateColors(svg, expectMonotone, options) {
|
|
14
|
+
// Parse colors
|
|
15
|
+
const palette = await (0, parse_1.parseColors)(svg, options);
|
|
16
|
+
// Check palette
|
|
17
|
+
palette.colors.forEach((color) => {
|
|
18
|
+
if (typeof color === 'string') {
|
|
19
|
+
throw new Error('Unexpected color: ' + color);
|
|
20
|
+
}
|
|
21
|
+
switch (color.type) {
|
|
22
|
+
case 'none':
|
|
23
|
+
case 'transparent':
|
|
24
|
+
return;
|
|
25
|
+
// Monotone
|
|
26
|
+
case 'current':
|
|
27
|
+
if (!expectMonotone) {
|
|
28
|
+
throw new Error('Unexpected color: ' + (0, colors_1.colorToString)(color));
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
// Palette
|
|
32
|
+
case 'rgb':
|
|
33
|
+
case 'hsl':
|
|
34
|
+
if (expectMonotone) {
|
|
35
|
+
throw new Error('Unexpected color: ' + (0, colors_1.colorToString)(color));
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
// Do not allow other colors
|
|
39
|
+
default:
|
|
40
|
+
throw new Error('Unexpected color: ' + (0, colors_1.colorToString)(color));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return palette;
|
|
44
|
+
}
|
|
45
|
+
exports.validateColors = validateColors;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// src/colors/validate.ts
|
|
2
|
+
import { colorToString } from "@iconify/utils/lib/colors";
|
|
3
|
+
import { parseColors } from "./parse.mjs";
|
|
4
|
+
async function validateColors(svg, expectMonotone, options) {
|
|
5
|
+
const palette = await parseColors(svg, options);
|
|
6
|
+
palette.colors.forEach((color) => {
|
|
7
|
+
if (typeof color === "string") {
|
|
8
|
+
throw new Error("Unexpected color: " + color);
|
|
9
|
+
}
|
|
10
|
+
switch (color.type) {
|
|
11
|
+
case "none":
|
|
12
|
+
case "transparent":
|
|
13
|
+
return;
|
|
14
|
+
case "current":
|
|
15
|
+
if (!expectMonotone) {
|
|
16
|
+
throw new Error("Unexpected color: " + colorToString(color));
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
case "rgb":
|
|
20
|
+
case "hsl":
|
|
21
|
+
if (expectMonotone) {
|
|
22
|
+
throw new Error("Unexpected color: " + colorToString(color));
|
|
23
|
+
}
|
|
24
|
+
return;
|
|
25
|
+
default:
|
|
26
|
+
throw new Error("Unexpected color: " + colorToString(color));
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return palette;
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
validateColors
|
|
33
|
+
};
|
package/lib/css/parser/text.js
CHANGED
|
@@ -103,12 +103,9 @@ function textTokensToRule(tokens) {
|
|
|
103
103
|
};
|
|
104
104
|
// Check for !important (with possibility to support other stuff like !default in future)
|
|
105
105
|
['important'].forEach((word) => {
|
|
106
|
-
if (result.value.slice(
|
|
107
|
-
'!' + word) {
|
|
106
|
+
if (result.value.slice(-1 - word.length).toLowerCase() === '!' + word) {
|
|
108
107
|
result[word] = true;
|
|
109
|
-
result.value = result.value
|
|
110
|
-
.slice(0, result.value.length - word.length - 1)
|
|
111
|
-
.trim();
|
|
108
|
+
result.value = result.value.slice(0, -1 - word.length).trim();
|
|
112
109
|
}
|
|
113
110
|
});
|
|
114
111
|
// Value cannot be empty
|
|
@@ -140,7 +137,7 @@ function textTokensToSelector(tokens) {
|
|
|
140
137
|
return;
|
|
141
138
|
}
|
|
142
139
|
const list = item
|
|
143
|
-
.slice(1,
|
|
140
|
+
.slice(1, -1)
|
|
144
141
|
.split(/\)\s?and\s?\(/i)
|
|
145
142
|
.map((item) => item.trim());
|
|
146
143
|
let match = true;
|
package/lib/css/parser/text.mjs
CHANGED
|
@@ -73,9 +73,9 @@ function textTokensToRule(tokens) {
|
|
|
73
73
|
index: tokens[0].index
|
|
74
74
|
};
|
|
75
75
|
["important"].forEach((word) => {
|
|
76
|
-
if (result.value.slice(
|
|
76
|
+
if (result.value.slice(-1 - word.length).toLowerCase() === "!" + word) {
|
|
77
77
|
result[word] = true;
|
|
78
|
-
result.value = result.value.slice(0,
|
|
78
|
+
result.value = result.value.slice(0, -1 - word.length).trim();
|
|
79
79
|
}
|
|
80
80
|
});
|
|
81
81
|
return result.value.length ? result : null;
|
|
@@ -97,7 +97,7 @@ function textTokensToSelector(tokens) {
|
|
|
97
97
|
if (typeof item !== "string" || item.charAt(0) !== "(" || item.charAt(item.length - 1) !== ")") {
|
|
98
98
|
return;
|
|
99
99
|
}
|
|
100
|
-
const list = item.slice(1,
|
|
100
|
+
const list = item.slice(1, -1).split(/\)\s?and\s?\(/i).map((item2) => item2.trim());
|
|
101
101
|
let match = true;
|
|
102
102
|
list.forEach((item2) => {
|
|
103
103
|
if (item2.indexOf("(") !== -1 || item2.indexOf(")") !== -1) {
|
|
File without changes
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.clearAPICache = exports.getAPICache = exports.storeAPICache = exports.apiCacheKey = void 0;
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const crypto_1 = require("crypto");
|
|
6
|
-
const scan_1 = require("
|
|
6
|
+
const scan_1 = require("../../misc/scan");
|
|
7
7
|
const cacheVersion = 1;
|
|
8
8
|
const storedFiles = Object.create(null);
|
|
9
9
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// src/api/cache.ts
|
|
1
|
+
// src/download/api/cache.ts
|
|
2
2
|
import { promises as fs } from "fs";
|
|
3
3
|
import { createHash } from "crypto";
|
|
4
|
-
import { scanDirectory } from "
|
|
4
|
+
import { scanDirectory } from "../../misc/scan.mjs";
|
|
5
5
|
var cacheVersion = 1;
|
|
6
6
|
var storedFiles = Object.create(null);
|
|
7
7
|
function apiCacheKey(query) {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.downloadFile = void 0;
|
|
7
|
+
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
8
|
+
const util_1 = require("util");
|
|
9
|
+
const stream_1 = require("stream");
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
const streamPipeline = (0, util_1.promisify)(stream_1.pipeline);
|
|
12
|
+
/**
|
|
13
|
+
* Download file
|
|
14
|
+
*/
|
|
15
|
+
async function downloadFile(query, target) {
|
|
16
|
+
const params = query.params ? query.params.toString() : '';
|
|
17
|
+
const url = query.uri + (params ? '?' + params : '');
|
|
18
|
+
const headers = query.headers;
|
|
19
|
+
const response = await (0, node_fetch_1.default)(url, {
|
|
20
|
+
headers,
|
|
21
|
+
});
|
|
22
|
+
if (!response.ok || !response.body) {
|
|
23
|
+
throw new Error(`Error downloading ${url}: ${response.status}`);
|
|
24
|
+
}
|
|
25
|
+
await streamPipeline(response.body, (0, fs_1.createWriteStream)(target));
|
|
26
|
+
}
|
|
27
|
+
exports.downloadFile = downloadFile;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/download/api/download.ts
|
|
2
|
+
import fetch from "node-fetch";
|
|
3
|
+
import { promisify } from "util";
|
|
4
|
+
import { pipeline } from "stream";
|
|
5
|
+
import { createWriteStream } from "fs";
|
|
6
|
+
var streamPipeline = promisify(pipeline);
|
|
7
|
+
async function downloadFile(query, target) {
|
|
8
|
+
const params = query.params ? query.params.toString() : "";
|
|
9
|
+
const url = query.uri + (params ? "?" + params : "");
|
|
10
|
+
const headers = query.headers;
|
|
11
|
+
const response = await fetch(url, {
|
|
12
|
+
headers
|
|
13
|
+
});
|
|
14
|
+
if (!response.ok || !response.body) {
|
|
15
|
+
throw new Error(`Error downloading ${url}: ${response.status}`);
|
|
16
|
+
}
|
|
17
|
+
await streamPipeline(response.body, createWriteStream(target));
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
downloadFile
|
|
21
|
+
};
|
|
File without changes
|
|
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.sendAPIQuery = void 0;
|
|
7
|
-
const
|
|
7
|
+
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
8
8
|
const cache_1 = require("./cache");
|
|
9
9
|
/**
|
|
10
10
|
* Send API query
|
|
@@ -38,7 +38,7 @@ async function sendQuery(query) {
|
|
|
38
38
|
console.log('Fetch:', url);
|
|
39
39
|
const headers = query.headers;
|
|
40
40
|
try {
|
|
41
|
-
const response = await (0,
|
|
41
|
+
const response = await (0, node_fetch_1.default)(url, {
|
|
42
42
|
headers,
|
|
43
43
|
});
|
|
44
44
|
if (response.status >= 400) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// src/api/index.ts
|
|
2
|
-
import
|
|
1
|
+
// src/download/api/index.ts
|
|
2
|
+
import fetch from "node-fetch";
|
|
3
3
|
import { apiCacheKey, getAPICache, storeAPICache } from "./cache.mjs";
|
|
4
4
|
async function sendAPIQuery(query, cache) {
|
|
5
5
|
const cacheKey = cache ? apiCacheKey(query) : "";
|
|
@@ -25,7 +25,7 @@ async function sendQuery(query) {
|
|
|
25
25
|
console.log("Fetch:", url);
|
|
26
26
|
const headers = query.headers;
|
|
27
27
|
try {
|
|
28
|
-
const response = await
|
|
28
|
+
const response = await fetch(url, {
|
|
29
29
|
headers
|
|
30
30
|
});
|
|
31
31
|
if (response.status >= 400) {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getGitRepoHash = void 0;
|
|
4
|
+
const exec_1 = require("../../misc/exec");
|
|
5
|
+
/**
|
|
6
|
+
* Get latest hash from cloned git repo
|
|
7
|
+
*/
|
|
8
|
+
async function getGitRepoHash(options) {
|
|
9
|
+
const result = await (0, exec_1.execAsync)('git rev-parse HEAD', {
|
|
10
|
+
cwd: options.target,
|
|
11
|
+
});
|
|
12
|
+
return result.stdout.trim();
|
|
13
|
+
}
|
|
14
|
+
exports.getGitRepoHash = getGitRepoHash;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// src/download/git/hash.ts
|
|
2
|
+
import { execAsync } from "../../misc/exec.mjs";
|
|
3
|
+
async function getGitRepoHash(options) {
|
|
4
|
+
const result = await execAsync("git rev-parse HEAD", {
|
|
5
|
+
cwd: options.target
|
|
6
|
+
});
|
|
7
|
+
return result.stdout.trim();
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
getGitRepoHash
|
|
11
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ExportTargetOptions } from '../../export/helpers/prepare';
|
|
2
|
+
import type { DocumentNotModified } from '../types/modified';
|
|
3
|
+
interface IfModifiedSinceOption {
|
|
4
|
+
ifModifiedSince: string | true;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Options for downloadGitRepo()
|
|
8
|
+
*/
|
|
9
|
+
export interface DownloadGitRepoOptions extends ExportTargetOptions, Partial<IfModifiedSinceOption> {
|
|
10
|
+
remote: string;
|
|
11
|
+
branch: string;
|
|
12
|
+
log?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Result
|
|
16
|
+
*/
|
|
17
|
+
export interface DownloadGitRepoResult {
|
|
18
|
+
target: string;
|
|
19
|
+
hash: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Download Git repo
|
|
23
|
+
*/
|
|
24
|
+
export declare function downloadGitRepo<T extends IfModifiedSinceOption & DownloadGitRepoOptions>(options: T): Promise<DownloadGitRepoResult | DocumentNotModified>;
|
|
25
|
+
export declare function downloadGitRepo(options: DownloadGitRepoOptions): Promise<DownloadGitRepoResult>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.downloadGitRepo = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const prepare_1 = require("../../export/helpers/prepare");
|
|
6
|
+
const exec_1 = require("../../misc/exec");
|
|
7
|
+
const hash_1 = require("./hash");
|
|
8
|
+
async function downloadGitRepo(options) {
|
|
9
|
+
const { remote, branch } = options;
|
|
10
|
+
// Check for last commit
|
|
11
|
+
const hasHashInTarget = options.target.indexOf('{hash}') !== -1;
|
|
12
|
+
if (options.ifModifiedSince || hasHashInTarget) {
|
|
13
|
+
// Get actual hash
|
|
14
|
+
const result = await (0, exec_1.execAsync)(`git ls-remote ${remote} --branch ${branch}`);
|
|
15
|
+
const parts = result.stdout.split(/\s/);
|
|
16
|
+
const latestHash = parts.shift();
|
|
17
|
+
if (hasHashInTarget) {
|
|
18
|
+
options.target = options.target.replace('{hash}', latestHash);
|
|
19
|
+
}
|
|
20
|
+
if (options.ifModifiedSince) {
|
|
21
|
+
try {
|
|
22
|
+
// Get expected hash
|
|
23
|
+
const expectedHash = options.ifModifiedSince === true
|
|
24
|
+
? await (0, hash_1.getGitRepoHash)(options)
|
|
25
|
+
: options.ifModifiedSince;
|
|
26
|
+
if (latestHash === expectedHash) {
|
|
27
|
+
return 'not_modified';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
//
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Prepare target directory
|
|
36
|
+
const target = (options.target = await (0, prepare_1.prepareDirectoryForExport)(options));
|
|
37
|
+
// Check if directory is empty if directory wasn't cleaned up
|
|
38
|
+
const files = options.cleanup ? [] : await fs_1.promises.readdir(target);
|
|
39
|
+
if (!files.length) {
|
|
40
|
+
if (options.log) {
|
|
41
|
+
console.log(`Cloning ${remote}#${branch} to ${target}`);
|
|
42
|
+
}
|
|
43
|
+
await (0, exec_1.execAsync)(`git clone --branch ${branch} --no-tags --depth 1 ${remote} "${target}"`);
|
|
44
|
+
}
|
|
45
|
+
// Get latest hash
|
|
46
|
+
const hash = await (0, hash_1.getGitRepoHash)(options);
|
|
47
|
+
return {
|
|
48
|
+
target,
|
|
49
|
+
hash,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
exports.downloadGitRepo = downloadGitRepo;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/download/git/index.ts
|
|
2
|
+
import { promises as fs } from "fs";
|
|
3
|
+
import {
|
|
4
|
+
prepareDirectoryForExport
|
|
5
|
+
} from "../../export/helpers/prepare.mjs";
|
|
6
|
+
import { execAsync } from "../../misc/exec.mjs";
|
|
7
|
+
import { getGitRepoHash } from "./hash.mjs";
|
|
8
|
+
async function downloadGitRepo(options) {
|
|
9
|
+
const { remote, branch } = options;
|
|
10
|
+
const hasHashInTarget = options.target.indexOf("{hash}") !== -1;
|
|
11
|
+
if (options.ifModifiedSince || hasHashInTarget) {
|
|
12
|
+
const result = await execAsync(`git ls-remote ${remote} --branch ${branch}`);
|
|
13
|
+
const parts = result.stdout.split(/\s/);
|
|
14
|
+
const latestHash = parts.shift();
|
|
15
|
+
if (hasHashInTarget) {
|
|
16
|
+
options.target = options.target.replace("{hash}", latestHash);
|
|
17
|
+
}
|
|
18
|
+
if (options.ifModifiedSince) {
|
|
19
|
+
try {
|
|
20
|
+
const expectedHash = options.ifModifiedSince === true ? await getGitRepoHash(options) : options.ifModifiedSince;
|
|
21
|
+
if (latestHash === expectedHash) {
|
|
22
|
+
return "not_modified";
|
|
23
|
+
}
|
|
24
|
+
} catch (err) {
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const target = options.target = await prepareDirectoryForExport(options);
|
|
29
|
+
const files = options.cleanup ? [] : await fs.readdir(target);
|
|
30
|
+
if (!files.length) {
|
|
31
|
+
if (options.log) {
|
|
32
|
+
console.log(`Cloning ${remote}#${branch} to ${target}`);
|
|
33
|
+
}
|
|
34
|
+
await execAsync(`git clone --branch ${branch} --no-tags --depth 1 ${remote} "${target}"`);
|
|
35
|
+
}
|
|
36
|
+
const hash = await getGitRepoHash(options);
|
|
37
|
+
return {
|
|
38
|
+
target,
|
|
39
|
+
hash
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
downloadGitRepo
|
|
44
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getGitHubRepoHash = void 0;
|
|
4
|
+
const api_1 = require("../api");
|
|
5
|
+
/**
|
|
6
|
+
* Get latest hash from GitHub using API
|
|
7
|
+
*/
|
|
8
|
+
async function getGitHubRepoHash(options) {
|
|
9
|
+
var _a;
|
|
10
|
+
const uri = `https://api.github.com/repos/${options.user}/${options.repo}/branches/${options.branch}`;
|
|
11
|
+
const data = await (0, api_1.sendAPIQuery)({
|
|
12
|
+
uri,
|
|
13
|
+
headers: {
|
|
14
|
+
Accept: 'application/vnd.github.v3+json',
|
|
15
|
+
Authorization: 'token ' + options.token,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
if (typeof data !== 'string') {
|
|
19
|
+
throw new Error(`Error downloading data from GitHub API: ${data}`);
|
|
20
|
+
}
|
|
21
|
+
const content = JSON.parse(data);
|
|
22
|
+
const hash = (_a = content === null || content === void 0 ? void 0 : content.commit) === null || _a === void 0 ? void 0 : _a.sha;
|
|
23
|
+
if (typeof hash !== 'string') {
|
|
24
|
+
throw new Error('Error parsing GitHub API response');
|
|
25
|
+
}
|
|
26
|
+
return hash;
|
|
27
|
+
}
|
|
28
|
+
exports.getGitHubRepoHash = getGitHubRepoHash;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/download/github/hash.ts
|
|
2
|
+
import { sendAPIQuery } from "../api/index.mjs";
|
|
3
|
+
async function getGitHubRepoHash(options) {
|
|
4
|
+
var _a;
|
|
5
|
+
const uri = `https://api.github.com/repos/${options.user}/${options.repo}/branches/${options.branch}`;
|
|
6
|
+
const data = await sendAPIQuery({
|
|
7
|
+
uri,
|
|
8
|
+
headers: {
|
|
9
|
+
Accept: "application/vnd.github.v3+json",
|
|
10
|
+
Authorization: "token " + options.token
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
if (typeof data !== "string") {
|
|
14
|
+
throw new Error(`Error downloading data from GitHub API: ${data}`);
|
|
15
|
+
}
|
|
16
|
+
const content = JSON.parse(data);
|
|
17
|
+
const hash = (_a = content == null ? void 0 : content.commit) == null ? void 0 : _a.sha;
|
|
18
|
+
if (typeof hash !== "string") {
|
|
19
|
+
throw new Error("Error parsing GitHub API response");
|
|
20
|
+
}
|
|
21
|
+
return hash;
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
getGitHubRepoHash
|
|
25
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ExportTargetOptions } from '../../export/helpers/prepare';
|
|
2
|
+
import type { DocumentNotModified } from '../types/modified';
|
|
3
|
+
import type { GitHubAPIOptions } from './types';
|
|
4
|
+
interface IfModifiedSinceOption {
|
|
5
|
+
ifModifiedSince: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Options for downloadGitRepo()
|
|
9
|
+
*/
|
|
10
|
+
export interface DownloadGitHubRepoOptions extends ExportTargetOptions, GitHubAPIOptions, Partial<IfModifiedSinceOption> {
|
|
11
|
+
cleanupOldFiles?: boolean;
|
|
12
|
+
cleanupOldDirectories?: boolean;
|
|
13
|
+
log?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Result
|
|
17
|
+
*/
|
|
18
|
+
export interface DownloadGitHubRepoResult {
|
|
19
|
+
rootDir: string;
|
|
20
|
+
actualDir: string;
|
|
21
|
+
hash: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Download GitHub repo using API
|
|
25
|
+
*/
|
|
26
|
+
export declare function downloadGitHubRepo<T extends IfModifiedSinceOption & DownloadGitHubRepoOptions>(options: T): Promise<DownloadGitHubRepoResult | DocumentNotModified>;
|
|
27
|
+
export declare function downloadGitHubRepo(options: DownloadGitHubRepoOptions): Promise<DownloadGitHubRepoResult>;
|
|
28
|
+
export {};
|