date-holidays
Version:
worldwide holidays
196 lines (179 loc) • 5.72 kB
JavaScript
const fs = require('fs')
const path = require('path')
const resolve = path.resolve
const jsyaml = require('js-yaml')
const PrePin = require('prepin')
const _pick = require('lodash.pick')
const _omit = require('lodash.omit')
const REGEX = /^([A-Z]+)\.yaml$/
const dirParser = path.dirname(require.resolve('date-holidays-parser'))
const config = {
dirname: resolve(__dirname, '..', 'data'),
countries: resolve(__dirname, '..', 'data', 'countries'),
factories: [
resolve(dirParser, '..', 'src', 'CalEventFactory.js'),
resolve(dirParser, '..', 'lib', 'CalEventFactory.cjs')
]
}
function Holidays2json (opts) {
this.opts = opts || {}
this.list = this.opts.list || []
}
Holidays2json.prototype = {
/**
* get list of supported countries from directory
*/
getList: function () {
let list = fs.readdirSync(config.countries)
list = list
.map((file) => {
if (REGEX.test(file)) {
return file.replace(REGEX, '$1')
} else {
return undefined
}
})
.filter(function (file) {
return file
})
.sort()
this.list = list
return this
},
/**
* load a single yaml file
*/
load: function (cc, filename) {
filename = filename || resolve(config.countries, cc + '.yaml')
const data = fs.readFileSync(filename, 'utf8')
const obj = jsyaml.load(data)
return obj
},
/**
* build `holidays.json file`
*/
build: function () {
const obj = this.load('0')
obj.holidays = {}
this.list.forEach(function (cc) {
Object.assign(obj.holidays, this.load(cc).holidays)
}.bind(this))
Object.assign(obj, this.load(null, resolve(config.dirname, 'names.yaml')))
if (this.opts.pick) {
obj.holidays = _pick(obj.holidays, this.opts.pick)
} else if (this.opts.omit) {
obj.holidays = _omit(obj.holidays, this.opts.omit)
}
obj.version = new Date().toISOString().replace(/^(.*)T.*$/, '$1')
this.holidays = obj
if (this.opts.min) this.prepin()
return this
},
/**
* save holidays
*/
save: function () {
const json = JSON.stringify(this.holidays, null, 2) + '\n'
fs.writeFileSync(resolve(config.dirname, 'holidays.json'), json, 'utf8')
fs.writeFileSync(resolve(__dirname, '..', 'src', 'data.js'), 'export const data = ' + json, 'utf8')
if (fs.existsSync(resolve(__dirname, '..', 'lib'))) {
fs.writeFileSync(resolve(__dirname, '..', 'lib', 'data.cjs'), 'exports.data = ' + json, 'utf8')
}
},
/**
* modify the factories to require only the minimum required packages
*/
prepin: function () {
// reduce final build size
const macros = dive(this.holidays)
config.factories.forEach(function (fa) {
new PrePin({ macros: macros, input: fa, output: fa }).proc().catch(function (e) {
console.error(e)
})
})
}
}
module.exports = Holidays2json
if (module === require.main) {
const args = process.argv.splice(2)
const getOption = function (option) {
const i = args.indexOf(option)
if (i !== -1) {
const list = (args[i + 1] || '').toUpperCase().split(',').sort()
if (list && list.length) return list
return true
}
}
if (getOption('-h') || getOption('--help')) {
console.log([
'',
'holidays2json [options]',
'',
'translate holidays.yaml data to json',
'',
'-p|--pick comma separated list of countries to pick',
' from holidays.json file',
'-o|--omit comma separated list of countries to omit',
' from holidays.json file',
'-m|--min minimize the package dependencies - e.g. if using webpack or',
' browserify',
'',
'NOTE: There are some countries which depend on data of others which',
' might render the file useless. e.g. "GU" requires "US", so try',
' to pick or omit both.',
'',
'Use in your build process in package.json "scripts" section.',
' "build" : "holidays2json -p US,CA,GU"',
'and run then with `npm run build`',
''
].join('\n '))
process.exit(0)
}
const opts = {
pick: getOption('--pick') || getOption('-p'),
omit: getOption('--omit') || getOption('-o'),
min: getOption('--min') || getOption('-m')
}
new Holidays2json(opts).getList().build().save()
}
/**
* searches for `days` to obtain macros for prepin
*/
function dive (data, macros) {
macros = macros || {
nojulian: true,
nohebrew: true,
noislamic: true,
nochinese: true,
nobengali: true,
noequinox: true
}
switch (toString.call(data)) {
case '[object Object]':
Object.keys(data).forEach(function (key) {
if (key === 'days') {
Object.keys(data[key]).forEach(function (key) {
if (/\b(Muharram|Safar|Rabi al-awwal|Rabi al-thani|Jumada al-awwal|Jumada al-thani|Rajab|Shaban|Ramadan|Shawwal|Dhu al-Qidah|Dhu al-Hijjah)\b/.test(key)) {
delete macros.noislamic
} else if (/\b(julian)\b/.test(key)) {
delete macros.nojulian
} else if (/\b(chinese|vietnamese|korean)\b/.test(key)) {
delete macros.nochinese
} else if (/\b(bengali-revised)\b/.test(key)) {
delete macros.nobengali
} else if (/\b(equinox|solstice)\b/.test(key)) {
delete macros.noequinox
} else if (/\b(Nisan|Iyyar|Sivan|Tamuz|Av|Elul|Tishrei|Cheshvan|Kislev|Tevet|Shvat|Adar)\b/.test(key)) {
delete macros.nohebrew
}
})
} else {
dive(data[key], macros)
}
})
break
}
return macros
}