feat(color): support custom colors

This commit is contained in:
Rafael Bardini 2023-09-04 02:29:45 +02:00
parent cde237f706
commit b1e2927570
6 changed files with 72 additions and 18 deletions

View File

@ -12,6 +12,7 @@ Inspired by [jsonresume-theme-flat](https://github.com/erming/jsonresume-theme-f
- 💄 Markdown support - 💄 Markdown support
- 📐 CSS grid layout - 📐 CSS grid layout
- 🌗 Light and dark modes - 🌗 Light and dark modes
- 🎨 Customizable colors
- 🧩 Standalone CLI - 🧩 Standalone CLI
- 📦 ESM and CommonJS builds - 📦 ESM and CommonJS builds
@ -50,3 +51,25 @@ _Even_ comes with a barebones CLI that reads resumes from `stdin` and outputs HT
```console ```console
npx jsonresume-theme-even < resume.json > resume.html npx jsonresume-theme-even < resume.json > resume.html
``` ```
## Options
### Colors
You can override theme colors via the `.meta.colors` resume field. Each entry defines a tuple of light and (optional) dark color values. If only one array value is defined, it will be used in both light and dark modes.
Here's an example using the default theme colors:
```json
{
"meta": {
"colors": {
"background": ["#ffffff", "#191e23"],
"dimmed": ["#f3f4f5", "#23282d"],
"primary": ["#191e23", "#fbfbfc"],
"secondary": ["#6c7781", "#ccd0d4"],
"accent": ["#0073aa", "#00a0d2"]
}
}
}
```

View File

@ -11,11 +11,12 @@ import References from './components/references.js'
import Skills from './components/skills.js' import Skills from './components/skills.js'
import Volunteer from './components/volunteer.js' import Volunteer from './components/volunteer.js'
import Work from './components/work.js' import Work from './components/work.js'
import colors from './utils/colors.js'
import html from './utils/html.js' import html from './utils/html.js'
export default function Resume(resume, css) { export default function Resume(resume, css) {
return html`<!DOCTYPE html> return html`<!DOCTYPE html>
<html lang="en"> <html lang="en" style="${colors(resume.meta)}">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
${Meta(resume.basics)} ${Meta(resume.basics)}

View File

@ -1,11 +1,23 @@
:root { :root {
color-scheme: light dark; color-scheme: light dark;
--color-background: #ffffff; /* White */ --color-background-light: #ffffff; /* White */
--color-muted: #f3f4f5; /* Light Gray 200 */ --color-dimmed-light: #f3f4f5; /* Light Gray 200 */
--color-primary: #191e23; /* Dark Gray 900 */ --color-primary-light: #191e23; /* Dark Gray 900 */
--color-secondary: #6c7781; /* Dark Gray 300 */ --color-secondary-light: #6c7781; /* Dark Gray 300 */
--color-accent: #0073aa; /* WordPress Blue */ --color-accent-light: #0073aa; /* WordPress Blue */
--color-background-dark: #191e23; /* Dark Gray 900 */
--color-dimmed-dark: #23282d; /* Dark Gray 800 */
--color-primary-dark: #fbfbfc; /* Light Gray 100 */
--color-secondary-dark: #ccd0d4; /* Light Gray 700 */
--color-accent-dark: #00a0d2; /* Medium Blue */
--color-background: var(--color-background-light);
--color-dimmed: var(--color-dimmed-light);
--color-primary: var(--color-primary-light);
--color-secondary: var(--color-secondary-light);
--color-accent: var(--color-accent-light);
--scale-ratio: 1.25; --scale-ratio: 1.25;
--scale0: 1rem; --scale0: 1rem;
@ -18,11 +30,11 @@
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root { :root {
--color-background: #191e23; /* Dark Gray 900 */ --color-background: var(--color-background-dark);
--color-muted: #23282d; /* Dark Gray 800 */ --color-dimmed: var(--color-dimmed-dark);
--color-primary: #fbfbfc; /* Light Gray 100 */ --color-primary: var(--color-primary-dark);
--color-secondary: #ccd0d4; /* Light Gray 700 */ --color-secondary: var(--color-secondary-dark);
--color-accent: #00a0d2; /* Medium Blue */ --color-accent: var(--color-accent-dark);
} }
} }
@ -128,7 +140,7 @@ h6 {
} }
blockquote { blockquote {
border-left: 0.2em solid var(--color-muted); border-left: 0.2em solid var(--color-dimmed);
padding-left: 1em; padding-left: 1em;
} }
@ -147,7 +159,7 @@ svg {
} }
.masthead { .masthead {
background: var(--color-muted); background: var(--color-dimmed);
display: inherit; display: inherit;
gap: inherit; gap: inherit;
grid-column: full; grid-column: full;
@ -206,7 +218,7 @@ blockquote > * + *,
} }
.tag-list > li { .tag-list > li {
background: var(--color-muted); background: var(--color-dimmed);
border-radius: 0.2em; border-radius: 0.2em;
padding: 0.2em 0.6em; padding: 0.2em 0.6em;
} }

View File

@ -2,7 +2,7 @@
exports[`renders a resume 1`] = ` exports[`renders a resume 1`] = `
"<!DOCTYPE html> "<!DOCTYPE html>
<html lang=\\"en\\"> <html lang=\\"en\\" style=\\"--color-background-light:lightgray; --color-background-dark:darkgray;\\">
<head> <head>
<meta charset=\\"utf-8\\"> <meta charset=\\"utf-8\\">

View File

@ -2,10 +2,21 @@ import { HtmlValidate } from 'html-validate'
import { expect, it } from 'vitest' import { expect, it } from 'vitest'
import { render } from '../index.js' import { render } from '../index.js'
import resume from 'resume-schema/sample.resume.json' assert { type: 'json' } import sampleResume from 'resume-schema/sample.resume.json' assert { type: 'json' }
// Overwrite empty sample resume values const resume = {
resume.basics.image = 'image.jpg' ...sampleResume,
meta: {
...sampleResume.meta,
colors: {
background: ['lightgray', 'darkgray'],
},
},
basics: {
...sampleResume.basics,
image: 'image.jpg',
},
}
it('renders a resume', () => { it('renders a resume', () => {
expect(render(resume)).toMatchSnapshot() expect(render(resume)).toMatchSnapshot()
@ -15,6 +26,7 @@ it('renders valid HTML', async () => {
const htmlvalidate = new HtmlValidate({ const htmlvalidate = new HtmlValidate({
extends: ['html-validate:recommended'], extends: ['html-validate:recommended'],
rules: { rules: {
'no-inline-style': 'off',
'no-trailing-whitespace': 'off', 'no-trailing-whitespace': 'off',
'tel-non-breaking': 'off', 'tel-non-breaking': 'off',
}, },

6
utils/colors.js Normal file
View File

@ -0,0 +1,6 @@
export default function colors(meta = {}) {
const { colors } = meta
return colors && Object.entries(colors)
.map(([name, [light, dark = light]]) => `--color-${name}-light:${light}; --color-${name}-dark:${dark};`)
.join(' ')
}