Skip to content

Commit

Permalink
Finalize #259: Metalsmith#debug first implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
webketje committed May 29, 2022
1 parent a753b51 commit 7d39a76
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ coverage.info
.DS_Store
examples/package-lock.json
*.tgz
*.log
.eslintcache
9 changes: 5 additions & 4 deletions lib/debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ debug.formatters.b = function (buffer) {
*/
function Debugger(namespace) {
if (!isString(namespace)) {
throw new Error('invalid debugger namespace')
const err = new Error(`invalid debugger namespace "${namespace}"`)
err.code = 'invalid_debugger_namespace'
throw err
}
// ANSI colors, see https://tintin.mudhalla.net/info/256color/
// the colors have been chosen to best integrate with dark & light bg
Expand All @@ -74,7 +76,7 @@ function Debugger(namespace) {
warn.color = 178

const info = namespacedDebug.extend('info')
info.color = 247
info.color = 51

const error = namespacedDebug.extend('error')
error.color = 196
Expand All @@ -91,8 +93,7 @@ function proxy(host, target, option) {
},
set(v) {
target[option] = v
},
configurable: false
}
})
}

Expand Down
44 changes: 31 additions & 13 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,6 @@ Metalsmith.prototype.env = function (vars, value) {
}
if (!(isFunction(value) || isObject(value))) {
this[symbol.env][vars.toUpperCase()] = value
if (this.debug.enabled && this.env('DEBUG_LOG')) {
this.debug.colors = false
}
return this
}
throw new TypeError('Environment variable values can only be primitive: Number, Boolean, String or null')
Expand Down Expand Up @@ -387,18 +384,39 @@ Metalsmith.prototype.build = function (callback) {
const clean = this.clean()
const dest = this.destination()

if (this.debug.enabled && this.env('DEBUG_LOG')) {
this[symbol.log] = writeStream(this.path(this.env('DEBUG_LOG')))
this.debug.handle = fileLogHandler(this[symbol.log])
this.debug.colors = false
}
const result = (clean ? rm(dest) : Promise.resolve())
.then(() => {
if (this.debug.enabled && this.env('DEBUG_LOG')) {
this[symbol.log] = writeStream(this.path(this.env('DEBUG_LOG')))
this.debug.handle = fileLogHandler(this[symbol.log])
this.debug.colors = false

const result = (clean ? rm(dest) : Promise.resolve()).then(this.process.bind(this)).then((files) => {
return this.write(files).then(() => {
if (this[symbol.log]) this[symbol.log].end()
return files
return new Promise((resolve, reject) => {
this[symbol.log].on('error', (err) => {
let error = err
if (error.code === 'ENOENT') {
error = new Error(
`Inexistant directory path "${path.dirname(this.env('DEBUG_LOG'))}" given for DEBUG_LOG`
)
error.code = 'invalid_logpath'
reject(error)
}
})
if (this[symbol.log].pending) {
this[symbol.log].on('ready', () => resolve())
} else {
resolve()
}
})
}
})
.then(this.process.bind(this))
.then((files) => {
return this.write(files).then(() => {
if (this[symbol.log]) this[symbol.log].end()
return files
})
})
})

/** block required for Metalsmith 2.x callback-flow compat */
if (isFunction(callback)) {
Expand Down
Empty file.
Empty file.
109 changes: 105 additions & 4 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ const fixture = path.resolve.bind(path, __dirname, 'fixtures')
const d = require('debug')

describe('Metalsmith', function () {
const cachedDebugLog = d.log
beforeEach(function () {
d.colors = true
d.log = cachedDebugLog
return rm('test/tmp')
})

Expand Down Expand Up @@ -362,6 +365,7 @@ describe('Metalsmith', function () {
it('should allow plugins to use debug instances', function (done) {
const m = Metalsmith(fixture('basic'))
let fakeStream = []
m.debug.colors = true
m.debug.handle = fileLogHandler({
write(arg) {
fakeStream.push(arg)
Expand All @@ -382,29 +386,50 @@ describe('Metalsmith', function () {
' \x1B[38;5;247;1mmetalsmith:test \x1B[0mA log \x1B[38;5;247m+0ms\x1B[0m\n',
' \x1B[38;5;178;1mmetalsmith:test:warn \x1B[0mA warning \x1B[38;5;178m+0ms\x1B[0m\n',
' \x1B[38;5;196;1mmetalsmith:test:error \x1B[0mAn error \x1B[38;5;196m+0ms\x1B[0m\n',
' \x1B[38;5;247;1mmetalsmith:test:info \x1B[0mAn info \x1B[38;5;247m+0ms\x1B[0m\n'
' \x1B[38;5;51;1mmetalsmith:test:info \x1B[0mAn info \x1B[38;5;51m+0ms\x1B[0m\n'
])
done()
})
})

it('should error when an invalid namespace is passed', function () {
const m = Metalsmith(fixture('test/tmp'))
try {
m.debug(new Error())
} catch (err) {
assert.strictEqual(err.code, 'invalid_debugger_namespace')
}
})

it('should error when an invalid namespace is passed', function () {
const m = Metalsmith(fixture('test/tmp'))
try {
m.debug(new Error())
} catch (err) {
assert.strictEqual(err.code, 'invalid_debugger_namespace')
}
})

it("should convert metalsmith.env('debug', true) to debug all namespaces", function (done) {
const m = Metalsmith(fixture('basic'))
m.debug.colors = true

let fakeStream
m.debug.handle = fileLogHandler({
write(arg) {
fakeStream = arg
}
})

m.env({
debug: true
})
m.use(function plugin(files, m, next) {
const debug = m.debug('metalsmith:test')
debug('A log')
next()
}).process(() => {
}).process((err) => {
if (err) done(err)
assert.strictEqual(fakeStream, ' \x1B[38;5;247;1mmetalsmith:test \x1B[0mA log \x1B[38;5;247m+0ms\x1B[0m\n')
assert.strictEqual(m.env('debug'), '*')
done()
})
})
Expand All @@ -429,6 +454,82 @@ describe('Metalsmith', function () {
done()
})
})

it("should write a log file when metalsmith.env('debug_log') is set to a valid path", function (done) {
const m = Metalsmith(fixture('debug-log'))

m.env('debug', true)
.env('debug_log', fixture('debug-log/metalsmith.log'))
.use(function plugin(files, m, next) {
const debug = m.debug('metalsmith:test')
debug('A log')
next()
})
.build((err, files) => {
if (err) {
done(err)
} else {
assert(
require('fs')
.readFileSync(fixture('debug-log/metalsmith.log'), 'utf-8')
.match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z metalsmith:test A log\n/),
true
)
done()
}
})
})

it("should error when metalsmith.env('debug_log') dir does not exist", function (done) {
const m = Metalsmith(fixture('debug-log'))

m.env('debug', true)
.env('debug_log', fixture('debug-log/inexistant/metalsmith.log'))
.use(function plugin(files, m, next) {
const debug = m.debug('metalsmith:test')
debug('A log')
next()
})
.build((err, files) => {
if (err) {
assert.strictEqual(err.code, 'invalid_logpath')
assert(err.message.match(/Inexistant directory path ".*" given for DEBUG_LOG/))
done()
} else {
done(new Error('No error was thrown'))
}
})
})

it('should provide a debug %b formatter', function (done) {
const m = Metalsmith(fixture('debug-log'))
let fakeStream = null
m.debug.handle = fileLogHandler({
write(arg) {
fakeStream = arg
}
})

m.env('debug', true)
.use(function plugin(files, m, next) {
const debug = m.debug('metalsmith:test')
debug(
'%b',
Buffer.from(
'We keep referring to Metalsmith as a "static site generator", but it\'s a lot more than that. Since everything is a plugin, the core library is actually just an abstraction for manipulating a directory of files.'
)
)
next()
})
.process(() => {
assert(
fakeStream.endsWith(
'We keep referring to Metalsmith as a "static site generator", but it\'s a lot more than that. Since everything is a plugin, the core library is actually just an abstraction for manipulating a directory...\n'
)
)
done()
})
})
})

describe('#read', function () {
Expand Down

0 comments on commit 7d39a76

Please sign in to comment.