1 |
|
2 | const Metalsmith = require('metalsmith');
|
3 | const uppercamelcase = require('uppercamelcase');
|
4 | const async = require('async');
|
5 | const ejsRender = require('consolidate').ejs.render;
|
6 | const multimatch = require('multimatch');
|
7 | const kebabCase = require('kebab-case');
|
8 | const { getNpmRegistry } = require('ice-npm-utils');
|
9 | const transform = require('./transform');
|
10 | const logger = require('./logger');
|
11 |
|
12 | const TEMPLATE_PATH = '.template';
|
13 |
|
14 | module.exports = (options) => {
|
15 | return new Promise((resolve, reject) => {
|
16 | render(options, (err) => {
|
17 | if (err) {
|
18 | reject(err);
|
19 | } else {
|
20 | resolve();
|
21 | }
|
22 | });
|
23 | });
|
24 | };
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 | function render(options, done) {
|
36 | const {
|
37 | src,
|
38 | dest,
|
39 | name = '',
|
40 | npmName,
|
41 | transformRegexp,
|
42 | ...opts
|
43 | } = options;
|
44 |
|
45 | logger.verbose('Metalsmith template render', { name, src, dest });
|
46 |
|
47 |
|
48 | const metalsmith = Metalsmith(src);
|
49 | metalsmith.frontmatter(false);
|
50 |
|
51 | const data = Object.assign(metalsmith.metadata(), {
|
52 | name: kebabCase(name).replace(/^-/, ''),
|
53 | npmName: kebabCase(npmName || name).replace(/^-/, ''),
|
54 | className: uppercamelcase(name),
|
55 | inPlace: dest === process.cwd(),
|
56 | noEscape: true,
|
57 | registry: getNpmRegistry(npmName || name),
|
58 | categories: {},
|
59 | category: '',
|
60 | ...opts,
|
61 | });
|
62 | logger.verbose('Metalsmith render options', data);
|
63 |
|
64 | metalsmith
|
65 | .use(renderTemplateFiles())
|
66 | .use(transformFile(data.skipGitIgnore, transformRegexp))
|
67 | .ignore([TEMPLATE_PATH, 'meta.js']);
|
68 |
|
69 | metalsmith
|
70 | .clean(false)
|
71 | .source('.')
|
72 | .destination(dest)
|
73 | .build((err) => {
|
74 |
|
75 | done(err, () => {
|
76 | logMessage(data);
|
77 | });
|
78 | });
|
79 |
|
80 | return data;
|
81 | }
|
82 |
|
83 | function transformFile(skipGitIgnore, transformRegexp) {
|
84 | return (files, metalsmith, done) => {
|
85 | transform(files, {
|
86 | ...metalsmith.metadata(),
|
87 | skipGitIgnore,
|
88 | transformRegexp,
|
89 | }, done);
|
90 | };
|
91 | }
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 | function renderTemplateFiles(skipInterpolation) {
|
101 | skipInterpolation =
|
102 | typeof skipInterpolation === 'string'
|
103 | ? [skipInterpolation]
|
104 | : skipInterpolation;
|
105 |
|
106 | logger.verbose('Metasmith renderTemplateFiles', skipInterpolation);
|
107 |
|
108 | return (files, metalsmith, done) => {
|
109 | logger.verbose('Metasmith renderTemplateFiles callback');
|
110 |
|
111 | const keys = Object.keys(files);
|
112 | const metalsmithMetadata = metalsmith.metadata();
|
113 |
|
114 |
|
115 | Object.keys(metalsmithMetadata).forEach((key) => {
|
116 | if (key === 'type') {
|
117 | if (
|
118 | metalsmithMetadata[key].react &&
|
119 | metalsmithMetadata[key].vue
|
120 | ) {
|
121 | metalsmithMetadata.materialType = ['react', 'vue'];
|
122 | } else if (metalsmithMetadata[key].react) {
|
123 | metalsmithMetadata.materialType = 'react';
|
124 | } else if (metalsmithMetadata[key].vue) {
|
125 | metalsmithMetadata.materialType = 'vue';
|
126 | }
|
127 | }
|
128 | });
|
129 |
|
130 | async.each(
|
131 | keys,
|
132 | (file, next) => {
|
133 |
|
134 | if (
|
135 | skipInterpolation &&
|
136 | multimatch([file], skipInterpolation, { dot: true }).length
|
137 | ) {
|
138 | return next();
|
139 | }
|
140 | const str = files[file].contents.toString();
|
141 |
|
142 | logger.verbose('ejsRender start', file);
|
143 | ejsRender(str, metalsmithMetadata, (err, res) => {
|
144 | if (err) {
|
145 | err.message = `[${file}] ${err.message}`;
|
146 | return next(err);
|
147 | }
|
148 |
|
149 | logger.verbose('ejsRender success', file);
|
150 |
|
151 | files[file].contents = new Buffer(res);
|
152 | next();
|
153 | });
|
154 | },
|
155 | done
|
156 | );
|
157 | };
|
158 | }
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 | function logMessage(message, data) {
|
167 | if (!message) return;
|
168 | ejsRender(message, data, (err, res) => {
|
169 | if (err) {
|
170 | console.error(
|
171 | `\n Error when rendering template complete message: ${
|
172 | err.message.trim()}`
|
173 | );
|
174 | } else {
|
175 | console.log(
|
176 | `\n${
|
177 | res
|
178 | .split(/\r?\n/g)
|
179 | .map((line) => ` ${line}`)
|
180 | .join('\n')}`
|
181 | );
|
182 | }
|
183 | });
|
184 | }
|