Boostrap project
13
.eslintignore
Normal file
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
20
.eslintrc.cjs
Normal file
|
@ -0,0 +1,20 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
|
||||
plugins: ['svelte3', '@typescript-eslint'],
|
||||
ignorePatterns: ['*.cjs'],
|
||||
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
|
||||
settings: {
|
||||
'svelte3/typescript': () => require('typescript')
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2017: true,
|
||||
node: true
|
||||
}
|
||||
};
|
10
.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
1
.npmrc
Normal file
|
@ -0,0 +1 @@
|
|||
engine-strict=true
|
13
.prettierignore
Normal file
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
9
.prettierrc
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"pluginSearchDirs": ["."],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
26
README.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
# public-spaces.de
|
||||
|
||||
This is the code for Public Spaces e.V. website, built on [SvelteKit](https://kit.svelte.dev/) and [Ghost](https://ghost.org/).
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To create a production version of your app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
44
package.json
Normal file
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"name": "public-spaces.de",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --plugin-search-dir . --check . && eslint .",
|
||||
"format": "prettier --plugin-search-dir . --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^2.0.0",
|
||||
"@sveltejs/adapter-static": "^2.0.1",
|
||||
"@sveltejs/kit": "^1.5.0",
|
||||
"@types/luxon": "^3.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-svelte3": "^4.0.0",
|
||||
"prettier": "^2.8.0",
|
||||
"prettier-plugin-svelte": "^2.8.1",
|
||||
"svelte": "^3.54.0",
|
||||
"svelte-check": "^3.0.1",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^4.2.0"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@fontsource/roboto-flex": "^4.5.5",
|
||||
"@tryghost/content-api": "^1.11.7",
|
||||
"@types/tryghost__content-api": "^1.3.11",
|
||||
"feed": "^4.2.2",
|
||||
"lucide-svelte": "^0.130.0",
|
||||
"luxon": "^3.3.0",
|
||||
"sass": "^1.60.0",
|
||||
"simple-icons": "^8.9.0",
|
||||
"svelte-preprocess": "^5.0.3"
|
||||
}
|
||||
}
|
12
src/app.d.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
12
src/app.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
85
src/app.scss
Normal file
|
@ -0,0 +1,85 @@
|
|||
@import '@fontsource/roboto-flex/variable-full.css';
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
font-family: 'Roboto FlexVariable', 'Roboto Flex', 'RobotoVariable', 'Roboto', 'Segoe UI', Tahoma,
|
||||
Geneva, Verdana, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-stretch: 120%;
|
||||
//font-size: 1.1em;
|
||||
|
||||
@include formatting;
|
||||
}
|
||||
|
||||
:root {
|
||||
@include variables;
|
||||
}
|
||||
|
||||
/*
|
||||
Improved screen reader only CSS class
|
||||
@author Gaël Poupard
|
||||
@note Based on Yahoo!'s technique
|
||||
@author Thierry Koblentz
|
||||
@see https://developer.yahoo.com/blogs/ydn/clip-hidden-content-better-accessibility-53456.html
|
||||
* 1.
|
||||
@note `clip` is deprecated but works everywhere
|
||||
@see https://developer.mozilla.org/en-US/docs/Web/CSS/clip
|
||||
* 2.
|
||||
@note `clip-path` is the future-proof version, but not very well supported yet
|
||||
@see https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path
|
||||
@see http://caniuse.com/#search=clip-path
|
||||
@author Yvain Liechti
|
||||
@see https://twitter.com/ryuran78/status/778943389819604992
|
||||
* 3.
|
||||
@note preventing text to be condensed
|
||||
author J. Renée Beach
|
||||
@see https://medium.com/@jessebeach/beware-smushed-off-screen-accessible-text-5952a4c2cbfe
|
||||
@note Drupal 8 goes with word-wrap: normal instead
|
||||
@see https://www.drupal.org/node/2045151
|
||||
@see http://cgit.drupalcode.org/drupal/commit/?id=5b847ea
|
||||
* 4.
|
||||
@note !important is important
|
||||
@note Obviously you wanna hide something
|
||||
@author Harry Roberts
|
||||
@see https://csswizardry.com/2016/05/the-importance-of-important/
|
||||
*/
|
||||
|
||||
.sr-only {
|
||||
border: 0 !important;
|
||||
clip: rect(1px, 1px, 1px, 1px) !important; /* 1 */
|
||||
-webkit-clip-path: inset(50%) !important;
|
||||
clip-path: inset(50%) !important; /* 2 */
|
||||
height: 1px !important;
|
||||
margin: -1px !important;
|
||||
overflow: hidden !important;
|
||||
padding: 0 !important;
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
white-space: nowrap !important; /* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
Use in conjunction with .sr-only to only display content when it's focused.
|
||||
@note Useful for skip links
|
||||
@see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
|
||||
@note Based on a HTML5 Boilerplate technique, included in Bootstrap
|
||||
@note Fixed a bug with position: static on iOS 10.0.2 + VoiceOver
|
||||
@author Sylvain Pigeard
|
||||
@see https://github.com/twbs/bootstrap/issues/20732
|
||||
*/
|
||||
.sr-only-focusable:focus,
|
||||
.sr-only-focusable:active {
|
||||
clip: auto !important;
|
||||
-webkit-clip-path: none !important;
|
||||
clip-path: none !important;
|
||||
height: auto !important;
|
||||
margin: auto !important;
|
||||
overflow: visible !important;
|
||||
width: auto !important;
|
||||
white-space: normal !important;
|
||||
}
|
2
src/assets/logo/LOGO-berlin-werbefrei.svg
Normal file
After Width: | Height: | Size: 20 KiB |
408
src/assets/logo/LOGO-hamburg-werbefrei.svg
Normal file
|
@ -0,0 +1,408 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg18"
|
||||
width="1234.8944"
|
||||
height="1099.8466"
|
||||
viewBox="0 0 1234.8944 1099.8465"
|
||||
sodipodi:docname="hwf_logo.pdf"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs22">
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath46">
|
||||
<path
|
||||
d="M 0,841.89 H 1190.551 V 0 H 0 Z"
|
||||
id="path44" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="namedview20"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false" />
|
||||
<g
|
||||
id="g26"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Page 1"
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,-162.32346,1118.6181)">
|
||||
<g
|
||||
id="g28"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,438.44801,204.74473)">
|
||||
<path
|
||||
d="M 0,0 H 7.436 V -41.606 H 0 v 18.058 H -21.305 V -41.606 H -28.8 V 0 h 7.495 V -17.41 H 0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path30" />
|
||||
</g>
|
||||
<g
|
||||
id="g32"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,471.0393,171.00252)">
|
||||
<path
|
||||
d="M 0,0 H 15.226 L 7.613,17.704 Z m 21.954,-15.64 -4.19,9.738 H -2.479 l -4.19,-9.738 h -7.672 L 4.485,25.967 h 6.197 L 29.508,-15.64 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path34" />
|
||||
</g>
|
||||
<g
|
||||
id="g36"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,558.61546,204.74473)">
|
||||
<path
|
||||
d="m 0,0 h 5.96 v -41.606 h -6.727 v 27.501 l -10.977,-20.774 h -5.075 l -11.036,20.479 0.059,-27.206 h -6.728 V 0 h 6.02 l 14.281,-27.207 z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path38" />
|
||||
</g>
|
||||
<g
|
||||
id="g40">
|
||||
<g
|
||||
id="g42"
|
||||
clip-path="url(#clipPath46)">
|
||||
<g
|
||||
id="g48"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,607.84747,160.26567)">
|
||||
<path
|
||||
d="m 0,0 c 1.259,0.983 1.889,2.518 1.889,4.604 0,2.084 -0.64,3.638 -1.918,4.662 -1.28,1.022 -3.276,1.534 -5.991,1.534 H -16.642 V -1.476 H -6.02 c 2.754,0 4.76,0.493 6.02,1.476 m -16.642,16.701 h 9.62 c 5.231,0 7.848,1.948 7.848,5.843 0,1.967 -0.648,3.423 -1.947,4.367 -1.299,0.944 -3.267,1.417 -5.901,1.417 h -9.62 z M 7.111,10.446 C 8.43,8.676 9.089,6.511 9.089,3.954 c 0,-3.541 -1.27,-6.314 -3.807,-8.321 -2.538,-2.007 -6.03,-3.01 -10.475,-3.01 h -18.885 v 41.606 h 18.295 c 4.327,0 7.72,-0.955 10.179,-2.862 2.459,-1.909 3.689,-4.574 3.689,-7.997 0,-2.204 -0.58,-4.111 -1.74,-5.724 -1.161,-1.614 -2.765,-2.794 -4.811,-3.542 2.4,-0.668 4.259,-1.887 5.577,-3.658"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path50" />
|
||||
</g>
|
||||
<g
|
||||
id="g52"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,632.84759,155.74181)">
|
||||
<path
|
||||
d="M 0,0 C -2.951,2.95 -4.427,7.259 -4.427,12.924 V 37.711 H 3.01 v -25.2 c 0,-3.58 0.844,-6.285 2.537,-8.115 1.691,-1.83 4.17,-2.744 7.436,-2.744 3.226,0 5.685,0.924 7.377,2.774 1.691,1.848 2.537,4.544 2.537,8.085 v 25.2 h 7.437 V 12.924 C 30.334,7.297 28.858,2.999 25.907,0.029 22.957,-2.942 18.648,-4.427 12.983,-4.427 7.278,-4.427 2.95,-2.951 0,0"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path54" />
|
||||
</g>
|
||||
<g
|
||||
id="g56"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,712.83153,182.08333)">
|
||||
<path
|
||||
d="m 0,0 c 1.337,1.082 2.007,2.744 2.007,4.987 0,2.282 -0.67,3.944 -2.007,4.987 -1.338,1.042 -3.443,1.564 -6.314,1.564 h -9.915 V -1.623 h 9.915 c 2.871,0 4.976,0.54 6.314,1.623 M 11.213,-24.167 H 2.951 l -7.141,13.278 c -0.669,1.259 -1.496,2.145 -2.479,2.657 -0.983,0.51 -2.223,0.766 -3.718,0.766 h -5.783 v -16.701 h -7.495 v 41.606 h 18.413 c 4.721,0 8.311,-1.053 10.771,-3.157 C 7.977,12.177 9.207,9.138 9.207,5.164 9.207,1.977 8.312,-0.649 6.521,-2.715 4.73,-4.78 2.203,-6.129 -1.062,-6.757 1.141,-7.348 2.911,-8.902 4.249,-11.42 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path58" />
|
||||
</g>
|
||||
<g
|
||||
id="g60"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,778.55326,179.89807)">
|
||||
<path
|
||||
d="m 0,0 v -19.947 c -1.889,-0.945 -4.181,-1.693 -6.875,-2.243 -2.695,-0.551 -5.439,-0.827 -8.233,-0.827 -4.288,0 -8.007,0.856 -11.154,2.568 -3.148,1.711 -5.557,4.17 -7.229,7.377 -1.673,3.206 -2.509,7.012 -2.509,11.42 0,4.367 0.836,8.153 2.509,11.36 1.672,3.206 4.052,5.665 7.14,7.377 3.088,1.711 6.718,2.567 10.889,2.567 2.911,0 5.645,-0.423 8.203,-1.269 2.557,-0.846 4.682,-2.056 6.374,-3.629 L -3.423,9.266 c -1.928,1.494 -3.827,2.566 -5.695,3.215 -1.869,0.65 -3.925,0.974 -6.167,0.974 -4.289,0 -7.525,-1.268 -9.708,-3.807 -2.184,-2.537 -3.276,-6.304 -3.276,-11.3 0,-10.231 4.486,-15.345 13.456,-15.345 2.675,0 5.35,0.374 8.026,1.121 V -5.43 h -8.97 V 0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path62" />
|
||||
</g>
|
||||
<g
|
||||
id="g64"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,273.49132,128.63388)">
|
||||
<path
|
||||
d="m 0,0 h 15.244 l -30.859,-87.373 h -13.013 l -21.936,62.834 -22.061,-62.834 H -85.638 L -116.373,0 h 16.111 L -78.574,-65.065 -55.77,0 h 11.278 l 22.184,-65.437 z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path66" />
|
||||
</g>
|
||||
<g
|
||||
id="g68"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,309.72389,15.098095)">
|
||||
<path
|
||||
d="M 0,0 V 87.373 H 58.497 V 74.731 H 15.616 V 50.688 H 56.018 V 38.172 H 15.616 V 12.642 H 58.497 V 0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path70" />
|
||||
</g>
|
||||
<g
|
||||
id="g72"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,470.9269,81.04579)">
|
||||
<path
|
||||
d="m 0,0 c 2.808,2.271 4.214,5.763 4.214,10.472 0,4.791 -1.406,8.282 -4.214,10.472 -2.81,2.189 -7.231,3.285 -13.261,3.285 H -34.082 V -3.408 h 20.821 C -7.231,-3.408 -2.81,-2.273 0,0 M 23.547,-50.751 H 6.197 l -14.996,27.885 c -1.406,2.643 -3.141,4.503 -5.205,5.577 -2.067,1.073 -4.669,1.611 -7.808,1.611 h -12.146 v -35.073 h -15.739 v 87.373 h 38.667 c 9.915,0 17.453,-2.212 22.618,-6.631 5.162,-4.421 7.745,-10.803 7.745,-19.147 0,-6.693 -1.88,-12.207 -5.638,-16.545 -3.761,-4.338 -9.069,-7.169 -15.926,-8.489 4.627,-1.24 8.344,-4.505 11.154,-9.791 z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path74" />
|
||||
</g>
|
||||
<g
|
||||
id="g76"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,583.65625,35.227924)">
|
||||
<path
|
||||
d="m 0,0 c 2.643,2.064 3.966,5.287 3.966,9.667 0,4.379 -1.344,7.642 -4.028,9.791 -2.686,2.147 -6.878,3.223 -12.579,3.223 H -34.949 V -3.098 h 22.308 C -6.859,-3.098 -2.646,-2.065 0,0 m -34.949,35.073 h 20.201 c 10.987,0 16.483,4.09 16.483,12.27 0,4.131 -1.363,7.188 -4.09,9.171 -2.727,1.983 -6.859,2.974 -12.393,2.974 H -34.949 Z M 14.934,21.937 c 2.767,-3.718 4.151,-8.263 4.151,-13.633 0,-7.436 -2.664,-13.261 -7.993,-17.475 -5.329,-4.214 -12.663,-6.32 -21.998,-6.32 h -39.659 v 87.373 h 38.419 c 9.088,0 16.214,-2.004 21.379,-6.011 5.162,-4.009 7.746,-9.604 7.746,-16.793 0,-4.628 -1.221,-8.635 -3.656,-12.021 C 10.885,33.668 7.517,31.189 3.222,29.62 8.261,28.215 12.165,25.654 14.934,21.937"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path78" />
|
||||
</g>
|
||||
<g
|
||||
id="g80"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,628.42521,15.098095)">
|
||||
<path
|
||||
d="M 0,0 V 87.373 H 58.496 V 74.731 H 15.615 V 50.688 H 56.018 V 38.172 H 15.615 V 12.642 H 58.496 V 0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path82" />
|
||||
</g>
|
||||
<g
|
||||
id="g84"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,725.05052,15.098095)">
|
||||
<path
|
||||
d="M 0,0 V 87.373 H 57.257 V 74.607 H 15.739 V 50.813 H 54.778 V 38.048 H 15.739 V 0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path86" />
|
||||
</g>
|
||||
<g
|
||||
id="g88"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,881.90536,81.04579)">
|
||||
<path
|
||||
d="m 0,0 c 2.808,2.271 4.214,5.763 4.214,10.472 0,4.791 -1.406,8.282 -4.214,10.472 -2.81,2.189 -7.23,3.285 -13.261,3.285 H -34.082 V -3.408 h 20.821 C -7.23,-3.408 -2.81,-2.273 0,0 M 23.547,-50.751 H 6.196 l -14.995,27.885 c -1.406,2.643 -3.141,4.503 -5.206,5.577 -2.065,1.073 -4.668,1.611 -7.807,1.611 h -12.146 v -35.073 h -15.739 v 87.373 h 38.667 c 9.915,0 17.453,-2.212 22.618,-6.631 5.162,-4.421 7.746,-10.803 7.746,-19.147 0,-6.693 -1.881,-12.207 -5.64,-16.545 -3.76,-4.338 -9.068,-7.169 -15.924,-8.489 4.626,-1.24 8.343,-4.505 11.153,-9.791 z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path90" />
|
||||
</g>
|
||||
<g
|
||||
id="g92"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,930.37797,15.098095)">
|
||||
<path
|
||||
d="M 0,0 V 87.373 H 58.496 V 74.731 H 15.615 V 50.688 H 56.018 V 38.172 H 15.615 V 12.642 H 58.496 V 0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path94" />
|
||||
</g>
|
||||
<path
|
||||
d="m 1026.3586,128.63375 h 20.7741 V 15.098095 h -20.7741 z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path96" />
|
||||
<g
|
||||
id="g98"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,465.18534,384.28252)">
|
||||
<path
|
||||
d="m 0,0 c -2.719,-40.258 -11.772,-80.677 -25.435,-118.405 h 92.799 l -0.05,50.42 c 0,15.392 12.482,27.866 27.866,27.866 h 0.034 c 15.384,0 27.867,-12.474 27.867,-27.866 l -0.051,-50.42 h 92.8 C 202.166,-80.677 193.113,-40.258 190.394,0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path100" />
|
||||
</g>
|
||||
<g
|
||||
id="g102"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,491.16185,540.93152)">
|
||||
<path
|
||||
d="M 0,0 4.269,-7.393 8.546,0 h 8.539 l -4.27,7.4 4.27,7.393 H 8.546 L 4.269,22.186 0,14.793 H -8.539 L -4.27,7.4 -8.539,0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path104" />
|
||||
</g>
|
||||
<g
|
||||
id="g106"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,675.51016,540.93152)">
|
||||
<path
|
||||
d="M 0,0 4.277,-7.393 8.546,0 h 8.539 l -4.269,7.4 4.269,7.393 H 8.546 L 4.277,22.186 0,14.793 H -8.539 L -4.27,7.4 -8.539,0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path108" />
|
||||
</g>
|
||||
<g
|
||||
id="g110"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,458.15344,523.9271)">
|
||||
<path
|
||||
d="m 0,0 v -6.89 -6.89 -6.89 h 59.35 v 6.89 6.89 V 0 H 45.57 V -6.89 H 36.565 V 0 H 22.785 V -6.89 H 13.78 V 0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path112" />
|
||||
</g>
|
||||
<g
|
||||
id="g114"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,446.70034,388.84835)">
|
||||
<path
|
||||
d="M 0,0 H 218.845 V 13.78 H 203.566 V 79.957 H 157.148 V 13.78 H 132.562 V 79.957 H 86.144 V 13.78 H 61.698 V 79.957 H 15.28 V 13.78 H 0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path116" />
|
||||
</g>
|
||||
<g
|
||||
id="g118"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,642.50162,523.9271)">
|
||||
<path
|
||||
d="m 0,0 v -6.89 -6.89 -6.89 h 59.35 v 6.89 6.89 V 0 H 45.57 V -6.89 H 36.565 V 0 H 22.785 V -6.89 H 13.78 V 0 Z"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path120" />
|
||||
</g>
|
||||
<g
|
||||
id="g122"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,782.75914,618.09829)">
|
||||
<path
|
||||
d="m 0,0 c -0.934,1.608 -2.235,3.749 -3.956,6.345 -1.461,2.203 -3.2,4.695 -5.259,7.432 -2.581,3.434 -5.654,7.221 -9.216,11.202 -5.096,5.697 -11.211,11.773 -18.428,17.777 -2.892,2.406 -5.974,4.791 -9.221,7.138 -2.928,2.117 -5.995,4.191 -9.219,6.213 -5.679,3.56 -11.811,6.939 -18.436,10.009 -2.965,1.375 -6.05,2.668 -9.21,3.91 -2.985,1.172 -6.057,2.277 -9.22,3.31 -5.845,1.911 -11.973,3.583 -18.433,4.928 -3.009,0.626 -6.078,1.19 -9.222,1.675 -3.008,0.463 -6.08,0.859 -9.215,1.182 -2.051,0.212 -4.16,0.351 -6.265,0.498 -2.949,0.208 -5.955,0.346 -9.011,0.421 -0.07,0.036 -0.128,0.072 -0.204,0.107 -0.706,0.32 -1.693,0.609 -2.788,0.773 h 0.019 l -0.831,12.469 c -0.528,0.196 -1.492,0.291 -2.109,-0.043 l -0.677,-12.391 c -1.47,-0.192 -2.743,-0.571 -3.449,-0.919 -0.777,-0.023 -1.565,-0.023 -2.335,-0.058 -3.12,-0.14 -6.196,-0.354 -9.215,-0.664 -3.134,-0.32 -6.195,-0.752 -9.22,-1.241 -3.133,-0.507 -6.201,-1.11 -9.217,-1.785 -6.403,-1.429 -12.561,-3.187 -18.432,-5.263 -6.468,-2.288 -12.614,-4.92 -18.435,-7.811 -3.18,-1.579 -6.239,-3.246 -9.224,-4.959 -3.553,-2.04 -6.965,-4.164 -10.25,-6.343 -2.829,-1.876 -5.567,-3.791 -8.186,-5.743 -0.352,-0.263 -0.684,-0.531 -1.033,-0.795 -2.844,-2.149 -5.585,-4.323 -8.182,-6.51 -0.285,-0.24 -0.546,-0.48 -0.828,-0.721 -2.956,-2.518 -5.758,-5.041 -8.39,-7.54 -3.604,-3.423 -6.888,-6.789 -9.881,-10.025 -3.2,-3.462 -6.064,-6.773 -8.553,-9.815 -0.104,-0.127 -0.191,-0.241 -0.294,-0.367 -3.838,-4.714 -6.813,-8.77 -8.923,-11.782 -0.108,-0.155 -0.191,-0.278 -0.296,-0.427 -0.868,-1.248 -1.615,-2.344 -2.162,-3.162 -0.94,-1.407 -1.411,-2.187 -1.411,-2.187 0,0 1.532,0.906 3.869,2.175 0.7,0.382 1.454,0.784 2.285,1.219 5.929,3.094 14.738,7.195 19.893,7.262 17.891,0.259 29.909,-13.446 29.909,-13.446 0,0 15.316,14.841 34.208,14.33 18.892,-0.504 27.194,-12.549 27.194,-12.549 0,0 11.034,13.137 30.845,13.299 0.007,-6.489 0.027,-26.038 0.041,-38.164 h -3.658 v -9.07 h -7.945 v -8.818 h 7.945 v -7.822 c -10.378,-2.302 -18.144,-11.545 -18.144,-22.615 h -6.496 v -13.78 h 59.35 v 13.78 h -6.496 c 0,11.068 -7.764,20.309 -18.138,22.613 v 7.824 h 7.938 v 8.818 h -7.938 v 9.07 h -3.696 V 7.043 c 18.275,-1.016 25.926,-13.214 25.926,-13.214 0,0 17.034,12.685 33.06,12.172 16.035,-0.507 28.204,-12.172 28.204,-12.172 0,0 11.293,12.938 31.908,12.938 11.79,0 20.052,-3.237 24.978,-6.009 C -2.157,-0.154 -0.9,-1.009 0,-1.687 1.15,-2.555 1.735,-3.134 1.735,-3.134 1.735,-3.134 1.15,-1.98 0,0"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path124" />
|
||||
</g>
|
||||
<path
|
||||
d="M 363.39529,150.89829 H 375.3748 V 838.46775 H 363.39529 Z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path126" />
|
||||
<path
|
||||
d="m 334.54131,150.89829 h 11.9795 v 687.56946 h -11.9795 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path128" />
|
||||
<g
|
||||
id="g130"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,222.33641,838.46763)">
|
||||
<path
|
||||
d="M 0,0 V -529.129 H 18.237 L 18.434,0 Z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path132" />
|
||||
</g>
|
||||
<g
|
||||
id="g134"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,299.09216,838.46763)">
|
||||
<path
|
||||
d="M 0,0 V -529.129 H 18.237 L 18.434,0 Z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path136" />
|
||||
</g>
|
||||
<path
|
||||
d="m 157.64644,150.89829 h 11.9808 v 687.56946 h -11.9808 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path138" />
|
||||
<path
|
||||
d="m 186.62127,150.89829 h 11.9808 v 687.56946 h -11.9808 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path140" />
|
||||
<path
|
||||
d="m 263.38287,150.89829 h 11.97561 v 687.56946 h -11.97561 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path142" />
|
||||
<path
|
||||
d="m 122.26928,150.89829 h 23.95381 v 687.56946 h -23.95381 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path144" />
|
||||
<path
|
||||
d="m 904.53647,150.89829 h 23.95381 v 687.56946 h -23.95381 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path146" />
|
||||
<path
|
||||
d="m 1009.9156,150.89829 h 11.9795 v 687.56946 h -11.9795 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path148" />
|
||||
<path
|
||||
d="M 829.09509,150.89829 H 841.0746 V 838.46775 H 829.09509 Z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path150" />
|
||||
<path
|
||||
d="m 800.0228,150.89829 h 11.97951 V 838.46775 H 800.0228 Z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path152" />
|
||||
<path
|
||||
d="m 852.38879,150.89829 h 11.9795 v 687.56946 h -11.9795 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path154" />
|
||||
<path
|
||||
d="m 881.13362,150.89829 h 11.9795 v 687.56946 h -11.9795 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path156" />
|
||||
<path
|
||||
d="m 974.20315,150.89829 h 11.97951 v 687.56946 h -11.97951 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path158" />
|
||||
<path
|
||||
d="m 945.34917,150.89829 h 11.9795 v 687.56946 h -11.9795 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path160" />
|
||||
<path
|
||||
d="m 1033.4276,150.89829 h 11.9795 v 687.56946 h -11.9795 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29944"
|
||||
id="path162" />
|
||||
<g
|
||||
id="g164"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,567.18291,723.76027)">
|
||||
<path
|
||||
d="M 0,0 C 2.436,0.25 4.934,0.399 7.439,0.536 V 88.275 H -10.995 V -1.584 c 0.599,0.104 1.172,0.246 1.775,0.343 C -6.195,-0.752 -3.134,-0.32 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path166" />
|
||||
</g>
|
||||
<g
|
||||
id="g168"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,700.41295,697.16614)">
|
||||
<path
|
||||
d="M 0,0 V 108.741 H -18.434 V 8.714 c 2.758,-1.102 5.466,-2.239 8.07,-3.446 C -6.762,3.598 -3.317,1.832 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path170" />
|
||||
</g>
|
||||
<g
|
||||
id="g172"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,612.77948,723.69296)">
|
||||
<path
|
||||
d="M 0,0 V 88.327 H -9.219 V 0.578 C -7.64,0.507 -6.037,0.466 -4.49,0.357 -2.981,0.252 -1.49,0.127 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path174" />
|
||||
</g>
|
||||
<g
|
||||
id="g176"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,636.18168,720.31676)">
|
||||
<path
|
||||
d="M 0,0 V 90.925 H -9.219 V 1.557 C -8.493,1.455 -7.737,1.386 -7.019,1.275 -4.626,0.906 -2.313,0.453 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path178" />
|
||||
</g>
|
||||
<g
|
||||
id="g180"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,659.58388,838.46775)">
|
||||
<path
|
||||
d="m 0,0 h -9.219 v -92.895 c 3.15,-0.789 6.224,-1.646 9.219,-2.575 z"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path182" />
|
||||
</g>
|
||||
<g
|
||||
id="g184"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,758.80962,650.55717)">
|
||||
<path
|
||||
d="M 0,0 C 0.249,-0.278 0.476,-0.547 0.72,-0.823 V 144.609 H -8.498 V 8.848 C -5.401,5.841 -2.569,2.872 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path186" />
|
||||
</g>
|
||||
<g
|
||||
id="g188"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,782.75901,618.09829)">
|
||||
<path
|
||||
d="M 0,0 C 0.114,-0.196 0.196,-0.345 0.299,-0.524 V 169.589 H -8.919 V 13.371 C -6.998,10.799 -5.341,8.434 -3.956,6.345 -2.235,3.749 -0.933,1.608 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path190" />
|
||||
</g>
|
||||
<g
|
||||
id="g192"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,723.81515,682.23405)">
|
||||
<path
|
||||
d="M 0,0 V 120.232 H -9.219 V 6.282 C -6.263,4.407 -3.424,2.493 -0.719,0.537 -0.473,0.359 -0.244,0.178 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path194" />
|
||||
</g>
|
||||
<g
|
||||
id="g196"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,500.08989,705.03643)">
|
||||
<path
|
||||
d="M 0,0 C 1.382,0.646 2.808,1.251 4.218,1.871 V 102.684 H -5.001 V -2.387 c 0.448,0.229 0.876,0.472 1.329,0.697 C -2.481,-1.099 -1.218,-0.569 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path198" />
|
||||
</g>
|
||||
<g
|
||||
id="g200"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,524.0411,714.50906)">
|
||||
<path
|
||||
d="M 0,0 C 1.245,0.405 2.55,0.736 3.817,1.112 V 95.394 H -5.401 V -1.839 c 0.584,0.216 1.141,0.46 1.732,0.669 C -2.474,-0.747 -1.218,-0.396 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path202" />
|
||||
</g>
|
||||
<g
|
||||
id="g204"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,411.08786,634.20597)">
|
||||
<path
|
||||
d="M 0,0 V 157.193 H -9.219 V -12.209 c 0.105,0.15 0.188,0.272 0.296,0.427 C -6.813,-8.77 -3.838,-4.714 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path206" />
|
||||
</g>
|
||||
<g
|
||||
id="g208"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,435.42331,660.4633)">
|
||||
<path
|
||||
d="M 0,0 C 2.632,2.499 5.434,5.023 8.39,7.541 L 8.554,136.986 H -9.88 V -10.025 C -6.888,-6.789 -3.603,-3.422 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path210" />
|
||||
</g>
|
||||
<g
|
||||
id="g212"
|
||||
transform="matrix(1.2994364,0,0,1.2994364,470.01288,688.15337)">
|
||||
<path
|
||||
d="M 0,0 V 115.677 H -9.219 V -6.538 c 0.35,0.265 0.681,0.532 1.034,0.795 C -5.567,-3.791 -2.829,-1.876 0,0"
|
||||
style="fill:#444141;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path214" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 23 KiB |
BIN
src/assets/logo/LOGO-public-spaces-2.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
src/assets/logo/LOGO-public-spaces.eps
Normal file
BIN
src/assets/logo/LOGO-public-spaces.jpg
Normal file
After Width: | Height: | Size: 799 KiB |
BIN
src/assets/logo/LOGO-public-spaces.png
Normal file
After Width: | Height: | Size: 12 KiB |
1
src/assets/logo/LOGO-public-spaces.svg
Normal file
After Width: | Height: | Size: 14 KiB |
10
src/lib/server/secrets.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { env } from '$env/dynamic/private';
|
||||
|
||||
const Secrets = {
|
||||
ghost: {
|
||||
url: env.GHOST_URL || 'https://demo.ghost.io',
|
||||
key: env.GHOST_CONTENT_TOKEN || '22444f78447824223cefc48062'
|
||||
}
|
||||
};
|
||||
|
||||
export default Secrets;
|
9
src/lib/variables.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { env } from '$env/dynamic/public';
|
||||
|
||||
const Variables = {
|
||||
/*calapi: {
|
||||
query_url: env.PUBLIC_CALAPI_QUERY_URL || 'http://localhost:8080/query'
|
||||
}*/
|
||||
};
|
||||
|
||||
export default Variables;
|
82
src/routes/(feeds)/posts.[format]/+server.ts
Normal file
|
@ -0,0 +1,82 @@
|
|||
import Secrets from '$lib/server/secrets';
|
||||
import type { RequestHandler } from './$types';
|
||||
import GhostContentAPI from '@tryghost/content-api';
|
||||
import { Feed } from 'feed';
|
||||
import { DateTime } from 'luxon';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
export const trailingSlash = 'never';
|
||||
export const prerender = true;
|
||||
|
||||
export const GET: RequestHandler = async (request) => {
|
||||
//const siteBase = `${request.url.protocol}//${request.url.host}/`
|
||||
const siteBase = `https://public-spaces-preview.pages.dev/`; // TODO: Change!
|
||||
|
||||
const api = new GhostContentAPI({
|
||||
url: Secrets.ghost.url,
|
||||
key: Secrets.ghost.key,
|
||||
version: 'v5.0'
|
||||
});
|
||||
|
||||
const posts = await api.posts.browse({
|
||||
limit: 100,
|
||||
include: ['authors', 'tags']
|
||||
});
|
||||
|
||||
const feed = new Feed({
|
||||
title: 'Public Spaces e.V.',
|
||||
generator: 'Public Spaces e.V. Web',
|
||||
description: 'Die neusten Beiträge von Public Spaces e.V.',
|
||||
language: 'de-DE',
|
||||
link: siteBase,
|
||||
feedLinks: {
|
||||
rss: `${siteBase}posts.rss`,
|
||||
json: `${siteBase}posts.json`,
|
||||
atom: `${siteBase}posts.atom`
|
||||
},
|
||||
id: siteBase,
|
||||
copyright: ''
|
||||
});
|
||||
|
||||
posts.forEach((post) => {
|
||||
const date = DateTime.fromISO(post.updated_at || post.published_at || post.created_at || '');
|
||||
const datePublished = DateTime.fromISO(post.published_at || post.created_at || '');
|
||||
|
||||
feed.addItem({
|
||||
id: `${siteBase}post/${post.slug}`,
|
||||
title: post.title || '',
|
||||
link: `${siteBase}post/${post.slug}`,
|
||||
date: date.toJSDate(),
|
||||
published: datePublished.toJSDate(),
|
||||
description: post.excerpt || '',
|
||||
content: post.html || undefined,
|
||||
author: post.authors?.map((author) => {
|
||||
return {
|
||||
name: author.name
|
||||
};
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
switch (request.params.format) {
|
||||
case 'rss':
|
||||
return new Response(feed.rss2(), {
|
||||
headers: {
|
||||
'Content-Type': 'application/rss+xml'
|
||||
}
|
||||
});
|
||||
case 'atom':
|
||||
return new Response(feed.atom1(), {
|
||||
headers: {
|
||||
'Content-Type': 'application/atom+xml'
|
||||
}
|
||||
});
|
||||
case 'json':
|
||||
return new Response(feed.json1(), {
|
||||
headers: {
|
||||
'Content-Type': 'application/feed+json'
|
||||
}
|
||||
});
|
||||
}
|
||||
throw error(404, 'Ungültiges Format');
|
||||
};
|
26
src/routes/(page)/[slug]/+page.server.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import Secrets from '$lib/server/secrets';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import GhostContentAPI from '@tryghost/content-api';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
const api = new GhostContentAPI({
|
||||
url: Secrets.ghost.url,
|
||||
key: Secrets.ghost.key,
|
||||
version: 'v5.0'
|
||||
});
|
||||
|
||||
let page = null;
|
||||
|
||||
try {
|
||||
page = await api.pages.read({
|
||||
slug: params.slug
|
||||
});
|
||||
} catch (e) {
|
||||
throw error(404, 'Seite Nicht Gefunden');
|
||||
}
|
||||
|
||||
return {
|
||||
page
|
||||
};
|
||||
};
|
31
src/routes/(page)/[slug]/+page.svelte
Normal file
|
@ -0,0 +1,31 @@
|
|||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.page?.title}</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>{data.page?.title}</h1>
|
||||
</div>
|
||||
|
||||
<div class="page">
|
||||
{@html data.page?.html}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.page {
|
||||
:global {
|
||||
@include ghostContentContainer;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
@include contentGrid;
|
||||
}
|
||||
</style>
|
24
src/routes/+error.svelte
Normal file
|
@ -0,0 +1,24 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
|
||||
const texts: { [key: number]: string } = {
|
||||
0: 'Ein unbekannter Fehler ist aufgetreten',
|
||||
404: 'Die angeforderte Seite wurde leider nicht gefunden.',
|
||||
500: 'Es ist ein interner Serverfehler aufgetreten.'
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<h1>{$page.status}: {$page.error?.message}</h1>
|
||||
|
||||
<p>
|
||||
{texts[$page.status] ?? texts[0]}
|
||||
Bitte versuche es später erneut, oder gehe zurück zur <a href="/">Startseite</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
@include contentGrid;
|
||||
}
|
||||
</style>
|
298
src/routes/+layout.svelte
Normal file
|
@ -0,0 +1,298 @@
|
|||
<script lang="ts">
|
||||
import { siTwitter, siInstagram, siTelegram } from 'simple-icons';
|
||||
import { Menu, X } from 'lucide-svelte';
|
||||
import Logo from '../assets/logo/LOGO-public-spaces.svg';
|
||||
import { getContext } from 'svelte';
|
||||
import '../app.scss';
|
||||
import type { LayoutData } from './$types';
|
||||
|
||||
export let data: LayoutData;
|
||||
|
||||
let menuOpen = false;
|
||||
</script>
|
||||
|
||||
<a href="#navigation" class="sr-only sr-only-focusable a11y-jump">Zur Navigation Springen</a>
|
||||
<a href="#content" class="sr-only sr-only-focusable a11y-jump">Zum Inhalt Springen</a>
|
||||
<div class="primary">
|
||||
<nav id="navigation">
|
||||
<div>
|
||||
<div class="logo-container">
|
||||
<a href="/" class="logo-link" title="Public Spaces e.V.">
|
||||
<img src={Logo} alt="Public Spaces Logo" style={data.isHome ? "opacity: 0; transform: translate(20%, 50%)":""} />
|
||||
<span class="sr-only">Public Spaces e.V.</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class={'offscreen-nav' + (menuOpen ? ' active' : '')}>
|
||||
<a
|
||||
href="/posts"
|
||||
on:click={() => {
|
||||
menuOpen = false;
|
||||
}}>Beiträge</a
|
||||
>
|
||||
<a
|
||||
href="/about"
|
||||
on:click={() => {
|
||||
menuOpen = false;
|
||||
}}>Über Uns</a
|
||||
>
|
||||
<a
|
||||
href="/contact"
|
||||
on:click={() => {
|
||||
menuOpen = false;
|
||||
}}>Kontakt</a
|
||||
>
|
||||
</div>
|
||||
<div class="offscreen-nav-button">
|
||||
<button
|
||||
on:click={() => {
|
||||
menuOpen = !menuOpen;
|
||||
}}
|
||||
>
|
||||
{#if !menuOpen}
|
||||
<Menu size={35} />
|
||||
{/if}
|
||||
{#if menuOpen}
|
||||
<X size={35} />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="main" role="main" id="content">
|
||||
<slot />
|
||||
</div>
|
||||
<footer>
|
||||
<div class="grid">
|
||||
<div class="primary-links">
|
||||
<a href="/imprint">Impressum</a>
|
||||
<a href="/data_protection">Datenschutz</a>
|
||||
<a href="/disclaimer">Disclaimer</a>
|
||||
</div>
|
||||
<div class="border" />
|
||||
<div class="socials">
|
||||
<!--<a
|
||||
href="https://twitter.com/TODO"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
title="Twitter"
|
||||
>
|
||||
{@html siTwitter.svg}
|
||||
<span class="sr-only">Twitter @TODO</span>
|
||||
</a>
|
||||
<a
|
||||
href="https://t.me/TODO"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
title="Telegram"
|
||||
>
|
||||
{@html siTelegram.svg}
|
||||
<span class="sr-only">Telegram @TODO</span>
|
||||
</a>-->
|
||||
</div>
|
||||
<div class="border" />
|
||||
<div class="supporters">
|
||||
<span class="title">Unterstützer des Vereins</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="copy-notice">
|
||||
CC-BY-4.0 {new Date().getFullYear()}, Public Spaces e.V.
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.primary {
|
||||
@include contentGrid;
|
||||
padding-top: var(--nav-space);
|
||||
|
||||
.main {
|
||||
grid-column: full-start/full-end;
|
||||
min-height: calc(100vh - 200px);
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 4em;
|
||||
background-color: var(--color-dark-surface);
|
||||
color: var(--color-dark-surface-text);
|
||||
grid-column: full-start/full-end;
|
||||
@include contentGrid;
|
||||
|
||||
.grid {
|
||||
grid-column: wide-start/wide-end;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1px 1fr 1px 1fr;
|
||||
gap: var(--gap);
|
||||
|
||||
@media (max-width: 700px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
> .border {
|
||||
width: 1px;
|
||||
margin: 10px 0;
|
||||
background-color: currentColor;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
> :not(.border) {
|
||||
padding: var(--gap);
|
||||
}
|
||||
|
||||
.primary-links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
> a {
|
||||
color: var(--color-dark-surface-text-dim);
|
||||
}
|
||||
}
|
||||
|
||||
.supporters {
|
||||
.title {
|
||||
color: var(--color-dark-surface-text-dim);
|
||||
}
|
||||
}
|
||||
|
||||
.socials {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
a {
|
||||
padding: var(--padding);
|
||||
text-decoration: none;
|
||||
background-color: var(--color-surface);
|
||||
margin: var(--padding);
|
||||
border-radius: var(--border-radius);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
:global(svg) {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copy-notice {
|
||||
text-align: center;
|
||||
padding: var(--gap);
|
||||
}
|
||||
}
|
||||
|
||||
nav {
|
||||
@include contentGrid;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 200;
|
||||
overflow: visible;
|
||||
@include glassSurface;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
|
||||
.logo-container {
|
||||
margin-right: auto;
|
||||
|
||||
.logo-placeholder,
|
||||
img {
|
||||
transition: opacity .25s, transform .25s;
|
||||
width: 100px;
|
||||
height: 45px;
|
||||
//background-color: var(--color-placeholder);
|
||||
//border-radius: var(--border-radius);
|
||||
}
|
||||
}
|
||||
|
||||
.offscreen-nav-button {
|
||||
width: 0;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
|
||||
transition: width 0.25s, opacity 0.25s;
|
||||
|
||||
> button {
|
||||
height: 100%;
|
||||
padding: 0 var(--gap);
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.offscreen-nav-button {
|
||||
display: block;
|
||||
z-index: 300;
|
||||
pointer-events: auto;
|
||||
width: fit-content;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.offscreen-nav {
|
||||
//display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 195;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 110px;
|
||||
font-size: 1.5em;
|
||||
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
|
||||
transition: height 0.25s, opacity 0.25s;
|
||||
|
||||
@include glassSurface;
|
||||
|
||||
&.active {
|
||||
overflow: auto;
|
||||
pointer-events: auto;
|
||||
height: 100vh;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
|
||||
> a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--padding);
|
||||
text-decoration: none;
|
||||
|
||||
&.logo-link {
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.a11y-jump:focus,
|
||||
.a11y-jump:active {
|
||||
padding: var(--gap) !important;
|
||||
background-color: var(--color-background);
|
||||
z-index: 9999;
|
||||
}
|
||||
</style>
|
9
src/routes/+layout.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import type { LayoutLoad } from './$types';
|
||||
|
||||
export const load = (async ({url}) => {
|
||||
return {
|
||||
isHome: url.pathname == "/"
|
||||
};
|
||||
}) satisfies LayoutLoad;
|
||||
|
||||
export const prerender = true;
|
24
src/routes/+page.server.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import type { PageServerLoad } from './$types';
|
||||
import GhostContentAPI from '@tryghost/content-api';
|
||||
import Secrets from '$lib/server/secrets';
|
||||
|
||||
export const load: PageServerLoad = async () => {
|
||||
const api = new GhostContentAPI({
|
||||
url: Secrets.ghost.url,
|
||||
key: Secrets.ghost.key,
|
||||
version: 'v5.0'
|
||||
});
|
||||
|
||||
const posts = await api.posts.browse({
|
||||
limit: 3,
|
||||
include: ['authors', 'tags']
|
||||
});
|
||||
|
||||
const about = await api.pages.read({
|
||||
slug: 'about'
|
||||
});
|
||||
|
||||
|
||||
|
||||
return { posts, about };
|
||||
};
|
230
src/routes/+page.svelte
Normal file
|
@ -0,0 +1,230 @@
|
|||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { ChevronRight } from 'lucide-svelte';
|
||||
import { DateTime } from 'luxon';
|
||||
import { onDestroy, setContext, onMount, tick } from 'svelte';
|
||||
import Logo from '../assets/logo/LOGO-public-spaces.svg';
|
||||
import HWFLogo from '../assets/logo/LOGO-hamburg-werbefrei.svg';
|
||||
import BWFLogo from '../assets/logo/LOGO-berlin-werbefrei.svg';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Public Spaces e.V.</title>
|
||||
<meta name="title" content={'Public Spaces e.V.'} />
|
||||
<meta
|
||||
name="description"
|
||||
content={'Public Spaces ist Trägerin zweier Voksinitiativen, die sich gegen ein Übermaß von Werbung im öffentlichen Raum richten.'}
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<div class="home-runner">
|
||||
<div class="hero">
|
||||
<div class="hero-runner">
|
||||
<img src={Logo} alt="Public Spaces Logo" />
|
||||
<div class="sub-logo-split">
|
||||
<img src={BWFLogo} alt="Berlin Werbefrei Logo" />
|
||||
<img src={HWFLogo} alt="Hamburg Werbefrei Logo" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h2>Über Public Spaces e.V.</h2>
|
||||
<p>
|
||||
Hier entsteht die Webseite des Vereins Public Spaces e.V.
|
||||
</p>
|
||||
<p>
|
||||
Public Spaces ist Trägerin zweier Volksinitiativen, die sich gegen ein Übermaß von Werbung im öffentlichen Raum richten.
|
||||
</p>
|
||||
|
||||
<a href="/about" class="more-cta">Mehr über uns <ChevronRight /></a>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Neuste Beiträge</h2>
|
||||
|
||||
<div class="posts">
|
||||
{#each data.posts as post}
|
||||
<a href={`/posts/${post.slug}`}>
|
||||
{#if !post.feature_image}
|
||||
<div class="image-placeholder">?</div>
|
||||
{/if}
|
||||
{#if post.feature_image}
|
||||
<img
|
||||
src={post.feature_image}
|
||||
alt={post.feature_image_alt || post.feature_image_caption || 'Article'}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<span class="title">{post.title}</span>
|
||||
<p>{post.excerpt}</p>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<a href="/posts" class="kg-btn">Alle Beiträge sehen</a>
|
||||
<!--<a href="/about" class="more-cta">Alle Beiträge <ChevronRight/></a>-->
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.home-runner {
|
||||
@include contentGrid;
|
||||
margin-top: calc(0px - var(--nav-space));
|
||||
}
|
||||
|
||||
.kg-btn {
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.more-cta {
|
||||
margin: var(--gap) var(--gap) var(--gap) auto;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
gap: var(--padding);
|
||||
font-size: 1.2em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.posts {
|
||||
grid-column: wide-start/wide-end;
|
||||
display: flex;
|
||||
gap: var(--gap);
|
||||
margin-top: 1em;
|
||||
|
||||
> * {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
flex-direction: column;
|
||||
|
||||
> * {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
img,
|
||||
.image-placeholder {
|
||||
width: 100%;
|
||||
height: 230px;
|
||||
background-color: var(--color-dark-surface);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.image-placeholder {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 3em;
|
||||
font-weight: 600;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.75em;
|
||||
margin-top: 0.8em;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
p {
|
||||
display: -webkit-box;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hero {
|
||||
grid-column: full-start/full-end;
|
||||
max-height: max(70vmin, 500px);
|
||||
min-height: 100px;
|
||||
height: 40vmax;
|
||||
position: relative;
|
||||
|
||||
|
||||
.hero-runner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
padding-top: 50px;
|
||||
|
||||
z-index: 2;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
color: white;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
|
||||
> img {
|
||||
flex-grow: 1;
|
||||
flex-basis: 0;
|
||||
object-fit: contain;
|
||||
object-position: center;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
height: 90%;
|
||||
|
||||
opacity: 1;
|
||||
transform: translate(0, 0);
|
||||
|
||||
animation-name: homeLogoIn;
|
||||
animation-duration: .25s;
|
||||
}
|
||||
|
||||
.sub-logo-split {
|
||||
margin-top: 20px;
|
||||
height: 30%;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
max-width: var(--layout-width);
|
||||
display: flex;
|
||||
gap: var(--gap);
|
||||
justify-content: space-around;
|
||||
|
||||
> img {
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
@media(max-width: 350px) {
|
||||
flex-direction: column;
|
||||
height: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes homeLogoIn {
|
||||
0% {transform: translate(-10%, -25%); opacity: 0}
|
||||
100% {transform: translate(0, 0); opacity: 1}
|
||||
}
|
||||
</style>
|
18
src/routes/posts/+page.server.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import type { PageServerLoad } from './$types';
|
||||
import GhostContentAPI from '@tryghost/content-api';
|
||||
import Secrets from '$lib/server/secrets';
|
||||
|
||||
export const load: PageServerLoad = async () => {
|
||||
const api = new GhostContentAPI({
|
||||
url: Secrets.ghost.url,
|
||||
key: Secrets.ghost.key,
|
||||
version: 'v5.0'
|
||||
});
|
||||
|
||||
const posts = await api.posts.browse({
|
||||
limit: 100,
|
||||
include: ['authors', 'tags']
|
||||
});
|
||||
|
||||
return { posts };
|
||||
};
|
127
src/routes/posts/+page.svelte
Normal file
|
@ -0,0 +1,127 @@
|
|||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Beiträge | Public Spaces e.V.</title>
|
||||
<meta name="title" content={'Beiträge'} />
|
||||
<meta
|
||||
name="description"
|
||||
content={'Lies die neusten Beiträge von Public Spaces e.V. Hier findest du Pressemitteilungen, Artikel und andere Inhalte.'}
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<div class="container">
|
||||
<h1>Beiträge</h1>
|
||||
|
||||
<div class="posts">
|
||||
{#each data.posts as post}
|
||||
<a href={`/posts/` + post.slug}>
|
||||
<div class="feature-image">
|
||||
{#if post.feature_image}
|
||||
<img
|
||||
src={post.feature_image}
|
||||
alt={post.feature_image_alt ||
|
||||
post.feature_image_caption ||
|
||||
post.title ||
|
||||
'Feature Image'}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="details">
|
||||
<span class="title">{post.title}</span>
|
||||
<span class="meta">
|
||||
{#each post.authors || [] as author, i}
|
||||
{i > 0 ? ' & ' : ''}<span>{author.name}</span>
|
||||
{/each} ·
|
||||
<span
|
||||
>{DateTime.fromISO(post.published_at || post.created_at || '2001-11-03')
|
||||
.setLocale('de-DE')
|
||||
.toLocaleString(DateTime.DATE_FULL)}</span
|
||||
>
|
||||
·
|
||||
<span
|
||||
>Ca. {post.reading_time || post.reading_time === 0
|
||||
? Math.max(1, post.reading_time) + ' Min.'
|
||||
: 'Unbekannte'} Lesezeit</span
|
||||
>
|
||||
</span>
|
||||
{#if post.custom_excerpt || post.excerpt}
|
||||
<p class="excerpt">
|
||||
{(post.custom_excerpt || post.excerpt)?.replaceAll('\n', ' ')}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
@include contentGrid;
|
||||
}
|
||||
|
||||
.posts {
|
||||
> a {
|
||||
display: flex;
|
||||
gap: var(--gap);
|
||||
padding: var(--gap) 0;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
display: block;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
|
||||
border-bottom: thin solid var(--color-border);
|
||||
}
|
||||
|
||||
> .feature-image {
|
||||
--size: 150px;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
flex-shrink: 0;
|
||||
|
||||
> img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
}
|
||||
|
||||
> .details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> .title {
|
||||
font-size: 1.6em;
|
||||
font-weight: 600;
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
> .meta {
|
||||
opacity: 0.75;
|
||||
margin-top: 5px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
> .excerpt {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
29
src/routes/posts/[slug]/+page.server.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import type { PageServerLoad } from './$types';
|
||||
import GhostContentAPI from '@tryghost/content-api';
|
||||
import Secrets from '$lib/server/secrets';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
const api = new GhostContentAPI({
|
||||
url: Secrets.ghost.url,
|
||||
key: Secrets.ghost.key,
|
||||
version: 'v5.0'
|
||||
});
|
||||
|
||||
let post = null;
|
||||
|
||||
try {
|
||||
post = await api.posts.read(
|
||||
{
|
||||
slug: params.slug
|
||||
},
|
||||
{ include: ['tags', 'authors'] }
|
||||
);
|
||||
} catch (e) {
|
||||
throw error(404, 'Artikel Nicht Gefunden');
|
||||
}
|
||||
|
||||
return {
|
||||
post
|
||||
};
|
||||
};
|
216
src/routes/posts/[slug]/+page.svelte
Normal file
|
@ -0,0 +1,216 @@
|
|||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Globe } from 'lucide-svelte';
|
||||
import { siTwitter } from 'simple-icons';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
$: publishTime = DateTime.fromISO(data.post.published_at || data.post.created_at || '2001-11-03');
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.post.title}</title>
|
||||
<meta name="title" content={data.post.meta_title || data.post.title} />
|
||||
<meta
|
||||
name="description"
|
||||
content={data.post.meta_description || data.post.custom_excerpt || data.post.excerpt}
|
||||
/>
|
||||
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@todo" /> <!-- TODO: Change me. -->
|
||||
<meta
|
||||
name="twitter:title"
|
||||
content={data.post.twitter_title || data.post.meta_title || data.post.title}
|
||||
/>
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content={data.post.twitter_description ||
|
||||
data.post.meta_description ||
|
||||
data.post.custom_excerpt ||
|
||||
data.post.excerpt}
|
||||
/>
|
||||
<meta name="twitter:image" content={data.post.twitter_image || data.post.feature_image} />
|
||||
|
||||
<meta property="og:type" content="article" />
|
||||
<meta
|
||||
property="og:title"
|
||||
content={data.post.og_title || data.post.meta_title || data.post.title}
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content={data.post.og_description ||
|
||||
data.post.meta_description ||
|
||||
data.post.custom_excerpt ||
|
||||
data.post.excerpt}
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content={data.post.og_image || data.post.twitter_image || data.post.feature_image}
|
||||
/>
|
||||
<meta property="article:published_time" content={data.post.published_at} />
|
||||
{#if data.post.updated_at}
|
||||
<meta property="article:modified_time" content={data.post.updated_at} />
|
||||
{/if}
|
||||
{#if data.post.primary_tag}
|
||||
<meta
|
||||
property="article:section"
|
||||
content={data.post.primary_tag.og_title || data.post.primary_tag.name}
|
||||
/>
|
||||
{/if}
|
||||
{@html `<script type="application/ld+json">${JSON.stringify({
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Article',
|
||||
headline: data.post.title,
|
||||
image: data.post.feature_image,
|
||||
datePublished: data.post.published_at,
|
||||
dateModified: data.post.updated_at,
|
||||
author: data.post.authors?.map((author) => {
|
||||
return {
|
||||
'@type': 'Person',
|
||||
name: author.name
|
||||
};
|
||||
})
|
||||
})}</script>`}
|
||||
</svelte:head>
|
||||
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>{data.post?.title}</h1>
|
||||
<span class="meta">
|
||||
<span>{publishTime.setLocale('de-DE').toLocaleString(DateTime.DATE_FULL)}</span> ·
|
||||
<span
|
||||
>Ca. {data.post.reading_time || data.post.reading_time === 0
|
||||
? Math.max(1, data.post.reading_time) + ' Min.'
|
||||
: 'Unbekannte'} Lesezeit</span
|
||||
>
|
||||
·
|
||||
<span>
|
||||
{#each data.post.tags || [] as tag, i}
|
||||
{i > 0 ? ', ' : ''}<span>{tag.name}</span><!--href={`/posts/` + tag.slug}-->
|
||||
{/each}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
{#if data.post.feature_image}
|
||||
<div class="feature-image">
|
||||
<figure>
|
||||
<img src={data.post.feature_image} alt={data.post.feature_image_alt || 'Feature Image'} />
|
||||
<figcaption>{@html data.post.feature_image_caption||""}</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="article">
|
||||
{@html data.post?.html}
|
||||
|
||||
<!--<pre>{JSON.stringify(data.post, null, 2)}</pre>-->
|
||||
</div>
|
||||
|
||||
<div class="authors">
|
||||
<hr />
|
||||
{#each data.post.authors || [] as author}
|
||||
<div class="author">
|
||||
<div class="pic">
|
||||
{#if author.profile_image}
|
||||
<img src={author.profile_image} alt={'Profilbild von ' + author.name} />
|
||||
{/if}
|
||||
{#if !author.profile_image}
|
||||
<div class="photo-placeholder" />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="meta">
|
||||
<span class="name">{author.name}</span>
|
||||
<p>{author.bio || ''}</p>
|
||||
<div class="links">
|
||||
{#if author.website}
|
||||
<a href={author.website}><Globe /> {new URL(author.website).host}</a>
|
||||
{/if}
|
||||
{#if author.twitter}
|
||||
<a href={'https://twitter.com/' + author.twitter} class="twitter"
|
||||
>{@html siTwitter.svg} {author.twitter}</a
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.article {
|
||||
:global {
|
||||
@include ghostContentContainer;
|
||||
}
|
||||
}
|
||||
|
||||
.authors {
|
||||
@include contentGrid;
|
||||
|
||||
.author {
|
||||
display: flex;
|
||||
gap: var(--gap);
|
||||
margin-bottom: var(--gap);
|
||||
|
||||
> * {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.pic {
|
||||
width: 125px;
|
||||
|
||||
img,
|
||||
.photo-placeholder {
|
||||
width: 125px;
|
||||
height: 125px;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
background-color: var(--color-dark-surface);
|
||||
}
|
||||
}
|
||||
|
||||
.meta {
|
||||
width: 0;
|
||||
flex-grow: 1;
|
||||
padding: var(--padding);
|
||||
.name {
|
||||
font-size: 2em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.links {
|
||||
display: flex;
|
||||
gap: var(--gap);
|
||||
a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
:global(svg) {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
margin-right: var(--padding);
|
||||
}
|
||||
|
||||
&.twitter {
|
||||
:global(svg) {
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
@include articleHeader;
|
||||
}
|
||||
</style>
|
668
src/variables.scss
Normal file
|
@ -0,0 +1,668 @@
|
|||
/* Variables and mixins declared here will be available in all other SCSS files */
|
||||
@mixin ghostContentContainer {
|
||||
@include contentGrid;
|
||||
@include formatting;
|
||||
}
|
||||
|
||||
@mixin glassSurface {
|
||||
background-color: var(--color-background);
|
||||
|
||||
@supports (backdrop-filter: blur(10px)) {
|
||||
backdrop-filter: blur(10px);
|
||||
background-color: var(--color-glass-surface);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin articleHeader {
|
||||
@include contentGrid;
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.meta {
|
||||
text-align: center;
|
||||
opacity: 0.75;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.feature-image {
|
||||
//grid-column: wide-start/wide-end;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin variables {
|
||||
--nav-space: 120px;
|
||||
|
||||
--color-placeholder: gray;
|
||||
|
||||
--color-glass-surface: rgba(255, 255, 255, 0.75);
|
||||
|
||||
--color-background: white;
|
||||
--color-text: #1c1c1c;
|
||||
--color-accent: #1c1c1c;
|
||||
--color-accent-contrast: white;
|
||||
--color-border: rgba(0, 0, 0, 0.2);
|
||||
--color-surface: rgba(127, 127, 127, 0.15);
|
||||
--color-dark-surface: rgba(0, 0, 0, 0.9);
|
||||
--color-dark-surface-text: white;
|
||||
--color-dark-surface-text-dim: #808080;
|
||||
--color-light-surface: rgba(255, 255, 255, 0.9);
|
||||
--color-light-surface-text: var(--color-text);
|
||||
--color-accent-surface: var(--color-accent);
|
||||
--color-accent-surface-text: white;
|
||||
--color-highlight-blue: rgba(10, 10, 255, 0.2);
|
||||
--color-highlight-white: rgba(200, 200, 200, 0.2);
|
||||
--color-highlight-grey: rgba(100, 100, 100, 0.2);
|
||||
--color-highlight-yellow: rgba(255, 230, 10, 0.2);
|
||||
--color-highlight-green: rgba(10, 255, 10, 0.2);
|
||||
--color-highlight-red: rgba(255, 10, 10, 0.2);
|
||||
--color-highlight-pink: rgba(255, 128, 255, 0.2);
|
||||
--color-highlight-purple: rgba(204, 30, 152, 0.2);
|
||||
--border-radius: 5px;
|
||||
|
||||
--gap: 20px;
|
||||
--padding: 10px;
|
||||
--layout-width: 720px;
|
||||
|
||||
--shadow-elevated: 4px 6px 20px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
@mixin contentGrid {
|
||||
display: grid;
|
||||
max-width: 100vw;
|
||||
overflow: hidden;
|
||||
|
||||
> * {
|
||||
max-width: min(100vw, 100%);
|
||||
}
|
||||
|
||||
grid-template-columns:
|
||||
[full-start] minmax(max(4vmin, var(--gap)), auto)
|
||||
[wide-start] minmax(auto, 240px)
|
||||
[main-start] min(var(--layout-width), calc(100% - max(8vmin, calc(var(--gap) * 2))))
|
||||
[main-end] minmax(auto, 240px)
|
||||
[wide-end] minmax(max(4vmin, var(--gap)), auto)
|
||||
[full-end];
|
||||
|
||||
> :global(*) {
|
||||
grid-column: main-start/main-end;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin button {
|
||||
text-decoration: none;
|
||||
background-color: var(--color-dark-surface);
|
||||
color: var(--color-dark-surface-text);
|
||||
display: inline-block;
|
||||
width: fit-content;
|
||||
margin: 0 auto;
|
||||
padding: 10px 20px;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
@mixin formatting {
|
||||
color: var(--color-text);
|
||||
|
||||
a,
|
||||
abbr,
|
||||
acronym,
|
||||
address,
|
||||
applet,
|
||||
article,
|
||||
aside,
|
||||
audio,
|
||||
big,
|
||||
blockquote,
|
||||
body,
|
||||
canvas,
|
||||
caption,
|
||||
cite,
|
||||
code,
|
||||
dd,
|
||||
del,
|
||||
details,
|
||||
dfn,
|
||||
div,
|
||||
dl,
|
||||
dt,
|
||||
em,
|
||||
embed,
|
||||
fieldset,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
form,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
header,
|
||||
hgroup,
|
||||
html,
|
||||
iframe,
|
||||
img,
|
||||
ins,
|
||||
kbd,
|
||||
label,
|
||||
legend,
|
||||
li,
|
||||
mark,
|
||||
menu,
|
||||
nav,
|
||||
object,
|
||||
ol,
|
||||
output,
|
||||
p,
|
||||
pre,
|
||||
q,
|
||||
ruby,
|
||||
s,
|
||||
samp,
|
||||
section,
|
||||
small,
|
||||
span,
|
||||
strike,
|
||||
strong,
|
||||
sub,
|
||||
summary,
|
||||
sup,
|
||||
table,
|
||||
tbody,
|
||||
td,
|
||||
tfoot,
|
||||
th,
|
||||
thead,
|
||||
time,
|
||||
tr,
|
||||
tt,
|
||||
ul,
|
||||
var,
|
||||
video {
|
||||
border: 0;
|
||||
font: inherit;
|
||||
font-size: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.7em;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: 400;
|
||||
margin-bottom: 0.5em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1.15em;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-bottom: thin dotted var(--color-border);
|
||||
margin: 40px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--color-accent);
|
||||
text-decoration: underline dotted currentColor;
|
||||
}
|
||||
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
dl {
|
||||
padding: 0 20px;
|
||||
|
||||
dt {
|
||||
color: var(--color-accent);
|
||||
font-weight: 600;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 20px 10px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
display: inline-block;
|
||||
overflow-x: auto;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
width: auto;
|
||||
|
||||
tr th {
|
||||
border: 1px solid var(--color-border);
|
||||
padding: 10px 16px;
|
||||
background-color: var(--color-surface);
|
||||
}
|
||||
|
||||
tr td {
|
||||
border: 1px solid var(--color-border);
|
||||
padding: 10px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-size: 1em;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: var(--color-dark-surface);
|
||||
color: var(--color-dark-surface-text);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
:not(pre) > code,
|
||||
kbd {
|
||||
padding: 0.48em 0.5em;
|
||||
line-height: 1em;
|
||||
display: inline-block;
|
||||
background-color: var(--color-surface);
|
||||
border: thin solid var(--color-border);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
kbd {
|
||||
font-weight: 200;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
:not(pre) > code {
|
||||
background-color: var(--color-surface);
|
||||
border: thin solid var(--color-border);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
blockquote:not([class]) {
|
||||
font-style: italic;
|
||||
padding: 0.5em 2em;
|
||||
position: relative;
|
||||
margin: 1em 0;
|
||||
|
||||
cite {
|
||||
display: block;
|
||||
margin-top: 0.75em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
background: var(--color-accent);
|
||||
left: -1em;
|
||||
width: 0.2em;
|
||||
}
|
||||
}
|
||||
|
||||
mark {
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -0.2em;
|
||||
left: -0.2em;
|
||||
right: -0.2em;
|
||||
bottom: -0.2em;
|
||||
background-color: var(--color-accent);
|
||||
opacity: 0.25;
|
||||
transform: skew(-6deg);
|
||||
}
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 0.5;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25rem;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.25rem;
|
||||
}
|
||||
|
||||
figure {
|
||||
max-width: 100%;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
> figcaption {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.4em;
|
||||
padding: 1.1em 1.5em 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.kg-gallery-container {
|
||||
.kg-gallery-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
gap: var(--gap);
|
||||
margin: var(--gap) 0;
|
||||
|
||||
.kg-gallery-image {
|
||||
> img {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.kg-embed-card {
|
||||
iframe {
|
||||
width: 100%;
|
||||
min-height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.kg-card {
|
||||
&.kg-style-dark {
|
||||
background-color: var(--color-dark-surface);
|
||||
color: var(--color-dark-surface-text);
|
||||
}
|
||||
&.kg-style-light {
|
||||
background-color: var(--color-light-surface);
|
||||
color: var(--color-light-surface-text);
|
||||
}
|
||||
&.kg-style-accent {
|
||||
background-color: var(--color-accent-surface);
|
||||
color: var(--color-accent-surface-text);
|
||||
}
|
||||
&.kg-style-image {
|
||||
color: white;
|
||||
text-shadow: 0 0 10px black;
|
||||
}
|
||||
}
|
||||
|
||||
.kg-align-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.kg-align-left {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.kg-align-right {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.kg-callout-card {
|
||||
display: flex;
|
||||
border-radius: var(--border-radius);
|
||||
margin: 2em 0;
|
||||
overflow: hidden;
|
||||
|
||||
background-color: var(--bg);
|
||||
|
||||
.kg-callout-emoji {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--gap);
|
||||
font-size: 2em;
|
||||
|
||||
background-color: var(--bg);
|
||||
}
|
||||
|
||||
.kg-callout-text {
|
||||
//display: flex;
|
||||
padding: var(--gap);
|
||||
/*align-items: center;*/
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
&.kg-callout-card-blue {
|
||||
--bg: var(--color-highlight-blue);
|
||||
}
|
||||
|
||||
&.kg-callout-card-white {
|
||||
--bg: var(--color-highlight-white);
|
||||
}
|
||||
|
||||
&.kg-callout-card-grey {
|
||||
--bg: var(--color-highlight-grey);
|
||||
}
|
||||
|
||||
&.kg-callout-card-yellow {
|
||||
--bg: var(--color-highlight-yellow);
|
||||
}
|
||||
|
||||
&.kg-callout-card-green {
|
||||
--bg: var(--color-highlight-green);
|
||||
}
|
||||
|
||||
&.kg-callout-card-red {
|
||||
--bg: var(--color-highlight-red);
|
||||
}
|
||||
|
||||
&.kg-callout-card-pink {
|
||||
--bg: var(--color-highlight-pink);
|
||||
}
|
||||
|
||||
&.kg-callout-card-purple {
|
||||
--bg: var(--color-highlight-purple);
|
||||
}
|
||||
|
||||
&.kg-callout-card-accent {
|
||||
--bg: var(--color-accent-surface);
|
||||
color: var(--color-accent-surface-text);
|
||||
}
|
||||
}
|
||||
|
||||
.kg-btn {
|
||||
@include button;
|
||||
background-color: var(--color-accent-surface);
|
||||
color: var(--color-accent-surface-text);
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.kg-header-card-button {
|
||||
@include button;
|
||||
}
|
||||
|
||||
.kg-header-card {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 7em 0;
|
||||
margin: 5em 0;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--gap);
|
||||
|
||||
.kg-header-card-header {
|
||||
font-size: 4em;
|
||||
font-weight: 800;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.kg-header-card-subheader {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.kg-width-full {
|
||||
grid-column: full-start/full-end;
|
||||
|
||||
img {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.kg-width-wide {
|
||||
grid-column: wide-start/wide-end;
|
||||
}
|
||||
|
||||
figure.kg-bookmark-card {
|
||||
a {
|
||||
display: flex;
|
||||
border-radius: var(--border-radius);
|
||||
border: thin solid var(--color-border);
|
||||
overflow: hidden;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
|
||||
.kg-bookmark-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
flex-basis: 100%;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
padding: var(--gap);
|
||||
overflow: hidden;
|
||||
|
||||
.kg-bookmark-title {
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.4em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.kg-bookmark-description {
|
||||
display: -webkit-box;
|
||||
line-height: 1.5em;
|
||||
margin-top: 3px;
|
||||
font-weight: 400;
|
||||
max-height: 44px;
|
||||
overflow-y: hidden;
|
||||
opacity: 0.7;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.kg-bookmark-metadata {
|
||||
display: flex;
|
||||
margin-top: 2em;
|
||||
white-space: nowrap;
|
||||
|
||||
> img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
> span {
|
||||
opacity: 0.7;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
max-width: 240px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.kg-bookmark-publisher::before {
|
||||
content: '•';
|
||||
margin: 0 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.kg-bookmark-thumbnail {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
min-width: 33%;
|
||||
|
||||
> img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
static/favicon.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
33
svelte.config.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
//import adapter from '@sveltejs/adapter-auto';
|
||||
import adapter from '@sveltejs/adapter-static';
|
||||
import { vitePreprocess } from '@sveltejs/kit/vite';
|
||||
import preprocess from 'svelte-preprocess';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
||||
// for more information about preprocessors
|
||||
preprocess: [
|
||||
vitePreprocess(),
|
||||
preprocess({
|
||||
scss: {
|
||||
prependData: '@use "src/variables.scss" as *;'
|
||||
},
|
||||
preserve: ['ld+json']
|
||||
})
|
||||
],
|
||||
|
||||
kit: {
|
||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
||||
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||
adapter: adapter({
|
||||
|
||||
}),
|
||||
prerender: {
|
||||
entries: ['*', '/posts.rss', '/posts.atom', '/posts.json']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
17
tsconfig.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true
|
||||
}
|
||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||
//
|
||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||
}
|
13
vite.config.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()],
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
additionalData: '@use "src/variables.scss" as *;'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|