Compare commits

...

191 commits

Author SHA1 Message Date
SevicheCC
55648926cc
update url 2025-01-01 16:24:22 +08:00
SevicheCC
14eca348d5
post modify 2024-10-30 02:30:30 +08:00
SevicheCC
ec77b7991c
new post 2024-10-29 02:36:58 +08:00
SevicheCC
f89931db5e
new friend 2024-10-27 13:45:52 +08:00
SevicheCC
351defae29
test fish 2024-10-21 19:12:52 +08:00
SevicheCC
7f991888c8
update about 2024-10-21 10:39:57 +08:00
SevicheCC
88c2451f1c
test fish 2024-10-15 21:00:00 +08:00
SevicheCC
44161293b1
test fish 2024-10-15 12:05:21 +08:00
SevicheCC
6857d0db43
fix css 2024-10-15 11:59:36 +08:00
SevicheCC
709a0ecced
fix url 2024-10-15 00:45:49 +08:00
SevicheCC
d2a4de22ec
fix:empty file 2024-10-15 00:16:12 +08:00
SevicheCC
163636db1c
new post 2024-10-14 23:53:58 +08:00
SevicheCC
fc3dc11a6c
fix typo 2024-09-15 03:41:53 +08:00
SevicheCC
d26faa908c
fix typo 2024-09-15 00:03:54 +08:00
SevicheCC
605955c529
new post 2024-09-14 23:03:53 +08:00
SevicheCC
688f43a179
fix post title 2024-02-23 21:37:04 +08:00
SevicheCC
cfbd3e80dc
update post text 2024-02-23 21:19:02 +08:00
SevicheCC
73ba867450
new post 2024-02-23 21:13:12 +08:00
SevicheCC
8184b22820
new post * 2 2024-01-22 21:01:46 +08:00
SevicheCC
b111507444
new post 2023-10-27 21:11:03 +08:00
SevicheCC
c1f5625dfc
new friend 2023-10-27 21:10:50 +08:00
SevicheCC
75c75e6eb0
fix typo and missing sentence 2023-09-10 22:11:28 +08:00
SevicheCC
c625f93890
new post 2023-09-10 20:41:25 +08:00
SevicheCC
9246a9e62a
chore(deps): update nelify cli 2023-09-10 20:39:47 +08:00
SevicheCC
caa4ee96ee
new post 2023-09-04 22:08:27 +08:00
SevicheCC
bd40930dd1
fix typo 2023-09-01 23:34:18 +08:00
SevicheCC
5f0f13791f
update project 2023-09-01 23:32:42 +08:00
SevicheCC
81b2dfe5eb
add new post 2023-08-27 19:16:38 +08:00
SevicheCC
044ee42fbd
Update netlify-cli 2023-08-16 13:41:31 +08:00
SevicheCC
de1c154c5a
Update Friend's name 2023-08-16 13:41:17 +08:00
SevicheCC
bf1cf00372
remove comment parade 2023-08-02 00:49:21 +08:00
SevicheCC
e4c443f5de
update friends link 2023-05-29 10:30:38 +08:00
SevicheCC
6b9f76c2f4
update friends link 2023-05-28 21:19:24 +08:00
SevicheCC
d608d52f96
update friends url 2023-05-28 21:04:05 +08:00
SevicheCC
b99e3bbce4
fix: pwa build error 2023-05-28 02:35:24 +08:00
SevicheCC
51001b4c9a
fix: http font 2023-05-28 01:38:05 +08:00
SevicheCC
bcbcc19cc4
add post detail about gpt 2023-05-19 21:56:11 +08:00
SevicheCC
c172e458dd
update deps & add links 2023-05-19 21:24:54 +08:00
SevicheCC
d3d15f2319
new post 2023-05-19 01:56:33 +08:00
SevicheCC
893b52a54c
fix giscus style 2023-05-10 14:31:42 +08:00
SevicheCC
c6ee95ed14
update default theme 2023-05-09 16:28:45 +08:00
SevicheCC
1a4d315dc8
compress avatar 2023-05-09 16:16:50 +08:00
SevicheCC
f012cd49df
update deps 2023-05-09 16:04:33 +08:00
SevicheCC
3a101d930d
add whitespace 2023-05-09 02:06:17 +08:00
SevicheCC
d368b27ccb
update personal info 2023-05-09 01:58:33 +08:00
SevicheCC
b55b7e743e
merge with upstream 3f449443be 2023-05-09 01:43:16 +08:00
SevicheCC
f61de8a4ef
new posts and remark42 2023-05-09 00:55:32 +08:00
sevichecc
3eee6f2e08
post: 🔨 fix indent 2023-02-16 01:19:23 +08:00
sevichecc
9a4524334b
post: 🔨 fix referenct 2023-02-16 00:47:24 +08:00
sevichecc
e6121d7ce6
post: 🔨remove emoji 2023-02-16 00:27:01 +08:00
sevichecc
5fa39eff5f
post: new post about tools 2023-02-16 00:20:09 +08:00
sevichecc
dfe8c3c86b
chore: ♻️ expand build space 2023-02-04 11:57:44 +08:00
sevichecc
3b0f1e0054
post: 🔨 little tweaks 2023-02-04 11:56:49 +08:00
sevichecc
bc1a63a3c6
post: ♻️ refactor content 2023-02-04 00:05:09 +08:00
sevichecc
ba77428863
post: 🧼 make some improvement 2023-02-03 23:49:21 +08:00
sevichecc
6887d2d2f4
post: 🔨 missing url 2023-02-03 23:47:17 +08:00
sevichecc
67fc487ebd
refactor: ♻️ remove deploy test 2023-02-03 23:40:54 +08:00
sevichecc
76c25dca25
chore: ⬆️ merge with upsteam 8ce01f4b70 2023-02-03 23:39:47 +08:00
sevichecc
8e03d5a6f9
chore: ⬆️ merge with upsteam a8e5c55228 2023-02-03 23:37:25 +08:00
sevichecc
43fa4b6f1d
fix: 🔨 losing image 2023-02-03 23:29:04 +08:00
sevichecc
5839788ec5
chore: ⬆️ update devpendencies 2023-02-03 21:37:22 +08:00
sevichecc
7caf081bf0
post: 🔨 little tweaks 2023-02-03 21:36:47 +08:00
sevichecc
ce5cb61e4a
post: 🔖 monthly reading 2023-02-03 21:35:36 +08:00
sevichecc
89e26218da
post:🔨 update release version 2023-02-01 15:33:00 +08:00
sevichecc
f88ed05c3a
post: ♻️ rewrite 2023-02-01 15:27:19 +08:00
sevichecc
ea843494dd
refactor: ♻️ weaken the action buttons 2023-01-30 17:28:52 +08:00
sevichecc
3b91c65936
format code 2023-01-30 13:53:06 +08:00
sevichecc
40468ba170
🔨 decrese the card shadow and remove image shadow 2023-01-30 13:42:38 +08:00
sevichecc
34a9bb8bc7
update deploy script 2023-01-30 00:39:24 +08:00
sevichecc
09304b5ff2
new post 2023-01-30 00:01:05 +08:00
sevichecc
fd852e8662
replace image source 2023-01-29 18:13:40 +08:00
sevichecc
01ef65192c
add footer since date 2023-01-29 18:13:00 +08:00
sevichecc
2dc0ae6a29
merge with upsteam 89d8512758 2023-01-27 17:39:56 +08:00
sevichecc
c62a1d3d9c
merge with upsteam 055d890c79 (diff-02b812f3ec51006878cda37f92a36abc785ee5518b84340ce4a7ed41051c93f0) 2023-01-26 00:45:59 +08:00
sevichecc
c86396d231
merge with upsteam 455fcd5941 2023-01-26 00:43:14 +08:00
sevichecc
8f026e2f82
merge with upsteam 5731381edb 2023-01-26 00:39:09 +08:00
sevichecc
97a7368f78
merge with upsteam 7f6cc6bc09 2023-01-26 00:30:36 +08:00
sevichecc
8f785854a2
merge with upsteam 950fc38068 2023-01-26 00:22:34 +08:00
sevichecc
2495dc7278
merge with upsteam 2ef763fc34 2023-01-26 00:15:28 +08:00
sevichecc
3bb83c69db
merge with upsteam 35b3514bd8 2023-01-26 00:10:01 +08:00
sevichecc
6b0931e36f
merge with upsteam 29b6cc4abd 2023-01-26 00:07:15 +08:00
sevichecc
cccd540138
merge with upsteam 85d1b5d057 2023-01-26 00:05:50 +08:00
sevichecc
fd675ffba6
merge with upsteam 16c08d841c 2023-01-26 00:03:16 +08:00
sevichecc
e1192c07c9
merge with upsteam 93bfad5146 2023-01-25 23:55:50 +08:00
sevichecc
fcdd5e5b8b
merge with upsteam 07f4ac77bc 2023-01-25 23:49:28 +08:00
sevichecc
4a4437fa89
fix typo 2023-01-22 11:56:09 +08:00
sevichecc
54ef29e9df
update README 2023-01-22 03:04:43 +08:00
sevichecc
3117fea376
new psot 2023-01-22 03:03:34 +08:00
sevichecc
f9900cf2ce
fix blockquote inline style 2023-01-13 18:29:16 +08:00
sevichecc
6b9ddc6515
fix wrong newline marker 2023-01-13 18:17:19 +08:00
sevichecc
d9bab31169
expand node space size 2023-01-13 18:16:31 +08:00
sevichecc
7ca12e188f
test rollup override 2023-01-13 17:56:10 +08:00
sevichecc
65742201d7
add new line 2023-01-13 17:44:07 +08:00
sevichecc
3dcc661557
fix wrong codeblock 2023-01-13 16:09:18 +08:00
sevichecc
412977735d
new post 2023-01-13 15:58:43 +08:00
sevichecc
fea2bb0eb7
Merge branch 'main' of https://github.com/Sevichecc/Urara-Blog 2023-01-13 15:56:11 +08:00
sevichecc
46c00bd873
new post 2023-01-13 15:55:34 +08:00
sevichecc
7db3e8e84c
new post 2023-01-09 12:59:38 +08:00
a820252f19
change the key's path 2023-01-08 01:13:40 +08:00
896ca068b7
fix typo 2023-01-07 22:12:11 +08:00
ebcc44815d
update post detail 2023-01-06 19:20:18 +08:00
39101d900b
revert packeage version 2023-01-01 21:54:52 +08:00
93f88e280e
update dependency and update post 2023-01-01 21:28:57 +08:00
60e4c8e2a9
new post 2023-01-01 21:15:22 +08:00
656c3846b9
add tags 2022-12-31 16:13:41 +08:00
1fc6d7059c
fix format 2022-12-30 17:06:29 +08:00
d794908974
add newsletter post 2022-12-30 16:56:04 +08:00
0aab4b206c
fix typo 2022-12-27 17:04:47 +08:00
6c025d206a
update project 2022-12-27 16:44:46 +08:00
sevichecc
f6d906fbc5
replace the bookmark link 2022-12-26 17:08:33 +08:00
sevichecc
a1229cc818
update 2022-12-26 16:21:57 +08:00
sevichecc
66f7be3031 typo 2022-12-23 15:06:50 +08:00
sevichecc
dc2dde8179 update post 2022-12-22 17:24:29 +08:00
sevichecc
f2a72ff665 update post 2022-12-22 17:11:59 +08:00
sevichecc
a4b09a51b5 revert u-photo 2022-12-22 00:20:41 +08:00
sevichecc
5ac936411d compress images 2022-12-22 00:12:20 +08:00
sevichecc
a552789045 update dependecies 2022-12-22 00:12:05 +08:00
sevichecc
8063db4288 add webring 2022-12-22 00:11:53 +08:00
sevichecc
66e70995ff update post 2022-12-21 01:49:06 +08:00
sevichecc
78f03b17af revert heti 2022-12-21 00:24:30 +08:00
sevichecc
8bb2dfba88 update snow and heti 2022-12-20 23:43:46 +08:00
sevichecc
fb398f01e5 new friends 2022-12-20 14:07:15 +08:00
sevichecc
5fbfeb2a14 update post 2022-12-20 14:03:38 +08:00
sevichecc
3da4beb5ac remove imagetool 2022-12-20 00:48:52 +08:00
sevichecc
4a76821732 Update dependencies 2022-12-20 00:45:56 +08:00
sevichecc
c2ee7651c8 update post 2022-12-20 00:36:57 +08:00
sevichecc
51d0ccfc4d update post 2022-12-20 00:31:40 +08:00
sevichecc
c5c84b6614 typo 2022-12-20 00:30:39 +08:00
sevichecc
4dfc70fbfd typo 2022-12-20 00:24:51 +08:00
sevichecc
51e83043c2 new post 2022-12-20 00:12:20 +08:00
sevichecc
acdd20d4a8 revert imagetool 2022-12-18 16:16:30 +08:00
sevichecc
a72c359538
update PGP keys 2022-12-17 11:51:19 +08:00
sevichecc
f97821910f
fix avatar 2022-12-16 00:55:16 +08:00
sevichecc
33eb87f572
merge witih upsteam c283797207 2022-12-15 23:23:21 +08:00
sevichecc
33938da75c
merge with upsteam 6eed620c37 2022-12-15 23:04:28 +08:00
sevichecc
fac88146a3
revert footnote 2022-12-14 18:41:51 +08:00
sevichecc
b75c60446b
update email 2022-12-14 18:15:15 +08:00
sevichecc
f97af151ff
update dependencies 2022-12-14 17:00:00 +08:00
sevichecc
26db89bc7e
fix date 2022-12-12 17:28:51 +08:00
sevichecc
c0b4685c7d
typo 2022-12-12 17:25:22 +08:00
sevichecc
469f5cfa3c
new post 2022-12-12 17:23:23 +08:00
sevichecc
1dfadf2ca1
change pgp url in profile 2022-12-12 15:39:59 +08:00
sevichecc
46eb1dcdde
move pgp path 2022-12-12 15:37:36 +08:00
sevichecc
8182065dcb
fix pgp url 2022-12-12 14:21:30 +08:00
sevichecc
2e8a8d00f4
update key url 2022-12-12 14:10:37 +08:00
sevichecc
b79470639f
update key 2022-12-12 14:06:54 +08:00
sevichecc
50ca3f23fe compress image 2022-12-10 11:14:03 +08:00
sevichecc
28b408bcd4 compress size of image 2022-12-10 02:56:08 +08:00
sevichecc
3791f92a60 update to vite 4.0 & dependencies 2022-12-10 02:46:18 +08:00
sevichecc
2a58c54703 fix trailingSlash 2022-12-10 02:40:13 +08:00
sevichecc
f0b5baec3a merge with upsteam 1ad522ad69 2022-12-08 20:34:21 +08:00
sevichecc
ba8072ed97 minify cover image 2022-12-08 18:59:59 +08:00
sevichecc
20200c540f new post 2022-12-08 18:25:41 +08:00
sevichecc
08949974ff revert post title 2022-11-21 14:30:09 +08:00
sevichecc
16f0222a17 replace acount of remove follow 2022-11-19 17:58:03 +08:00
sevichecc
bc42a8069c revert card title 2022-11-19 17:38:25 +08:00
sevichecc
da8707e219 merge with upsteam e5438c818b 2022-11-19 17:06:15 +08:00
sevichecc
9f3dd18a29 merge with upsteam 1d6a799ca1 2022-11-19 14:48:03 +08:00
sevichecc
61d8b528bd fix: header and head 2022-11-17 22:37:03 +08:00
sevichecc
aef66c2278 update devpendencies 2022-11-17 21:45:51 +08:00
sevichecc
a7afea3b62 update with 9f3df09 2022/11/16 2022-11-16 14:01:37 +08:00
sevichecc
f41426b657 feat:add pleroma redirect 2022-11-14 21:54:49 +08:00
sevichecc
0e650c5e72 change cover image 2022-11-01 15:31:40 +08:00
sevichecc
5ed354da07 fix path of cover image and upgrade dependance 2022-11-01 15:16:27 +08:00
sevichecc
2db40dc64a new post 2022-11-01 14:29:19 +08:00
sevichecc
aa73a982d7 new post 2022-10-16 17:06:46 +08:00
sevichecc
0cfe982419 typo 2022-10-03 21:56:58 +08:00
sevichecc
b758269bcb fix: resolve JavaScript heap out of memory problem 2022-10-03 21:42:57 +08:00
sevichecc
e21f200413 revert: remove template in code block 2022-10-03 21:19:33 +08:00
sevichecc
d990868296 typo 2022-10-03 19:39:41 +08:00
sevichecc
ba9f0cb316 new post 2022-10-03 19:38:54 +08:00
sevichecc
2318fbb0a4 new post 2022-10-03 19:37:32 +08:00
sevichecc
939dd01dcb fix: remove redundant css class 2022-10-02 23:24:10 +08:00
sevichecc
a6014f2701 fix: change theme overflow 2022-10-02 23:01:22 +08:00
sevichecc
0a2e7d6c4d new post 2022-10-02 14:30:03 +08:00
sevichecc
d5e0938a4f new post 2022-10-01 22:57:14 +08:00
sevichecc
68da2b2c4d new post 2022-10-01 22:43:30 +08:00
sevichecc
e3d3106970 new post 2022-10-01 22:31:08 +08:00
sevichecc
1514bc87c0 fix: change friend's name 2022-09-30 22:59:18 +08:00
sevichecc
ee25a10322 fix:修复标题问题 2022-09-30 22:32:31 +08:00
sevichecc
eb8bffb49b new friends 2022-09-25 14:13:59 +08:00
sevichecc
2f0f551806 merge with upstream 4745cd 2022-09-10 11:18:21 +08:00
sevichecc
2aa93f55f8 merge with 894b532 2022-09-10 11:13:07 +08:00
sevichecc
a83280d7c7 update post summary 2022-09-08 13:30:44 +08:00
sevichecc
1c13a53032 merge with 39b858a 2022-09-08 00:02:13 +08:00
sevichecc
65cf431855 merge with 39b858a 2022-09-07 23:58:47 +08:00
sevichecc
381f3b952b migrate route 2022-09-07 23:29:18 +08:00
sevichecc
64ad865a62 marge with upsteam 2022-09-05 13:41:04 +08:00
sevichecc
c14ed1c151 move friends 2022-09-03 14:23:36 +08:00
sevichecc
21021e8fe1 regular format 2022-09-03 13:09:41 +08:00
sevichecc
f7bd62db4d new post and merge with upsteam 3a99081 2022-09-03 13:04:22 +08:00
217 changed files with 18185 additions and 5839 deletions

35
.gitignore vendored
View file

@ -1,15 +1,26 @@
.DS_Store
node_modules
.svelte-kit
/package
src/routes/**/
src/routes/*.md
static/
# build output
build
.vercel_build_output/
.netlify/
.env.local
.env.**.local
myblog/urara/2022-06-12-appwrite.md
static
.svelte-kit
.netlify
.vercel
# dependencies
node_modules
# env
*.local
# logs
pnpm-debug.log*
# macOS-specific files
.DS_Store
# temp file
src/routes/**/+page.svelte.md
src/routes/**/+page.md
src/static
*.config.js
urara.js

1
.npmrc
View file

@ -1 +1,2 @@
engine-strict=true
strict-peer-dependencies=false

2
.nvmrc
View file

@ -1 +1 @@
v18.4.0
v19.4.0

View file

@ -1,7 +1,7 @@
{
"editor.formatOnSave": true,
"files.eol": "\n",
"typescript.tsdk": "node_modules\\typescript\\lib",
"typescript.tsdk": "node_modules/typescript/lib",
"css.lint.unknownAtRules": "ignore",
"svelte.plugin.css.diagnostics.enable": false,
"[html]": {

View file

@ -20,7 +20,7 @@ My Tech Blog, base on [Urara](https://github.com/importantimport/urara)
## TODO
- [ ] Note Page
- [ ] Archie Page
- [ ] Archvie Page
- [ ] Refactoring the atom feed format
- [ ] NeoDB component
- [ ] ...

View file

@ -1,7 +1,5 @@
#!/bin/bash
echo "————————1. Build locally————————"
netlify build
echo "————————2.Deploy test————————"
netlify deploy
echo "————————3.Deploy————————"
echo "————————2.Deploy————————————————"
netlify deploy --prod

View file

@ -13,6 +13,7 @@ import { parse, join } from 'path'
import { visit } from 'unist-util-visit'
import { toString } from 'mdast-util-to-string'
import Slugger from 'github-slugger'
import remarkFFF from 'remark-fff'
import remarkFootnotes from 'remark-footnotes'
// highlighter
@ -24,12 +25,12 @@ type VALUE = { [key in string | number]: VALUE } | Array<VALUE> | string | boole
const remarkUraraFm =
() =>
(tree: Node<Data>, { data, filename }: { data: { fm?: Record<string, unknown> }; filename?: string }) => {
const filepath = (filename as string).split('/src/routes')[1]
const filepath = filename ? filename.split('/src/routes')[1] : 'unknown'
const { dir, name } = parse(filepath)
if (!data.fm) data.fm = {}
// Generate slug & path
data.fm.slug = filepath
data.fm.path = join(dir, `/${name}`.replace('/index', '').replace('.svelte', ''))
data.fm.path = join(dir, `/${name}`.replace('/+page', '').replace('.svelte', ''))
// Generate ToC
if (data.fm.toc !== false) {
const [slugs, toc]: [slugs: Slugger, toc: { depth: number; title: string; slug: string }[]] = [new Slugger(), []]
@ -40,23 +41,9 @@ const remarkUraraFm =
slug: slugs.slug(toString(node), false)
})
})
data.fm.toc = toc
if (toc.length > 0) data.fm.toc = toc
else data.fm.toc = false
}
// Auto-read created & updated
if (!data.fm.created || !data.fm.updated) {
const { ctime, mtime } = statSync(new URL(`./urara${filepath}`, import.meta.url))
if (!data.fm.created) data.fm.created = ctime
if (!data.fm.updated) data.fm.updated = mtime
}
// Remark FFF Experimental (Hugo -> MDsveX)
Object.entries({
image: 'images',
tags: 'category',
bookmark_of: 'bookmarkOf',
like_of: 'likeOf',
repost_of: 'repostOf',
in_reply_to: 'inReplyTo'
}).forEach(([output, input]: string[]) => (data.fm = { ...data.fm, [output]: data.fm![input] }))
}
// Better type definitions needed
@ -72,9 +59,7 @@ const remarkUraraSpoiler = () => (tree: Node<Data>) =>
return node
})
const defineConfig = (config: MdsvexOptions) => config
export default defineConfig({
export default {
extensions: ['.svelte.md', '.md'],
smartypants: {
dashes: 'oldschool'
@ -104,9 +89,24 @@ export default defineConfig({
)}\` }`
}
},
remarkPlugins: [remarkUraraFm, remarkUraraSpoiler, [remarkFootnotes, { inlineNotes: true }]],
remarkPlugins: [
[
remarkFFF as any,
{
presets: ['hugo'],
target: 'mdsvex',
autofill: {
provider: 'fs',
path: (path: string) => path.replace('/src/routes/', '/urara/')
}
}
],
remarkUraraFm,
remarkUraraSpoiler,
[remarkFootnotes, { inlineNotes: true }]
],
rehypePlugins: [
rehypeSlug,
rehypeSlug as any,
[rehypeAutolinkHeadings, { behavior: 'wrap' }],
[
rehypeExternalLinks,
@ -116,4 +116,4 @@ export default defineConfig({
}
]
]
})
} as MdsvexOptions

View file

@ -1,8 +1,7 @@
[build]
command = "npx pnpm i --store=node_modules/.pnpm-store && npx pnpm build"
command = "corepack prepare pnpm@8.5.1 --activate && pnpm i && npx pnpm build"
publish = "build"
[build.environment]
NPM_FLAGS = "--version"
AWS_LAMBDA_JS_RUNTIME = "nodejs16.x"
@ -26,13 +25,17 @@ node_bundler = "esbuild"
[[headers]]
for = "/*"
[headers.values]
Access-Control-Allow-Origin = "https://seviche.cc"
X-Frame-Options = "DENY"
Access-Control-Allow-Origin = "sevic.me"
X-Frame-Options = "SAMEORIGIN"
X-Content-Type-Options = "nosniff"
X-XSS-Protection = "1; mode=block"
Content-Security-Policy = "style-src 'self' 'unsafe-inline' https://cdn.commento.io/css/commento.css http://fonts.cdnfonts.com/css/lato ; script-src 'self' 'unsafe-inline' https://*.seviche.cc https://giscus.app https://hexoverc.vercel.app/umami.js https://cdn.splitbee.io/sb.js https://cdn.commento.io/js/commento.js"
Content-Security-Policy = "script-src 'self' 'unsafe-inline' https://*.seviche.cc https://giscus.app https://hexoverc.vercel.app/umami.js https://cdn.splitbee.io/sb.js https://plausiable.seviche.cc/js/script.js"
Referrer-Policy = "strict-origin-when-cross-origin"
Permissions-Policy = "usb=()"
[[redirects]]
from = "/.well-known/webfinger"
to = "https://kongwoo.icu/.well-known/webfinger?resource=acct:blog@kongwoo.icu"
status = 302
force = true
[[redirects]]
from = "/.well-known/host-meta"

View file

@ -12,16 +12,12 @@
"tsc:watch": "tsc -w -p tsconfig.node.json",
"urara:build": "node urara.js build",
"urara:watch": "node urara.js watch",
"kit:dev": "cross-env NODE_OPTIONS=--max_old_space_size=7680 vite dev",
"kit:build": "cross-env NODE_OPTIONS=--max_old_space_size=7680 vite build",
"kit:dev": "cross-env NODE_OPTIONS=--max_old_space_size=11474 vite dev",
"kit:build": "cross-env NODE_OPTIONS=--max_old_space_size=11474 vite build",
"dev:parallel": "npm-run-all -p -r tsc:watch urara:watch \"kit:dev {@} \" --",
"dev": "npm-run-all -s tsc \"dev:parallel {@} \" --",
"build": "npm-run-all -s tsc urara:build kit:build clean",
"preview": "vite preview",
"dev:urara": "node urara.js watch",
"dev:kit": "export NODE_OPTIONS=--max_old_space_size=8192 && MODE=development svelte-kit dev",
"build:urara": "node urara.ts build",
"build:kit": "export NODE_OPTIONS=--max_old_space_size=8192 && svelte-kit build",
"check": "svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
@ -29,58 +25,66 @@
"zhlint": "zhlint urara/*/*.md --fix && zhlint urara/*.md --fix"
},
"devDependencies": {
"@iconify-json/heroicons-outline": "^1.1.2",
"@iconify-json/heroicons-solid": "^1.1.2",
"@iconify-json/ic": "^1.1.9",
"@iconify-json/simple-icons": "1.1.21",
"@iconify-json/material-symbols": "1.1.14",
"@iconify-json/mdi": "^1.1.30",
"@iconify-json/uil": "^1.1.2",
"@sveltejs/adapter-auto": "1.0.0-next.64",
"@sveltejs/adapter-node": "1.0.0-next.86",
"@sveltejs/adapter-static": "1.0.0-next.39",
"@sveltejs/kit": "1.0.0-next.405",
"@tailwindcss/typography": "^0.5.4",
"@types/node": "^18.7.8",
"@iconify-json/heroicons-outline": "^1.1.6",
"@iconify-json/heroicons-solid": "^1.1.7",
"@iconify-json/ic": "^1.1.13",
"@iconify-json/icon-park-twotone": "1.1.9",
"@iconify-json/material-symbols": "1.1.41",
"@iconify-json/mdi": "^1.1.52",
"@iconify-json/simple-icons": "1.1.52",
"@iconify-json/uil": "^1.1.4",
"@sveltejs/adapter-netlify": "^2.0.7",
"@sveltejs/adapter-static": "^2.0.2",
"@sveltejs/adapter-vercel": "2.4.3",
"@sveltejs/kit": "^1.19.0",
"@tailwindcss/typography": "^0.5.9",
"@types/node": "^20.2.5",
"@types/unist": "^2.0.6",
"@typescript-eslint/eslint-plugin": "^5.33.1",
"@typescript-eslint/parser": "^5.33.1",
"autoprefixer": "^10.4.8",
"chalk": "^5.0.1",
"@typescript-eslint/eslint-plugin": "^5.59.7",
"@typescript-eslint/parser": "^5.59.7",
"@unocss/extractor-svelte": "^0.51.13",
"@vite-pwa/sveltekit": "^0.1.3",
"chalk": "^5.2.0",
"chokidar": "^3.5.3",
"cross-env": "^7.0.3",
"cssnano": "^5.1.13",
"daisyui": "^2.24.0",
"eslint": "^8.22.0",
"eslint-config-prettier": "^8.5.0",
"daisyui": "^2.51.6",
"eslint": "^8.41.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-svelte3": "^4.0.0",
"fenceparser": "^2.2.0",
"fff-flavored-frontmatter": "~0.2.2",
"github-slugger": "^1.4.0",
"mdast-util-to-string": "^3.1.0",
"fff-flavored-frontmatter": "~0.5.3",
"github-slugger": "^2.0.0",
"mdast-util-to-string": "^3.2.0",
"mdsvex": "^0.10.6",
"netlify-cli": "^16.3.1",
"npm-run-all": "^4.1.5",
"postcss": "^8.4.16",
"prettier": "^2.7.1",
"prettier-plugin-svelte": "^2.7.0",
"postcss": "^8.4.23",
"postcss-lightningcss": "^0.7.0",
"prettier": "^2.8.8",
"prettier-plugin-svelte": "^2.10.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-external-links": "^2.0.0",
"rehype-slug": "^5.0.1",
"remark": "^14.0.2",
"rehype-external-links": "^2.1.0",
"rehype-slug": "^5.1.0",
"remark": "^14.0.3",
"remark-fff": "~0.5.3",
"remark-footnotes": "~2.0.0",
"shiki-twoslash": "^3.1.0",
"svelte": "^3.49.0",
"rollup": "^3.23.0",
"shiki-twoslash": "^3.1.2",
"svelte": "^3.59.1",
"svelte-bricks": "^0.1.7",
"svelte-check": "^2.8.1",
"svelte-preprocess": "^4.10.7",
"svelte-typeahead": "^4.2.4",
"tailwindcss": "^3.1.8",
"tslib": "^2.4.0",
"typescript": "^4.7.4",
"unist-util-visit": "^4.1.0",
"unocss": "^0.45.8",
"vite": "^3.0.9",
"vite-plugin-pwa": "^0.12.3",
"workbox-window": "^6.5.4"
"svelte-check": "^3.4.3",
"svelte-preprocess": "^5.0.4",
"svelte-typeahead": "^4.4.1",
"sveltekit-embed": "^0.0.12",
"tailwindcss": "^3.3.2",
"tslib": "^2.5.2",
"typescript": "^5.0.4",
"unist-util-visit": "^4.1.2",
"unocss": "^0.51.13",
"vite": "^4.3.9",
"vite-imagetools": "^4.0.19",
"vite-plugin-pwa": "^0.14.7",
"workbox-build": "^6.6.0",
"workbox-window": "^6.6.0"
}
}

File diff suppressed because it is too large Load diff

11
src/app.d.ts vendored
View file

@ -1,8 +1,9 @@
/// <reference types="@sveltejs/kit" />
import { FFFBase, FFFExtra } from 'fff-flavored-frontmatter'
import type { FFFBase, FFFMention } from 'fff-flavored-frontmatter'
interface ImportMetaEnv extends Readonly<Record<string, string>> {
readonly URARA_SITE_PROTOCOL?: 'http://' | 'https://'
readonly URARA_SITE_DOMAIN?: string
}
@ -14,8 +15,8 @@ interface ImportMeta {
declare global {
namespace Urara {
namespace Post {
type Frontmatter = Omit<FFFBase, 'created' | 'updated' | 'image' | 'audio' | 'video' | 'flags'> &
Pick<FFFExtra, 'in_reply_to'> & {
type Frontmatter = Omit<FFFBase, 'flags'> &
Pick<FFFMention, 'in_reply_to'> & {
/**
* post type.
* @remarks auto-generated
@ -50,6 +51,10 @@ declare global {
* @remarks auto-generated or set manually
*/
updated: string
/**
* the published date of the post.
*/
published?: string
/**
* the featured image for article, or image for "photo" / "multi-photo" posts.
* @remarks currently only supports string

View file

@ -13,5 +13,6 @@
<body itemscope itemtype="https://schema.org/WebPage">
%sveltekit.body%
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

View file

@ -56,7 +56,12 @@ html {
/* .urara-prose a */
.urara-prose :is(p, li) > a {
@apply bg-[length:100%_0.2em] hover:bg-[length:100%_100%] bg-[position:0_88%] bg-gradient-to-t from-secondary/50 to-secondary/40 bg-no-repeat transition-all ease-in-out !no-underline;
@apply underline
font-normal
hover:decoration-red-700/50
hover:text-red-700
decoration-2
underline-offset-4 decoration-gray-700/30;
}
/* .urara-prose misc */
@ -188,9 +193,9 @@ pre.twoslash data-lsp:hover::before {
.urara-prose blockquote:before {
vertical-align: -0.4em;
@apply mr-2 text-5xl leading-3 italic font-serif opacity-25;
@apply mr-2 text-5xl mt-4 leading-3 italic font-serif opacity-25 float-left;
}
.urara-prose blockquote p {
@apply inline opacity-80 before:content-[''] after:content-[''];
@apply opacity-80 before:content-[''] after:content-[''];
}

7
src/hooks.server.ts Normal file
View file

@ -0,0 +1,7 @@
import type { Handle } from '@sveltejs/kit'
import { site } from '$lib/config/site'
export const handle: Handle = async ({ event, resolve }) =>
await resolve(event, {
transformPageChunk: ({ html }) => html.replace('<html lang="en">', `<html lang="${site.lang ?? 'en'}">`)
})

View file

@ -0,0 +1,5 @@
<button class="tooltip tooltip-left opacity-60 hover:opacity-100" data-tip="Jump to comments">
<a href="#post-comment" class="btn btn-circle btn-ghost hover:bg-red-10">
<span class="i-heroicons-outline-chat-alt-2" />
</a>
</button>

View file

@ -1,3 +0,0 @@
<a href="#post-comment" class="btn btn-lg btn-circle btn-ghost bg-base-100 shadow-lg hover:shadow-xl">
<span class="i-heroicons-outline-chat-alt-2" />
</a>

View file

@ -3,10 +3,12 @@
export let post: Urara.Post
</script>
<button class="tooltip tooltip-left opacity-60 hover:opacity-100" data-tip="Translate">
<a
href={`https://translate.google.com/translate?sl=auto&tl=${
navigator.languages ? navigator.languages[0] : navigator.language
}&u=${site.protocol + site.domain + post.path}`}
class="btn btn-lg btn-circle btn-ghost bg-base-100 shadow-lg hover:shadow-xl">
class="btn btn-circle btn-ghost">
<span class="i-heroicons-outline-translate" />
</a>
</button>

View file

@ -3,10 +3,12 @@
export let post: Urara.Post
</script>
<button class="tooltip tooltip-left opacity-60 hover:opacity-100" data-tip="Share">
<a
href={`https://www.addtoany.com/share#url=${site.protocol + site.domain + post.path}&title=${encodeURI(
post.title ?? post.path.slice(1)
)}`}
class="btn btn-lg btn-circle btn-ghost bg-base-100 shadow-lg hover:shadow-xl">
class="btn btn-circle btn-ghost">
<span class="i-heroicons-outline-share" />
</a>
</button>

View file

@ -0,0 +1,63 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte'
import type { Remark42Config } from '$lib/types/post'
export let post: Urara.Post
export let config: Remark42Config
let remark42Instance: any
onMount(() => {
const [c, s] = [document.createElement('script'), document.createElement('script')]
c.id = 'remark42_config'
c.type = 'application/javascript'
c.innerHTML = `
var remark_config = {
host: '${config.host}',
site_id: '${config.site_id || 'remark'}',
url: '${post.path}',
components: [${config.components || "'embed'"}],
max_shown_comments: ${config.max_shown_comments || 15},
max_last_comments: ${config.max_last_comments || 15},
theme: '${config.theme || 'light'}',
page_title: '${config.page_title || post.title}',
locale: '${config.locale || 'en'}',
show_email_subscription: ${config.show_email_subscription || true},
show_rss_subscription: ${config.show_rss_subscription || true},
simple_view: ${config.simple_view || false},
no_footer: ${config.no_footer || false},
}`
s.id = 'remark42_script'
s.type = 'application/javascript'
s.innerHTML = `!function(e,n){for(var o=0;o<e.length;o++){var r=n.createElement("script"),c=".js",d=n.head||n.body;"noModule"in r?(r.type="module",c=".mjs"):r.async=!0,r.defer=!0,r.src='${config.host}/web/'+e[o]+c,d.appendChild(r)}}(remark_config.components||["embed"],document);`
document.head.appendChild(c)
document.head.appendChild(s)
const opt = {
...config,
url: post.path
}
const checkRemark42 = () => {
if ((window as any).REMARK42) {
remark42Instance = (window as any).REMARK42.createInstance({
node: document.getElementById('remark42') as HTMLElement,
...opt
})
} else {
setTimeout(checkRemark42, 100)
}
}
checkRemark42()
})
onDestroy(() => {
if (remark42Instance && typeof remark42Instance.destroy === 'function') {
remark42Instance.destroy()
}
})
</script>
<div id="remark42" />

View file

@ -1,117 +0,0 @@
<!-- <script lang="ts">
import { onMount } from 'svelte'
import { site } from '$lib/config/site'
import type { WalineConfig } from '$lib/types/post'
export let post: Urara.Post
export let config: WalineConfig
onMount(() => {
const waline = document.createElement('script')
const [c, s] = [document.createElement('script'), document.createElement('script')]
c.id = 'disqus_config'
c.type = 'application/javascript'
console.log(waline)
Object.entries({
src: 'https://unpkg.com/@waline/client@v2/dist/waline.js',
serverURL: config.serverURL,
path: config.path ?? post.path ?? window.location.pathname,
lang: config.lang ?? 'en',
emoji: config.emoji ?? ['//unpkg.com/@waline/emojis@1.0.1/weibo'],
dark: config.dark ?? false,
meta: config.meta ?? ['nick', 'mail', 'link'],
requiredMeta: config.requiredMeta ?? [],
login: config.login ?? 'enable',
wordLimit: config.wordLimit ?? 0,
pageSize: config.pageSize ?? 10,
imageUploader: config.imageUploader,
highlighter: config.highlighter,
texRender: config.texRender,
copyright: config.copyright ?? true,
crossorigin: 'anonymous',
async: ''
}).forEach(([key, value]) => waline.setAttribute(key, value))
setTimeout(() => {
const observer = new MutationObserver(() => {
document.getElementById('giscus-loading').remove()
observer.disconnect()
})
observer.observe(document.getElementById('giscus'), {
childList: true
})
document.getElementById('giscus-container').appendChild(waline)
}, 1000)
})
</script>
<link rel="stylesheet" href="https://unpkg.com/@waline/client@v2/dist/waline.css" />
<div id="waline" class="waline-container" />
<style>
.waline-container {
background-color: var(--card-background);
border-radius: var(--card-border-radius);
box-shadow: var(--shadow-l1);
padding: 2%;
}
.waline-container .vcount {
color: var(--card-text-color-main);
}
.v[data-class='v'] .vcard {
flex: 1;
width: 0;
padding-bottom: 0.5em;
border-bottom: 0; /*删掉回复下面的线*/
}
.v[data-class='v'] .vcard .vquote {
border-left: 1px solid rgba(237, 237, 237, 0.5);
}
@media (max-width: 580px) {
.v[data-class='v'] .vheader .vheader-item:not(:last-child) {
border-bottom: 1px solid rgba(237, 237, 237, 0.8); /*输入框分割线*/
}
}
/*日间模式*/
:root {
--waline-theme-color: #34495e; /*主题色,提交按钮*/
--waline-active-color: #246bb1; /*鼠标移到提交按钮上的颜色*/
/* 徽章 */
--waline-badge-color: #34495e; /*博主徽章色*/
--waline-avatar-radius: 5px;
--waline-avatar-size: 6rem;
--waline-dark-grey: #34495e; /*ID颜色*/
--waline-text-color: #34495e; /*字体颜色*/
--waline-font-size: 1.7rem; /*字体大小颜色*/
}
/*夜间模式*/
:root[data-scheme='dark'] {
--waline-theme-color: #acc6e0;
--waline-white: #34495e; /*按键字体颜色*/
--waline-active-color: #8ab1d8;
--waline-light-grey: #666;
--waline-dark-grey: #acc6e0; /*ID颜色*/
--waline-badge-color: #acc6e0;
/* 布局颜色 */
--waline-text-color: rgba(255, 255, 255, 0.7);
--waline-bgcolor: #515151;
--waline-bgcolor-light: #66696b; /*行内代码块颜色*/
--waline-border-color: #9b9c9c;
--waline-disable-bgcolor: #444;
--waline-disable-color: #272727;
/* 特殊颜色 */
--waline-bq-color: #9b9c9c; /*quote*/
/* 其他颜色 */
--waline-info-bgcolor: #acc6e0;
--waline-info-color: #9b9c9c;
}
.v[data-class='v'] .vcontent .vemoji {
width: 2.2em; /*表情包大小修改*/
margin: 0.25em;
}
.v[data-class='v'] .vheader {
border-bottom: 1px solid rgba(237, 237, 237, 0.8); /*输入框分割线*/
}
.v[data-class='v'] .vpanel {
border-radius: 8px; /*输入框圆角*/
}
</style> -->

View file

@ -74,6 +74,36 @@
</script>
<div class="flex flex-col gap-8">
{#if config?.form === true}
<form id="webmention-form" method="post" action="https://webmention.io/{config.username}/webmention">
<input type="hidden" name="target" value={site.protocol + site.domain + post.path} />
<div class="label gap-4">
<span class="label-text">send webmentions here:</span>
<!-- {#if config?.commentParade === true}
<span class="label-text-alt text-right">
or <a
class="hover:!text-primary"
href="https://quill.p3k.io/?dontask=1&me=https://commentpara.de/&reply={encodeURI(
site.protocol + site.domain + post.path
)}">
comment anonymously
</a>
</span>
{/if} -->
</div>
<div class="flex gap-2">
<div class="flex-1">
<input
class="input input-bordered focus:input-primary w-full"
type="text"
id="reply-url"
name="source"
placeholder="https://example.com/my-post" />
</div>
<button class="btn btn-primary flex-none mt-auto" type="submit" id="webmention-submit">Send</button>
</div>
</form>
{/if}
<div class="flex">
<p class="flex-1 m-auto italic opacity-50">
<!-- {`Sort by=${config?.sortBy ?? 'Created'}&sort-dir=${sortDirUp ? 'up' : 'down'}`} -->
@ -172,34 +202,4 @@
{:else}
<button id="webmention-loading" class="btn btn-lg btn-block flex btn-ghost loading" />
{/if}
{#if config?.form === true}
<form id="webmention-form" method="post" action="https://webmention.io/{config.username}/webmention">
<input type="hidden" name="target" value={site.protocol + site.domain + post.path} />
<div class="label gap-4">
<span class="label-text">send webmentions here:</span>
{#if config?.commentParade === true}
<span class="label-text-alt text-right">
or <a
class="hover:!text-primary"
href="https://quill.p3k.io/?dontask=1&me=https://commentpara.de/&reply={encodeURI(
site.protocol + site.domain + post.path
)}">
comment anonymously
</a>
</span>
{/if}
</div>
<div class="flex gap-2">
<div class="flex-1">
<input
class="input input-bordered focus:input-primary w-full"
type="text"
id="reply-url"
name="source"
placeholder="https://example.com/my-post" />
</div>
<button class="btn btn-primary flex-none mt-auto" type="submit" id="webmention-submit">Send</button>
</div>
</form>
{/if}
</div>

View file

@ -24,7 +24,7 @@
.then(
({ links }) => links.find((link: { rel: string }) => link.rel === 'http://ostatus.org/schema/1.0/subscribe').template
)
.then(template => (window.location.href = template.replace('{uri}', `sevichecc@kongwoo.icu`)))
.then(template => (window.location.href = template.replace('{uri}', `blog@seviche.cc`)))
.catch(error => console.error(error))
$: if (input)
input.length < 5 ? (status = '') : input.includes('@') && input.includes('.') ? (status = 'success') : (status = 'warning')

View file

@ -3,8 +3,8 @@
</script>
<script lang="ts">
export let user = undefined
export let repo = undefined
export let user = ''
export let repo = ''
let info: {
html_url: string
description: string

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { dev } from '$app/env'
import { dev } from '$app/environment'
let className = undefined
export { className as class }
export let src = undefined

View file

@ -19,10 +19,10 @@
<div class="rounded-full border-2 border-white shadow-xl w-16 h-16">
<img
class="hover:rotate-[360deg] transition-transform duration-1000 ease-in-out m-0"
src={avatar ?? site.author.avatar}
alt={name ?? site.author.name}
loading="lazy"
decoding="async" />
decoding="async"
src={avatar ?? site.author.avatar} />
</div>
</div>
{#if subname}

View file

@ -1,22 +1,26 @@
<script lang="ts">
export let id = undefined
export let list = undefined
export let playlist = undefined
export let start = undefined
export let autoplay = false
export let disablekb = false
export let controls = true
export let id: string
export let list: boolean | undefined = undefined
export let playlist: string | undefined = undefined
export let start: string | undefined = undefined
export let autoplay: boolean = false
export let disablekb: boolean = false
export let controls: boolean = true
export let fs = true
export let loop = false
const src = `https://www.youtube.com/embed/${id}?${list ? `listType=playlist&list=${list}&` : ''}${
playlist ? `playlist=${playlist}&` : ''
}${start ? `start=${start}` : ''}${autoplay ? 'autoplay=1&' : ''}${disablekb ? 'disablekb=1&' : ''}${
controls ? '' : 'controls=0&'
}${fs ? '' : 'fs=0&'}${loop ? 'loop=1' : ''}`
const src = `https://www.youtube.com/embed/${id}?${new URLSearchParams({
...(list ? { listType: 'playlist', list: 'true' } : {}),
...(playlist ? { playlist } : {}),
...(start ? { start } : {}),
autoplay: autoplay ? '1' : '0',
disablekb: disablekb ? '1' : '0',
controls: controls ? '1' : '0',
fs: fs ? '1' : '0',
loop: loop ? '1' : '0'
}).toString()}`
</script>
<div class="relative pb-[56.25%] mb-2">
<div class="relative pb-[56.25%] mb-4">
<iframe
{src}
class="absolute w-full h-full"

View file

@ -16,7 +16,7 @@
<p>
{#if footerConfig.nav}
{#each footerConfig.nav as { text, link }, i}
<a href={link} rel="noopener external" target="_blank">{text}</a>
<a href={link} rel="noopener noreferrer external" target="_blank">{text}</a>
{#if i + 1 < footerConfig.nav.length}
<span class="mr-1">·</span>
{/if}
@ -30,7 +30,7 @@
<br />
Powered by
<a
rel="noopener external"
rel="noopener noreferrer external"
target="_blank"
class="tooltip tooltip-secondary hover:text-secondary"
data-tip="🌸 [δ] - Based on MDsveX & SvelteKit 🌸"

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { dev } from '$app/env'
import { dev } from '$app/environment'
import { head } from '$lib/config/general'
import { site } from '$lib/config/site'
import OpenGraph from '$lib/components/head_opengraph.svelte'

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { browser, dev } from '$app/env'
import { browser, dev } from '$app/environment'
import { fly } from 'svelte/transition'
import { site } from '$lib/config/site'
import { theme } from '$lib/config/general'
@ -41,7 +41,8 @@
if (browser)
currentTheme =
localStorage.getItem('theme') ?? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'night' : 'lemonade')
localStorage.getItem('theme') ??
(window.matchMedia('(prefers-color-scheme: dark)').matches ? theme?.[1].name : theme[0].name ?? theme[0].name)
</script>
<svelte:head>
@ -54,34 +55,32 @@
id="header"
class:-translate-y-32={!pin && scrollY > 0}
class="fixed z-50 w-screen transition-all duration-500 ease-in-out border-b-2 border-transparent max-h-[4.125rem] {scrollY >
32 && 'backdrop-blur border-base-content/10 bg-base-100/30 md:bg-base-200/30'}">
32 && 'backdrop-blur !border-base-content/10 bg-base-100/30 md:bg-base-200/30'}">
{#if !search}
<div in:fly={{ x: -50, duration: 300, delay: 300 }} out:fly={{ x: -50, duration: 300 }} class="navbar">
<div class="navbar-start">
{#if headerConfig.nav}
<Nav {path} {title} {pin} {scrollY} nav={headerConfig.nav} />
{/if}
<a href="/" sveltekit:prefetch class="btn btn-ghost normal-case text-lg">{site.title}</a>
<a href="/" class="btn btn-ghost normal-case text-lg">{site.title}</a>
</div>
<div class="navbar-end">
<!-- {#if headerConfig.search} -->
<!-- The button to open modal -->
<!-- <label for="search-modal" class="btn btn-square btn-ghost ml-2"><span class="i-heroicons-outline-search" /></label> -->
<!-- <button
on:click={() => {
search = !search
}}
type="submit"
class="btn btn-square btn-ghost ml-2">
{#if headerConfig.search}
<button aria-label="search" on:click={() => (search = !search)} tabindex="0" class="btn btn-square btn-ghost">
<span class="i-heroicons-outline-search" />
</button> -->
<!-- {/if} -->
</button>
{/if}
<div id="change-theme" class="dropdown dropdown-end">
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<!-- reference: https://github.com/saadeghi/daisyui/issues/1285 -->
<div tabindex="0" class="btn btn-square btn-ghost">
<span class="i-heroicons-outline-color-swatch" />
</div>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<!-- reference: https://github.com/saadeghi/daisyui/issues/1285 -->
<ul
tabindex="0"
class="flex shadow-2xl menu dropdown-content bg-base-100 text-base-content rounded-box w-52 p-2 gap-2 overflow-y-auto max-h-[21.5rem]"
class="flex flex-nowrap shadow-2xl menu dropdown-content bg-base-100 text-base-content rounded-box w-52 p-2 gap-2 overflow-y-auto max-h-[21.5rem]"
class:hidden={!pin}>
{#each theme as { name, text }}
<button
@ -92,7 +91,7 @@
}}
class:border-2={currentTheme === name}
class:border-primary={currentTheme === name}
class="btn btn-ghost hover:bg-primary group rounded-lg flex bg-base-100 p-2 transition-all">
class="btn btn-ghost w-full hover:bg-primary group rounded-lg flex bg-base-100 p-2 transition-all">
<p class="flex-1 text-left text-base-content group-hover:text-primary-content transition-color">
{text ?? name}
</p>
@ -108,6 +107,14 @@
</div>
</div>
</div>
{:else}
<div in:fly={{ x: 50, duration: 300, delay: 300 }} out:fly={{ x: 50, duration: 300 }} class="navbar">
<Search />
<button on:click={() => (search = !search)} tabindex="0" class="btn btn-square btn-ghost">
<span class="i-heroicons-outline-x" />
</button>
</div>
{/if}
</header>
<button

View file

@ -6,6 +6,8 @@
export let pin: boolean
</script>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<!-- reference: https://github.com/saadeghi/daisyui/issues/1285 -->
<div class="dropdown lg:hidden">
<label for="navbar-dropdown" tabindex="0" class="btn btn-square btn-ghost">
<span class="i-heroicons-outline-menu-alt-1" />
@ -14,11 +16,12 @@
id="navbar-dropdown"
tabindex="0"
class:hidden={!pin}
class="menu menu-compact dropdown-content bg-base-100 text-base-content shadow-lg rounded-box max-w-52 p-2">
class="menu menu-compact dropdown-content bg-base-100 text-base-content shadow-lg rounded-box min-w-max max-w-52 p-2
">
{#each nav as { text, link, children }}
{#if link && !children}
<li>
<a sveltekit:prefetch class:font-bold={link === path} href={link}>{text}</a>
<a class:font-bold={link === path} href={link}>{text}</a>
</li>
{:else if children}
<li tabindex="0">
@ -29,7 +32,7 @@
<ul class="bg-base-100 text-base-content shadow-lg p-2">
{#each children as { text, link }}
<li>
<a sveltekit:prefetch class:font-bold={link === path} href={link}>{text}</a>
<a class:font-bold={link === path} href={link}>{text}</a>
</li>
{/each}
</ul>
@ -49,18 +52,19 @@
{#each nav as { text, link, children }}
{#if link && !children}
<li>
<a sveltekit:prefetch class:font-bold={link === path} href={link}>{text}</a>
<a class="!rounded-btn" class:font-bold={link === path} href={link}>{text}</a>
</li>
{:else if children}
<li tabindex="0">
<span class:font-bold={children.some(({ link }) => link === path)} class="gap-1">
<li>
<span class:font-bold={children.some(({ link }) => link === path)} class="!rounded-btn gap-1">
{text}
<span class="i-heroicons-solid-chevron-down -mr-1" />
</span>
<ul class="bg-base-100 text-base-content shadow-lg p-2">
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<ul tabindex="0" class="menu rounded-box bg-base-100 text-base-content shadow-lg p-2">
{#each children as { text, link }}
<li>
<a sveltekit:prefetch class:font-bold={link === path} href={link}>{text}</a>
<a class:font-bold={link === path} href={link}>{text}</a>
</li>
{/each}
</ul>

View file

@ -1,102 +1,21 @@
<script lang="ts">
import { onMount, createEventDispatcher } from 'svelte'
import { site } from '$lib/config/site'
import { header as headerConfig } from '$lib/config/general'
import Typeahead from 'svelte-typeahead'
import { page } from '$app/stores'
// ref : https://github.com/saadeghi/daisyui/blob/master/src/docs/src/components/Search.svelte
</script>
<form>
<input type="checkbox" id="search-modal" class="modal-toggle " />
<label for="search-modal" class="modal cursor-pointer w-full items-start pt-16 ">
<label class="modal-box w-11/12 max-w-4xl " for="">
<div class="form-control">
<span
class="i-heroicons-outline-search text-base-content pointer-events-none absolute z-10 my-2 ml-3 stroke-current opacity-60 w-5" />
</div>
<Typeahead placeholder="Search is not avaible …" limit={8} label="Search" inputAfterSelect="clear">
<div class="py-1 text-sm" />
</Typeahead>
<div class="pointer-events-none absolute right-14 top-8 gap-1 opacity-50 hidden lg:flex">
<kbd class="kbd kbd-sm">ESC</kbd>
</div>
</label>
</label>
<form
action={headerConfig?.search?.provider === 'duckduckgo' ? '//duckduckgo.com/' : '//google.com/search'}
method="get"
class="flex-1">
<input
type="text"
name="q"
class="input input-ghost input-bordered xl:bg-base-100 xl:text-base-content transition-all w-full h-12" />
<input
type="hidden"
name={headerConfig?.search?.provider === 'duckduckgo' ? 'sites' : 'sitesearch'}
value={site.protocol + site.domain} />
<button type="submit" class="btn btn-square btn-ghost ml-2">
<span class="i-heroicons-outline-search" />
</button>
</form>
<!-- <script lang="ts">
import { onMount, createEventDispatcher } from "svelte"
import { page } from "$app/stores"
import { goto } from "$app/navigation"
import Typeahead from "svelte-typeahead"
import { pages } from "@src/lib/data.js"
const dispatch = createEventDispatcher()
let searchIndex = []
pages.forEach((group) => {
group.items.forEach((item) => {
searchIndex.push(item)
})
})
let seachboxEl
function handleKeydown(e) {
if ((e.keyCode === 75 && e.metaKey) || (e.keyCode === 75 && e.ctrlKey)) {
e.preventDefault()
seachboxEl.querySelector("input[type=search]").focus()
dispatch("focus")
}
}
function onSelect({ detail }) {
goto(searchIndex[detail.originalIndex].href)
dispatch("search", detail)
}
</script>
<svelte:window on:keydown={handleKeydown} />
-->
<style global>
.searchbox [data-svelte-typeahead] {
background: none;
width: 100%;
max-width: 100%;
}
[data-svelte-search] label {
display: none;
}
[data-svelte-search] input {
background-color: transparent;
color: inherit;
border-radius: 0.5em;
padding-left: 2em;
}
[data-svelte-search] input::placeholder {
color: inherit;
}
[data-svelte-search] input:focus {
outline-color: hsla(var(--bc) / 0.2);
background-color: hsl(var(--b1));
color: hsla(var(--bc));
}
[data-svelte-typeahead] .svelte-typeahead-list {
transform: translateY(0.5em);
background: hsl(var(--b1));
border-radius: var(--rounded-btn);
overflow: hidden;
}
[data-svelte-typeahead] .svelte-typeahead-list .selected,
[data-svelte-typeahead] .svelte-typeahead-list .selected:hover {
background: hsl(var(--n));
color: hsl(var(--nc));
}
[data-svelte-typeahead] .svelte-typeahead-list li {
color: hsl(var(--bc));
}
[data-svelte-typeahead] .svelte-typeahead-list li:hover {
background: hsl(var(--b2));
color: hsl(var(--bc));
}
[data-svelte-typeahead] .svelte-typeahead-list li:not(:last-of-type) {
border-bottom-color: hsla(var(--bc) / 0.1);
}
</style>

File diff suppressed because one or more lines are too long

View file

@ -1,12 +1,12 @@
<script lang="ts">
export let post: Urara.Post
const actions = import.meta.glob<{ default: unknown }>('/src/lib/components/actions/*.svelte', { eager: true })
const actions = import.meta.glob<any>('/src/lib/components/actions/*.svelte', { eager: true, import: 'default' })
</script>
<div class="sticky top-24 hidden xl:flex flex-col gap-4 w-fit h-[calc(100vh-12rem)] ml-auto mr-8 my-8 justify-center">
<div class="sticky top-24 hidden xl:flex flex-col gap-4 w-fit max-h-[calc(100vh-12rem)] ml-auto mr-6 my-8 justify-center">
{#if Object.keys(actions).length}
{#each Object.values(actions) as action}
<svelte:component this={action.default} {post} />
<svelte:component this={action} {post} />
{/each}
{/if}
</div>

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { browser } from '$app/env'
import { browser } from '$app/environment'
import { post as postConfig } from '$lib/config/post'
import { posts as storedPosts } from '$lib/stores/posts'
import { title as storedTitle } from '$lib/stores/title'
@ -35,11 +35,10 @@
itemprop="blogPost"
class:md:mb-8={!preview}
class:lg:mb-16={!preview}
class:h-entry={preview}
class:group={preview}
class:image-full={preview && post.type === 'article' && post.image}
class:before:!rounded-none={preview && post.image}
class="card bg-base-100 rounded-none md:rounded-box md:shadow-xl z-10">
class="h-entry card bg-base-100 rounded-none md:rounded-box md:shadow-lg md:shadow-grey-10 overflow-hidden z-10">
{#if !preview && postConfig.bridgy}
<div id="bridgy" class="hidden">
{#each post.flags?.some( flag => flag.startsWith('bridgy') ) ? post.flags.flatMap( flag => (flag.startsWith('bridgy') ? flag.slice(7) : []) ) : [...(postConfig.bridgy.post ?? []), ...(postConfig.bridgy[post.type] ?? [])] as target}
@ -73,9 +72,10 @@
<div class="flex flex-col gap-2">
{#if post.image && !preview}
<figure
class={`md:order-last mb-4 ${post.type === 'article' ? 'flex-col gap-2 -mx-4 -mt-8 md:mt-0' : 'flex-col -mx-8'}`}>
class={`md:order-last rounded-lg mb-4 ${post.type === 'article' ? 'flex-col gap-2 -mt-8 md:mt-0' : 'flex-col -mx-8'}'
}`}>
<Image
class={`${post.type === 'article' ? 'u-featured rounded-box shadow-xl' : 'u-photo'}`}
class={`${post.type === 'article' ? 'u-featured' : 'u-photo'}`}
src={post.image}
alt={post.image}
{loading}
@ -91,7 +91,7 @@
<a itemprop="url" class="u-url p-name" href={post.path}>{post.title ?? post.path.slice(1)}</a>
</h2>
{:else}
<h1 itemprop="name headline" class="card-title text-3xl mb-8 p-name">{post.title ?? post.path.slice(1)}</h1>
<h1 itemprop="name headline" class="card-title text-2xl mb-8 p-name">{post.title ?? post.path.slice(1)}</h1>
{/if}
{/if}
{#if post.summary}

View file

@ -3,7 +3,7 @@
import { toSnake } from '$lib/utils/case'
export let post: Urara.Post
export let config: CommentConfig
const comments = import.meta.glob<{ default: unknown }>('/src/lib/components/comments/*.svelte', { eager: true })
const comments = import.meta.glob<any>('/src/lib/components/comments/*.svelte', { eager: true, import: 'default' })
let currentComment: string | undefined = undefined
let currentConfig: unknown | undefined = undefined
currentComment = localStorage.getItem('comment') ?? toSnake(config.use[0])
@ -14,8 +14,9 @@
{#if config?.use.length > 0}
<div id="post-comment" class="card card-body">
{#if config.use.length > 1}
<div class="tabs w-full mb-8" class:tabs-boxed={config?.['style'] === 'boxed'}>
<div class="tabs w-full" class:tabs-boxed={config?.['style'] === 'boxed'}>
{#each config.use as name}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<span
on:click={() => {
currentComment = toSnake(name)
@ -33,7 +34,7 @@
{#if currentComment}
{#key currentComment}
<svelte:component
this={comments[`/src/lib/components/comments/${currentComment}.svelte`].default}
this={comments[`/src/lib/components/comments/${currentComment}.svelte`]}
{post}
config={currentConfig} />
{/key}

View file

@ -1,6 +1,6 @@
<script lang="ts">
import { fly } from 'svelte/transition'
import { browser } from '$app/env'
import { browser } from '$app/environment'
import Card from '$lib/components/post_card.svelte'
import Head from '$lib/components/head.svelte'
import Toc from '$lib/components/post_toc.svelte'
@ -22,7 +22,7 @@
<div
in:fly={{ x: 25, duration: 300, delay: 500 }}
out:fly={{ x: 25, duration: 300 }}
class="flex-1 w-full max-w-screen-md order-first ease-out transform mx-auto xl:mr-0">
class="flex-1 w-full order-first ease-out transform mx-auto xl:mr-0 xl:ml-0">
{#if browser}
<Action {post} />
{/if}
@ -30,7 +30,7 @@
<div
in:fly={{ x: -25, duration: 300, delay: 500 }}
out:fly={{ x: -25, duration: 300 }}
class="flex-1 w-full max-w-screen-md xl:order-last ease-out transform mx-auto xl:mr-0">
class="flex-1 w-full xl:order-last ease-out transform mx-auto xl:ml-0 xl:mr-0">
{#if browser && post.toc}
<div class="h-full hidden xl:block">
<Toc toc={post.toc} />

View file

@ -7,10 +7,9 @@
<nav class="flex flex-col md:flex-row flex-warp justify-evenly">
{#if prev}
<div
href={prev.path}
class:image-full={prev['image']}
class:md:rounded-r-box={next && !next['image']}
class="flex-1 card group rounded-none before:!rounded-none">
class="flex-1 card group rounded-none before:!rounded-none overflow-hidden">
{#if prev['image']}
<figure class="!block">
<Image
@ -34,10 +33,9 @@
{/if}
{#if next}
<div
href={next.path}
class:image-full={next['image']}
class:md:rounded-l-box={prev && !prev['image']}
class="flex-1 card group rounded-none before:!rounded-none">
class="flex-1 card group rounded-none before:!rounded-none overflow-hidden">
{#if next['image']}
<figure class="!block">
<Image

View file

@ -6,25 +6,12 @@
<div class="flex flex-wrap gap-2 rounded-box outline outline-neutral/10 p-4 {className}">
<span class="flex-none font-bold uppercase opacity-30">Reply to:&nbsp;</span>
{#if Array.isArray(in_reply_to)}
{#each in_reply_to as reply}
<a
href={reply}
rel="noopener external"
target="_blank"
class="flex-none flex rounded-badge bg-base-200 hover:bg-base-300 transition-all gap-2 px-4 u-in-reply-to">
<span class="i-heroicons-outline-reply my-auto !w-4 !h-4" />
{reply}
</a>
{/each}
{:else}
<a
href={in_reply_to}
rel="noopener external"
rel="noopener noreferrer external"
target="_blank"
class="ml-auto flex-none flex rounded-badge bg-base-200 hover:bg-base-300 transition-all gap-2 px-4 u-in-reply-to">
<span class="i-heroicons-outline-reply my-auto !w-4 !h-4" />
{in_reply_to}
</a>
{/if}
</div>

View file

@ -18,15 +18,15 @@
{site.author.name}
</a>
<span class:hidden={preview} class="opacity-50">/</span>
<a href={post.path} class="swap hover:swap-active u-url u-uid">
<a href={post.path} class="u-url u-uid swap group/time">
<time
class="swap-off font-semibold opacity-75 duration-500 ease-in-out mr-auto dt-published"
class="group-hover/time:opacity-0 font-semibold opacity-75 duration-500 ease-in-out mr-auto dt-published"
datetime={jsonPublished}
itemprop="datePublished">
{stringPublished}
</time>
<time
class="swap-on font-semibold text-primary duration-500 ease-in-out mr-auto dt-updated"
class="opacity-0 group-hover/time:opacity-100 font-semibold text-primary duration-500 ease-in-out mr-auto dt-updated"
datetime={jsonUpdated}
itemprop="dateModified">
{stringUpdated}

View file

@ -4,7 +4,6 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte'
import Tree from '$lib/components/post_toc_tree.svelte'
export let toc: Urara.Post.Toc[]
let intersecting: string[] = []
@ -34,7 +33,7 @@
// @ts-ignore: Cannot find name 'headingsObserver'
if (typeof headingsObserver !== 'undefined') headingsObserver.disconnect()
// @ts-ignore: Cannot find name 'articleObserver'
if (typeof headingsObserver !== 'undefined') articleObserver.disconnect()
if (typeof articleObserver !== 'undefined') articleObserver.disconnect()
})
$: if (intersecting.length > 0) bordered = intersecting
@ -53,16 +52,29 @@
aria-label="TableOfContent"
dir="rtl"
class="max-h-[calc(100vh-12rem)] overflow-y-hidden hover:overflow-y-auto">
<Tree
toc={toc.reduce(
(acc, heading) => {
let parent = acc
// @ts-ignore Type 'Toc | undefined' is not assignable to type 'Toc.' ts(2322)
while (parent.depth + 1 < heading.depth) parent = parent.children.at(-1)
parent.children = [...(parent.children ?? []), { ...heading, children: [] }]
return acc
},
{ depth: toc[0].depth - 1, children: [] }
)} />
<ul dir="ltr" id="toc-list-root">
{#each toc as { depth, title, slug }}
<li id={`toc-item-${slug}`} class="flex flex-col">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<span
dir="ltr"
on:click={() =>
// @ts-ignore Object is possibly 'null'. ts(2531)
document.getElementById(slug).scrollIntoView({ behavior: 'smooth' })}
id={`toc-link-${slug}`}
class="cursor-pointer border-l-4 border-transparent transition-all hover:border-primary hover:bg-base-content hover:bg-opacity-10 active:bg-primary active:text-primary-content active:font-bold pr-4 {depth <=
2
? 'py-3'
: 'py-2'}"
class:pl-4={depth <= 2}
class:pl-8={depth === 3}
class:pl-12={depth === 4}
class:pl-16={depth === 5}
class:pl-20={depth === 6}>
{title}
</span>
</li>
{/each}
</ul>
</nav>
</aside>

View file

@ -1,33 +0,0 @@
<script lang="ts">
export let toc: Urara.Post.Toc
const { title, slug, depth, children } = toc
</script>
{#if title}
<span
dir="ltr"
on:click={() =>
// @ts-ignore Object is possibly 'null'. ts(2531)
document.getElementById(slug).scrollIntoView({ behavior: 'smooth' })}
id={`toc-link-${slug}`}
class="cursor-pointer border-l-4 border-transparent transition-all hover:border-primary hover:bg-base-content hover:bg-opacity-10 active:bg-primary active:text-primary-content active:font-bold pr-4 {depth <=
2
? 'py-3'
: 'py-2'}"
class:pl-4={depth <= 2}
class:pl-8={depth === 3}
class:pl-12={depth === 4}
class:pl-16={depth === 5}
class:pl-20={depth === 6}>
{title}
</span>
{/if}
{#if children}
<ul dir="ltr" id={`toc-list-${slug ?? 'root'}`}>
{#each children as child}
<li id={`toc-item-${child.slug}`} class="flex flex-col">
<svelte:self toc={child} />
</li>
{/each}
</ul>
{/if}

View file

@ -1,10 +1,37 @@
<script lang="ts">
/* @see {@link https://github.com/sveltejs/kit/issues/241#issuecomment-1363621896} */
type Image = {
src: string
w: number
h: number
}
const sources = import.meta.glob<Image[]>(['/src/static/**/*.{jpg,jpeg,png,webp,avif}', '!/src/static/assets'], {
query: {
format: 'avif',
quality: '80',
width: '736',
source: ''
},
import: 'default',
eager: true
})
let className: string | undefined = undefined
export { className as class }
export let src: string
export let alt: string = src
export let loading: 'eager' | 'lazy' = 'lazy'
export let decoding: 'async' | 'sync' | 'auto' = 'async'
let source: Image[] | undefined = sources[`/src/static${src}`]
</script>
{#if source}
<picture>
<source srcset={source.map(({ src, w }) => `${src} ${w}w`).join(', ')} type="image/avif" />
<img {src} {alt} class={className ?? 'rounded-lg my-2'} {loading} {decoding} />
</picture>
{:else}
<img {src} {alt} class={className ?? 'rounded-lg my-2'} {loading} {decoding} />
{/if}

View file

@ -0,0 +1,13 @@
<script lang="ts">
import { fly } from 'svelte/transition'
export let path: string = ''
</script>
{#key path}
<div
class="bg-base-100 md:bg-base-200 min-h-screen pt-16 md:pb-8 lg:pb-16"
in:fly={{ y: 100, duration: 300, delay: 300 }}
out:fly={{ y: -100, duration: 300 }}>
<slot />
</div>
{/key}

View file

@ -57,14 +57,14 @@ export const friends: Friend[] = [
rel: 'friend',
name: '夏诤',
title: 'SummberBlue',
link: 'https://summerblue.space/',
link: 'https://blog.summerrrrrr.blue',
descr: '早睡早起身体好'
},
{
id: 'loikin',
rel: 'friend',
name: 'Loikin',
title: '此生未命名',
title: '浣心',
link: 'https://blog.loikein.one/',
descr: '用爱和理性对抗荒谬',
avatar: '/assets/loikin.png'
@ -74,8 +74,42 @@ export const friends: Friend[] = [
rel: 'friend',
name: '鲨',
title: '一只脆脆鲨',
link: 'http://blog.sharktale.xyz/',
link: 'https://woods.sharktale.xyz/',
descr: '遇见一只脆脆鲨',
avatar: 'https://s2.loli.net/2022/03/30/xwOzn9G8TIqFPvR.jpg'
},
{
id: 'kwaa',
rel: 'friend',
name: '藍 +85CD',
title: './kwaa.dev',
link: 'https://kwaa.dev',
descr: '[DATA EXPUNGED]',
avatar: 'https://kwaa.dev/assets/any@512.webp'
},
{
id: 'debula',
rel: 'friend',
title: '秘密花园',
name: '本宝宝',
link: 'https://blog.debula.ml',
descr: '月亮一直跟着我走,它迷路了吗?',
avatar: 'https://blog.debula.ml/usr/uploads/violet.jpg'
},
{
id: 'zhuzi',
rel: 'friend',
title: 'Bambooom',
name: '竹子',
link: 'https://zhuzi.dev',
descr: 'Blah Blah Booooom'
},
{
id: 'litomore',
rel: 'friend',
title: "LitoMore's Mind",
name: 'LitoMore',
link: 'https://litomore.me',
avatar: 'https://litomore.me/favicon.svg'
}
]

View file

@ -1,121 +1,61 @@
import type { ThemeConfig, HeadConfig, HeaderConfig, FooterConfig, DateConfig, FeedConfig } from '$lib/types/general'
export const theme: ThemeConfig = [
{
name: 'lemonade',
text: 'Light'
},
{
name: 'night',
text: 'Dark'
},
{
name: 'cupcake',
text: 'Cupcake'
},
{
name: 'bumblebee',
text: 'Bumblebee'
},
{
name: 'emerald',
text: 'Emerald'
},
{
name: 'corporate',
text: 'Corporate'
},
{
name: 'valentine',
text: 'Valentine'
},
{
name: 'synthwave',
text: 'Synthwave'
},
{
name: 'retro',
text: 'Retro'
},
{
name: 'cyberpunk',
text: 'Cyberpunk'
},
{
name: 'halloween',
text: 'Halloween'
},
{
name: 'garden',
text: 'Garden'
},
{
name: 'forest',
text: 'Forest'
},
{
name: 'aqua',
text: 'Aqua'
},
{
name: 'lofi',
text: 'Lo-Fi'
},
{
name: 'pastel',
text: 'Pastel'
},
{
name: 'fantasy',
text: 'Fantasy'
},
{
name: 'wirefream',
text: 'Wireframe'
},
{
name: 'black',
text: 'Black'
},
{
name: 'luxury',
text: 'Luxury'
text: 'Light'
},
{
name: 'dracula',
text: 'Dracula'
},
{
name: 'cmyk',
text: 'CMYK'
},
{
name: 'autumn',
text: 'Autumn'
},
{
name: 'business',
text: 'Business'
},
{
name: 'acid',
text: 'Acid'
},
// {
// name: 'lemonade',
// text: 'Lemonade'
// },
// {
// name: 'night',
// text: '🌃 Night'
// },
{
name: 'coffee',
text: 'Coffee'
},
{
name: 'winter',
text: 'Winter'
name: 'cupcake',
text: 'Cupcake'
},
{
name: 'valentine',
text: 'Valentine'
},
{
name: 'aqua',
text: 'Aqua'
},
{
name: 'synthwave',
text: 'Synthwave'
},
{
name: 'night',
text: 'Night'
},
// {
// name: 'lofi',
// text: 'Lo-Fi'
// },
{
name: 'garden',
text: 'Garden'
},
{
name: 'lemonade',
text: 'Lemonade'
},
{
name: 'cmyk',
text: 'CMYK'
},
{
name: 'retro',
text: 'Retro'
},
{
name: 'black',
text: 'Black'
}
]
@ -160,12 +100,20 @@ export const header: HeaderConfig = {
{
text: 'About',
link: '/about'
},
{
text: 'etc',
children: [
{
text: 'Bookmarks',
link: 'https://airtable.com/shrpftxf6JgRomP2X'
},
{
text: 'Daily Notes',
link: 'https://x.seviche.cc'
}
]
}
// ,
// {
// text: 'Notes',
// link: '/notes'
// }
]
}
@ -180,30 +128,11 @@ export const footer: FooterConfig = {
link: '/privacy'
}
],
html: '<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a>'
html: '<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a>',
since: '2021'
}
export const date: DateConfig = {
// toPublishedString: {
// locales: 'en-US',
// options: {
// year: 'numeric',
// weekday: 'short',
// month: 'short',
// day: 'numeric',
// timeZone: 'Asia/Shanghai'
// }
// },
// toUpdatedString: {
// locales: 'en-US',
// options: {
// year: 'numeric',
// weekday: 'short',
// month: 'short',
// day: 'numeric',
// timeZone: 'Asia/Shanghai'
// }
// },
locales: 'en-US',
options: {
year: 'numeric',

View file

@ -5,14 +5,14 @@ export const post: PostConfig = {
post: ['mastodon']
},
comment: {
use: ['Webmention', 'Giscus'],
use: ['Remark42','Webmention', 'Giscus'],
style: 'boxed',
webmention: {
username: 'seviche.cc',
username: 'sevic.me',
sortBy: 'created',
sortDir: 'down',
form: true,
commentParade: true
commentParade: false
},
giscus: {
// src: 'https://giscus.kwaa.dev/client.js',
@ -22,16 +22,10 @@ export const post: PostConfig = {
categoryID: 'DIC_kwDOHSra4c4CO9ua',
theme: 'light',
lang: 'en'
}
// waline: {
// serverURL: 'https://waline-seviche.vercel.app/',
// lang: 'en',
// emoji: [
// 'https://cdn.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs',
// 'https://cdn.jsdelivr.net/gh/norevi/blob-emoji-for-waline@2.0/blobs-gif',
// 'ttps://cdn.jsdelivr.net/gh/norevi/blob-emoji-for-waline@2.0/blobs-png'
// ],
// requiredMeta: ['nick', 'mail']
// }
},
remark42: {
host: 'https://remark42.seviche.cc',
no_footer: true
}
}
}

View file

@ -19,6 +19,53 @@ export const projects: Project[] = [
// img: 'https://usc1.contabostorage.com/cc0b816231a841b1b0232d5ef0c6deb1:image/2022/06/d4d2489936e4f647c25df6982c6ef924.png',
// link: 'https://haibian.seviche.cc'
// },
{
id: 'Raycast-NeoDB',
name: 'Raycast - NeoDB',
tags: ['React', 'React Hooks', 'Fediverse', 'TypeScript'],
description: 'Search NeoDB items and view item details',
feature: 'React',
img: 'https://github.com/raycast/extensions/raw/f7cf284a8c14e38aee758adb00120de827a144fb/extensions/neodb//metadata/neodb-1.png',
link: 'https://www.raycast.com/SevicheCC/neodb'
},
{
id: 'Raycast-Mastodon',
name: 'Raycast - Mastodon',
tags: ['React', 'React Hooks', 'Fediverse', 'TypeScript'],
description: 'Publish status from Raycast to Mastodon, and view your bookmarked status',
feature: 'React',
img: 'https://github.com/raycast/extensions/raw/1824339d4b3b404efb53e4fb09ac79d190437773/extensions/mastodon//media/command.png',
link: 'https://www.raycast.com/SevicheCC/mastodon'
},
{
id: 'Raycast-miniflux',
name: 'Raycast - Miniflux',
tags: ['React', 'React Hooks', 'Fediverse', 'TypeScript'],
description: 'Search RSS entries from Raycast, and more features',
feature: 'React',
img: 'https://github.com/raycast/extensions/raw/3fdad375dd06b7f390b629235c6a10c37d05fc79/extensions/miniflux//media/commands.png',
link: 'https://www.raycast.com/SevicheCC/miniflux'
},
{
id: 'Raycast-Akkoma',
name: 'Raycast - Akkoma',
tags: ['React', 'React Hooks', 'Fediverse', 'TypeScript'],
description: 'Publish status from Raycast to Akkoma or Pleroma, and view your bookmarked status',
feature: 'React',
img: 'https://github.com/raycast/extensions/raw/42e765bc6bf970054fd69abfdc6ab3dd2ea4942d/extensions/akkoma//media/command.png',
link: 'https://www.raycast.com/SevicheCC/akkoma'
},
{
id: 'miniflux-injector',
name: 'Miniflux-injector',
tags: ['Svelte', 'Browser Extension', 'Miniflux', 'RSS'],
description:
"Browser extension for the self-hosted miniflux bookmark service. Fork from <a href='https://github.com/Fivefold/linkding-injector' target='_blank'>linkding-injector</a>",
feature: 'Svelte',
img: 'https://usc1.contabostorage.com/cc0b816231a841b1b0232d5ef0c6deb1:image/2022/12/7ae29e6a539895491fbb88a28c95aed7.png',
link: 'https://github.com/Sevichecc/miniflux-injector'
},
{
id: 'fokify',
name: 'Fokify ',

View file

@ -1,36 +1,32 @@
import type { SiteConfig } from '$lib/types/site'
export const site: SiteConfig = {
protocol: 'https://',
domain: 'seviche.cc',
title: 'Seviche.cc',
subtitle: 'Tech / Code / Random Life',
protocol: import.meta.env.URARA_SITE_PROTOCOL ?? import.meta.env.DEV ? 'http://' : 'https://',
domain: 'sevic.me',
title: 'sevic.me',
subtitle: 'Random Frontend-Developer',
lang: 'zh',
description: 'Tech / Code / Random Life',
description: 'Random Frontend-Developer',
author: {
name: '酸橘汁腌鱼',
avatar: '/assets/avatar.jpg',
name: 'Sevi.C',
avatar: '/assets/avatar.png',
status: '🖤',
bio: ' Code / Tech <br> Living a Random Life ',
bio: 'Full-stack wizard.',
metadata: [
{
text: '',
icon: 'i-mdi-github',
link: 'https://github.com/sevichecc'
},
{
text: '',
icon: 'i-simple-icons-matrix',
link: 'https://matrix.to/#/@seviche:kongwoo.icu'
},
{
text: '',
icon: 'i-heroicons-solid-key',
link: 'https://keys.openpgp.org/vks/v1/by-fingerprint/76DF9F9CC0C3619AA12CB914AFF18B986818D8AD',
link: '/assets/DDDDDDDD.asc',
rel: 'pgpkey'
},
{
text: '',
icon: 'i-ic-twotone-rss-feed',
link: '/atom.xml',
rel: 'rss'
@ -44,6 +40,6 @@ export const site: SiteConfig = {
// }
]
},
keywords: ['Tech', 'Code', 'Random Life'],
keywords: ['Tech', 'Code', 'Seviche CC', 'Frondend Developer', 'Programming'],
themeColor: '#3D4451'
}

View file

@ -1,10 +1,3 @@
import type { WalineEmojiInfo } from '@waline/client'
type WalineImageUploader = (image: File) => Promise<string>
type WalineHighlighter = (code: string, lang: string) => string
type WalineTexRenderer = (blockMode: boolean, tex: string) => string
export type PostConfig = {
bridgy?: {
[kind: string]: ('fed' | 'mastodon' | 'flickr' | 'github' | 'twitter')[]
@ -22,8 +15,7 @@ export type CommentConfig = {
giscus?: GiscusConfig
/** Utterances config, more at https://utteranc.es */
utterances?: UtterancesConfig
/** Waline config, more at https://waline.js.org/en/reference/component.html#texrenderer */
waline?: WalineConfig
remark42?: Remark42Config
}
export type WebmentionConfig = {
@ -81,39 +73,35 @@ export type UtterancesConfig = {
theme?: string
}
export type DisqusConfig = {
shortname: string
lang?: string
}
// Refhttps://waline.js.org/reference/component.html
export type WalineConfig = {
/** Waline server address url */
serverURL: string
/** Article path id*/
path?: string
/** Display language. */
lang?: string
/** Emoji settings, for details see https://waline.js.org/en/guide/client/emoji.html */
emoji?: (string | WalineEmojiInfo)[] | false
/** Darkmode support */
dark?: string | boolean
/** Reviewer attributes. Optional values: 'nick', 'mail', 'link' */
meta?: string[]
/** Set required fields*/
requiredMeta?: string[]
/** login mode status */
login?: string
/** Comment word s limit. */
wordLimit?: number | [number, number]
/**number of comments per page. */
pageSize?: number
/** Custom image upload method. */
imageUploader?: WalineImageUploader | false
/** Code highlighting, use hanabi by default */
highlighter?: WalineHighlighter | false
/** Customize \TeX rendering */
texRender?: WalineTexRenderer | false
/** Whether show copyright and version in footer. */
copyright?: boolean
export type Remark42Config = {
/** hostname of Remark42 server, same as REMARK_URL in backend config, e.g. "https://demo.remark42.com" */
host: string
/** the SITE that you passed to Remark42 instance on start of backend. (default: remark) */
site_id?: string
/** url to the page with comments*/
url?: string
/** an array of widgets that should be rendered on a page (default: ['embed'] )*/
components?: ['embed' | 'last-comments' | 'counter']
/** maximum number of comments that is rendered on mobile version (default: 15 )*/
max_shown_comments?: number
/** maximum number of comments in the last comments widget (default: 15 )*/
max_last_comments?: number
/** changes UI theme, (default: light )*/
theme?: 'light' | 'dark'
/** title for current comments page (default: document.title)*/
page_title?: string
/**
* interface localization,
* English (en), Belarusian (be), Brazilian Portuguese (bp), Bulgarian (bg), Chinese (zh), Finnish (fi), French (fr), German (de), Japanese (ja), Korean (ko), Polish (pl), Russian (ru), Spanish (es), Turkish (tr), Ukrainian (ua), Italian (it) and Vietnamese (vi)
* default: en
*/
locale?: 'en' | 'be' | 'bp' | 'bg' | 'zh' | 'fi' | 'fr' | 'de' | 'ja' | 'ko' | 'pl' | 'ru' | 'es' | 'tr' | 'ua' | 'it' | 'vi'
/** enables email subscription (default: true) */
show_email_subscription?: boolean
/** enables RSS subscription, (default: true) */
show_rss_subscription?: boolean
/** minimized UI with basic info only, (default: false) */
simple_view?: boolean
/** hides footer with signature and links to Remark42,(default: false) */
no_footer?: boolean
}

View file

@ -1,8 +1,6 @@
import type { FFFAuthor } from 'fff-flavored-frontmatter'
export type SiteConfig = {
/** @deprecated - use `description` instead */
descr?: string
/** site protocol. for example: `https://` */
protocol: string
/** site domain. for example: `example.com` */

40
src/routes/+layout.svelte Normal file
View file

@ -0,0 +1,40 @@
<script lang="ts">
import type { LayoutData } from './$types'
import { onMount } from 'svelte'
import { browser, dev } from '$app/environment'
import { genTags } from '$lib/utils/posts'
import { posts, tags } from '$lib/stores/posts'
import { registerSW } from 'virtual:pwa-register'
import Head from '$lib/components/head_static.svelte'
import Header from '$lib/components/header.svelte'
import Transition from '$lib/components/transition.svelte'
import 'uno.css'
import '../app.pcss'
export let data: LayoutData
let { res, path } = data
$: if (data) path = data.path
posts.set(res)
tags.set(genTags(res))
onMount(
() =>
!dev &&
browser &&
registerSW({
immediate: true,
onRegistered: r => r && setInterval(async () => await r.update(), 198964),
onRegisterError: error => console.error(error)
})
)
</script>
<Head />
<Header {path} />
<Transition {path}>
<slot />
</Transition>

7
src/routes/+layout.ts Normal file
View file

@ -0,0 +1,7 @@
import type { LayoutLoad } from './$types'
export const prerender = true
export const trailingSlash = 'always'
export const load: LayoutLoad = async ({ url, fetch }) => ({
path: url.pathname,
res: await fetch('/posts.json').then(res => res.json())
})

View file

@ -2,15 +2,14 @@
import { onMount } from 'svelte'
import { fly } from 'svelte/transition'
import { page } from '$app/stores'
import { browser } from '$app/env'
import { browser } from '$app/environment'
import { goto } from '$app/navigation'
import { posts as storedPosts, tags as storedTags } from '$lib/stores/posts'
import { title as storedTitle } from '$lib/stores/title'
import Head from '$lib/components/head.svelte'
import Footer from '$lib/components/footer.svelte'
import Post from '$lib/components/post_card.svelte'
// import Post from '$lib/components/index_post.svelte'
import Profile from '$lib/components/index_profile.svelte'
import RemoteFollow from '$lib/components/extra/follow.svelte'
let allPosts: Urara.Post[]
let allTags: string[]
@ -19,9 +18,7 @@
storedTitle.set('')
$: storedPosts.subscribe(
storedPosts => (allPosts = (storedPosts as Urara.Post[]).filter(post => !post.flags?.includes('unlisted')))
)
$: storedPosts.subscribe(storedPosts => (allPosts = storedPosts.filter(post => !post.flags?.includes('unlisted'))))
$: storedTags.subscribe(storedTags => (allTags = storedTags as string[]))
@ -30,7 +27,7 @@
$: if (tags) {
posts = !tags ? allPosts : allPosts.filter(post => tags.every(tag => post.tags?.includes(tag)))
if (browser && window.location.pathname === '/')
window.history.replaceState({}, '', tags.length > 0 ? `?tags=${tags.toString()}` : `/`)
goto(tags.length > 0 ? `?tags=${tags.toString()}` : `/`, { replaceState: true })
}
onMount(() => {
@ -125,5 +122,3 @@
{/key}
</div>
</div>
<RemoteFollow />

View file

@ -1,38 +0,0 @@
<script lang="ts" context="module">
import type { Load } from './__types'
export const load: Load = ({ url: { pathname }, error, status }) => ({ props: { pathname, error, status } })
</script>
<script lang="ts">
import Head from '$lib/components/head.svelte'
import Footer from '$lib/components/footer.svelte'
export let pathname: string
export let error: Error
export let status: string
console.error(status, error.message)
</script>
<Head page={{ title: status ?? '404', path: pathname ?? '/404' }} />
<div class="flex flex-col flex-nowrap justify-center xl:flex-row xl:flex-wrap">
<div class="flex-none w-full max-w-screen-md mx-auto xl:mx-0">
<article
itemscope
itemtype="https://schema.org/BlogPosting"
class="card bg-base-100 rounded-none md:rounded-box shadow-xl md:mb-8 z-10">
<main itemprop="articleBody" class="card-body prose urara-prose">
<h1 class="opacity-20 text-6xl md:text-[12rem] -mt-2 mb-0">
{status ?? '404'}
</h1>
<h2 class="-mt-12 md:-mt-24">{error.message ?? 'Not found'}</h2>
<div class="card-actions">
<a href="/" class="btn btn-neutral no-underline shadow-xl hover:shadow-2xl mt-8">
<span class="i-heroicons-outline-home -ml-1 mr-2" />
Back to Home
</a>
</div>
</main>
</article>
<Footer sticky={true} class="flex-1 md:flex-initial" />
</div>
</div>

View file

@ -1,49 +0,0 @@
<script lang="ts" context="module">
import type { Load } from './__types'
export const prerender = true
export const load: Load = async ({ url, fetch }) => ({
props: {
path: url.pathname,
res: await fetch('/posts.json').then(res => res.json())
}
})
</script>
<script lang="ts">
import { onMount } from 'svelte'
import { browser, dev } from '$app/env'
import { fly } from 'svelte/transition'
import { genTags } from '$lib/utils/posts'
import { posts, tags } from '$lib/stores/posts'
import { registerSW } from 'virtual:pwa-register'
import Head from '$lib/components/head_static.svelte'
import Header from '$lib/components/header.svelte'
import 'uno.css'
import '../app.css'
export let res: Urara.Post[]
export let path: string
posts.set(res)
tags.set(genTags(res))
onMount(
() =>
!dev &&
browser &&
registerSW({
onRegistered: r => r && setInterval(async () => await r.update(), 198964),
onRegisterError: error => console.error(error)
})
)
</script>
<Head />
<Header {path} />
{#key path}
<div
class="bg-base-100 md:bg-base-200 min-h-screen pt-16 md:pb-8 lg:pb-16"
in:fly={{ y: 100, duration: 300, delay: 300 }}
out:fly={{ y: -100, duration: 300 }}>
<slot />
</div>
{/key}

View file

@ -1,12 +1,11 @@
import type { RequestHandler } from '@sveltejs/kit'
import type { RequestHandler } from './$types'
import { site } from '$lib/config/site'
import { feed } from '$lib/config/general'
import { favicon } from '$lib/config/icon'
import { genPosts, genTags } from '$lib/utils/posts'
const render = async (
posts = genPosts({ postHtml: true, postLimit: feed.limit, filterUnlisted: true })
): Promise<string> => `<?xml version='1.0' encoding='utf-8'?>
const render = (posts = genPosts({ postHtml: true, postLimit: feed.limit, filterUnlisted: true })): string =>
`<?xml version='1.0' encoding='utf-8'?>
<feed xmlns="http://www.w3.org/2005/Atom">
<id>${site.protocol + site.domain}/</id>
<title><![CDATA[${site.title}]]></title>${site.subtitle ? `\n <subtitle><![CDATA[${site.subtitle}]]></subtitle>` : ''}${
@ -39,11 +38,13 @@ const render = async (
</entry>`
)
.join('')}
</feed>`
</feed>`.trim()
export const GET: RequestHandler = async () => ({
export const prerender = true
export const trailingSlash = 'never'
export const GET: RequestHandler = async () =>
new Response(render(), {
headers: {
'Content-Type': 'application/atom+xml; charset=utf-8'
},
body: await render()
'content-type': 'application/atom+xml; charset=utf-8'
}
})

View file

@ -1,10 +1,11 @@
import type { RequestHandler } from '@sveltejs/kit'
import type { RequestHandler } from './$types'
import { json } from '@sveltejs/kit'
import { site } from '$lib/config/site'
import { feed } from '$lib/config/general'
import { favicon, any } from '$lib/config/icon'
import { genPosts } from '$lib/utils/posts'
const render = async (posts = genPosts({ postHtml: true, postLimit: feed.limit, filterUnlisted: true })) => ({
const render = (posts = genPosts({ postHtml: true, postLimit: feed.limit, filterUnlisted: true })) => ({
version: 'https://jsonfeed.org/version/1.1',
title: site.title,
home_page_url: site.protocol + site.domain,
@ -41,9 +42,11 @@ const render = async (posts = genPosts({ postHtml: true, postLimit: feed.limit,
}))
})
export const GET: RequestHandler = async () => ({
export const prerender = true
export const trailingSlash = 'never'
export const GET: RequestHandler = async () =>
json(render(), {
headers: {
'Content-Type': 'application/feed+json; charset=utf-8'
},
body: JSON.stringify(await render(), null, 2)
'content-type': 'application/feed+json; charset=utf-8'
}
})

View file

@ -1,9 +1,10 @@
<script lang="ts">
// @ts-nocheck
import Masonry from 'svelte-bricks'
import type { Friend } from '$lib/config/friends'
import { friends as allFriends } from '$lib/config/friends'
import { title as storedTitle } from '$lib/stores/title'
import Head from '$lib/components/head.svelte'
import Masonry from 'svelte-bricks'
import FriendComponent from '$lib/components/extra/friend.svelte'
const rnd = Math.random()
@ -16,7 +17,7 @@
storedTitle.set('')
</script>
<Head />
<Head page={{ title: 'Friends', path: '/friends' }} />
<Masonry
{items}

View file

@ -1,32 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit'
import { site } from '$lib/config/site'
import { any, maskable } from '$lib/config/icon'
export const GET: RequestHandler = () => ({
headers: {
'Content-Type': 'application/manifest+json; charset=utf-8'
},
body: JSON.stringify(
{
name: site.title,
short_name: site.title,
lang: site.lang,
description: site.description,
id: site.protocol + site.domain + '/',
start_url: '/',
scope: '/',
display: 'standalone',
orientation: 'portrait',
background_color: site.themeColor,
theme_color: site.themeColor,
icons: [
...Object.values(any)
.filter(icon => icon.sizes !== '180x180')
.map(icon => ({ ...icon, purpose: 'any' })),
...Object.values(maskable).map(icon => ({ ...icon, purpose: 'maskable' }))
]
},
null,
2
)
})

View file

@ -0,0 +1,37 @@
import type { RequestHandler } from './$types'
import { site } from '$lib/config/site'
import { any, maskable } from '$lib/config/icon'
export const prerender = true
export const trailingSlash = 'never'
export const GET: RequestHandler = () =>
new Response(
JSON.stringify(
{
name: site.title,
short_name: site.title,
lang: site.lang,
description: site.description,
id: site.protocol + site.domain + '/',
start_url: '/',
scope: '/',
display: 'standalone',
orientation: 'portrait',
background_color: site.themeColor,
theme_color: site.themeColor,
icons: [
...Object.values(any)
.filter(icon => icon.sizes !== '180x180')
.map(icon => ({ ...icon, purpose: 'any' })),
...Object.values(maskable).map(icon => ({ ...icon, purpose: 'maskable' }))
]
},
null,
2
),
{
headers: {
'Content-Type': 'application/manifest+json; charset=utf-8'
}
}
)

View file

@ -1,9 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit'
import { genPosts } from '$lib/utils/posts'
export const GET: RequestHandler = async () => ({
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
body: JSON.stringify(genPosts(), null, 2)
})

View file

@ -0,0 +1,7 @@
import type { RequestHandler } from './$types'
import { json } from '@sveltejs/kit'
import { genPosts } from '$lib/utils/posts'
export const prerender = true
export const trailingSlash = 'never'
export const GET: RequestHandler = async () => json(genPosts())

View file

@ -1,27 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit'
import { site } from '$lib/config/site'
import { genPosts } from '$lib/utils/posts'
const render = async (): Promise<string> => `<?xml version='1.0' encoding='utf-8'?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>${site.protocol + site.domain}</loc>
</url>
${genPosts()
.map(
post => `
<url>
<loc>${site.protocol + site.domain + post.path}</loc>
<lastmod>${new Date(post.updated ?? post.published ?? post.created).toISOString()}</lastmod>
<priority>0.5</priority>
</url>`
)
.join('')}
</urlset>`
export const GET: RequestHandler = async () => ({
headers: {
'Content-Type': 'application/xml; charset=utf-8'
},
body: await render()
})

View file

@ -0,0 +1,36 @@
import type { RequestHandler } from './$types'
import { site } from '$lib/config/site'
import { genPosts } from '$lib/utils/posts'
const render = (): string =>
`<?xml version='1.0' encoding='utf-8'?>
<urlset
xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="https://www.w3.org/1999/xhtml"
xmlns:mobile="https://www.google.com/schemas/sitemap-mobile/1.0"
xmlns:news="https://www.google.com/schemas/sitemap-news/0.9"
xmlns:image="https://www.google.com/schemas/sitemap-image/1.1"
xmlns:video="https://www.google.com/schemas/sitemap-video/1.1">
<url>
<loc>${site.protocol + site.domain}</loc>
</url>
${genPosts()
.map(
post => `
<url>
<loc>${site.protocol + site.domain + post.path}</loc>
<lastmod>${new Date(post.updated ?? post.published ?? post.created).toISOString()}</lastmod>
<priority>0.5</priority>
</url>`
)
.join('')}
</urlset>`.trim()
export const prerender = true
export const trailingSlash = 'never'
export const GET: RequestHandler = async () =>
new Response(render(), {
headers: {
'content-type': 'application/xml; charset=utf-8'
}
})

View file

@ -1,9 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit'
import { genPosts, genTags } from '$lib/utils/posts'
export const GET: RequestHandler = async () => ({
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
body: JSON.stringify(genTags(genPosts()), null, 2)
})

View file

@ -0,0 +1,7 @@
import type { RequestHandler } from './$types'
import { json } from '@sveltejs/kit'
import { genPosts, genTags } from '$lib/utils/posts'
export const prerender = true
export const trailingSlash = 'never'
export const GET: RequestHandler = async () => json(genTags(genPosts()))

View file

@ -1,29 +1,35 @@
// sveltekit config type
import type { Config } from '@sveltejs/kit'
// svelte preprocess
import preprocess from 'svelte-preprocess'
import adapterAuto from '@sveltejs/adapter-auto'
import adapterNode from '@sveltejs/adapter-node'
// svelte adapter
import adapterVercel from '@sveltejs/adapter-vercel'
import adapterNetlify from '@sveltejs/adapter-netlify'
import adapterStatic from '@sveltejs/adapter-static'
// svelte preprocessor
import { mdsvex } from 'mdsvex'
import mdsvexConfig from './mdsvex.config.js'
import { vitePreprocess } from '@sveltejs/kit/vite'
const defineConfig = (config: Config) => config
export default defineConfig({
export default {
extensions: ['.svelte', ...(mdsvexConfig.extensions as string[])],
preprocess: [mdsvex(mdsvexConfig), preprocess()],
preprocess: [mdsvex(mdsvexConfig), vitePreprocess()],
kit: {
adapter: Object.keys(process.env).some(key => ['VERCEL', 'CF_PAGES', 'NETLIFY'].includes(key))
? adapterAuto()
: process.env.ADAPTER === 'node'
? adapterNode({ out: 'build' })
adapter: Object.keys(process.env).some(key => key === 'VERCEL')
? adapterVercel()
: Object.keys(process.env).some(key => key === 'NETLIFY')
? adapterNetlify()
: adapterStatic({
pages: 'build',
assets: 'build',
fallback: undefined
}),
csp: { mode: 'auto' },
prerender: { default: true }
prerender: {
handleMissingId: 'warn'
},
csp: {
mode: 'auto',
directives: {
'style-src': ['self', 'unsafe-inline', 'https://giscus.app']
}
})
}
}
} as Config

View file

@ -1,63 +1,12 @@
// tailwind config type
import type { TailwindConfig } from 'tailwindcss/tailwind-config'
// @ts-ignore TS2305: Module 'tailwindcss/plugin' has no exported member 'TailwindPluginWithoutOptions'.
import type { TailwindPluginWithoutOptions } from 'tailwindcss/plugin'
// tailwind plugins
import { theme } from './src/lib/config/general'
// @ts-ignore Could not find a declaration file for module '@tailwindcss/typography'.
import typography from '@tailwindcss/typography'
// @ts-ignore Could not find a declaration file for module 'daisyui'.
import daisyui from 'daisyui'
interface Config extends TailwindConfig {
daisyui?: {
styled?: boolean
themes?: boolean | string[]
base?: boolean
utils?: boolean
logs?: boolean
rtl?: boolean
darkTheme?: string
prefix?: string
}
}
const defineConfig = (config: Config) => config
export default defineConfig({
export default {
content: ['./src/**/*.{html,md,js,svelte,ts}'],
theme: {
extend: {}
},
plugins: [typography as TailwindPluginWithoutOptions, daisyui as TailwindPluginWithoutOptions],
daisyui: {
themes: [
'light',
'dark',
'cupcake',
'bumblebee',
'emerald',
'corporate',
'synthwave',
'retro',
'cyberpunk',
'valentine',
'halloween',
'garden',
'forest',
'aqua',
'lofi',
'pastel',
'fantasy',
'wireframe',
'black',
'luxury',
'dracula',
'cmyk',
'autumn',
'business',
'acid',
'lemonade',
'night',
'coffee',
'winter'
]
theme: { extend: {} },
plugins: [typography, daisyui],
daisyui: { themes: theme.map(({ name }) => name) }
}
})

View file

@ -9,7 +9,7 @@ import chokidar from 'chokidar'
import chalk from 'chalk'
const config = {
extensions: ['svelte', 'md', 'js', 'ts'],
extensions: ['md'],
catch: ['ENOENT', 'EEXIST']
}
@ -102,7 +102,7 @@ const clean = () => {
switch (process.argv[2]) {
case 'watch':
{
let watcher = chokidar.watch('urara', {
const watcher = chokidar.watch('urara', {
ignored: (file: string) => path.basename(file).startsWith('.')
})
watcher

View file

@ -0,0 +1,27 @@
{
"aliases": [
"https://kongwoo.icu/users/blog"
],
"links": [
{
"href": "https://kongwoo.icu/users/blog",
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html"
},
{
"href": "https://kongwoo.icu/users/blog",
"rel": "self",
"type": "application/activity+json"
},
{
"href": "https://kongwoo.icu/users/blog",
"rel": "self",
"type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
"template": "https://kongwoo.icu/ostatus_subscribe?acct={uri}"
}
],
"subject": "acct:blog@kongwoo.icu"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View file

@ -12,7 +12,7 @@ lastmod: 2022-04-16T12:54:20.049Z
## 书签这回事
上回说到用 [自建网页书签 Flare](https://seviche.cc/blog/flare/) ,今天不小心把 SSH 链接弄坏了也就是连不上了因为搭载的服务不多所以把整个服务器都重装了Flare 网页书签也炸了。
上回说到用 [自建网页书签 Flare](https://sevic.me/blog/flare/) ,今天不小心把 SSH 链接弄坏了也就是连不上了因为搭载的服务不多所以把整个服务器都重装了Flare 网页书签也炸了。
其实搭建之后我没有用过(一次都没有),平时的书签管理主要靠搜索,各个浏览器之间的书签互相导入后,直接在搜索栏搜,如果是常用的网址,我用 Chorme 扩展 [eesel](https://chrome.google.com/webstore/detail/eesel-productivity-at-wor/jffaiidojfhflballoapgofphkadiono) 来解决,它可以列出最近用过的网页,按站点分类,查找起来很方便

View file

@ -2,16 +2,9 @@
title: Miniflux · 保存文章到 Pocket 以及 RSS
summary: 将 Miniflux 上的文章到保存到 Pocket/Instapaper,以及 RSS 相关文章和资源
created: 2022-03-10T16:24:38.663Z
preview: ''
draft: ''
tags:
- RSS
- Miniflux
changelogs:
- tag: '202203011'
summary:
- 添加了`instapaper`的连接方式
- 添加了Pocket按钮嵌入方式
lastmod: 2022-04-07T07:38:52.406Z
---

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -1,87 +0,0 @@
---
title: Git · 常用操作笔记
created: 2022-05-25
summary: 每次更新博客进行的操作以及常见错误处理
tags:
- Git
---
**资料:**
- [GIT CHEAT SHEET](https://education.github.com/git-cheat-sheet-education.pdf)
- [45 个 Git 经典操作场景,专治不会合代码](https://mp.weixin.qq.com/s/BzdgZXyM1UaNCUCXySL9Rw)
- [版本控制(Git) - 计算机教育中缺失的一课](https://missing-semester-cn.github.io/2020/version-control/)
- [战壕里面的 GitGit In The Trenches](http://cbx33.github.io/gitt/intro.html)
## 每次更新博客进行的操作
### 1. 追踪所有文件
(除了 gitignore 里面的),也可以单独加
`git add -A`
### 2. 提交上传信息
`git commit -m '一些信息如fixed something etc'`
### 3. push 到 Github
`git push origin main`
等待一会儿就好了,如果不行,换个网或者关掉 VPN 看看
## 常用 Git 操作
- `.gitignore`: 放不想传到 git repo 的文件/文件夹
- 当内容改动很多的时候,最好开一个 branch
- VSCode 文件后面的字母:
- Uuntrack
- M: modified
- A : on track
- 一般不在`main` 或`master` 修改代码,而是开一个 branch确定好后再 merge
- 下载叫做 pull上传是 push
| 命令 | 作用 |
| :----------------------------------------------------------- | ------------------------------------------------- |
| `git config --global user.name 名字` | 设置名字 |
| `git config --global user.email 邮箱` | 设置邮件 |
| `git init` | 初始化 |
| `git add -A` | 追踪所有文件(除了 gitignore 里面的),也可以单独加 |
| `git commit -m` | m 代表信息,后面要写 commit 相关信息 |
| `git status` | 查看 git 状态/信息 |
| `git log` | 查看 commit 日志,按 Q 才可以退出 |
| `git reset hard (commit的id` | 回到特定版本 |
| `git reset hard --HEAD` | 返回上一次改动 (还没有 commit) |
| `git branch` | 列出现在有的 branch,按 Q 退出 |
| `git branch branch'name)` | 创建新 branch |
| `git merge branch'name)` | 合并 branch 到 main |
| `git checkout (branch's name)` | 切换 branch |
| `git remote add origin https://github.com/用户名/仓库名.git` | 链接到 remote repo |
| `git pull` | 拉更新 |
| `git push origin (branch'name)` | push 到 remote repo |
## 常见问题
下面是一些我看过的文章
### 版本回滚
- [项目中 git 怎么回退到之前的版本 & git 放弃本地修改,强制拉取更新](https://mp.weixin.qq.com/s/MCtCQg7rcokf6IrZVINF4w)
- [Git 学习笔记:版本回退](https://mp.weixin.qq.com/s/98wEvWU6OYVkPauWn-XXng)
- [如果你还不会用 git 回滚代码,那你一定要来看看](https://mp.weixin.qq.com/s/FPiSyeivTKhoAgJmORZFog)
### 报错处理
- [git push 错误 failed to push some refs to 解决方法](https://blog.csdn.net/qq_39416311/article/details/102219428)
- [git 上传忽略 node_modules](https://blog.csdn.net/jiandan1127/article/details/81205530)
### 博客相关
- [GitHub Pages 绑定来自阿里云的域名](https://blog.csdn.net/qq_29232943/article/details/52786603)
- [Hexo 发布到 Github 丢失 readme 和 CNAME 解决方案](https://www.cnblogs.com/LandWind/articles/8269636.html)
- [把 HUGO 博客托管到 GITHUB 上](https://www.freesion.com/article/37111127345/)
### 其他
- [Github 上如何添加 LICENSE 文件?](https://www.cnblogs.com/chenmingjun/p/8555906.html)

Some files were not shown because too many files have changed in this diff Show more