refactor project structures

- vite.config.js: used to generate static cv in a single html file
- vite.config.site.js: used to build the jsoncv site, including editor and preview pages
This commit is contained in:
Reorx 2023-02-06 22:52:35 +08:00
parent aa2ac69904
commit 6461995fbf
27 changed files with 179 additions and 2148 deletions

14
index.html Normal file
View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CV</title>
<link rel="stylesheet" href="/src/scss/print.css">
<link rel="stylesheet" href="/src/themes/<%= theme %>/index.scss">
</head>
<body>
<div class="cv-container">
<%- include('src/themes/' + theme + '/index', locals) %>
</div>
</body>
</html>

2113
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,10 @@
"scripts": {
"dev": "vite --host",
"build": "vite build",
"preview": "vite preview"
"preview": "vite preview",
"dev-site": "vite -c vite.config.site.js --host",
"build-site": "vite -c vite.config.site.js build",
"preview-site": "vite -c vite.config.site.js preview"
},
"devDependencies": {
"@iconify-json/mdi": "^1.1.33",
@ -14,8 +17,9 @@
"rollup-plugin-node-polyfills": "^0.2.1",
"sass": "^1.54.8",
"vite": "^4.1.1",
"vite-plugin-ejs": "^1.6.4",
"vite-plugin-handlebars": "^1.6.0",
"vite-plugin-node-polyfills": "^0.7.0"
"vite-plugin-singlefile": "^0.13.2"
},
"dependencies": {
"@iconify/json": "^2.2.15",

View File

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JSONCV Editor</title>
<link rel="stylesheet" href="styles.scss" />
<link rel="stylesheet" href="../scss/styles.scss" />
</head>
<body>
<div id="main">
@ -29,7 +29,7 @@
<div class="middle column editor-container"></div>
<div class="right column">
<div class="output-json code-block" style="display: none;"></div>
<iframe class="output-html" src="/editor/preview.html" frameborder="0"></iframe>
<iframe class="output-html" src="/preview/" frameborder="0"></iframe>
</div>
</div>

View File

@ -7,6 +7,7 @@ import objectPath from 'object-path';
import { JSONEditor } from '@json-editor/json-editor/dist/jsoneditor';
import * as sampleModule from '../../sample.resume.json';
import * as jsoncvSchemaModule from '../../schema/jsoncv.schema.json';
import {
getCVData,
saveCVJSON,
@ -18,9 +19,8 @@ import {
propertiesToObject,
traverseDownObject,
} from '../lib/utils';
import * as jsoncvSchemaModule from '../schema/jsoncv.schema.json';
import { registerIconLib } from './iconlib';
import { registerTheme } from './theme';
import { registerIconLib } from './je-iconlib';
import { registerTheme } from './je-theme';
const propertiesInOrder = ['basics', 'education', 'work', 'skills', 'projects', 'sideProjects', 'languages', 'interests', 'references', 'awards', 'publications', 'volunteer', 'meta']
const basicsPropertiesInOrder = ['name', 'label', 'email', 'phone', 'url', 'summary', 'image', 'location', 'profiles']

View File

@ -2,11 +2,12 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CV</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="cv-container"></div>
<script src="main.js" type="module"></script>
<div>JSONCV</div>
<a href="/editor/">Editor</a>
</body>
</html>

22
src/lib/vite-plugins.js Normal file
View File

@ -0,0 +1,22 @@
/*
* This plugin allows for importing ejs files as strings.
*
* ref 1: https://vitejs.dev/guide/api-plugin.html#transforming-custom-file-types
* ref 2: https://github.com/vitejs/vite/issues/594#issuecomment-665915643
*/
export function TransformEjs() {
return {
name: 'transform-ejs',
transform(src, id) {
if (id.endsWith('.ejs')) {
return {
code: `export default ${JSON.stringify(src)}`,
map: null, // provide source map if available
}
}
},
}
}

View File

@ -1,9 +0,0 @@
import './print.css';
import * as exampleData from '../data/rxresume-mengxiao.converted.json';
import { applyThemeTo } from './themer';
const elCV = document.querySelector('.cv-container')
applyThemeTo('default', elCV, exampleData)

View File

@ -7,6 +7,6 @@
<body>
<div class="cv-container"></div>
<script src="preview.js" type="module"></script>
<script src="main.js" type="module"></script>
</body>
</html>

View File

@ -1,10 +1,10 @@
import '../print.css';
import '../scss/print.css';
import {
getCVData,
getCVSavedTime,
} from '../lib/store';
import { applyThemeTo } from '../themer';
import { applyThemeTo } from '../themes';
const themeName = 'default'
const elCV = document.querySelector('.cv-container')

19
src/themes/data.js Normal file
View File

@ -0,0 +1,19 @@
import { reformatDate } from '../lib/date';
import { getIconSVG } from '../lib/icons';
export function getRenderData(cvData) {
return {
cv: cvData,
fn: {
reformatDate,
getIconSVG,
urlNoSchema,
}
}
}
/* fn */
function urlNoSchema(url) {
return url.replace(/https?:\/\//, '')
}

View File

@ -1,7 +1,6 @@
import ejs from 'ejs';
import { reformatDate } from '../lib/date';
import { getIconSVG } from '../lib/icons';
import { getRenderData } from './data';
const themes = {}
@ -10,13 +9,13 @@ const themeNames = ['reorx']
// https://vitejs.dev/guide/features.html#disabling-css-injection-into-the-page
// note that `?raw` (https://vitejs.dev/guide/assets.html#importing-asset-as-string)
// cannot be used because we need vite to transform scss into css
const styleMoudules = import.meta.glob("../templates/*/index.scss", { "query": "?inline" })
const styleMoudules = import.meta.glob("./*/index.scss", { "query": "?inline" })
for (const name of themeNames) {
const templateModule = await import(`../templates/${name}/index.ejs`)
const templateModule = await import(`./${name}/index.ejs`)
// https://vitejs.dev/guide/features.html#glob-import
const styleModule = await styleMoudules[`../templates/${name}/index.scss`]()
const styleModule = await styleMoudules[`./${name}/index.scss`]()
themes[name] = {
template: templateModule.default,
@ -31,15 +30,8 @@ export function getTheme(name) {
return themes[name]
}
export function renderTheme(template, data, options) {
return ejs.render(template, {
cv: data,
fn: {
reformatDate,
getIconSVG,
urlNoSchema,
}
}, options)
export function renderTheme(template, cvData, options) {
return ejs.render(template, getRenderData(cvData), options)
}
const cvStyleId = 'cv-style'
@ -55,9 +47,3 @@ export function applyThemeTo(name, el, data) {
}
elStyle.innerHTML = theme.style
}
/* fn */
function urlNoSchema(url) {
return url.replace(/https?:\/\//, '')
}

View File

@ -19,7 +19,7 @@ $color-text-dim: #777;
h1 {
font-size: 36px;
font-weight: 600;
margin: .8em 0 .2em 0;
margin: .2em 0 .2em 0;
}
.label {
margin: .4em 0;

View File

@ -1,50 +1,21 @@
import { resolve } from 'path';
import { defineConfig } from 'vite';
import { ViteEjsPlugin } from 'vite-plugin-ejs';
import { viteSingleFile } from 'vite-plugin-singlefile';
const sampleFilename = './sample.resume.json'
let dataFilename = process.env.DATA_FILENAME || sampleFilename
import { TransformEjs } from './src/lib/vite-plugins';
import { getRenderData } from './src/themes/data';
const data = require(dataFilename)
const dataFilename = process.env.DATA_FILENAME || './sample.resume.json'
const outDir = process.env.OUT_DIR || 'dist'
const rootDir = resolve(__dirname, 'src')
const fileRegex = /\.(my-file-ext)$/
// ref 1: https://vitejs.dev/guide/api-plugin.html#transforming-custom-file-types
// ref 2: https://github.com/vitejs/vite/issues/594#issuecomment-665915643
function TransformEjs() {
return {
name: 'transform-ejs',
transform(src, id) {
if (id.endsWith('.ejs')) {
return {
code: `export default ${JSON.stringify(src)}`,
map: null, // provide source map if available
}
}
},
}
}
const cvData = require(dataFilename)
const data = getRenderData(cvData)
data.theme = process.env.THEME || 'reorx'
export default defineConfig({
// use relative path for assets
// base: "",
root: 'src',
// assetsInclude: ['**/*.ejs'],
build: {
// relative to root
outDir: "../dist",
// put assets in the same folder as index.html
// assetsDir: ".",
rollupOptions: {
input: {
main: resolve(rootDir, 'index.html'),
editor: resolve(rootDir, 'editor/index.html'),
editorPreview: resolve(rootDir, 'editor/preview.html'),
},
},
outDir: outDir,
},
resolve: {
alias: {
@ -54,5 +25,15 @@ export default defineConfig({
},
plugins: [
TransformEjs(),
ViteEjsPlugin(
data,
{
ejs: (viteConfig) => ({
// ejs options goes here.
views: [__dirname],
})
}
),
viteSingleFile(),
],
})

30
vite.config.site.js Normal file
View File

@ -0,0 +1,30 @@
import { defineConfig } from 'vite';
import { TransformEjs } from './src/lib/vite-plugins';
export default defineConfig({
root: 'src',
build: {
// allows 'import.meta.glob' to work
target: 'esnext',
rollupOptions: {
input: {
main: 'index.html',
editor: 'editor/index.html',
preview: 'preview/index.html',
// main: resolve(rootDir, 'index.html'),
// editor: resolve(rootDir, 'editor/index.html'),
// editorPreview: resolve(rootDir, 'editor/preview.html'),
},
},
},
resolve: {
alias: {
// remove the "Module "fs" has been externalized" warning for ejs
'fs': 'src/lib/fs-polyfill.js',
},
},
plugins: [
TransformEjs(),
],
})