|
2 | 2 |
|
3 | 3 | 'use strict'
|
4 | 4 |
|
5 |
| -const fs = require('fs'); |
6 |
| -const path = require('path'); |
7 |
| -const mkdirp = require('mkdirp'); |
| 5 | +const fs = require('fs') |
| 6 | +const path = require('path') |
| 7 | +const mkdirp = require('mkdirp') |
8 | 8 | const sh = require('shelljs')
|
9 | 9 |
|
10 |
| -const basename = path.basename; |
11 |
| -const dirname = path.dirname; |
12 |
| -const resolve = path.resolve; |
13 |
| -const normalize = path.normalize; |
14 |
| -const join = path.join; |
15 |
| -const relative = path.relative; |
16 |
| -const extension = path.extname; |
| 10 | +const basename = path.basename |
| 11 | +const dirname = path.dirname |
| 12 | +const resolve = path.resolve |
| 13 | +const normalize = path.normalize |
| 14 | +const join = path.join |
| 15 | +const relative = path.relative |
| 16 | +const extension = path.extname |
17 | 17 |
|
18 |
| -const src = 'src/'; |
19 |
| -const dest = 'dist/'; |
| 18 | +const src = 'src/' |
| 19 | +const dest = 'dist/' |
| 20 | +const base = path.resolve(__dirname, '..') |
20 | 21 |
|
21 | 22 | const walkSync = (dir, filelist = []) => {
|
22 | 23 | fs.readdirSync(dir).forEach(file => {
|
23 | 24 | filelist = fs.statSync(path.join(dir, file)).isDirectory()
|
24 |
| - ? walkSync(path.join(dir, file), filelist) |
25 |
| - : filelist.concat(path.join(dir, file)); |
26 |
| - }); |
27 |
| - return filelist; |
| 25 | + ? walkSync(path.join(dir, file), filelist) |
| 26 | + : filelist.concat(path.join(dir, file)) |
| 27 | + }) |
| 28 | + return filelist |
| 29 | +} |
| 30 | + |
| 31 | +const vendorName = (path) => { |
| 32 | + const nodeModules = Boolean(path.split('/')[0] === 'node_modules') |
| 33 | + const subDir = Boolean(path.indexOf('@') >= 0) |
| 34 | + let vendor |
| 35 | + if (nodeModules) { |
| 36 | + if (subDir) { |
| 37 | + vendor = `${path.split('/')[1]}/${path.split('/')[2]}` |
| 38 | + } else { |
| 39 | + vendor = `${path.split('/')[1]}` |
| 40 | + } |
| 41 | + } |
| 42 | + return vendor |
| 43 | +} |
| 44 | + |
| 45 | +function removeDuplicates( arr, prop ) { |
| 46 | + let obj = {}; |
| 47 | + return Object.keys(arr.reduce((prev, next) => { |
| 48 | + if(!obj[next[prop]]) obj[next[prop]] = next; |
| 49 | + return obj; |
| 50 | + }, obj)).map((i) => obj[i]); |
28 | 51 | }
|
29 | 52 |
|
30 | 53 | const findVendors = () => {
|
31 |
| - const vendors = { css: [], js: [], other: [] }; |
| 54 | + const vendors = [] |
| 55 | + // const assets = [] |
| 56 | + // const vendors = { css: [], js: [], other: [] } |
32 | 57 | const filenames = walkSync(src)
|
33 | 58 |
|
34 | 59 | filenames.forEach((filename) => {
|
35 | 60 | if (extension(filename) === '.html') {
|
36 |
| - const files = fs.readFileSync(filename, 'ascii').toString().split('\n'); |
| 61 | + const files = fs.readFileSync(filename, 'ascii').toString().split('\n') |
37 | 62 |
|
38 |
| - // go through the list of logFileLines |
| 63 | + // go through the list of code lines |
39 | 64 | files.forEach((file) => {
|
40 | 65 |
|
41 |
| - // if the current line matches SAVE, it will be stored in the variable lines |
42 |
| - if(file.match(/node_modules/)) { |
43 |
| - |
44 |
| - const js = file.match(/node_modules.*.js/) |
45 |
| - if (js !== null) { |
46 |
| - // vendors.js.indexOf(resolve(js[0])) === -1 ? vendors.js.push({'html':js[0],'absolute':resolve(js[0]) }) : ''; |
47 |
| - vendors.js.map((item) => { return item.html }).indexOf(js[0]) === -1 ? vendors.js.push({'html':js[0],'absolute':resolve(js[0]) }) : ''; |
48 |
| - } |
49 |
| - const css = file.match(/node_modules.*.css/) |
50 |
| - if (css !== null) { |
51 |
| - if (vendors.css.map((item) => { return item.html }).indexOf(css[0]) === -1) { |
52 |
| - // vendors.css.push(resolve(css[0])) |
53 |
| - vendors.css.push({'html':css[0],'absolute':resolve(css[0]) }) |
54 |
| - |
55 |
| - const assets = fs.readFileSync(css[0], 'ascii').toString().match(/url\(.*?\)/ig); |
56 |
| - assets.forEach(function(asset) { |
57 |
| - const assetPath = asset.replace(/\?.*/g, '').replace('url(','').replace(/\'/g, '').replace(')',''); |
58 |
| - vendors.other.push({'absolute' : resolve(dirname(css[0]), assetPath), 'relative' : assetPath }) |
59 |
| - }) |
| 66 | + // if the current line matches `/(?:href|src)="(node_modules.*.[css|js])"/`, it will be stored in the variable lines |
| 67 | + const nodeModules = file.match(/(?:href|src)="(node_modules.*.[css|js])"/) |
| 68 | + if (nodeModules) { |
| 69 | + let vendor = [] |
| 70 | + const src = nodeModules[1] |
| 71 | + const name = vendorName(src) |
| 72 | + let type |
| 73 | + let absolute |
| 74 | + |
| 75 | + vendor['name'] = name |
| 76 | + vendor['filetype'] = extension(src).replace('.', '') |
| 77 | + vendor['src'] = src |
| 78 | + vendor['absolute'] = resolve(src) |
| 79 | + |
| 80 | + if (vendors.findIndex(vendor => vendor.absolute === resolve(src)) === -1) { |
| 81 | + vendors.push(vendor) |
| 82 | + |
| 83 | + // Check it CSS file has assets |
| 84 | + if (extension(src) === '.css') { |
| 85 | + const assets = fs.readFileSync(resolve(src), 'ascii').toString().match(/(?:url)\((.*?)\)/ig) |
| 86 | + if (assets) { |
| 87 | + assets.forEach((asset) => { |
| 88 | + const assetPath = asset.match(/(?:url)\((.*?)\)/)[1] |
| 89 | + let subVendor = [] |
| 90 | + if (assetPath !== undefined) { |
| 91 | + // console.log(assetPath) |
| 92 | + const path = assetPath.replace(/\?.*/, '').replace(/\'|\"/, '') |
| 93 | + subVendor['name'] = name |
| 94 | + subVendor['filetype'] = 'other' |
| 95 | + subVendor['src'] = normalize(`css/${path}`) |
| 96 | + subVendor['absolute'] = resolve(dirname(src), path) |
| 97 | + |
| 98 | + vendors.push(subVendor) |
| 99 | + } |
| 100 | + }) |
| 101 | + } |
60 | 102 | }
|
61 | 103 | }
|
62 | 104 | }
|
63 | 105 | })
|
64 | 106 | }
|
65 | 107 | })
|
66 |
| - return vendors; |
| 108 | + return vendors |
67 | 109 | }
|
68 | 110 |
|
69 | 111 | const copyFiles = (files, dest) => {
|
70 | 112 | files.forEach((file) => {
|
71 |
| - mkdirp.sync(resolve(dest)); |
72 |
| - fs.createReadStream(file).pipe(fs.createWriteStream(resolve(dest, basename(file)))); |
73 |
| - }) |
74 |
| -} |
| 113 | + let dir |
| 114 | + file.filetype !== 'other' ? dir = resolve(dest, file.name, file.filetype) : dir = resolve(dest, file.name, dirname(file.src)) |
| 115 | + mkdirp.sync(dir) |
| 116 | + fs.createReadStream(file.absolute).pipe(fs.createWriteStream(resolve(dir, basename(file.src)))) |
75 | 117 |
|
76 |
| -const copyOtherFiles = (files, dest) => { |
77 |
| - files.forEach((file) => { |
78 |
| - mkdirp.sync(resolve(dest + dirname(file.relative))); |
79 |
| - fs.createReadStream(file.absolute).pipe(fs.createWriteStream(resolve(dest, file.relative))); |
| 118 | + if (fs.existsSync(`${file.absolute}.map`)) { |
| 119 | + fs.createReadStream(`${file.absolute}.map`).pipe(fs.createWriteStream(resolve(dir, `${basename(file.src)}.map`))) |
| 120 | + } |
80 | 121 | })
|
81 | 122 | }
|
82 | 123 |
|
83 |
| -const replaceRecursively = (filename, original) => { |
84 |
| - const replacement = 'vendors/' + extension(original).replace('.','') + '/' + basename(original); |
| 124 | +const replaceRecursively = (filename, vendor) => { |
| 125 | + const original = vendor.src |
| 126 | + const replacement = `vendors/${vendor.name}/${vendor.filetype}/${basename(vendor.src)}` |
85 | 127 | sh.sed('-i', original, replacement, filename)
|
86 | 128 | }
|
87 | 129 |
|
88 | 130 | const main = () => {
|
89 |
| - |
90 | 131 | const vendors = findVendors()
|
91 |
| - |
92 |
| - copyFiles(vendors.css.map((item) => { return item.absolute }), './dist/vendors/css/'); |
93 |
| - copyFiles(vendors.js.map((item) => { return item.absolute }), './dist/vendors/js/'); |
94 |
| - copyOtherFiles(vendors.other, './dist/vendors/css/'); |
95 |
| - |
| 132 | + copyFiles(vendors.map((file) => { return file }), './dist/vendors/') |
96 | 133 | const filenames = walkSync(dest)
|
97 | 134 | filenames.forEach((filename) => {
|
98 | 135 | if (extension(filename) === '.html') {
|
99 |
| - vendors.css.map((item) => { |
100 |
| - replaceRecursively(resolve(filename), item.html) |
101 |
| - }) |
102 |
| - vendors.js.map((item) => { |
103 |
| - replaceRecursively(resolve(filename), item.html) |
| 136 | + vendors.map((vendor) => { |
| 137 | + if (vendor.filetype !== 'other') { |
| 138 | + replaceRecursively(resolve(filename), vendor) |
| 139 | + } |
104 | 140 | })
|
105 | 141 | }
|
106 | 142 | })
|
|
0 commit comments