mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-27 08:02:01 +00:00
feat: .nuxtignore (#4647)
This commit is contained in:
parent
a303ea89b3
commit
59be77a2f3
@ -16,6 +16,7 @@
|
|||||||
"fs-extra": "^7.0.1",
|
"fs-extra": "^7.0.1",
|
||||||
"glob": "^7.1.3",
|
"glob": "^7.1.3",
|
||||||
"hash-sum": "^1.0.2",
|
"hash-sum": "^1.0.2",
|
||||||
|
"ignore": "^5.0.4",
|
||||||
"lodash": "^4.17.11",
|
"lodash": "^4.17.11",
|
||||||
"pify": "^4.0.1",
|
"pify": "^4.0.1",
|
||||||
"semver": "^5.6.0",
|
"semver": "^5.6.0",
|
||||||
|
@ -31,6 +31,7 @@ import {
|
|||||||
isIndexFileAndFolder
|
isIndexFileAndFolder
|
||||||
} from '@nuxt/utils'
|
} from '@nuxt/utils'
|
||||||
|
|
||||||
|
import Ignore from './ignore'
|
||||||
import BuildContext from './context'
|
import BuildContext from './context'
|
||||||
|
|
||||||
const glob = pify(Glob)
|
const glob = pify(Glob)
|
||||||
@ -86,6 +87,9 @@ export default class Builder {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
this.bundleBuilder = this.getBundleBuilder(bundleBuilder)
|
this.bundleBuilder = this.getBundleBuilder(bundleBuilder)
|
||||||
|
this.ignore = new Ignore({
|
||||||
|
rootDir: this.options.srcDir
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getBundleBuilder(BundleBuilder) {
|
getBundleBuilder(BundleBuilder) {
|
||||||
@ -132,6 +136,18 @@ export default class Builder {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async resolveFiles(dir, cwd = this.options.srcDir) {
|
||||||
|
return this.ignore.filter(await glob(`${dir}/**/*.{${this.supportedExtensions.join(',')}}`, {
|
||||||
|
cwd,
|
||||||
|
ignore: this.options.ignore
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
async resolveRelative(dir) {
|
||||||
|
const dirPrefix = new RegExp(`^${dir}/`)
|
||||||
|
return (await this.resolveFiles(dir)).map(file => ({ src: file.replace(dirPrefix, '') }))
|
||||||
|
}
|
||||||
|
|
||||||
resolvePlugins() {
|
resolvePlugins() {
|
||||||
// Check plugins exist then set alias to their real path
|
// Check plugins exist then set alias to their real path
|
||||||
return Promise.all(this.plugins.map(async (p) => {
|
return Promise.all(this.plugins.map(async (p) => {
|
||||||
@ -318,14 +334,12 @@ export default class Builder {
|
|||||||
router: this.options.router,
|
router: this.options.router,
|
||||||
env: this.options.env,
|
env: this.options.env,
|
||||||
head: this.options.head,
|
head: this.options.head,
|
||||||
middleware: fsExtra.existsSync(path.join(this.options.srcDir, this.options.dir.middleware)),
|
|
||||||
store: this.options.store,
|
store: this.options.store,
|
||||||
globalName: this.options.globalName,
|
globalName: this.options.globalName,
|
||||||
globals: this.globals,
|
globals: this.globals,
|
||||||
css: this.options.css,
|
css: this.options.css,
|
||||||
plugins: this.plugins,
|
plugins: this.plugins,
|
||||||
appPath: './App.js',
|
appPath: './App.js',
|
||||||
ignorePrefix: this.options.ignorePrefix,
|
|
||||||
layouts: Object.assign({}, this.options.layouts),
|
layouts: Object.assign({}, this.options.layouts),
|
||||||
loading:
|
loading:
|
||||||
typeof this.options.loading === 'string'
|
typeof this.options.loading === 'string'
|
||||||
@ -344,10 +358,7 @@ export default class Builder {
|
|||||||
// -- Layouts --
|
// -- Layouts --
|
||||||
if (fsExtra.existsSync(path.resolve(this.options.srcDir, this.options.dir.layouts))) {
|
if (fsExtra.existsSync(path.resolve(this.options.srcDir, this.options.dir.layouts))) {
|
||||||
const configLayouts = this.options.layouts
|
const configLayouts = this.options.layouts
|
||||||
const layoutsFiles = await glob(`${this.options.dir.layouts}/**/*.{${this.supportedExtensions.join(',')}}`, {
|
const layoutsFiles = await this.resolveFiles(this.options.dir.layouts)
|
||||||
cwd: this.options.srcDir,
|
|
||||||
ignore: this.options.ignore
|
|
||||||
})
|
|
||||||
layoutsFiles.forEach((file) => {
|
layoutsFiles.forEach((file) => {
|
||||||
const name = file
|
const name = file
|
||||||
.replace(new RegExp(`^${this.options.dir.layouts}/`), '')
|
.replace(new RegExp(`^${this.options.dir.layouts}/`), '')
|
||||||
@ -392,16 +403,14 @@ export default class Builder {
|
|||||||
} else if (this._nuxtPages) {
|
} else if (this._nuxtPages) {
|
||||||
// Use nuxt.js createRoutes bases on pages/
|
// Use nuxt.js createRoutes bases on pages/
|
||||||
const files = {}
|
const files = {}
|
||||||
;(await glob(`${this.options.dir.pages}/**/*.{${this.supportedExtensions.join(',')}}`, {
|
const ext = new RegExp(`\\.(${this.supportedExtensions.join('|')})$`)
|
||||||
cwd: this.options.srcDir,
|
for (const page of await this.resolveFiles(this.options.dir.pages)) {
|
||||||
ignore: this.options.ignore
|
const key = page.replace(ext, '')
|
||||||
})).forEach((f) => {
|
|
||||||
const key = f.replace(new RegExp(`\\.(${this.supportedExtensions.join('|')})$`), '')
|
|
||||||
// .vue file takes precedence over other extensions
|
// .vue file takes precedence over other extensions
|
||||||
if (/\.vue$/.test(f) || !files[key]) {
|
if (/\.vue$/.test(page) || !files[key]) {
|
||||||
files[key] = f.replace(/(['"])/g, '\\$1')
|
files[key] = page.replace(/(['"])/g, '\\$1')
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
templateVars.router.routes = createRoutes(
|
templateVars.router.routes = createRoutes(
|
||||||
Object.values(files),
|
Object.values(files),
|
||||||
this.options.srcDir,
|
this.options.srcDir,
|
||||||
@ -438,9 +447,24 @@ export default class Builder {
|
|||||||
// -- Store --
|
// -- Store --
|
||||||
// Add store if needed
|
// Add store if needed
|
||||||
if (this.options.store) {
|
if (this.options.store) {
|
||||||
|
templateVars.storeModules = (await this.resolveRelative(this.options.dir.store))
|
||||||
|
.sort(({ src: p1 }, { src: p2 }) => {
|
||||||
|
// modules are sorted from low to high priority (for overwriting properties)
|
||||||
|
let res = p1.split('/').length - p2.split('/').length
|
||||||
|
if (res === 0 && p1.includes('/index.')) {
|
||||||
|
res = -1
|
||||||
|
} else if (res === 0 && p2.includes('/index.')) {
|
||||||
|
res = 1
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
})
|
||||||
|
|
||||||
templatesFiles.push('store.js')
|
templatesFiles.push('store.js')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- Middleware --
|
||||||
|
templateVars.middleware = await this.resolveRelative(this.options.dir.middleware)
|
||||||
|
|
||||||
// Resolve template files
|
// Resolve template files
|
||||||
const customTemplateFiles = this.options.build.templates.map(
|
const customTemplateFiles = this.options.build.templates.map(
|
||||||
t => t.dst || path.basename(t.src || t)
|
t => t.dst || path.basename(t.src || t)
|
||||||
@ -676,6 +700,10 @@ export default class Builder {
|
|||||||
...this.options.watch
|
...this.options.watch
|
||||||
].map(this.nuxt.resolver.resolveAlias)
|
].map(this.nuxt.resolver.resolveAlias)
|
||||||
|
|
||||||
|
if (this.ignore.ignoreFile) {
|
||||||
|
nuxtRestartWatch.push(this.ignore.ignoreFile)
|
||||||
|
}
|
||||||
|
|
||||||
this.watchers.restart = chokidar
|
this.watchers.restart = chokidar
|
||||||
.watch(nuxtRestartWatch, this.options.watchers.chokidar)
|
.watch(nuxtRestartWatch, this.options.watchers.chokidar)
|
||||||
.on('all', (event, _path) => {
|
.on('all', (event, _path) => {
|
||||||
|
51
packages/builder/src/ignore.js
Normal file
51
packages/builder/src/ignore.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
import ignore from 'ignore'
|
||||||
|
|
||||||
|
export default class Ignore {
|
||||||
|
constructor(options) {
|
||||||
|
this.rootDir = options.rootDir
|
||||||
|
this.addIgnoresRules()
|
||||||
|
}
|
||||||
|
|
||||||
|
static get IGNORE_FILENAME() {
|
||||||
|
return '.nuxtignore'
|
||||||
|
}
|
||||||
|
|
||||||
|
findIgnoreFile() {
|
||||||
|
if (!this.ignoreFile) {
|
||||||
|
const ignoreFile = path.resolve(this.rootDir, Ignore.IGNORE_FILENAME)
|
||||||
|
if (fs.existsSync(ignoreFile) && fs.statSync(ignoreFile).isFile()) {
|
||||||
|
this.ignoreFile = ignoreFile
|
||||||
|
this.ignore = ignore()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.ignoreFile
|
||||||
|
}
|
||||||
|
|
||||||
|
readIgnoreFile() {
|
||||||
|
if (this.findIgnoreFile()) {
|
||||||
|
return fs.readFileSync(this.ignoreFile, 'utf8')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addIgnoresRules() {
|
||||||
|
const content = this.readIgnoreFile()
|
||||||
|
if (content) {
|
||||||
|
this.ignore.add(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filter(paths) {
|
||||||
|
if (this.ignore) {
|
||||||
|
return this.ignore.filter([].concat(paths || []))
|
||||||
|
}
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
delete this.ignore
|
||||||
|
delete this.ignoreFile
|
||||||
|
this.addIgnoresRules()
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,8 @@
|
|||||||
<% if (middleware) { %>
|
|
||||||
const files = require.context('@/<%= dir.middleware %>', false, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/)
|
|
||||||
const filenames = files.keys()
|
|
||||||
|
|
||||||
function getModule(filename) {
|
|
||||||
const file = files(filename)
|
|
||||||
return file.default || file
|
|
||||||
}
|
|
||||||
const middleware = {}
|
const middleware = {}
|
||||||
|
<% middleware.forEach(m => {
|
||||||
// Generate the middleware
|
const name = m.src.replace(new RegExp(`\\.(${extensions})$`), '')
|
||||||
for (const filename of filenames) {
|
%>
|
||||||
const name = filename.replace(/^\.\//, '').replace(/\.(<%= extensions %>)$/, '')
|
middleware['<%= name %>'] = require('@/<%= dir.middleware %>/<%= m.src %>');
|
||||||
middleware[name] = getModule(filename)
|
middleware['<%= name %>'] = middleware['<%= name %>'].default || middleware['<%= name %>']
|
||||||
}
|
<% }) %>
|
||||||
|
|
||||||
export default middleware
|
export default middleware
|
||||||
<% } else { %>export default {}<% } %>
|
|
||||||
|
@ -6,29 +6,12 @@ Vue.use(Vuex)
|
|||||||
const log = console // on server-side, consola will catch all console.log
|
const log = console // on server-side, consola will catch all console.log
|
||||||
const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations']
|
const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations']
|
||||||
let store = {}
|
let store = {}
|
||||||
let fileResolver
|
|
||||||
|
|
||||||
void (function updateModules() {
|
void (function updateModules() {
|
||||||
fileResolver = require.context('@/<%= dir.store %>', true, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/)
|
<% storeModules.some(s => {
|
||||||
|
if(s.src.indexOf('index.') === 0) { %>
|
||||||
// Paths are sorted from low to high priority (for overwriting properties)
|
store = normalizeRoot(require('@/<%= dir.store %>/<%= s.src %>'), '<%= dir.store %>/<%= s.src %>')
|
||||||
const paths = fileResolver.keys().sort((p1, p2) => {
|
<% return true }}) %>
|
||||||
let res = p1.split('/').length - p2.split('/').length
|
|
||||||
|
|
||||||
if (res === 0 && p1.includes('/index.')) {
|
|
||||||
res = -1
|
|
||||||
} else if (res === 0 && p2.includes('/index.')) {
|
|
||||||
res = 1
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
})
|
|
||||||
|
|
||||||
// Check if {dir.store}/index.js exists
|
|
||||||
const indexPath = paths.find(path => path.includes('./index.'))
|
|
||||||
|
|
||||||
if (indexPath) {
|
|
||||||
store = requireModule(indexPath, { isRoot: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
// If store is an exported method = classic mode (deprecated)
|
// If store is an exported method = classic mode (deprecated)
|
||||||
if (typeof store === 'function') {
|
if (typeof store === 'function') {
|
||||||
@ -38,47 +21,17 @@ void (function updateModules() {
|
|||||||
// Enforce store modules
|
// Enforce store modules
|
||||||
store.modules = store.modules || {}
|
store.modules = store.modules || {}
|
||||||
|
|
||||||
for (const path of paths) {
|
<% storeModules.forEach(s => {
|
||||||
// Remove store path + extension (./foo/index.js -> foo/index)
|
if(s.src.indexOf('index.') !== 0) { %>
|
||||||
const namespace = path.replace(/^\.\//, '').replace(/\.(<%= extensions %>)$/, '')
|
resolveStoreModules(require('@/<%= dir.store %>/<%= s.src %>'), '<%= s.src %>')<% }}) %>
|
||||||
|
|
||||||
// Ignore indexFile, handled before
|
|
||||||
if (namespace === 'index') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const namespaces = namespace.split('/')
|
|
||||||
let moduleName = namespaces[namespaces.length - 1]
|
|
||||||
const moduleData = requireModule(path, { isState: moduleName === 'state' })
|
|
||||||
|
|
||||||
// If path is a known Vuex property
|
|
||||||
if (VUEX_PROPERTIES.includes(moduleName)) {
|
|
||||||
const property = moduleName
|
|
||||||
const storeModule = getStoreModule(store, namespaces, { isProperty: true })
|
|
||||||
|
|
||||||
// Replace state since it's a function
|
|
||||||
mergeProperty(storeModule, moduleData, property)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// If file is foo/index.js, it should be saved as foo
|
|
||||||
const isIndexModule = (moduleName === 'index')
|
|
||||||
if (isIndexModule) {
|
|
||||||
namespaces.pop()
|
|
||||||
moduleName = namespaces[namespaces.length - 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
const storeModule = getStoreModule(store, namespaces)
|
|
||||||
|
|
||||||
for (const property of VUEX_PROPERTIES) {
|
|
||||||
mergeProperty(storeModule, moduleData[property], property)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the environment supports hot reloading...
|
// If the environment supports hot reloading...
|
||||||
<% if (isDev) { %>
|
<% if (isDev) { %>
|
||||||
if (process.client && module.hot) {
|
if (process.client && module.hot) {
|
||||||
// Whenever any Vuex module is updated...
|
// Whenever any Vuex module is updated...
|
||||||
module.hot.accept(fileResolver.id, () => {
|
module.hot.accept([<% storeModules.forEach(s => { %>
|
||||||
|
'@/<%= dir.store %>/<%= s.src %>',<% }) %>
|
||||||
|
], () => {
|
||||||
// Update `root.modules` with the latest definitions.
|
// Update `root.modules` with the latest definitions.
|
||||||
updateModules()
|
updateModules()
|
||||||
// Trigger a hot update in the store.
|
// Trigger a hot update in the store.
|
||||||
@ -94,26 +47,68 @@ export const createStore = store instanceof Function ? store : () => {
|
|||||||
}, store))
|
}, store))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamically require module
|
function resolveStoreModules(moduleData, filename) {
|
||||||
function requireModule(path, { isRoot = false, isState = false } = {}) {
|
moduleData = moduleData.default || moduleData
|
||||||
const file = fileResolver(path)
|
// Remove store src + extension (./foo/index.js -> foo/index)
|
||||||
let moduleData = file.default || file
|
const namespace = filename.replace(/\.(<%= extensions %>)$/, '')
|
||||||
|
const namespaces = namespace.split('/')
|
||||||
|
let moduleName = namespaces[namespaces.length - 1]
|
||||||
|
const filePath = `<%= dir.store %>/${filename}`
|
||||||
|
|
||||||
if (isState && typeof moduleData !== 'function') {
|
moduleData = moduleName === 'state'
|
||||||
log.warn(`${path} should export a method that returns an object`)
|
? normalizeState(moduleData, filePath)
|
||||||
const state = Object.assign({}, moduleData)
|
: normalizeModule(moduleData, filePath)
|
||||||
return () => state
|
|
||||||
}
|
// If src is a known Vuex property
|
||||||
if (isRoot && moduleData.commit) {
|
if (VUEX_PROPERTIES.includes(moduleName)) {
|
||||||
throw new Error('[nuxt] <%= dir.store %>/' + path.replace('./', '') + ' should export a method that returns a Vuex instance.')
|
const property = moduleName
|
||||||
|
const storeModule = getStoreModule(store, namespaces, { isProperty: true })
|
||||||
|
|
||||||
|
// Replace state since it's a function
|
||||||
|
mergeProperty(storeModule, moduleData, property)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRoot && typeof moduleData !== 'function') {
|
// If file is foo/index.js, it should be saved as foo
|
||||||
|
const isIndexModule = (moduleName === 'index')
|
||||||
|
if (isIndexModule) {
|
||||||
|
namespaces.pop()
|
||||||
|
moduleName = namespaces[namespaces.length - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
const storeModule = getStoreModule(store, namespaces)
|
||||||
|
|
||||||
|
for (const property of VUEX_PROPERTIES) {
|
||||||
|
mergeProperty(storeModule, moduleData[property], property)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeRoot(moduleData, filePath) {
|
||||||
|
moduleData = moduleData.default || moduleData
|
||||||
|
|
||||||
|
if (moduleData.commit) {
|
||||||
|
throw new Error(`[nuxt] ${filePath} should export a method that returns a Vuex instance.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof moduleData !== 'function') {
|
||||||
// Avoid TypeError: setting a property that has only a getter when overwriting top level keys
|
// Avoid TypeError: setting a property that has only a getter when overwriting top level keys
|
||||||
moduleData = Object.assign({}, moduleData)
|
moduleData = Object.assign({}, moduleData)
|
||||||
}
|
}
|
||||||
|
return normalizeModule(moduleData, filePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeState(moduleData, filePath) {
|
||||||
|
if (typeof moduleData !== 'function') {
|
||||||
|
log.warn(`${filePath} should export a method that returns an object`)
|
||||||
|
const state = Object.assign({}, moduleData)
|
||||||
|
return () => state
|
||||||
|
}
|
||||||
|
return normalizeModule(moduleData, filePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeModule(moduleData, filePath) {
|
||||||
if (moduleData.state && typeof moduleData.state !== 'function') {
|
if (moduleData.state && typeof moduleData.state !== 'function') {
|
||||||
log.warn(`'state' should be a method that returns an object in ${path}`)
|
log.warn(`'state' should be a method that returns an object in ${filePath}`)
|
||||||
const state = Object.assign({}, moduleData.state)
|
const state = Object.assign({}, moduleData.state)
|
||||||
// Avoid TypeError: setting a property that has only a getter when overwriting top level keys
|
// Avoid TypeError: setting a property that has only a getter when overwriting top level keys
|
||||||
moduleData = Object.assign({}, moduleData, { state: () => state })
|
moduleData = Object.assign({}, moduleData, { state: () => state })
|
||||||
|
4
test/fixtures/with-config/.nuxtignore
vendored
Normal file
4
test/fixtures/with-config/.nuxtignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
layouts/test-ignore.vue
|
||||||
|
pages/test-ignore.vue
|
||||||
|
store/test-ignore.js
|
||||||
|
middleware/test-ignore.js
|
1
test/fixtures/with-config/layouts/test-ignore.vue
vendored
Normal file
1
test/fixtures/with-config/layouts/test-ignore.vue
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
throw new Error('This file should be ignored!!')
|
1
test/fixtures/with-config/middleware/test-ignore.js
vendored
Normal file
1
test/fixtures/with-config/middleware/test-ignore.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
throw new Error('This file should be ignored!!')
|
0
test/fixtures/with-config/pages/test-ignore.vue
vendored
Normal file
0
test/fixtures/with-config/pages/test-ignore.vue
vendored
Normal file
1
test/fixtures/with-config/store/test-ignore.js
vendored
Normal file
1
test/fixtures/with-config/store/test-ignore.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
throw new Error('This file should be ignored!!')
|
@ -180,6 +180,11 @@ describe('with-config', () => {
|
|||||||
.rejects.toMatchObject({ statusCode: 404 })
|
.rejects.toMatchObject({ statusCode: 404 })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should ignore files in .nuxtignore', async () => {
|
||||||
|
await expect(rp(url('/test-ignore')))
|
||||||
|
.rejects.toMatchObject({ statusCode: 404 })
|
||||||
|
})
|
||||||
|
|
||||||
test('renderAndGetWindow options', async () => {
|
test('renderAndGetWindow options', async () => {
|
||||||
const fakeErrorLog = jest.fn()
|
const fakeErrorLog = jest.fn()
|
||||||
const mockOptions = {
|
const mockOptions = {
|
||||||
|
@ -5478,7 +5478,7 @@ ignore@^4.0.6:
|
|||||||
resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
||||||
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
|
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
|
||||||
|
|
||||||
ignore@^5.0.2:
|
ignore@^5.0.2, ignore@^5.0.4:
|
||||||
version "5.0.4"
|
version "5.0.4"
|
||||||
resolved "https://registry.npmjs.org/ignore/-/ignore-5.0.4.tgz#33168af4a21e99b00c5d41cbadb6a6cb49903a45"
|
resolved "https://registry.npmjs.org/ignore/-/ignore-5.0.4.tgz#33168af4a21e99b00c5d41cbadb6a6cb49903a45"
|
||||||
integrity sha512-WLsTMEhsQuXpCiG173+f3aymI43SXa+fB1rSfbzyP4GkPP+ZFVuO0/3sFUGNBtifisPeDcl/uD/Y2NxZ7xFq4g==
|
integrity sha512-WLsTMEhsQuXpCiG173+f3aymI43SXa+fB1rSfbzyP4GkPP+ZFVuO0/3sFUGNBtifisPeDcl/uD/Y2NxZ7xFq4g==
|
||||||
|
Loading…
Reference in New Issue
Block a user