const fs = require("fs") const espree = require("espree") const format = require("string-format") const core = require('@actions/core') // Parse the AST const espreeOptions = { ecmaVersion: 6, sourceType: "module", range: true, } class ConfigParser { constructor(staticSiteConfig) { this.pathPropertyNuxt = `router: {\n base: '{0}'\n }` this.pathPropertyNext = `basePath: '{0}'` this.pathPropertyGatsby = `pathPrefix: '{0}'` this.configskeleton = `export default {\n {0}\n}` this.staticSiteConfig = staticSiteConfig this.config = fs.existsSync(this.staticSiteConfig.filePath) ? fs.readFileSync(this.staticSiteConfig.filePath, "utf8") : null this.validate() } validate() { if (!this.config) { core.info(`original raw configuration was empty:\n${this.config}`) core.info('Generating a default configuration to start from...') // Update the `config` property with a default configuration file this.config = this.generateConfigFile() } } generateConfigFile() { switch (this.staticSiteConfig.type) { case "nuxt": return format(this.configskeleton, format(this.pathPropertyNuxt, this.staticSiteConfig.newPath)) break case "next": return format(this.configskeleton, format(this.pathPropertyNext, this.staticSiteConfig.newPath)) break case "gatsby": return format(this.configskeleton, format(this.pathPropertyGatsby, this.staticSiteConfig.newPath)) break default: throw "Unknown config type" } } generateConfigProperty() { switch (this.staticSiteConfig.type) { case "nuxt": return format(this.pathPropertyNuxt, this.staticSiteConfig.newPath) break case "next": return format(this.pathPropertyNext, this.staticSiteConfig.newPath) break case "gatsby": return format(this.pathPropertyGatsby, this.staticSiteConfig.newPath) break default: throw "Unknown config type" } } parse() { core.info(`original configuration:\n${this.config}`) const ast = espree.parse(this.config, espreeOptions); // Find the default export declaration node var exportNode = ast.body.find(node => node.type === 'ExpressionStatement') if (exportNode) { var property = this.getPropertyModuleExport(exportNode) } else { exportNode = ast.body.find(node => node.type === 'ExportDefaultDeclaration') if (!exportNode) throw "Unable to find default export" var property = this.getPropertyExportDefault(exportNode) } if (property) { switch (this.staticSiteConfig.type) { case "nuxt": this.parseNuxt(property) break case "next": case "gatsby": this.parseNextGatsby(property) break default: throw "Unknown config type" } } core.info(`parsed configuration:\n${this.config}`) fs.writeFileSync(this.staticSiteConfig.filePath, this.config) return this.config } getPropertyModuleExport(exportNode) { var propertyNode = exportNode.expression.right.properties.find( node => node.key.type === 'Identifier' && node.key.name === this.staticSiteConfig.pathName ) if (!propertyNode) { core.info("Unable to find property, insert it : " + this.staticSiteConfig.pathName) if (exportNode.expression.right.properties.length > 0) { this.config = this.config.slice(0, exportNode.expression.right.properties[0].range[0]) + this.generateConfigProperty() + ',\n' + this.config.slice(exportNode.expression.right.properties[0].range[0]) core.info("new config = \n" + this.config) } else { this.config = this.config.slice(0, exportNode.expression.right.range[0] + 1) + '\n ' + this.generateConfigProperty() + '\n' + this.config.slice(exportNode.expression.right.range[1] - 1) core.info("new config = \n" + this.config) } } return propertyNode } getPropertyExportDefault(exportNode) { var propertyNode = exportNode.declaration.properties.find( node => node.key.type === 'Identifier' && node.key.name === this.staticSiteConfig.pathName ) if (!propertyNode) { core.info("Unable to find property, insert it " + this.staticSiteConfig.pathName) if (exportNode.declaration.properties.length > 0) { this.config = this.config.slice(0, exportNode.declaration.properties[0].range[0]) + this.generateConfigProperty() + ',\n' + this.config.slice(exportNode.declaration.properties[0].range[0]) core.info("new config = \n" + this.config) } else { this.config = this.config.slice(0, exportNode.declaration.range[0] + 1) + '\n ' + this.generateConfigProperty() + '\n' + this.config.slice(exportNode.declaration.range[1] - 1) core.info("new config = \n" + this.config) } } return propertyNode } parseNuxt(propertyNode) { // Find the base node if (propertyNode && propertyNode.value.type === 'ObjectExpression') { var baseNode = propertyNode.value.properties.find(node => node.key.type === 'Identifier' && node.key.name === this.staticSiteConfig.subPathName)//'base') if (baseNode) { // Swap the base value by a hardcoded string and print it this.config = this.config.slice(0, baseNode.value.range[0]) + `'${this.staticSiteConfig.newPath}'` + this.config.slice(baseNode.value.range[1]) } } } parseNextGatsby(pathNode) { if (pathNode) { this.config = this.config.slice(0, pathNode.value.range[0]) + `'${this.staticSiteConfig.newPath}'` + this.config.slice(pathNode.value.range[1]) } } } module.exports = {ConfigParser}