Skip to content

Commit 144d85d

Browse files
author
Alexander Yukal
committed
Merge branch 'dev'
2 parents 94346ff + 78e8d1e commit 144d85d

File tree

9 files changed

+10263
-58
lines changed

9 files changed

+10263
-58
lines changed

.github/workflows/node.js.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3+
4+
name: Node.js CI
5+
6+
on:
7+
push:
8+
branches: [ master, dev ]
9+
pull_request:
10+
branches: [ master ]
11+
12+
jobs:
13+
build:
14+
15+
runs-on: ubuntu-latest
16+
17+
strategy:
18+
matrix:
19+
node-version: [10.x, 12.x, 14.x]
20+
21+
steps:
22+
- uses: actions/checkout@v2
23+
- name: Use Node.js ${{ matrix.node-version }}
24+
uses: actions/setup-node@v1
25+
with:
26+
node-version: ${{ matrix.node-version }}
27+
- run: npm ci
28+
- run: npm test

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2020 Alexander
3+
Copyright (c) 2020 Alexander Yukal
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,6 @@ $ gulp html
140140
$ npx gulp html
141141
```
142142

143-
### TODO
144-
To avoid collisions with the same file names, we should split the responsibility of pages
145-
and libraries in the data directory using the nested paths cutting them with a dot symbol.
146-
147143
## Libraries Using `gulp-json-loader`
148144

149145
- [gulp-data](https://www.npmjs.com/package/gulp-data)

changes.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ v1.1.0:
2222

2323
- Implemented data caching
2424
- The data that has already been loaded will be getting from the cache
25+
26+
- Added tests

lib/gulp-json-loader.js

Lines changed: 96 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,30 @@
11
'use strict';
22

3+
/**
4+
* GulpJsonLoader
5+
*
6+
* @file
7+
* @ingroup Plugins
8+
* @version 1.2
9+
* @license MIT
10+
* @author Alexander Yukal <yukal@email.ua>
11+
*/
12+
313
const Util = require('util');
414
const Path = require('path');
515
const Fs = require('fs');
616

717
const APP_PATH = process.cwd();
8-
const DEFAULT_SOURCE_PATH = './src';
18+
const DEFAULT_SOURCE_PATH = 'src';
919
const BREAK_LINE = process.platform === 'win32' ? '\r\n' : '\n';
10-
const ERR_TOP_DIR = 'Working with top-level directories is prohibited!';
20+
const ERR_EXTERNAL_PATH = 'Working with external paths is prohibited!';
1121

12-
const CachedData = {};
1322
const BrushColors = {
1423
red: 1,
1524
cyan: 6,
1625
grey: 8
1726
};
1827

19-
const getAbsolutePath = (path, subdir = '') => {
20-
if (path.startsWith('/')) {
21-
path = '.' + path;
22-
}
23-
24-
path = Path.join(APP_PATH, path);
25-
26-
return subdir
27-
? Path.join(path, subdir)
28-
: path;
29-
}
30-
3128
/**
3229
* brush
3330
* Adding the ANSI escape codes to a textual data
@@ -66,19 +63,36 @@ const reportAction = (ctx, pathJson, filename, action) => {
6663
process.stdout.write(message);
6764
}
6865

69-
const loadImportsAsync = (ctx, imports) => {
66+
const loadImportsAsync = (ctx, imports, cachedData) => {
7067
return new Promise((resolve, reject) => {
7168
if (!Array.isArray(imports)) {
69+
7270
reject(new Error('Imports should be an Array'));
71+
7372
} else {
74-
const storage = {};
75-
loadImportsRecursively({ ctx, imports, storage, resolve, reject });
73+
74+
if (imports.length < 1) {
75+
resolve({});
76+
return;
77+
}
78+
79+
const options = { ctx, imports, cachedData, pocket: {} };
80+
81+
loadImportsRecursively(options, (error, pocket) => {
82+
if (error !== null) {
83+
reject(error);
84+
return;
85+
}
86+
87+
resolve(pocket);
88+
});
89+
7690
}
7791
});
7892
};
7993

80-
const loadImportsRecursively = async (options) => {
81-
const { ctx, imports, storage, resolve, reject, idx = 0 } = options;
94+
const loadImportsRecursively = async (options, callback) => {
95+
const { ctx, imports, cachedData, pocket, idx = 0 } = options;
8296
const { report, pathData } = ctx;
8397

8498
if (idx < imports.length) {
@@ -87,78 +101,78 @@ const loadImportsRecursively = async (options) => {
87101
const jsonRelativePath = imports[idx] + '.json';
88102
const jsonFullPath = Path.join(pathData, 'imports', jsonRelativePath);
89103
const jsonFilename = Path.basename(jsonFullPath, '.json');
90-
const cacheKey = 'imports:' + jsonFullPath.replace(APP_PATH, '');
104+
const cacheKey = jsonFullPath.replace(`${APP_PATH}/`, '');
91105

92106
if (!jsonFullPath.startsWith(APP_PATH)) {
93-
reject(new Error(ERR_TOP_DIR));
107+
callback(new Error(ERR_EXTERNAL_PATH), null);
94108
return;
95109
}
96110

97-
if (!CachedData.hasOwnProperty(cacheKey)) {
111+
if (!cachedData.hasOwnProperty(cacheKey)) {
98112
try {
99113

100114
const jsonData = await Fs.promises.readFile(jsonFullPath, 'utf8');
101115

102-
CachedData[cacheKey] = JSON.parse(jsonData);
116+
cachedData[cacheKey] = JSON.parse(jsonData);
103117
action = 'Loaded';
104118

105119
} catch (error) {
106120

107-
reject(error);
121+
callback(error, null);
108122
return;
109123

110124
}
111125
}
112126

113127
report && reportAction(ctx, jsonFullPath, jsonFilename, action);
114128

115-
Object.defineProperty(storage, jsonFilename, {
116-
value: CachedData[cacheKey],
129+
Object.defineProperty(pocket, jsonFilename, {
130+
value: cachedData[cacheKey],
117131
enumerable: true
118132
});
119133

120134
options.idx = idx + 1;
121-
loadImportsRecursively(options);
135+
loadImportsRecursively(options, callback);
122136

123-
} else {
124-
resolve(storage);
137+
} else if (callback !== undefined) {
138+
callback(null, pocket);
125139
}
126140
}
127141

128142
async function loadJsonData(file) {
129-
const { report, pathHtml, pathData, dataEntry } = this;
143+
const { report, pathHtml, pathData, dataEntry, cachedData } = this;
130144

131-
const pathJson = file.path
145+
const jsonFullPath = file.path
132146
.replace(pathHtml, `${pathData}/pages`)
133147
.slice(0, -3) + 'json';
134148

135-
const cacheKey = 'data:' + pathJson.replace(APP_PATH, '');
149+
const cacheKey = jsonFullPath.replace(`${APP_PATH}/`, '');
136150

137151
const filename = Path.basename(file.path, '.pug');
138152
const pocket = { filename };
139153

140-
if (CachedData.hasOwnProperty(pathJson)) {
141-
report && reportAction(this, pathJson, filename, 'Cached');
142-
return CachedData[cacheKey];
154+
if (cachedData.hasOwnProperty(cacheKey)) {
155+
report && reportAction(this, jsonFullPath, filename, 'Cached');
156+
return cachedData[cacheKey];
143157
}
144158

145159
let jsonData = '';
146160

147161
try {
148-
jsonData = await Fs.promises.readFile(pathJson, 'utf8');
162+
jsonData = await Fs.promises.readFile(jsonFullPath, 'utf8');
149163
jsonData = JSON.parse(jsonData);
150164
} catch (err) {
151165
return pocket;
152166
}
153167

154-
report && reportAction(this, pathJson, filename, 'Loaded');
168+
report && reportAction(this, jsonFullPath, filename, 'Loaded');
155169

156170
if (jsonData.hasOwnProperty('imports')) {
157171
const { data = {}, imports = [] } = jsonData;
158172

159173
try {
160174

161-
const importedData = await loadImportsAsync(this, imports);
175+
const importedData = await loadImportsAsync(this, imports, cachedData);
162176

163177
Object.defineProperty(data, 'imports', {
164178
value: importedData,
@@ -170,7 +184,7 @@ async function loadJsonData(file) {
170184
const coloredErrorMesage = brush('red', err.message);
171185
process.stderr.write(coloredErrorMesage + BREAK_LINE);
172186

173-
return;
187+
return pocket;
174188

175189
}
176190

@@ -180,13 +194,13 @@ async function loadJsonData(file) {
180194
});
181195
}
182196

183-
CachedData[cacheKey] = pocket;
197+
cachedData[cacheKey] = pocket;
184198

185199
return pocket;
186200
}
187201

188-
const factory = (options) => {
189-
if (options === undefined) {
202+
const factory = (options, testMode = false) => {
203+
if (!options) {
190204
const packagePath = Path.join(APP_PATH, 'package.json');
191205
const Package = require(packagePath);
192206

@@ -202,25 +216,57 @@ const factory = (options) => {
202216
: DEFAULT_SOURCE_PATH;
203217

204218
const pathHtml = options.hasOwnProperty('pathHtml')
205-
? getAbsolutePath(options.pathHtml)
206-
: getAbsolutePath(sourcePath, 'html');
219+
? Path.join(APP_PATH, options.pathHtml)
220+
: Path.join(APP_PATH, sourcePath, 'html');
207221

208222
const pathData = options.hasOwnProperty('pathData')
209-
? getAbsolutePath(options.pathData)
210-
: getAbsolutePath(sourcePath, 'data');
223+
? Path.join(APP_PATH, options.pathData)
224+
: Path.join(APP_PATH, sourcePath, 'data');
211225

212226
if (!pathHtml.startsWith(APP_PATH) || !pathData.startsWith(APP_PATH)) {
213227
// Please put your source files into your project directory.
214-
throw new Error(ERR_TOP_DIR);
228+
throw new Error(ERR_EXTERNAL_PATH);
215229
}
216230

217-
return loadJsonData.bind({
231+
const context = {
232+
sourcePath,
218233
pathHtml,
219234
pathData,
220235
dataEntry,
221236
locales,
222237
report,
223-
});
238+
cachedData: {}
239+
};
240+
241+
if (testMode) {
242+
return {
243+
context,
244+
loader: loadJsonData.bind(context),
245+
}
246+
}
247+
248+
return loadJsonData.bind(context);
249+
}
250+
251+
factory.forTest = () => {
252+
return {
253+
// Package,
254+
// BrushColors,
255+
256+
constants: {
257+
APP_PATH,
258+
DEFAULT_SOURCE_PATH,
259+
BREAK_LINE,
260+
ERR_EXTERNAL_PATH,
261+
},
262+
263+
brush,
264+
reportAction,
265+
loadImportsAsync,
266+
loadImportsRecursively,
267+
loadJsonData,
268+
// factory,
269+
};
224270
}
225271

226272
module.exports = factory;

0 commit comments

Comments
 (0)