Merge remote-tracking branch 'origin/main'
This commit is contained in:
15
app.js
15
app.js
@@ -1,19 +1,20 @@
|
|||||||
var createError = require('http-errors');
|
const createError = require('http-errors');
|
||||||
var express = require('express');
|
const express = require('express');
|
||||||
var path = require('path');
|
const path = require('path');
|
||||||
var cookieParser = require('cookie-parser');
|
const cookieParser = require('cookie-parser');
|
||||||
var logger = require('morgan');
|
const logger = require('morgan');
|
||||||
|
|
||||||
var indexRouter = require('./routes/index');
|
var indexRouter = require('./routes/index');
|
||||||
var usersRouter = require('./routes/users');
|
var usersRouter = require('./routes/users');
|
||||||
const apiRouter = require('./routes/api');
|
const apiRouter = require('./routes/api');
|
||||||
const sitesRouter = require('./routes/sites');
|
const sitesRouter = require('./routes/sites');
|
||||||
|
|
||||||
var app = express();
|
const app = express();
|
||||||
|
|
||||||
// view engine setup
|
// view engine setup
|
||||||
app.set('views', path.join(__dirname, 'views'));
|
app.set('views', path.join(__dirname, 'views'));
|
||||||
app.set('view engine', 'twig');
|
|
||||||
|
app.set('view engine', 'ejs');
|
||||||
|
|
||||||
app.use(logger('dev'));
|
app.use(logger('dev'));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|||||||
921
package-lock.json
generated
921
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@@ -3,7 +3,10 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node ./bin/www"
|
"start": "concurrently \"npm run start:server\" \"npm run start:css\"",
|
||||||
|
"start:server": "node ./bin/www",
|
||||||
|
"start:css": "tailwindcss -i ./styles/base.css -o ./public/stylesheets/style.css --watch",
|
||||||
|
"build:css": "tailwindcss -i ./styles/base.css -o ./public/stylesheets/style.css --minify"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@axe-core/playwright": "^4.10.1",
|
"@axe-core/playwright": "^4.10.1",
|
||||||
@@ -12,10 +15,16 @@
|
|||||||
"axe-playwright": "^2.1.0",
|
"axe-playwright": "^2.1.0",
|
||||||
"cookie-parser": "~1.4.4",
|
"cookie-parser": "~1.4.4",
|
||||||
"debug": "~2.6.9",
|
"debug": "~2.6.9",
|
||||||
|
"ejs": "^3.1.10",
|
||||||
"express": "~4.16.1",
|
"express": "~4.16.1",
|
||||||
"http-errors": "~1.6.3",
|
"http-errors": "~1.6.3",
|
||||||
"morgan": "~1.9.1",
|
"morgan": "~1.9.1",
|
||||||
"twig": "~0.10.3",
|
|
||||||
"jsdom": "^26.1.0"
|
"jsdom": "^26.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tailwindcss/cli": "^4.1.7",
|
||||||
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
|
"tailwindcss": "^4.1.7",
|
||||||
|
"concurrently": "^8.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,402 @@
|
|||||||
body {
|
/*! tailwindcss v4.1.7 | MIT License | https://tailwindcss.com */
|
||||||
padding: 50px;
|
@layer properties;
|
||||||
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
@layer theme, base, components, utilities;
|
||||||
|
@layer theme {
|
||||||
|
:root, :host {
|
||||||
|
--font-sans: "Raleway", sans-serif;
|
||||||
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
||||||
|
"Courier New", monospace;
|
||||||
|
--color-blue-400: oklch(70.7% 0.165 254.624);
|
||||||
|
--color-slate-900: oklch(20.8% 0.042 265.755);
|
||||||
|
--color-gray-200: oklch(92.8% 0.006 264.531);
|
||||||
|
--color-gray-400: oklch(70.7% 0.022 261.325);
|
||||||
|
--color-gray-800: oklch(27.8% 0.033 256.848);
|
||||||
|
--color-black: oklch(0% 0 0);
|
||||||
|
--color-white: oklch(100% 0 0);
|
||||||
|
--spacing: 0.25rem;
|
||||||
|
--text-xs: 0.75rem;
|
||||||
|
--text-xs--line-height: calc(1 / 0.75);
|
||||||
|
--text-base: 1rem;
|
||||||
|
--text-base--line-height: calc(1.5 / 1);
|
||||||
|
--radius-sm: 0.25rem;
|
||||||
|
--default-transition-duration: 150ms;
|
||||||
|
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
--default-font-family: var(--font-sans);
|
||||||
|
--default-mono-font-family: var(--font-mono);
|
||||||
|
--color-primary: oklch(0.57 0.203362 257.1706);
|
||||||
|
--color-secondary: oklch(0.56 0.0176 257.23);
|
||||||
|
--color-bodylinks: oklch(0.48 0.0789 211.58);
|
||||||
|
--color-warning: oklch(84.42% 0.1722 84.93);
|
||||||
|
--h1: calc(var(--text-base) * 2.25);
|
||||||
|
--h2: calc(var(--text-base) * 1.75);
|
||||||
|
--h3: calc(var(--text-base) * 1.5);
|
||||||
|
--h4: calc(var(--text-base) * 1.25);
|
||||||
|
--h5: calc(var(--text-base) * 1.125);
|
||||||
|
--h6: calc(var(--text-base) * 1.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@layer base {
|
||||||
|
*, ::after, ::before, ::backdrop, ::file-selector-button {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0 solid;
|
||||||
|
}
|
||||||
|
html, :host {
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
tab-size: 4;
|
||||||
|
font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
|
||||||
|
font-feature-settings: var(--default-font-feature-settings, normal);
|
||||||
|
font-variation-settings: var(--default-font-variation-settings, normal);
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
height: 0;
|
||||||
|
color: inherit;
|
||||||
|
border-top-width: 1px;
|
||||||
|
}
|
||||||
|
abbr:where([title]) {
|
||||||
|
-webkit-text-decoration: underline dotted;
|
||||||
|
text-decoration: underline dotted;
|
||||||
|
}
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #00B7FF;
|
color: inherit;
|
||||||
|
-webkit-text-decoration: inherit;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
b, strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
code, kbd, samp, pre {
|
||||||
|
font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
|
||||||
|
font-feature-settings: var(--default-mono-font-feature-settings, normal);
|
||||||
|
font-variation-settings: var(--default-mono-font-variation-settings, normal);
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
sub, sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
text-indent: 0;
|
||||||
|
border-color: inherit;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
:-moz-focusring {
|
||||||
|
outline: auto;
|
||||||
|
}
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
ol, ul, menu {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
img, svg, video, canvas, audio, iframe, embed, object {
|
||||||
|
display: block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
img, video {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
button, input, select, optgroup, textarea, ::file-selector-button {
|
||||||
|
font: inherit;
|
||||||
|
font-feature-settings: inherit;
|
||||||
|
font-variation-settings: inherit;
|
||||||
|
letter-spacing: inherit;
|
||||||
|
color: inherit;
|
||||||
|
border-radius: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
:where(select:is([multiple], [size])) optgroup {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
:where(select:is([multiple], [size])) optgroup option {
|
||||||
|
padding-inline-start: 20px;
|
||||||
|
}
|
||||||
|
::file-selector-button {
|
||||||
|
margin-inline-end: 4px;
|
||||||
|
}
|
||||||
|
::placeholder {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {
|
||||||
|
::placeholder {
|
||||||
|
color: currentcolor;
|
||||||
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
|
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
::-webkit-date-and-time-value {
|
||||||
|
min-height: 1lh;
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
::-webkit-datetime-edit {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
::-webkit-datetime-edit-fields-wrapper {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
|
||||||
|
padding-block: 0;
|
||||||
|
}
|
||||||
|
:-moz-ui-invalid {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {
|
||||||
|
appearance: button;
|
||||||
|
}
|
||||||
|
::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
[hidden]:where(:not([hidden="until-found"])) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@layer utilities {
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
@media (width >= 40rem) {
|
||||||
|
max-width: 40rem;
|
||||||
|
}
|
||||||
|
@media (width >= 48rem) {
|
||||||
|
max-width: 48rem;
|
||||||
|
}
|
||||||
|
@media (width >= 64rem) {
|
||||||
|
max-width: 64rem;
|
||||||
|
}
|
||||||
|
@media (width >= 80rem) {
|
||||||
|
max-width: 80rem;
|
||||||
|
}
|
||||||
|
@media (width >= 96rem) {
|
||||||
|
max-width: 96rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mx-auto {
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
.mt-8 {
|
||||||
|
margin-top: calc(var(--spacing) * 8);
|
||||||
|
}
|
||||||
|
.mr-2 {
|
||||||
|
margin-right: calc(var(--spacing) * 2);
|
||||||
|
}
|
||||||
|
.mb-4 {
|
||||||
|
margin-bottom: calc(var(--spacing) * 4);
|
||||||
|
}
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
.h-8 {
|
||||||
|
height: calc(var(--spacing) * 8);
|
||||||
|
}
|
||||||
|
.min-h-\[70dvh\] {
|
||||||
|
min-height: 70dvh;
|
||||||
|
}
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.justify-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.gap-8 {
|
||||||
|
gap: calc(var(--spacing) * 8);
|
||||||
|
}
|
||||||
|
.space-x-4 {
|
||||||
|
:where(& > :not(:last-child)) {
|
||||||
|
--tw-space-x-reverse: 0;
|
||||||
|
margin-inline-start: calc(calc(var(--spacing) * 4) * var(--tw-space-x-reverse));
|
||||||
|
margin-inline-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-x-reverse)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bg-gray-200 {
|
||||||
|
background-color: var(--color-gray-200);
|
||||||
|
}
|
||||||
|
.bg-gray-800 {
|
||||||
|
background-color: var(--color-gray-800);
|
||||||
|
}
|
||||||
|
.p-4 {
|
||||||
|
padding: calc(var(--spacing) * 4);
|
||||||
|
}
|
||||||
|
.py-4 {
|
||||||
|
padding-block: calc(var(--spacing) * 4);
|
||||||
|
}
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.text-blue-400 {
|
||||||
|
color: var(--color-blue-400);
|
||||||
|
}
|
||||||
|
.text-bodylinks {
|
||||||
|
color: var(--color-bodylinks);
|
||||||
|
}
|
||||||
|
.text-gray-800 {
|
||||||
|
color: var(--color-gray-800);
|
||||||
|
}
|
||||||
|
.text-white {
|
||||||
|
color: var(--color-white);
|
||||||
|
}
|
||||||
|
.hover\:text-gray-400 {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
color: var(--color-gray-400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color: var(--color-slate-900);
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
font-size: var(--text-base);
|
||||||
|
line-height: var(--tw-leading, var(--text-base--line-height));
|
||||||
|
color: var(--color-gray-200);
|
||||||
|
}
|
||||||
|
::selection {
|
||||||
|
background: var(--color-warning);
|
||||||
|
}
|
||||||
|
@layer components {
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
h1, .h1 {
|
||||||
|
font-size: var(--h1);
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
h2, .h2 {
|
||||||
|
font-size: var(--h2);
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
h3, .h3 {
|
||||||
|
font-size: var(--h3);
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
h4, .h4 {
|
||||||
|
font-size: var(--h4);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
h5, .h5 {
|
||||||
|
font-size: var(--h5);
|
||||||
|
}
|
||||||
|
h6, .h6 {
|
||||||
|
font-size: var(--h6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a, .link {
|
||||||
|
color: var(--color-bodylinks);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 200ms;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h1 a, .h1 a, h2 a, .h2 a, h3 a, .h3 a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
li ul, li ol {
|
||||||
|
margin: 0 1rem;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
ol {
|
||||||
|
list-style-type: decimal;
|
||||||
|
}
|
||||||
|
ol ol {
|
||||||
|
list-style: lower-alpha;
|
||||||
|
}
|
||||||
|
ol ol ol {
|
||||||
|
list-style: lower-roman;
|
||||||
|
}
|
||||||
|
ol ol ol ol {
|
||||||
|
list-style: lower-alpha;
|
||||||
|
}
|
||||||
|
pre, code, samp, style {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
pre code {
|
||||||
|
background-color: inherit;
|
||||||
|
border-radius: 0;
|
||||||
|
color: inherit;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
background-color: color-mix(in srgb, oklch(0% 0 0) 30%, transparent);
|
||||||
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
|
background-color: color-mix(in oklab, var(--color-black) 30%, transparent);
|
||||||
|
}
|
||||||
|
padding-inline: 3px;
|
||||||
|
padding-block: 2px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: var(--text-xs);
|
||||||
|
line-height: var(--tw-leading, var(--text-xs--line-height));
|
||||||
|
color: var(--color-black);
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
background-color: black;
|
||||||
|
border: none;
|
||||||
|
display: block;
|
||||||
|
height: 1px;
|
||||||
|
margin: 1rem 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
@property --tw-space-x-reverse {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0;
|
||||||
|
}
|
||||||
|
@layer properties {
|
||||||
|
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
||||||
|
*, ::before, ::after, ::backdrop {
|
||||||
|
--tw-space-x-reverse: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
styles/base.css
Normal file
5
styles/base.css
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@import 'tailwindcss';
|
||||||
|
@import './colors.css';
|
||||||
|
@import './typography.css';
|
||||||
|
|
||||||
|
@plugin "@tailwindcss/typography";
|
||||||
41
styles/colors.css
Normal file
41
styles/colors.css
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/* Theme color definitions */
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--color-black: oklch(0% 0 0);
|
||||||
|
--color-white: oklch(100% 0 0);
|
||||||
|
|
||||||
|
--color-background: oklch(89.75% 0 0);
|
||||||
|
--color-text: var(--color-black);
|
||||||
|
|
||||||
|
--color-primary: oklch(0.57 0.203362 257.1706);
|
||||||
|
--color-primary-100: color-mix(in oklch, var(--color-primary) 10%, white);
|
||||||
|
--color-primary-200: color-mix(in oklch, var(--color-primary) 20%, white);
|
||||||
|
--color-primary-300: color-mix(in oklch, var(--color-primary) 30%, white);
|
||||||
|
--color-primary-400: color-mix(in oklch, var(--color-primary) 40%, white);
|
||||||
|
--color-primary-500: color-mix(in oklch, var(--color-primary) 50%, white);
|
||||||
|
--color-primary-600: color-mix(in oklch, var(--color-primary) 60%, white);
|
||||||
|
--color-primary-700: color-mix(in oklch, var(--color-primary) 70%, white);
|
||||||
|
--color-primary-800: color-mix(in oklch, var(--color-primary) 80%, white);
|
||||||
|
--color-primary-900: color-mix(in oklch, var(--color-primary) 90%, white);
|
||||||
|
|
||||||
|
--color-secondary: oklch(0.56 0.0176 257.23);
|
||||||
|
--color-secondary-100: color-mix(in oklch, var(--color-secondary) 10%, white);
|
||||||
|
--color-secondary-200: color-mix(in oklch, var(--color-secondary) 20%, white);
|
||||||
|
--color-secondary-300: color-mix(in oklch, var(--color-secondary) 30%, white);
|
||||||
|
--color-secondary-400: color-mix(in oklch, var(--color-secondary) 40%, white);
|
||||||
|
--color-secondary-500: color-mix(in oklch, var(--color-secondary) 50%, white);
|
||||||
|
--color-secondary-600: color-mix(in oklch, var(--color-secondary) 60%, white);
|
||||||
|
--color-secondary-700: color-mix(in oklch, var(--color-secondary) 70%, white);
|
||||||
|
--color-secondary-800: color-mix(in oklch, var(--color-secondary) 80%, white);
|
||||||
|
--color-secondary-900: color-mix(in oklch, var(--color-secondary) 90%, white);
|
||||||
|
|
||||||
|
--color-bodylinks: oklch(0.48 0.0789 211.58);
|
||||||
|
--color-footlinks: oklch(0.65 0.1104 212.2);
|
||||||
|
|
||||||
|
--color-success: oklch(64.01% 0.1751 146.7);
|
||||||
|
--color-info: oklch(0.55 0.0922 211.57);
|
||||||
|
--color-warning: oklch(84.42% 0.1722 84.93);
|
||||||
|
--color-danger: oklch(0.5126 0.1865 22.61);
|
||||||
|
--color-light: oklch(98.16% 0.0017 247.8);
|
||||||
|
--color-dark: oklch(34.51% 0.0133 248.2);
|
||||||
|
}
|
||||||
150
styles/typography.css
Normal file
150
styles/typography.css
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
/* Basic typographical styles */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All font sizes are based on 16px base font size and 1920px wide screen
|
||||||
|
* Default size is expressed as percentage of screen width.
|
||||||
|
* text-14px: 12px-27px, default: 14px
|
||||||
|
* text-16px: 14px-28px, default: 16px
|
||||||
|
* text-18px: 14px-30px, default: 18px
|
||||||
|
* text-20px: 16px-32px, default: 20px
|
||||||
|
* text-22px: 17px-33px, default: 22px
|
||||||
|
* text-25px: 18px-35px, default: 25px
|
||||||
|
* text-30px: 19px-37px, default: 30px
|
||||||
|
* text-35px: 20px-40px, default: 35px
|
||||||
|
* text-38px: 22px-48px, default: 38px
|
||||||
|
* text-40px: 24px-56px, default: 40px
|
||||||
|
* text-45px: 25px-64px, default: 45px
|
||||||
|
* text-50px: 27px-72px, default: 50px
|
||||||
|
* text-55px: 28px-76px, default: 55px
|
||||||
|
* text-60px: 30px-80px, default: 60px
|
||||||
|
* text-70px: 30px-76px, default: 70px
|
||||||
|
* text-75px: 32px-80px, default: 75px
|
||||||
|
*/
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--font-sans: "Raleway", sans-serif;
|
||||||
|
--line-height: 1.6;
|
||||||
|
|
||||||
|
--text-base: 1rem;
|
||||||
|
--text-14px: clamp(0.75rem, 0.7292vw, 1.7rem);
|
||||||
|
--text-16px: clamp(0.875rem, 0.8333vw, 1.8rem);
|
||||||
|
--text-18px: clamp(0.875rem, 0.9375vw, 1.9rem);
|
||||||
|
--text-20px: clamp(1rem, 1.0417vw, 2rem);
|
||||||
|
--text-22px: clamp(1.1rem, 1.15vw, 2.1rem);
|
||||||
|
--text-25px: clamp(1.125rem, 1.3021vw, 2.2rem);
|
||||||
|
--text-30px: clamp(1.185rem, 1.5625vw, 2.35rem);
|
||||||
|
--text-35px: clamp(1.25rem, 1.8229vw, 2.5rem);
|
||||||
|
--text-38px: clamp(1.4rem, 1.9791vw, 3rem);
|
||||||
|
--text-40px: clamp(1.5rem, 2.0834vw, 3.5rem);
|
||||||
|
--text-45px: clamp(1.6rem, 2.3438vw, 4rem);
|
||||||
|
--text-50px: clamp(1.7rem, 2.6042vw, 4.5rem);
|
||||||
|
--text-70px: clamp(1.9rem, 3.6458vw, 4.8rem);
|
||||||
|
--text-75px: clamp(2rem, 3.9063vw, 5rem);
|
||||||
|
|
||||||
|
--h1: calc(var(--text-base) * 2.25);
|
||||||
|
--h2: calc(var(--text-base) * 1.75);
|
||||||
|
--h3: calc(var(--text-base) * 1.5);
|
||||||
|
--h4: calc(var(--text-base) * 1.25);
|
||||||
|
--h5: calc(var(--text-base) * 1.125);
|
||||||
|
--h6: calc(var(--text-base) * 1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
@apply font-sans text-base text-gray-200 bg-slate-900;
|
||||||
|
}
|
||||||
|
|
||||||
|
::selection { background: var(--color-warning); }
|
||||||
|
|
||||||
|
@layer components {
|
||||||
|
h1, h2, h3,
|
||||||
|
h4, h5, h6 {
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, .h1 {
|
||||||
|
font-size: var(--h1);
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2, .h2 {
|
||||||
|
font-size: var(--h2);
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3, .h3 {
|
||||||
|
font-size: var(--h3);
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4, .h4 {
|
||||||
|
font-size: var(--h4);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5, .h5 { font-size: var(--h5); }
|
||||||
|
|
||||||
|
h6, .h6 { font-size: var(--h6); }
|
||||||
|
}
|
||||||
|
|
||||||
|
a, .link {
|
||||||
|
color: var(--color-bodylinks);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 200ms;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover { color: var(--color-primary); }
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 a, .h1 a,
|
||||||
|
h2 a, .h2 a,
|
||||||
|
h3 a, .h3 a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
li ul, li ol { margin: 0 1rem; }
|
||||||
|
|
||||||
|
ul { list-style-type: disc; }
|
||||||
|
|
||||||
|
ol { list-style-type: decimal; }
|
||||||
|
|
||||||
|
ol ol { list-style: lower-alpha; }
|
||||||
|
|
||||||
|
ol ol ol { list-style: lower-roman; }
|
||||||
|
|
||||||
|
ol ol ol ol { list-style: lower-alpha; }
|
||||||
|
|
||||||
|
pre, code,
|
||||||
|
samp, style { font-family: monospace; }
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code {
|
||||||
|
background-color: inherit;
|
||||||
|
border-radius: 0;
|
||||||
|
color: inherit;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
@apply bg-black/30 px-[3px] py-[2px] font-mono text-black text-xs rounded-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
background-color: black;
|
||||||
|
border: none;
|
||||||
|
display: block;
|
||||||
|
height: 1px;
|
||||||
|
margin: 1rem 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
3
views/error.ejs
Normal file
3
views/error.ejs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<h1><%= message %></h1>
|
||||||
|
<h2><%= error.status %></h2>
|
||||||
|
<pre><%= error.stack %></pre>
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{% extends 'layout.twig' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>{{message}}</h1>
|
|
||||||
<h2>{{error.status}}</h2>
|
|
||||||
<pre>{{error.stack}}</pre>
|
|
||||||
{% endblock %}
|
|
||||||
16
views/footer.ejs
Normal file
16
views/footer.ejs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<footer class="bg-gray-800 text-white p-4 mt-8">
|
||||||
|
<div class="container mx-auto text-center">
|
||||||
|
<div class="flex justify-center gap-8 items-center mb-4">
|
||||||
|
<p>© <%= new Date().getFullYear() %> <%= title %>. All rights reserved.</p>
|
||||||
|
<p>Powered by <a href="https://example.com" class="text-bodylinks">Your Company</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="/privacy" class="text-blue-400">Privacy Policy</a> |
|
||||||
|
<a href="/terms" class="text-blue-400">Terms of Service</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
32
views/header.ejs
Normal file
32
views/header.ejs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Raleway:wght@100..900&display=swap">
|
||||||
|
|
||||||
|
<title>
|
||||||
|
<%= title %>
|
||||||
|
</title>
|
||||||
|
|
||||||
|
<link rel='stylesheet' href='/stylesheets/style.css' />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<main class="">
|
||||||
|
<header class="bg-gray-200 w-full">
|
||||||
|
<div class="container mx-auto flex justify-between items-center text-gray-800 py-4">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<!-- <img src="/images/logo.png" alt="Logo" class="h-8 mr-2"> -->
|
||||||
|
<h1 class=""><%= title %></h1>
|
||||||
|
</div>
|
||||||
|
<nav>
|
||||||
|
<ul class="flex space-x-4">
|
||||||
|
<li><a href="/" class="text-white hover:text-gray-400">Home</a></li>
|
||||||
|
<li><a href="/about" class="text-white hover:text-gray-400">About</a></li>
|
||||||
|
<li><a href="/contact" class="text-white hover:text-gray-400">Contact</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
8
views/index.ejs
Normal file
8
views/index.ejs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<%- include('header'); -%>
|
||||||
|
|
||||||
|
<article class="container mx-auto py-4 min-h-[70dvh]">
|
||||||
|
<h2>Welcome to the <%= title %> EJS Template</h2>
|
||||||
|
<p>This is a simple example of using EJS for templating.</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<%- include('footer'); -%>
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{% extends 'layout.twig' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>{{title}}</h1>
|
|
||||||
<p>Welcome to {{title}}</p>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>{{ title }}</title>
|
|
||||||
<link rel='stylesheet' href='/stylesheets/style.css' />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{% block body %}{% endblock %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in New Issue
Block a user