chore: change eslint & prettier config

This commit is contained in:
Kim, Jimin 2023-06-29 15:53:51 +09:00
parent fc827d74fe
commit b43871c516
103 changed files with 3581 additions and 3543 deletions

View file

@ -1,41 +1,41 @@
{
"name": "@developomp-site/blog-content",
"version": "0.0.0",
"license": "MIT",
"files": [
"dist/**"
],
"scripts": {
"build": "ts-node --experimental-specifier-resolution=node ./src",
"clean": "rm -rf .turbo node_modules dist"
},
"dependencies": {
"@developomp-site/tsconfig": "workspace:*",
"@types/ejs": "^3.1.1",
"@types/katex": "^0.14.0",
"@types/markdown-it": "^12.2.3",
"@types/read-time-estimate": "^0.0.0",
"@types/svgo": "^3.0.0",
"@types/tinycolor2": "^1.4.3",
"canvas": "^2.11.2",
"ejs": "^3.1.8",
"gray-matter": "^4.0.3",
"markdown-it": "^13.0.1",
"markdown-it-anchor": "^8.6.5",
"markdown-it-attrs": "^4.1.4",
"markdown-it-footnote": "^3.0.3",
"markdown-it-highlight-lines": "^1.0.2",
"markdown-it-mark": "^3.0.1",
"markdown-it-sub": "^1.0.0",
"markdown-it-sup": "^1.0.0",
"markdown-it-task-checkbox": "^1.0.6",
"markdown-it-texmath": "^1.0.0",
"markdown-toc": "^1.2.0",
"read-time-estimate": "^0.0.3",
"simple-icons": "^7.21.0",
"slugify": "^1.6.6",
"svgo": "^3.0.2",
"tinycolor2": "^1.4.2",
"typescript": "^4.9.4"
}
"name": "@developomp-site/blog-content",
"version": "0.0.0",
"license": "MIT",
"files": [
"dist/**"
],
"scripts": {
"build": "ts-node --experimental-specifier-resolution=node ./src",
"clean": "rm -rf .turbo node_modules dist"
},
"dependencies": {
"@developomp-site/tsconfig": "workspace:*",
"@types/ejs": "^3.1.1",
"@types/katex": "^0.14.0",
"@types/markdown-it": "^12.2.3",
"@types/read-time-estimate": "^0.0.0",
"@types/svgo": "^3.0.0",
"@types/tinycolor2": "^1.4.3",
"canvas": "^2.11.2",
"ejs": "^3.1.8",
"gray-matter": "^4.0.3",
"markdown-it": "^13.0.1",
"markdown-it-anchor": "^8.6.5",
"markdown-it-attrs": "^4.1.4",
"markdown-it-footnote": "^3.0.3",
"markdown-it-highlight-lines": "^1.0.2",
"markdown-it-mark": "^3.0.1",
"markdown-it-sub": "^1.0.0",
"markdown-it-sup": "^1.0.0",
"markdown-it-task-checkbox": "^1.0.6",
"markdown-it-texmath": "^1.0.0",
"markdown-toc": "^1.2.0",
"read-time-estimate": "^0.0.3",
"simple-icons": "^7.21.0",
"slugify": "^1.6.6",
"svgo": "^3.0.2",
"tinycolor2": "^1.4.2",
"typescript": "^4.9.4"
}
}

View file

@ -16,19 +16,19 @@ import postProcess from "./postProcess"
import { ContentMap, ParseMode, PortfolioData, SeriesMap } from "./types/types"
export const contentMap: ContentMap = {
date: {},
tags: {},
meta: {
tags: [],
},
posts: {},
series: {},
unsearchable: {},
date: {},
tags: {},
meta: {
tags: [],
},
posts: {},
series: {},
unsearchable: {},
}
export const seriesMap: SeriesMap = {}
export const portfolioData: PortfolioData = {
skills: new Set(),
projects: {},
skills: new Set(),
projects: {},
}
/**
@ -36,8 +36,8 @@ export const portfolioData: PortfolioData = {
*/
try {
fs.rmSync("dist", { recursive: true })
// eslint-disable-next-line no-empty
fs.rmSync("dist", { recursive: true })
// eslint-disable-next-line no-empty
} catch (err) {}
/**
@ -45,16 +45,16 @@ try {
*/
if (!fs.lstatSync(markdownPath).isDirectory())
throw Error("Invalid markdown path")
throw Error("Invalid markdown path")
if (!fs.lstatSync(markdownPath + "/posts").isDirectory())
throw Error(`Cannot find directory: ${markdownPath + "/posts"}`)
throw Error(`Cannot find directory: ${markdownPath + "/posts"}`)
if (!fs.lstatSync(markdownPath + "/unsearchable").isDirectory())
throw Error(`Cannot find directory: ${markdownPath + "/posts"}`)
throw Error(`Cannot find directory: ${markdownPath + "/posts"}`)
if (!fs.lstatSync(markdownPath + "/series").isDirectory())
throw Error(`Cannot find directory: ${markdownPath + "/posts"}`)
throw Error(`Cannot find directory: ${markdownPath + "/posts"}`)
/**
* Parse
@ -77,11 +77,11 @@ postProcess()
fs.writeFileSync(mapFilePath, JSON.stringify(contentMap))
fs.writeFileSync(
portfolioFilePath,
JSON.stringify({
...portfolioData,
skills: Array.from(portfolioData.skills),
})
portfolioFilePath,
JSON.stringify({
...portfolioData,
skills: Array.from(portfolioData.skills),
})
)
saveIndex()

View file

@ -24,37 +24,37 @@ import { MarkdownData, ParseMode } from "./types/types"
const slugifyIt = (s: string) => slugify(s, { lower: true, strict: true })
const md = markdownIt({
// https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md
highlight: (str, lang) => {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(str, { language: lang }).value
// eslint-disable-next-line no-empty
} catch (error) {}
}
// https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md
highlight: (str, lang) => {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(str, { language: lang }).value
// eslint-disable-next-line no-empty
} catch (error) {}
}
return "" // use external default escaping
},
html: true,
return "" // use external default escaping
},
html: true,
})
.use(markdownItTexMath, {
engine: katex,
delimiters: "dollars",
})
.use(markdownItAnchor, {
permalink: markdownItAnchor.permalink.ariaHidden({
placement: "before",
symbol: "#",
renderHref: (s) => `#${slugifyIt(s)}`,
}),
slugify: slugifyIt,
})
.use(markdownItTaskCheckbox)
.use(markDownItMark)
.use(markdownItSub)
.use(markdownItSup)
.use(highlightLines)
.use(markdownItFootnote)
.use(markdownItTexMath, {
engine: katex,
delimiters: "dollars",
})
.use(markdownItAnchor, {
permalink: markdownItAnchor.permalink.ariaHidden({
placement: "before",
symbol: "#",
renderHref: (s) => `#${slugifyIt(s)}`,
}),
slugify: slugifyIt,
})
.use(markdownItTaskCheckbox)
.use(markDownItMark)
.use(markdownItSub)
.use(markdownItSup)
.use(highlightLines)
.use(markdownItFootnote)
/**
* parse the front matter if it exists
@ -64,70 +64,70 @@ const md = markdownIt({
* @param {ParseMode} mode
*/
export default function parseMarkdown(
markdownRaw: string,
path: string,
mode: ParseMode
markdownRaw: string,
path: string,
mode: ParseMode
): MarkdownData {
const fileHasFrontMatter = markdownRaw.startsWith("---")
const fileHasFrontMatter = markdownRaw.startsWith("---")
const frontMatter = fileHasFrontMatter
? matter(markdownRaw.slice(0, nthIndex(markdownRaw, "---", 2) + 3)).data
: {}
const frontMatter = fileHasFrontMatter
? matter(markdownRaw.slice(0, nthIndex(markdownRaw, "---", 2) + 3)).data
: {}
if (fileHasFrontMatter) {
if (mode != ParseMode.PORTFOLIO) {
if (!frontMatter.title)
throw Error(`Title is not defined in file: ${path}`)
if (fileHasFrontMatter) {
if (mode != ParseMode.PORTFOLIO) {
if (!frontMatter.title)
throw Error(`Title is not defined in file: ${path}`)
if (mode != ParseMode.UNSEARCHABLE && !frontMatter.date)
throw Error(`Date is not defined in file: ${path}`)
}
if (mode != ParseMode.UNSEARCHABLE && !frontMatter.date)
throw Error(`Date is not defined in file: ${path}`)
}
if (mode === ParseMode.PORTFOLIO) {
if (frontMatter.overview) {
frontMatter.overview = md.render(frontMatter.overview)
}
}
}
if (mode === ParseMode.PORTFOLIO) {
if (frontMatter.overview) {
frontMatter.overview = md.render(frontMatter.overview)
}
}
}
//
// work with rendered DOM
//
//
// work with rendered DOM
//
const dom = new JSDOM(
md.render(
fileHasFrontMatter
? markdownRaw.slice(nthIndex(markdownRaw, "---", 2) + 3)
: markdownRaw
) || ""
)
const dom = new JSDOM(
md.render(
fileHasFrontMatter
? markdownRaw.slice(nthIndex(markdownRaw, "---", 2) + 3)
: markdownRaw
) || ""
)
// add .hljs class to all block codes
// add .hljs class to all block codes
dom.window.document.querySelectorAll("pre > code").forEach((item) => {
item.classList.add("hljs")
})
dom.window.document.querySelectorAll("pre > code").forEach((item) => {
item.classList.add("hljs")
})
// add parent div to tables (horizontally scroll table on small displays)
// add parent div to tables (horizontally scroll table on small displays)
dom.window.document.querySelectorAll("table").forEach((item) => {
// `element` is the element you want to wrap
const parent = item.parentNode
if (!parent) return // stop if table doesn't have a parent node
const wrapper = dom.window.document.createElement("div")
wrapper.style.overflowX = "auto"
dom.window.document.querySelectorAll("table").forEach((item) => {
// `element` is the element you want to wrap
const parent = item.parentNode
if (!parent) return // stop if table doesn't have a parent node
const wrapper = dom.window.document.createElement("div")
wrapper.style.overflowX = "auto"
parent.replaceChild(wrapper, item)
wrapper.appendChild(item)
})
parent.replaceChild(wrapper, item)
wrapper.appendChild(item)
})
frontMatter.content = dom.window.document.documentElement.innerHTML
frontMatter.content = dom.window.document.documentElement.innerHTML
return frontMatter as MarkdownData
return frontMatter as MarkdownData
}
export function generateToc(markdownRaw: string): string {
return md.render(toc(markdownRaw).content, {
slugify: slugifyIt,
})
return md.render(toc(markdownRaw).content, {
slugify: slugifyIt,
})
}

View file

@ -1,21 +1,21 @@
{
"Programming Languages": [
"javascript",
"typescript",
"python",
"rust",
"csharp C#"
],
"Web Front End": ["react", "svelte", "tailwindcss Tailwind"],
"Desktop Front End": ["gtk", "electron", "tauri"],
"Back End": ["firebase"],
"DevOps": ["docker", "githubactions GH Actions"],
"Game Development": ["unity"],
"Etc": [
"figma",
"markdown",
"notion",
"google Google-Fu",
"discord Discord Bot"
]
"Programming Languages": [
"javascript",
"typescript",
"python",
"rust",
"csharp C#"
],
"Web Front End": ["react", "svelte", "tailwindcss Tailwind"],
"Desktop Front End": ["gtk", "electron", "tauri"],
"Back End": ["firebase"],
"DevOps": ["docker", "githubactions GH Actions"],
"Game Development": ["unity"],
"Etc": [
"figma",
"markdown",
"notion",
"google Google-Fu",
"discord Discord Bot"
]
}

View file

@ -1,9 +1,9 @@
svg {
/* from github */
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
sans-serif, Apple Color Emoji, Segoe UI Emoji;
font-size: 14px;
color: #777777;
/* from github */
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
sans-serif, Apple Color Emoji, Segoe UI Emoji;
font-size: 14px;
color: #777777;
}
h1,
@ -12,50 +12,50 @@ h3,
h4,
h5,
h6 {
text-align: center;
text-align: center;
}
.items-wrapper {
display: grid;
grid-template-columns: repeat(5, 1fr);
display: grid;
grid-template-columns: repeat(5, 1fr);
column-gap: 10px;
row-gap: 15px;
column-gap: 10px;
row-gap: 15px;
}
.badge {
display: flex;
flex-direction: column;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
justify-content: center;
align-items: center;
text-align: center;
gap: 5px;
gap: 5px;
}
.badge-box {
display: flex;
display: flex;
justify-content: center;
align-items: center;
justify-content: center;
align-items: center;
border-radius: 7px;
border-radius: 7px;
width: 70px;
height: 70px;
width: 70px;
height: 70px;
}
.icon-container > svg {
height: 40px !important;
height: 40px !important;
}
.white {
color: white;
fill: white;
color: white;
fill: white;
}
.black {
color: black;
fill: black;
color: black;
fill: black;
}

View file

@ -12,127 +12,127 @@ import skills from "./portfolio/skills.json"
import { writeToFile } from "./util"
export default function postProcess() {
sortDates()
fillTags()
parseSeries()
generatePortfolioSVGs()
sortDates()
fillTags()
parseSeries()
generatePortfolioSVGs()
}
function sortDates() {
const TmpDate = contentMap.date
contentMap.date = {}
Object.keys(TmpDate)
.sort()
.forEach((sortedDateKey) => {
contentMap.date[sortedDateKey] = TmpDate[sortedDateKey]
})
const TmpDate = contentMap.date
contentMap.date = {}
Object.keys(TmpDate)
.sort()
.forEach((sortedDateKey) => {
contentMap.date[sortedDateKey] = TmpDate[sortedDateKey]
})
}
function fillTags() {
contentMap.meta.tags = Object.keys(contentMap.tags)
contentMap.meta.tags = Object.keys(contentMap.tags)
}
function parseSeries() {
// sort series map
for (const seriesURL in seriesMap) {
seriesMap[seriesURL].sort((a, b) => {
if (a.index < b.index) return -1
if (a.index > b.index) return 1
// sort series map
for (const seriesURL in seriesMap) {
seriesMap[seriesURL].sort((a, b) => {
if (a.index < b.index) return -1
if (a.index > b.index) return 1
return 0
})
}
return 0
})
}
// series length and order
for (const seriesURL in seriesMap) {
contentMap.series[seriesURL].length = seriesMap[seriesURL].length
contentMap.series[seriesURL].order = seriesMap[seriesURL].map(
(item) => item.url
)
}
// series length and order
for (const seriesURL in seriesMap) {
contentMap.series[seriesURL].length = seriesMap[seriesURL].length
contentMap.series[seriesURL].order = seriesMap[seriesURL].map(
(item) => item.url
)
}
}
function generatePortfolioSVGs() {
/**
* render skills.svg
*/
/**
* render skills.svg
*/
// todo: wait add ejs once it's available
// todo: wait add ejs once it's available
const style = readFileSync("./src/portfolio/style.css", "utf-8")
const style = readFileSync("./src/portfolio/style.css", "utf-8")
const data: {
[key: string]: Badge[] | { [key: string]: Badge[] }
} = {}
const data: {
[key: string]: Badge[] | { [key: string]: Badge[] }
} = {}
// C O G N I T O - H A Z A R D
// THIS PART OF THE CODE WAS WRITTEN IN 3 AM
// C O G N I T O - H A Z A R D
// C O G N I T O - H A Z A R D
// THIS PART OF THE CODE WAS WRITTEN IN 3 AM
// C O G N I T O - H A Z A R D
for (const key in skills) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (skills[key] instanceof Array) {
if (!data[key]) {
data[key] = []
}
for (const key in skills) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (skills[key] instanceof Array) {
if (!data[key]) {
data[key] = []
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
;(skills[key] as string[]).forEach((badge) =>
(data[key] as Badge[]).push(parseBadge(badge))
)
} else {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
for (const subKey in skills[key]) {
if (!data[key]) data[key] = {}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
;(skills[key] as string[]).forEach((badge) =>
(data[key] as Badge[]).push(parseBadge(badge))
)
} else {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
for (const subKey in skills[key]) {
if (!data[key]) data[key] = {}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (!data[key][subKey]) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
data[key][subKey] = []
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (!data[key][subKey]) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
data[key][subKey] = []
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
skills[key][subKey].forEach((badge: string) =>
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
(data[key][subKey] as Badge[]).push(parseBadge(badge))
)
}
}
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
skills[key][subKey].forEach((badge: string) =>
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
(data[key][subKey] as Badge[]).push(parseBadge(badge))
)
}
}
}
const renderedSVG = ejs.render(
readFileSync("./src/portfolio/skills.ejs", "utf-8"),
{ style, data },
{ views: ["./src/portfolio"] }
)
const renderedSVG = ejs.render(
readFileSync("./src/portfolio/skills.ejs", "utf-8"),
{ style, data },
{ views: ["./src/portfolio"] }
)
writeToFile(
"./dist/public/img/skills.svg",
optimize(renderedSVG, { multipass: true }).data
)
writeToFile(
"./dist/public/img/skills.svg",
optimize(renderedSVG, { multipass: true }).data
)
}
function parseBadge(badgeRaw: string): Badge {
const isMultiWord = badgeRaw.includes(" ")
const words = badgeRaw.split(" ")
const slug = words[0]
const isMultiWord = badgeRaw.includes(" ")
const words = badgeRaw.split(" ")
const slug = words[0]
// @ts-ignore
const icon = icons["si" + slug[0].toUpperCase() + slug.slice(1)]
// @ts-ignore
const icon = icons["si" + slug[0].toUpperCase() + slug.slice(1)]
const color = tinycolor(icon.hex).lighten(5).desaturate(5)
const color = tinycolor(icon.hex).lighten(5).desaturate(5)
return {
svg: icon.svg,
hex: color.toHexString(),
isDark: color.isDark(),
title: isMultiWord ? words.slice(1).join(" ") : icon.title,
}
return {
svg: icon.svg,
hex: color.toHexString(),
isDark: color.isDark(),
title: isMultiWord ? words.slice(1).join(" ") : icon.title,
}
}

View file

@ -15,15 +15,15 @@ import { ParseMode } from "../types/types"
* Data that's passed from {@link parseFile} to other function
*/
export interface DataToPass {
path: string
urlPath: string
markdownRaw: string
markdownData: {
content: string
[key: string]: unknown
}
humanizedDuration: string
totalWords: number
path: string
urlPath: string
markdownRaw: string
markdownData: {
content: string
[key: string]: unknown
}
humanizedDuration: string
totalWords: number
}
/**
@ -33,23 +33,23 @@ export interface DataToPass {
* @param {string} path - path of file or folder
*/
export function recursiveParse(mode: ParseMode, path: string): void {
// get name of the file or folder that's currently being parsed
const fileOrFolderName = path2FileOrFolderName(path)
// get name of the file or folder that's currently being parsed
const fileOrFolderName = path2FileOrFolderName(path)
// stop if the file or folder starts with a underscore
if (fileOrFolderName.startsWith("_")) return
// stop if the file or folder starts with a underscore
if (fileOrFolderName.startsWith("_")) return
const stats = fs.lstatSync(path)
const stats = fs.lstatSync(path)
// if it's a directory, call this function to every files/directories in it
// if it's a file, parse it and then save it to file
if (stats.isDirectory()) {
fs.readdirSync(path).map((childPath) => {
recursiveParse(mode, `${path}/${childPath}`)
})
} else if (stats.isFile()) {
parseFile(mode, path)
}
// if it's a directory, call this function to every files/directories in it
// if it's a file, parse it and then save it to file
if (stats.isDirectory()) {
fs.readdirSync(path).map((childPath) => {
recursiveParse(mode, `${path}/${childPath}`)
})
} else if (stats.isFile()) {
parseFile(mode, path)
}
}
/**
@ -59,50 +59,50 @@ export function recursiveParse(mode: ParseMode, path: string): void {
* @param {string} path - path of the markdown file
*/
function parseFile(mode: ParseMode, path: string): void {
// stop if it is not a markdown file
if (!path.endsWith(".md")) {
console.log(`Ignoring non markdown file at: ${path}`)
return
}
// stop if it is not a markdown file
if (!path.endsWith(".md")) {
console.log(`Ignoring non markdown file at: ${path}`)
return
}
/**
* Parse markdown
*/
/**
* Parse markdown
*/
const markdownRaw = fs.readFileSync(path, "utf8")
const markdownData = parseMarkdown(markdownRaw, path, mode)
const { humanizedDuration, totalWords } = readTimeEstimate(
markdownData.content,
275,
12,
500,
["img", "Image"]
)
const markdownRaw = fs.readFileSync(path, "utf8")
const markdownData = parseMarkdown(markdownRaw, path, mode)
const { humanizedDuration, totalWords } = readTimeEstimate(
markdownData.content,
275,
12,
500,
["img", "Image"]
)
const dataToPass: DataToPass = {
path,
urlPath: path2URL(path),
markdownRaw,
markdownData,
humanizedDuration,
totalWords,
}
const dataToPass: DataToPass = {
path,
urlPath: path2URL(path),
markdownRaw,
markdownData,
humanizedDuration,
totalWords,
}
switch (mode) {
case ParseMode.POSTS:
parsePost(dataToPass)
break
switch (mode) {
case ParseMode.POSTS:
parsePost(dataToPass)
break
case ParseMode.SERIES:
parseSeries(dataToPass)
break
case ParseMode.SERIES:
parseSeries(dataToPass)
break
case ParseMode.UNSEARCHABLE:
parseUnsearchable(dataToPass)
break
case ParseMode.UNSEARCHABLE:
parseUnsearchable(dataToPass)
break
case ParseMode.PORTFOLIO:
parseProjects(dataToPass)
break
}
case ParseMode.PORTFOLIO:
parseProjects(dataToPass)
break
}
}

View file

@ -8,65 +8,70 @@ import { DataToPass } from "."
import { PostData } from "../types/types"
export default function parsePost(data: DataToPass): void {
const { urlPath, markdownRaw, markdownData, humanizedDuration, totalWords } =
data
const {
urlPath,
markdownRaw,
markdownData,
humanizedDuration,
totalWords,
} = data
const postData: PostData = {
title: markdownData.title as string,
date: "",
readTime: humanizedDuration,
wordCount: totalWords,
tags: [],
}
const postData: PostData = {
title: markdownData.title as string,
date: "",
readTime: humanizedDuration,
wordCount: totalWords,
tags: [],
}
/**
* Dates
*/
/**
* Dates
*/
const postDate = new Date(markdownData.date as string)
postData.date = postDate.toLocaleString("default", {
month: "short",
day: "numeric",
year: "numeric",
})
const postDate = new Date(markdownData.date as string)
postData.date = postDate.toLocaleString("default", {
month: "short",
day: "numeric",
year: "numeric",
})
const YYYY_MM_DD = postDate.toISOString().split("T")[0]
if (contentMap.date[YYYY_MM_DD]) {
contentMap.date[YYYY_MM_DD].push(urlPath)
} else {
contentMap.date[YYYY_MM_DD] = [urlPath]
}
const YYYY_MM_DD = postDate.toISOString().split("T")[0]
if (contentMap.date[YYYY_MM_DD]) {
contentMap.date[YYYY_MM_DD].push(urlPath)
} else {
contentMap.date[YYYY_MM_DD] = [urlPath]
}
/**
* Tags
*/
/**
* Tags
*/
postData.tags = markdownData.tags as string[]
if (postData.tags) {
postData.tags.forEach((tag) => {
if (contentMap.tags[tag]) {
contentMap.tags[tag].push(urlPath)
} else {
contentMap.tags[tag] = [urlPath]
}
})
}
postData.tags = markdownData.tags as string[]
if (postData.tags) {
postData.tags.forEach((tag) => {
if (contentMap.tags[tag]) {
contentMap.tags[tag].push(urlPath)
} else {
contentMap.tags[tag] = [urlPath]
}
})
}
/**
*
*/
/**
*
*/
contentMap.posts[urlPath] = postData
addDocument({
title: markdownData.title,
body: markdownData.content,
url: urlPath,
})
writeToFile(
`${contentDirectoryPath}${urlPath}.json`,
JSON.stringify({
content: markdownData.content,
toc: generateToc(markdownRaw),
})
)
contentMap.posts[urlPath] = postData
addDocument({
title: markdownData.title,
body: markdownData.content,
url: urlPath,
})
writeToFile(
`${contentDirectoryPath}${urlPath}.json`,
JSON.stringify({
content: markdownData.content,
toc: generateToc(markdownRaw),
})
)
}

View file

@ -9,46 +9,46 @@ import { portfolioData } from ".."
import { DataToPass } from "."
export default function parseProjects(data: DataToPass): void {
const { urlPath, markdownRaw, markdownData } = data
const { urlPath, markdownRaw, markdownData } = data
if (markdownData.badges) {
;(markdownData.badges as string[]).forEach((slug) => {
// todo: handle cases when icon is not on simple-icons
const icon: SimpleIcon =
// @ts-ignore
icons["si" + slug[0].toUpperCase() + slug.slice(1)]
if (markdownData.badges) {
;(markdownData.badges as string[]).forEach((slug) => {
// todo: handle cases when icon is not on simple-icons
const icon: SimpleIcon =
// @ts-ignore
icons["si" + slug[0].toUpperCase() + slug.slice(1)]
portfolioData.skills.add(slug)
portfolioData.skills.add(slug)
const color = tinycolor(icon.hex).lighten(5).desaturate(5)
const color = tinycolor(icon.hex).lighten(5).desaturate(5)
// save svg icon
writeToFile(
`${iconsDirectoryPath}/${icon.slug}.json`,
JSON.stringify({
svg: icon.svg,
hex: color.toHexString(),
isDark: color.isDark(),
title: icon.title,
})
)
})
}
// save svg icon
writeToFile(
`${iconsDirectoryPath}/${icon.slug}.json`,
JSON.stringify({
svg: icon.svg,
hex: color.toHexString(),
isDark: color.isDark(),
title: icon.title,
})
)
})
}
// remove /projects/ prefix
portfolioData.projects[urlPath.replace("/projects/", "")] = {
name: markdownData.name as string,
image: markdownData.image as string,
overview: markdownData.overview as string,
badges: (markdownData.badges as string[]) || [],
repo: (markdownData.repo as string) || "",
}
// remove /projects/ prefix
portfolioData.projects[urlPath.replace("/projects/", "")] = {
name: markdownData.name as string,
image: markdownData.image as string,
overview: markdownData.overview as string,
badges: (markdownData.badges as string[]) || [],
repo: (markdownData.repo as string) || "",
}
writeToFile(
`${contentDirectoryPath}${urlPath}.json`,
JSON.stringify({
content: markdownData.content,
toc: generateToc(markdownRaw),
})
)
writeToFile(
`${contentDirectoryPath}${urlPath}.json`,
JSON.stringify({
content: markdownData.content,
toc: generateToc(markdownRaw),
})
)
}

View file

@ -8,140 +8,141 @@ import { DataToPass } from "."
import { PostData } from "../types/types"
export default function parseSeries(data: DataToPass): void {
const {
path,
urlPath: _urlPath,
markdownRaw,
markdownData,
humanizedDuration,
totalWords,
} = data
const {
path,
urlPath: _urlPath,
markdownRaw,
markdownData,
humanizedDuration,
totalWords,
} = data
// last part of the url without the slash
let lastPath = _urlPath.slice(_urlPath.lastIndexOf("/") + 1)
if (!lastPath.includes("_") && !lastPath.startsWith("0"))
throw Error(`Invalid series file name at: "${path}"`)
// last part of the url without the slash
let lastPath = _urlPath.slice(_urlPath.lastIndexOf("/") + 1)
if (!lastPath.includes("_") && !lastPath.startsWith("0"))
throw Error(`Invalid series file name at: "${path}"`)
// if file is a series descriptor or not (not = regular series post)
const isFileDescriptor = lastPath.startsWith("0") && !lastPath.includes("_")
// if file is a series descriptor or not (not = regular series post)
const isFileDescriptor = lastPath.startsWith("0") && !lastPath.includes("_")
// series post url
if (isFileDescriptor) {
lastPath = ""
} else {
lastPath = lastPath
.slice(lastPath.indexOf("_") + 1) // get string after the series index
.replace(/\/$/, "") // remove trailing slash
}
// series post url
if (isFileDescriptor) {
lastPath = ""
} else {
lastPath = lastPath
.slice(lastPath.indexOf("_") + 1) // get string after the series index
.replace(/\/$/, "") // remove trailing slash
}
// get url until right before the lastPath
const urlUntilLastPath = _urlPath.slice(0, _urlPath.lastIndexOf("/") + 1)
// get url until right before the lastPath
const urlUntilLastPath = _urlPath.slice(0, _urlPath.lastIndexOf("/") + 1)
// remove trailing slash if it's a regular series post
const urlPath =
(isFileDescriptor
? urlUntilLastPath.replace(/\/$/, "")
: urlUntilLastPath) + lastPath
// remove trailing slash if it's a regular series post
const urlPath =
(isFileDescriptor
? urlUntilLastPath.replace(/\/$/, "")
: urlUntilLastPath) + lastPath
// todo: separate interface for series descriptor (no word count and read time)
const postData: PostData = {
title: markdownData.title as string,
date: "",
readTime: humanizedDuration,
wordCount: totalWords,
tags: [],
}
// todo: separate interface for series descriptor (no word count and read time)
const postData: PostData = {
title: markdownData.title as string,
date: "",
readTime: humanizedDuration,
wordCount: totalWords,
tags: [],
}
/**
* Date
*/
/**
* Date
*/
const postDate = new Date(markdownData.date as string)
postData.date = postDate.toLocaleString("default", {
month: "short",
day: "numeric",
year: "numeric",
})
const postDate = new Date(markdownData.date as string)
postData.date = postDate.toLocaleString("default", {
month: "short",
day: "numeric",
year: "numeric",
})
const YYYY_MM_DD = postDate.toISOString().split("T")[0]
if (contentMap.date[YYYY_MM_DD]) {
contentMap.date[YYYY_MM_DD].push(urlPath)
} else {
contentMap.date[YYYY_MM_DD] = [urlPath]
}
const YYYY_MM_DD = postDate.toISOString().split("T")[0]
if (contentMap.date[YYYY_MM_DD]) {
contentMap.date[YYYY_MM_DD].push(urlPath)
} else {
contentMap.date[YYYY_MM_DD] = [urlPath]
}
/**
* Tags
*/
/**
* Tags
*/
postData.tags = markdownData.tags as string[]
if (postData.tags) {
postData.tags.forEach((tag) => {
if (contentMap.tags[tag]) {
contentMap.tags[tag].push(urlPath)
} else {
contentMap.tags[tag] = [urlPath]
}
})
}
postData.tags = markdownData.tags as string[]
if (postData.tags) {
postData.tags.forEach((tag) => {
if (contentMap.tags[tag]) {
contentMap.tags[tag].push(urlPath)
} else {
contentMap.tags[tag] = [urlPath]
}
})
}
/**
*
*/
/**
*
*/
addDocument({
title: markdownData.title,
body: markdownData.content,
url: urlPath,
})
addDocument({
title: markdownData.title,
body: markdownData.content,
url: urlPath,
})
contentMap.posts[urlPath] = postData
contentMap.posts[urlPath] = postData
// series markdown starting with 0 is a series descriptor
if (isFileDescriptor) {
contentMap.series[urlPath] = {
...postData,
order: [],
length: 0,
}
} else {
// put series post in appropriate series
for (const key of Object.keys(contentMap.series)) {
if (urlPath.includes(key)) {
const index = parseInt(
_urlPath.slice(
_urlPath.lastIndexOf("/") + 1,
_urlPath.lastIndexOf("_")
)
)
// series markdown starting with 0 is a series descriptor
if (isFileDescriptor) {
contentMap.series[urlPath] = {
...postData,
order: [],
length: 0,
}
} else {
// put series post in appropriate series
for (const key of Object.keys(contentMap.series)) {
if (urlPath.includes(key)) {
const index = parseInt(
_urlPath.slice(
_urlPath.lastIndexOf("/") + 1,
_urlPath.lastIndexOf("_")
)
)
if (isNaN(index)) throw Error(`Invalid series index at: ${path}`)
if (isNaN(index))
throw Error(`Invalid series index at: ${path}`)
const itemToPush = {
index: index,
url: urlPath,
}
const itemToPush = {
index: index,
url: urlPath,
}
if (seriesMap[key]) {
seriesMap[key].push(itemToPush)
} else {
seriesMap[key] = [itemToPush]
}
if (seriesMap[key]) {
seriesMap[key].push(itemToPush)
} else {
seriesMap[key] = [itemToPush]
}
break
}
}
}
break
}
}
}
/**
* Save content
*/
/**
* Save content
*/
writeToFile(
`${contentDirectoryPath}${urlPath}.json`,
JSON.stringify({
content: markdownData.content,
toc: generateToc(markdownRaw),
})
)
writeToFile(
`${contentDirectoryPath}${urlPath}.json`,
JSON.stringify({
content: markdownData.content,
toc: generateToc(markdownRaw),
})
)
}

View file

@ -5,30 +5,30 @@ import { contentMap } from ".."
import { DataToPass } from "."
export default function parseUnsearchable(data: DataToPass): void {
const { urlPath: _urlPath, markdownData } = data
const { urlPath: _urlPath, markdownData } = data
// convert path like /XXX/YYY/ZZZ to /YYY/ZZZ
const urlPath = _urlPath.slice(_urlPath.slice(1).indexOf("/") + 1)
// convert path like /XXX/YYY/ZZZ to /YYY/ZZZ
const urlPath = _urlPath.slice(_urlPath.slice(1).indexOf("/") + 1)
addDocument({
title: markdownData.title,
body: markdownData.content,
url: urlPath,
})
addDocument({
title: markdownData.title,
body: markdownData.content,
url: urlPath,
})
// Parse data that will be written to map.js
contentMap.unsearchable[urlPath] = {
title: markdownData.title as string,
}
// Parse data that will be written to map.js
contentMap.unsearchable[urlPath] = {
title: markdownData.title as string,
}
/**
* Save content
*/
/**
* Save content
*/
writeToFile(
`${contentDirectoryPath}/unsearchable${urlPath}.json`,
JSON.stringify({
content: markdownData.content,
})
)
writeToFile(
`${contentDirectoryPath}/unsearchable${urlPath}.json`,
JSON.stringify({
content: markdownData.content,
})
)
}

View file

@ -8,19 +8,19 @@ import elasticlunr from "elasticlunr"
import { searchIndexFilePath } from "./config"
const elasticlunrIndex = elasticlunr(function () {
this.addField("title" as never)
this.addField("body" as never)
this.setRef("url" as never)
this.addField("title" as never)
this.addField("body" as never)
this.setRef("url" as never)
})
export function addDocument(doc: {
title?: unknown
body?: string
url?: string
title?: unknown
body?: string
url?: string
}) {
elasticlunrIndex.addDoc(doc)
elasticlunrIndex.addDoc(doc)
}
export function saveIndex() {
fs.writeFileSync(searchIndexFilePath, JSON.stringify(elasticlunrIndex))
fs.writeFileSync(searchIndexFilePath, JSON.stringify(elasticlunrIndex))
}

View file

@ -1,4 +1,4 @@
declare module "markdown-it-texmath" {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default function texmath(md: MarkdownIt, ...params: any[]): void
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default function texmath(md: MarkdownIt, ...params: any[]): void
}

View file

@ -1,6 +1,6 @@
declare module "markdown-toc" {
export default function toc(str: string): {
json: JSON
content: string
}
export default function toc(str: string): {
json: JSON
content: string
}
}

View file

@ -1,32 +1,32 @@
export interface ContentMap {
// key: YYYY-MM-DD
// value: url
date: { [key: string]: string[] }
// key: YYYY-MM-DD
// value: url
date: { [key: string]: string[] }
// key: tag name
// value: url
tags: {
[key: string]: string[]
}
// key: tag name
// value: url
tags: {
[key: string]: string[]
}
// list of all meta data
meta: {
tags: string[]
}
// list of all meta data
meta: {
tags: string[]
}
// searchable, non-series posts
// must have a post date
// tag is not required
posts: {
[key: string]: PostData
}
// searchable, non-series posts
// must have a post date
// tag is not required
posts: {
[key: string]: PostData
}
// series posts have "previous post" and "next post" button so they need to be ordered
series: { [key: string]: Series }
// series posts have "previous post" and "next post" button so they need to be ordered
series: { [key: string]: Series }
// urls of unsearchable posts
// it is here to quickly check if a post exists or not
unsearchable: { [key: string]: { title: string } }
// urls of unsearchable posts
// it is here to quickly check if a post exists or not
unsearchable: { [key: string]: { title: string } }
}
/**
@ -34,58 +34,58 @@ export interface ContentMap {
*/
export enum ParseMode {
POSTS,
SERIES,
UNSEARCHABLE,
PORTFOLIO,
POSTS,
SERIES,
UNSEARCHABLE,
PORTFOLIO,
}
export interface MarkdownData {
content: string
[key: string]: unknown
content: string
[key: string]: unknown
}
export interface PostData {
title: string
date: string
readTime: string
wordCount: number
tags?: string[]
title: string
date: string
readTime: string
wordCount: number
tags?: string[]
}
export interface PageData {
title: string
date: string
readTime: string
wordCount: number
tags: string[]
toc?: string
content: string
title: string
date: string
readTime: string
wordCount: number
tags: string[]
toc?: string
content: string
// series
// series
seriesHome: string
prev?: string
next?: string
seriesHome: string
prev?: string
next?: string
// series home
// series home
order: string[]
length: number
order: string[]
length: number
// portfolio
// portfolio
image: string // image url
overview: string
badges: string[]
repo: string
image: string // image url
overview: string
badges: string[]
repo: string
}
export interface Badge {
svg: string
hex: string
isDark: boolean
title: string
svg: string
hex: string
isDark: boolean
title: string
}
/**
@ -93,23 +93,23 @@ export interface Badge {
*/
export interface Series {
title: string
date: string
readTime: string
wordCount: number
order: string[]
length: number
tags?: string[]
title: string
date: string
readTime: string
wordCount: number
order: string[]
length: number
tags?: string[]
}
export interface SeriesMap {
// key: url
[key: string]: SeriesEntry[]
// key: url
[key: string]: SeriesEntry[]
}
export interface SeriesEntry {
index: number
url: string
index: number
url: string
}
/**
@ -117,25 +117,25 @@ export interface SeriesEntry {
*/
export interface PortfolioData {
// a set of valid simple icons slug
skills: Set<string>
// a set of valid simple icons slug
skills: Set<string>
// key: url
projects: {
[key: string]: PortfolioProject
}
// key: url
projects: {
[key: string]: PortfolioProject
}
}
export interface PortfolioOverview {
// link to my github
github: string
description: string
// link to my github
github: string
description: string
}
export interface PortfolioProject {
name: string
image: string // url to the image
overview: string
badges: string[] // array of valid simpleIcons slug
repo: string // url of the git repository
name: string
image: string // url to the image
overview: string
badges: string[] // array of valid simpleIcons slug
repo: string // url of the git repository
}

View file

@ -9,9 +9,9 @@ import { markdownPath } from "./config"
* @param {string} pathToConvert
*/
export function path2URL(pathToConvert: string): string {
return `/${relative(markdownPath, pathToConvert)}`
.replace(/\.[^/.]+$/, "") // remove the file extension
.replace(/ /g, "-") // replace all space with a dash
return `/${relative(markdownPath, pathToConvert)}`
.replace(/\.[^/.]+$/, "") // remove the file extension
.replace(/ /g, "-") // replace all space with a dash
}
/**
@ -20,33 +20,34 @@ export function path2URL(pathToConvert: string): string {
* @param {string} inputPath - path to parse
*/
export function path2FileOrFolderName(inputPath: string): string {
// remove trailing slash
if (inputPath[-1] == "/") inputPath = inputPath.slice(0, inputPath.length - 1)
// remove trailing slash
if (inputPath[-1] == "/")
inputPath = inputPath.slice(0, inputPath.length - 1)
// get the last section
return inputPath.slice(inputPath.lastIndexOf("/") + 1)
// get the last section
return inputPath.slice(inputPath.lastIndexOf("/") + 1)
}
// gets the nth occurance of a pattern in string
// returns -1 if nothing is found
// https://stackoverflow.com/a/14482123/12979111
export function nthIndex(str: string, pat: string, n: number) {
let i = -1
let i = -1
while (n-- && i++ < str.length) {
i = str.indexOf(pat, i)
if (i < 0) break
}
while (n-- && i++ < str.length) {
i = str.indexOf(pat, i)
if (i < 0) break
}
return i
return i
}
export function writeToFile(filePath: string, dataToWrite: string) {
// create directory to put the files
fs.mkdirSync(filePath.slice(0, filePath.lastIndexOf("/")), {
recursive: true,
})
// create directory to put the files
fs.mkdirSync(filePath.slice(0, filePath.lastIndexOf("/")), {
recursive: true,
})
// write content to the file
fs.writeFileSync(filePath, dataToWrite)
// write content to the file
fs.writeFileSync(filePath, dataToWrite)
}

View file

@ -1,16 +1,16 @@
{
"extends": "@developomp-site/tsconfig/node16.json",
"include": ["src"],
"ts-node": {
"esm": true
},
"compilerOptions": {
"moduleResolution": "Node",
"isolatedModules": false,
"noImplicitAny": false,
"esModuleInterop": true,
"allowJs": true,
"resolveJsonModule": true
},
"exclude": ["dist", "node_modules"]
"extends": "@developomp-site/tsconfig/node16.json",
"include": ["src"],
"ts-node": {
"esm": true
},
"compilerOptions": {
"moduleResolution": "Node",
"isolatedModules": false,
"noImplicitAny": false,
"esModuleInterop": true,
"allowJs": true,
"resolveJsonModule": true
},
"exclude": ["dist", "node_modules"]
}

View file

@ -1,17 +1,20 @@
/** @type {import("eslint").Linter.Config} */
module.exports = {
extends: [
"plugin:@typescript-eslint/recommended",
"plugin:json/recommended",
"eslint:recommended",
"prettier",
"turbo",
],
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
rules: {
"@next/next/no-html-link-for-pages": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-empty-interface": "off",
},
root: true,
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"turbo",
],
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint", "simple-import-sort"],
rules: {
// import related
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"import/first": "error",
"import/newline-after-import": "error",
"import/no-duplicates": "error",
},
}

View file

@ -1,16 +1,18 @@
{
"name": "@developomp-site/eslint-config",
"version": "0.0.0",
"main": "index.js",
"scripts": {
"clean": "rm -rf node_modules"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.46.0",
"@typescript-eslint/parser": "^5.46.0",
"eslint-config-next": "^12.3.4",
"eslint-config-prettier": "^8.5.0",
"eslint-config-turbo": "latest",
"eslint-plugin-json": "^3.1.0"
}
"name": "@developomp-site/eslint-config",
"version": "0.0.0",
"main": "index.js",
"scripts": {
"clean": "rm -rf node_modules"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.60.1",
"@typescript-eslint/parser": "^5.60.1",
"eslint": "^8.43.0",
"eslint-config-prettier": "^8.8.0",
"eslint-config-turbo": "latest",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-simple-import-sort": "^10.0.0",
"typescript": "^5.1.6"
}
}

View file

@ -1,12 +1,12 @@
{
"name": "@developomp-site/tailwind-config",
"version": "0.0.0",
"private": true,
"main": "index.js",
"scripts": {
"clean": "rm -rf node_modules"
},
"devDependencies": {
"tailwindcss": "^3.2.4"
}
"name": "@developomp-site/tailwind-config",
"version": "0.0.0",
"private": true,
"main": "index.js",
"scripts": {
"clean": "rm -rf node_modules"
},
"devDependencies": {
"tailwindcss": "^3.2.4"
}
}

View file

@ -1,8 +1,8 @@
module.exports = {
content: [
// app content
`src/**/*.{js,ts,jsx,tsx}`,
// include packages if not transpiling
// "../../packages/**/*.{js,ts,jsx,tsx}",
],
content: [
// app content
`src/**/*.{js,ts,jsx,tsx}`,
// include packages if not transpiling
// "../../packages/**/*.{js,ts,jsx,tsx}",
],
}

View file

@ -1,5 +1,5 @@
{
"env": {
"node": true
}
"env": {
"node": true
}
}

View file

@ -1,143 +1,143 @@
export interface Theme {
font: {
sansSerif: string
monospace: string
}
font: {
sansSerif: string
monospace: string
}
color: {
text: {
highContrast: string
default: string
gray: string
}
background: string
}
color: {
text: {
highContrast: string
default: string
gray: string
}
background: string
}
maxDisplayWidth: {
mobile: string
desktop: string
}
maxDisplayWidth: {
mobile: string
desktop: string
}
component: {
anchor: {
color: {
default: string
hover: string
active: string
header: string
}
}
component: {
anchor: {
color: {
default: string
hover: string
active: string
header: string
}
}
blockQuote: {
color: {
background: string
borderLeft: string
}
}
blockQuote: {
color: {
background: string
borderLeft: string
}
}
card: {
color: {
background: string
hoverGlow: string
}
}
card: {
color: {
background: string
hoverGlow: string
}
}
code: {
inline: {
color: {
text: string
background: string
border: string
}
}
block: {
color: {
border: string
highlight: string
}
style: string
}
}
code: {
inline: {
color: {
text: string
background: string
border: string
}
}
block: {
color: {
border: string
highlight: string
}
style: string
}
}
footer: {
color: {
background: string
text: string
}
}
footer: {
color: {
background: string
text: string
}
}
header: {
color: {
background: string
hover: string
text: string
}
height: string
}
header: {
color: {
background: string
hover: string
text: string
}
height: string
}
input: {
color: {
background: {
default: string
itemHover: string
}
border: {
default: string
hover: string
focus: string
}
placeHolder: string
}
}
input: {
color: {
background: {
default: string
itemHover: string
}
border: {
default: string
hover: string
focus: string
}
placeHolder: string
}
}
kbd: {
color: {
text: string
border: string
outerShadow: string
innerShadow: string
background: string
}
}
kbd: {
color: {
text: string
border: string
outerShadow: string
innerShadow: string
background: string
}
}
mark: {
color: {
text: string
background: string
}
}
mark: {
color: {
text: string
background: string
}
}
scrollbar: {
color: {
track: string
thumb: string
}
width: string
borderRadius: string
}
scrollbar: {
color: {
track: string
thumb: string
}
width: string
borderRadius: string
}
scrollProgressBar: {
color: {
background: string
foreground: string
}
}
scrollProgressBar: {
color: {
background: string
foreground: string
}
}
table: {
color: {
border: string
even: string
}
}
table: {
color: {
border: string
even: string
}
}
ui: {
color: {
background: {
default: string
hover: string
}
border: string
}
}
}
ui: {
color: {
background: {
default: string
hover: string
}
border: string
}
}
}
}

View file

@ -1,22 +1,22 @@
{
"name": "@developomp-site/theme",
"version": "0.0.0",
"types": "./index.d.ts",
"private": true,
"license": "MIT",
"scripts": {
"dev": "nodemon --ignore dist/ --exec pnpm build",
"build": "npx ts-node ./build.ts",
"clean": "rm -rf .turbo node_modules dist"
},
"devDependencies": {
"@types/merge-deep": "^3.0.0",
"@types/node": "^18.11.11",
"merge-deep": "^3.0.3",
"nodemon": "^2.0.20",
"tailwindcss": "^3.2.4",
"ts-node": "^10.9.1",
"tsup": "^5.12.9",
"utility-types": "^3.10.0"
}
"name": "@developomp-site/theme",
"version": "0.0.0",
"types": "./index.d.ts",
"private": true,
"license": "MIT",
"scripts": {
"dev": "nodemon --ignore dist/ --exec pnpm build",
"build": "npx ts-node ./build.ts",
"clean": "rm -rf .turbo node_modules dist"
},
"devDependencies": {
"@types/merge-deep": "^3.0.0",
"@types/node": "^18.11.11",
"merge-deep": "^3.0.3",
"nodemon": "^2.0.20",
"tailwindcss": "^3.2.4",
"ts-node": "^10.9.1",
"tsup": "^5.12.9",
"utility-types": "^3.10.0"
}
}

View file

@ -1,71 +1,71 @@
/* from highlight.js/styles/atom-one-dark-reasonable.css */
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em;
display: block;
overflow-x: auto;
padding: 1em;
}
code.hljs {
padding: 3px 5px;
padding: 3px 5px;
}
.hljs {
color: #abb2bf;
background: #282c34;
color: #abb2bf;
background: #282c34;
}
.hljs-keyword,
.hljs-operator,
.hljs-pattern-match {
color: #f92672;
color: #f92672;
}
.hljs-function,
.hljs-pattern-match .hljs-constructor {
color: #61aeee;
color: #61aeee;
}
.hljs-function .hljs-params {
color: #a6e22e;
color: #a6e22e;
}
.hljs-function .hljs-params .hljs-typing {
color: #fd971f;
color: #fd971f;
}
.hljs-module-access .hljs-module {
color: #7e57c2;
color: #7e57c2;
}
.hljs-constructor {
color: #e2b93d;
color: #e2b93d;
}
.hljs-constructor .hljs-string {
color: #9ccc65;
color: #9ccc65;
}
.hljs-comment,
.hljs-quote {
color: #b18eb1;
font-style: italic;
color: #b18eb1;
font-style: italic;
}
.hljs-doctag,
.hljs-formula {
color: #c678dd;
color: #c678dd;
}
.hljs-deletion,
.hljs-name,
.hljs-section,
.hljs-selector-tag,
.hljs-subst {
color: #e06c75;
color: #e06c75;
}
.hljs-literal {
color: #56b6c2;
color: #56b6c2;
}
.hljs-addition,
.hljs-attribute,
.hljs-meta .hljs-string,
.hljs-regexp,
.hljs-string {
color: #98c379;
color: #98c379;
}
.hljs-built_in,
.hljs-class .hljs-title,
.hljs-title.class_ {
color: #e6c07b;
color: #e6c07b;
}
.hljs-attr,
.hljs-number,
@ -75,7 +75,7 @@ code.hljs {
.hljs-template-variable,
.hljs-type,
.hljs-variable {
color: #d19a66;
color: #d19a66;
}
.hljs-bullet,
.hljs-link,
@ -83,14 +83,14 @@ code.hljs {
.hljs-selector-id,
.hljs-symbol,
.hljs-title {
color: #61aeee;
color: #61aeee;
}
.hljs-emphasis {
font-style: italic;
font-style: italic;
}
.hljs-strong {
font-weight: 700;
font-weight: 700;
}
.hljs-link {
text-decoration: underline;
text-decoration: underline;
}

View file

@ -3,165 +3,145 @@ import type { Theme } from "../.."
import { readFileSync } from "fs"
export default {
font: {
sansSerif: "'Noto Sans KR', sans-serif", // https://fonts.google.com/noto/specimen/Noto+Sans+KR
monospace: "'Source Code Pro', monospace",
},
font: {
sansSerif: "'Noto Sans KR', sans-serif", // https://fonts.google.com/noto/specimen/Noto+Sans+KR
monospace: "'Source Code Pro', monospace",
},
color: {
text: {
highContrast: "#FFFFFF",
default: "#EEEEEE",
gray: "#CCC",
},
background: "#36393F",
},
color: {
text: {
highContrast: "#FFFFFF",
default: "#EEEEEE",
gray: "#CCC",
},
background: "#36393F",
},
maxDisplayWidth: {
mobile: "1024px", // max-w-screen-lg
desktop: "1536px", // max-w-screen-2xl
},
maxDisplayWidth: {
mobile: "1024px", // max-w-screen-lg
desktop: "1536px", // max-w-screen-2xl
},
component: {
anchor: {
color: {
default: "#66AAFF",
hover: "#4592F7",
active: "#4592F7",
header: "#778899",
},
},
component: {
anchor: {
color: {
default: "#66AAFF",
hover: "#4592F7",
active: "#4592F7",
header: "#778899",
},
},
blockQuote: {
color: {
background: "#FFFFFF12",
borderLeft: "#FFFFFF4D",
},
},
blockQuote: {
color: {
background: "#FFFFFF12",
borderLeft: "#FFFFFF4D",
},
},
card: {
color: {
background: "#2F3136",
hoverGlow: "#FFFFFF33",
},
},
card: {
color: {
background: "#2F3136",
hoverGlow: "#FFFFFF33",
},
},
code: {
inline: {
color: {
text: "#FFFFFF",
background: "#444",
border: "#666",
},
},
block: {
color: {
border: "#555",
highlight: "#14161A",
},
style: readFileSync(__dirname + "/codeblock.css", "utf-8"),
},
},
code: {
inline: {
color: {
text: "#FFFFFF",
background: "#444",
border: "#666",
},
},
block: {
color: {
border: "#555",
highlight: "#14161A",
},
style: readFileSync(__dirname + "/codeblock.css", "utf-8"),
},
},
footer: {
color: {
background: "#000000",
text: "",
},
},
footer: {
color: {
background: "#000000",
text: "",
},
},
header: {
color: {
background: "#202225", // custom
hover: "#3F3F46", // zinc-700
text: "#D4D4D8", // zinc-300
},
height: "16px", // h-4
},
header: {
color: {
background: "#202225", // custom
hover: "#3F3F46", // zinc-700
text: "#D4D4D8", // zinc-300
},
height: "16px", // h-4
},
input: {
color: {
background: {
default: "#36393f",
itemHover: "#202225",
},
border: {
default: "#555555",
hover: "#808080",
focus: "#a3a3a3", // neutral-400
},
placeHolder: "#A9A9A9",
},
},
input: {
color: {
background: {
default: "#36393f",
itemHover: "#202225",
},
border: {
default: "#555555",
hover: "#808080",
focus: "#a3a3a3", // neutral-400
},
placeHolder: "#A9A9A9",
},
},
kbd: {
color: {
text: "#FFFFFF",
border: "#555555",
outerShadow: "#FFFFFF4D",
innerShadow: "#000000",
background: "#000000",
},
},
kbd: {
color: {
text: "#FFFFFF",
border: "#555555",
outerShadow: "#FFFFFF4D",
innerShadow: "#000000",
background: "#000000",
},
},
mark: {
color: {
text: "#FFFFFF",
background: "#FFFF0080",
},
},
mark: {
color: {
text: "#FFFFFF",
background: "#FFFF0080",
},
},
scrollbar: {
color: {
track: "#18181B",
thumb: "#888888",
},
width: "8px", // w-2
borderRadius: "4px", // rounded
},
scrollbar: {
color: {
track: "#18181B",
thumb: "#888888",
},
width: "8px", // w-2
borderRadius: "4px", // rounded
},
scrollProgressBar: {
color: {
background: "#52525B", // zinc 600
foreground: "#D4D4D8", // zinc-300
},
},
scrollProgressBar: {
color: {
background: "#52525B", // zinc 600
foreground: "#D4D4D8", // zinc-300
},
},
table: {
color: {
border: "#777777",
even: "#21272E",
},
},
table: {
color: {
border: "#777777",
even: "#21272E",
},
},
ui: {
color: {
background: {
default: "#202225",
hover: "#3F3F46", // zinc-700
},
border: "#555",
},
},
},
ui: {
color: {
background: {
default: "#202225",
hover: "#3F3F46", // zinc-700
},
border: "#555",
},
},
},
} as Theme
/*
dark: {
backgroundColor0: "#18181b",
backgroundColor1: "#36393F",
backgroundColor2: "#2F3136",
color0: "#FFFFFF",
color1: "#EEEEEE",
color2: "#CCC",
}
light: {
backgroundColor0: "#FFFFFF",
backgroundColor1: "#F7F7F7",
backgroundColor2: "#DDDDDD",
color0: "#000000",
color1: "#111111",
color2: "#555",
}
*/

View file

@ -1,27 +1,27 @@
/* from highlight.js/styles/default.css */
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em;
display: block;
overflow-x: auto;
padding: 1em;
}
code.hljs {
padding: 3px 5px;
padding: 3px 5px;
}
.hljs {
background: #f0f0f0;
color: #444;
background: #f0f0f0;
color: #444;
}
.hljs-comment {
color: #888;
color: #888;
}
.hljs-punctuation,
.hljs-tag {
color: #444a;
color: #444a;
}
.hljs-tag .hljs-attr,
.hljs-tag .hljs-name {
color: #444;
color: #444;
}
.hljs-attribute,
.hljs-doctag,
@ -29,7 +29,7 @@ code.hljs {
.hljs-meta .hljs-keyword,
.hljs-name,
.hljs-selector-tag {
font-weight: 700;
font-weight: 700;
}
.hljs-deletion,
.hljs-number,
@ -39,12 +39,12 @@ code.hljs {
.hljs-string,
.hljs-template-tag,
.hljs-type {
color: #800;
color: #800;
}
.hljs-section,
.hljs-title {
color: #800;
font-weight: 700;
color: #800;
font-weight: 700;
}
.hljs-link,
.hljs-operator,
@ -54,26 +54,26 @@ code.hljs {
.hljs-symbol,
.hljs-template-variable,
.hljs-variable {
color: #bc6060;
color: #bc6060;
}
.hljs-literal {
color: #78a960;
color: #78a960;
}
.hljs-addition,
.hljs-built_in,
.hljs-bullet,
.hljs-code {
color: #397300;
color: #397300;
}
.hljs-meta {
color: #1f7199;
color: #1f7199;
}
.hljs-meta .hljs-string {
color: #4d99bf;
color: #4d99bf;
}
.hljs-emphasis {
font-style: italic;
font-style: italic;
}
.hljs-strong {
font-weight: 700;
font-weight: 700;
}

View file

@ -7,120 +7,120 @@ import { DeepPartial } from "utility-types"
import BaseTheme from "../dark"
export default merge<Theme, DeepPartial<Theme>>(BaseTheme, {
color: {
text: {
highContrast: "#000000",
default: "#111111",
gray: "#555",
},
background: "#F7F7F7",
},
component: {
anchor: {
color: {
header: "#D3D3D3",
},
},
color: {
text: {
highContrast: "#000000",
default: "#111111",
gray: "#555",
},
background: "#F7F7F7",
},
component: {
anchor: {
color: {
header: "#D3D3D3",
},
},
blockQuote: {
color: {
background: "#0000000D",
borderLeft: "#0000001A",
},
},
blockQuote: {
color: {
background: "#0000000D",
borderLeft: "#0000001A",
},
},
card: {
color: {
background: "#FFFFFF",
hoverGlow: "#00000040",
},
},
card: {
color: {
background: "#FFFFFF",
hoverGlow: "#00000040",
},
},
code: {
inline: {
color: {
text: "#000000",
background: "#EEE",
border: "#BBB",
},
},
block: {
color: {
border: "#BBB",
highlight: "#DDDDDD",
},
style: readFileSync(__dirname + "/codeblock.css", "utf-8"),
},
},
code: {
inline: {
color: {
text: "#000000",
background: "#EEE",
border: "#BBB",
},
},
block: {
color: {
border: "#BBB",
highlight: "#DDDDDD",
},
style: readFileSync(__dirname + "/codeblock.css", "utf-8"),
},
},
footer: {
color: {
background: "#FFFFFF",
text: "",
},
},
footer: {
color: {
background: "#FFFFFF",
text: "",
},
},
input: {
color: {
background: {
default: "#EEEEEE",
itemHover: "#FFFFFF",
},
border: {
default: "#CCCCCC",
hover: "#808080",
focus: "#000000",
},
placeHolder: "#777777",
},
},
input: {
color: {
background: {
default: "#EEEEEE",
itemHover: "#FFFFFF",
},
border: {
default: "#CCCCCC",
hover: "#808080",
focus: "#000000",
},
placeHolder: "#777777",
},
},
kbd: {
color: {
text: "#333333",
border: "#CCCCCC",
outerShadow: "#00000033",
innerShadow: "#FFFFFF",
background: "#F7F7F7",
},
},
kbd: {
color: {
text: "#333333",
border: "#CCCCCC",
outerShadow: "#00000033",
innerShadow: "#FFFFFF",
background: "#F7F7F7",
},
},
mark: {
color: {
text: "#000000",
background: "#FFFF00BF",
},
},
mark: {
color: {
text: "#000000",
background: "#FFFF00BF",
},
},
scrollbar: {
color: {
track: "#FFFFFF",
thumb: "#DDDDDD",
},
},
scrollbar: {
color: {
track: "#FFFFFF",
thumb: "#DDDDDD",
},
},
scrollProgressBar: {
color: {
background: "#d4d4d8", // zinc-300
foreground: "#52525b", // zinc-600
},
},
scrollProgressBar: {
color: {
background: "#d4d4d8", // zinc-300
foreground: "#52525b", // zinc-600
},
},
table: {
color: {
border: "#DDD",
even: "#F2F2F2",
},
},
table: {
color: {
border: "#DDD",
even: "#F2F2F2",
},
},
ui: {
color: {
background: {
default: "#FFFFFF",
hover: "#EEEEEE",
},
border: "#CCC",
},
},
},
ui: {
color: {
background: {
default: "#FFFFFF",
hover: "#EEEEEE",
},
border: "#CCC",
},
},
},
}) as Theme

View file

@ -1,9 +1,9 @@
{
"compilerOptions": {
"types": ["node"],
"moduleResolution": "Node",
"esModuleInterop": true
},
"include": ["src"],
"exclude": ["dist", "node_modules"]
"compilerOptions": {
"types": ["node"],
"moduleResolution": "Node",
"esModuleInterop": true
},
"include": ["src"],
"exclude": ["dist", "node_modules"]
}

View file

@ -1,20 +1,20 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Default",
"compilerOptions": {
"composite": false,
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"inlineSources": false,
"isolatedModules": true,
"moduleResolution": "node",
"noUnusedLocals": false,
"noUnusedParameters": false,
"preserveWatchOutput": true,
"skipLibCheck": true,
"strict": true
},
"exclude": ["node_modules"]
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Default",
"compilerOptions": {
"composite": false,
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"inlineSources": false,
"isolatedModules": true,
"moduleResolution": "node",
"noUnusedLocals": false,
"noUnusedParameters": false,
"preserveWatchOutput": true,
"skipLibCheck": true,
"strict": true
},
"exclude": ["node_modules"]
}

View file

@ -1,10 +1,10 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Node 16",
"extends": "./base.json",
"compilerOptions": {
"lib": ["ES2020"],
"module": "commonjs",
"target": "ES2020"
}
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Node 16",
"extends": "./base.json",
"compilerOptions": {
"lib": ["ES2020"],
"module": "commonjs",
"target": "ES2020"
}
}

View file

@ -1,6 +1,6 @@
{
"name": "@developomp-site/tsconfig",
"version": "0.0.0",
"private": true,
"license": "MIT"
"name": "@developomp-site/tsconfig",
"version": "0.0.0",
"private": true,
"license": "MIT"
}

View file

@ -1,11 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "React Library",
"extends": "./base.json",
"compilerOptions": {
"jsx": "react-jsx",
"lib": ["dom", "ES2015"],
"module": "ESNext",
"target": "es6"
}
"$schema": "https://json.schemastore.org/tsconfig",
"display": "React Library",
"extends": "./base.json",
"compilerOptions": {
"jsx": "react-jsx",
"lib": ["dom", "ES2015"],
"module": "ESNext",
"target": "es6"
}
}

View file

@ -1,4 +1,4 @@
module.exports = {
root: true,
extends: ["developomp-site"],
};
root: true,
extends: ["developomp-site"],
}

View file

@ -1,28 +1,28 @@
{
"name": "@developomp-site/utils",
"version": "0.0.0",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"sideEffects": false,
"license": "MIT",
"files": [
"dist/**"
],
"scripts": {
"build": "tsup src/index.tsx --format esm,cjs --dts --external react",
"dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react",
"lint": "TIMING=1 eslint \"src/**/*.ts*\"",
"clean": "rm -rf .turbo node_modules dist"
},
"devDependencies": {
"@developomp-site/eslint-config": "workspace:*",
"@developomp-site/tsconfig": "workspace:*",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9",
"eslint": "^8.29.0",
"react": "^18.2.0",
"tsup": "^5.12.9",
"typescript": "^4.9.4"
}
"name": "@developomp-site/utils",
"version": "0.0.0",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"sideEffects": false,
"license": "MIT",
"files": [
"dist/**"
],
"scripts": {
"build": "tsup src/index.tsx --format esm,cjs --dts --external react",
"dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react",
"lint": "TIMING=1 eslint \"src/**/*.ts*\"",
"clean": "rm -rf .turbo node_modules dist"
},
"devDependencies": {
"@developomp-site/eslint-config": "workspace:*",
"@developomp-site/tsconfig": "workspace:*",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9",
"eslint": "^8.29.0",
"react": "^18.2.0",
"tsup": "^5.12.9",
"typescript": "^4.9.4"
}
}

View file

@ -1,5 +1,5 @@
{
"extends": "@developomp-site/tsconfig/react-library.json",
"include": ["."],
"exclude": ["dist", "build", "node_modules"]
"extends": "@developomp-site/tsconfig/react-library.json",
"include": ["."],
"exclude": ["dist", "build", "node_modules"]
}