Read-Write pp3 files

feature/pp3
Clovis Gauzy 2020-12-01 10:12:34 +01:00
parent aead01ff3d
commit c4bc6ca3fd
2 changed files with 103 additions and 0 deletions

View File

@ -173,3 +173,4 @@ const rawtherapee = (file, options = {}) => {
}
module.exports = rawtherapee
module.exports.PP3 = require('./src/lib/pp3.js')

102
src/lib/pp3.js Normal file
View File

@ -0,0 +1,102 @@
const fs = require('fs')
const readline = require('readline')
const paramParser = (line) => {
switch (true) {
case line === 'true': return true
case line === 'false': return false
case line === 'null': return null
case /^[0-9-]+\.?[0-9]*$/.test(line): return Number(line)
case /;/.test(line):
line = line.split(';')
line.pop()
return line.map(l => paramParser(l))
default: return line
}
}
const paramReducer = (acc, cur, idx, src) => {
if (/^_/.test(cur)) return acc
switch (typeof src[cur]) {
case 'object':
if (Array.isArray(src[cur])) acc += `${cur}=${src[cur].join(';')};\n`
else {
acc += `\n[${cur}]\n`
acc += Object.keys(src[cur]).reduce((acc0, cur0, idx0) => paramReducer(acc0, cur0, idx0, src[cur]), '')
}
break
default:
acc = `${cur}=${String(src[cur])}\n` + acc
}
return acc
}
class PP3 {
static load (file) {
return new Promise((resolve, reject) => {
if (!file) return reject(new Error('Filename is mandatory.'))
if (!fs.existsSync(file)) return reject(new Error(`${file} didn't exists.`))
if (!/\.pp3$/i.test(file)) return reject(new Error('Filename have a bad extension.'))
const rl = readline.createInterface({
input: fs.createReadStream(file),
output: process.stdout,
terminal: false
})
let rub
const tree = {}
rl.on('line', (line) => {
const isRub = /^\[(.+)\]$/.exec(line)
if (isRub) {
rub = isRub[1]
tree[rub] = {}
}
const isParam = /^(.+)=(.+)$/.exec(line)
if (isParam) {
const p = paramParser(isParam[2].trim())
if (rub) tree[rub][isParam[1].trim()] = p
else tree[isParam[1].trim()] = p
}
})
rl.on('close', () => {
const out = new PP3(tree)
out._pp3 = {
source: {
url: file,
date: new Date()
}
}
resolve(out)
})
})
}
constructor (tree) {
if (tree) {
Object.keys(tree).forEach(k => {
this[k] = tree[k]
})
}
}
toString () {
return Object.keys(this).reduce((acc, cur, idx) => paramReducer(acc, cur, idx, this), '')
}
save (file) {
return new Promise((resolve, reject) => {
if (!file && (!this._pp3 || this._pp3.source || this._pp3.source.url)) return reject(new Error('You need to specify an output destination.'))
if (!file) file = this._pp3.source.url
const out = this.toString()
fs.writeFileSync(file, out, 'utf8')
if (!this._pp3) this._pp3 = {}
if (!this._pp3.saved) this._pp3.saved = []
this._pp3.saved.push({
url: file,
date: new Date()
})
resolve(out)
})
}
}
module.exports = PP3