|
require("dotenv").config(); |
|
|
|
const fs = require("fs"); |
|
const path = require("path"); |
|
|
|
const { Client } = require("@notionhq/client"); |
|
const { NotionToMarkdown } = require("notion-to-md"); |
|
const slugify = require("slugify").default; |
|
const asyncSerial = require("@barelyhuman/useless/asyncSerial").default; |
|
|
|
const config = { |
|
// Token for a Notion Integration |
|
apiToken: process.env.NOTION_API_TOKEN, |
|
// a database table of the |
|
baseDB: process.env.NOTION_BASE_DB, |
|
}; |
|
|
|
const notion = new Client({ |
|
auth: config.apiToken, |
|
}); |
|
|
|
// passing notion client to the option |
|
const n2m = new NotionToMarkdown({ notionClient: notion }); |
|
|
|
const indexGen = indexContentGenerator(); |
|
|
|
(async function main() { |
|
const { results } = await notion.databases.query({ |
|
database_id: config.baseDB, |
|
}); |
|
|
|
const props = getPropsFromBlocks(results); |
|
|
|
await asyncSerial(props, dirMapper, { limit: 1 }); |
|
|
|
indexGen.commit(); |
|
|
|
fs.writeFileSync(path.join(".", "src", "README.md"), indexGen.value); |
|
|
|
updateConfigWithProps(props); |
|
})(); |
|
|
|
function normalizePropItem(propItem, target, key) { |
|
if (!propItem) return; |
|
|
|
const value = propItem[propItem.type]; |
|
|
|
if (typeof value === "undefined" || value === null) return; |
|
|
|
if ( |
|
typeof value === "string" || |
|
typeof value === "number" || |
|
typeof value === "boolean" |
|
) { |
|
target[key] = value; |
|
} else if (Array.isArray(value)) { |
|
value.map((inner) => normalizePropItem(inner, target, key)); |
|
} else if (typeof value === "object" && value !== null) { |
|
if ("type" in value) { |
|
normalizePropItem(value, target, key); |
|
} else if ("content" in value) { |
|
target[key] = value; |
|
} |
|
} |
|
} |
|
|
|
function updateConfigWithProps(dirs) { |
|
const uniqueArray = []; |
|
dirs.reduce((acc, item) => { |
|
const key = item.type.content; |
|
if (!acc.has(key)) { |
|
uniqueArray.push(item); |
|
acc.add(key); |
|
} |
|
|
|
return acc; |
|
}, new Set()); |
|
|
|
// define path to config |
|
const configPath = "./src/.vuepress/config.js"; |
|
let config = fs.readFileSync(configPath, "utf-8"); |
|
config = normalizeNav(config, uniqueArray); |
|
fs.writeFileSync(configPath, config); |
|
} |
|
|
|
function normalizeNav(config, directories) { |
|
const out = config.replace( |
|
/nav:[ ]*\[[^\]]+\](,)*/, |
|
`nav:[ |
|
${directories.map( |
|
(x) => |
|
`{ |
|
text: "${x.type.content}", |
|
link:"/${slugify(x.type.content.toLowerCase())}/" |
|
}` |
|
)} |
|
],` |
|
); |
|
return out; |
|
} |
|
|
|
function getPropsFromBlocks(blocks) { |
|
const directories = []; |
|
blocks.forEach((item) => { |
|
var props = {}; |
|
props.id = item.id; |
|
Object.keys(item.properties).forEach((prop) => { |
|
normalizePropItem(item.properties[prop], props, prop); |
|
}); |
|
if (props.published) { |
|
directories.push(props); |
|
} |
|
}); |
|
|
|
return directories; |
|
} |
|
|
|
async function dirMapper(propItem) { |
|
const _category = propItem.type.content; |
|
const categorySlug = slugify(propItem.type.content.toLowerCase()); |
|
const _dirPath = path.join(".", "src", categorySlug); |
|
|
|
fs.mkdirSync(_dirPath, { |
|
recursive: true, |
|
}); |
|
|
|
indexGen.add(`- [${_category}](/${categorySlug}/)`); |
|
|
|
const mdblocks = await n2m.pageToMarkdown(propItem.id); |
|
const mdString = n2m.toMarkdownString(mdblocks); |
|
|
|
let fileName = slugify(propItem.title.content.toLowerCase()); |
|
|
|
if (propItem.title.content.toLowerCase() === categorySlug.toLowerCase()) { |
|
fileName = "README"; |
|
} |
|
//writing to file |
|
let _fpath = path.join(".", "src", categorySlug, fileName); |
|
|
|
const finalMDString = "# " + propItem.title.content + "\n\n" + mdString; |
|
fs.writeFileSync(_fpath + ".md", finalMDString); |
|
|
|
const _dirBaseFile = path.join(_dirPath, "README.md"); |
|
const hasBaseFile = fs.existsSync(_dirBaseFile); |
|
|
|
if (!hasBaseFile) { |
|
fs.writeFileSync(_dirBaseFile, `# ${_category}`); |
|
} |
|
} |
|
|
|
function indexContentGenerator() { |
|
let indexContent = ` |
|
# Contents |
|
|
|
{{template}}`; |
|
return { |
|
add(value) { |
|
indexContent = indexContent.replace( |
|
"{{template}}", |
|
`${value} |
|
{{template}}` |
|
); |
|
}, |
|
commit() { |
|
indexContent = indexContent.replace("{{template}}", ""); |
|
}, |
|
value: indexContent, |
|
}; |
|
} |