13 Commits
Author SHA1 Message Date
klemek 49978afd4c fix: space missing between footer parts
Lint / Oxlint (push) Successful in 57s
Lint / TypeScript (push) Successful in 1m1s
Lint / ESLint (push) Successful in 1m4s
Deploy / Build (push) Successful in 1m39s
Deploy / Deploy to Stapler (push) Successful in 4m16s
2026-07-20 15:24:54 +02:00
klemek 1079ae9df1 feat: indieweb standards
Lint / ESLint (push) Successful in 2m3s
Lint / Oxlint (push) Successful in 2m3s
Lint / TypeScript (push) Successful in 2m14s
Deploy / Build (push) Successful in 5m4s
Deploy / Deploy to Stapler (push) Successful in 4m9s
2026-07-20 11:06:21 +02:00
klemek 2145c0f703 tools: add 0.0.0.0 server
Deploy / Build (push) Successful in 1m42s
Deploy / Deploy to Stapler (push) Successful in 1m20s
2026-07-19 16:05:29 +02:00
klemek b70d4d7b38 chore: release 1.9.4
Deploy / Build (push) Successful in 7m33s
Lint / ESLint (push) Successful in 3m52s
Lint / Oxlint (push) Successful in 2m55s
Deploy / Deploy to Stapler (push) Successful in 3m23s
Lint / TypeScript (push) Successful in 4m42s
2026-07-17 11:39:21 +02:00
klemek f0eb08b97a fix(vite): better obfuscate
Deploy / Deploy to Stapler (push) Has been cancelled
Deploy / Build (push) Has been cancelled
Lint / ESLint (push) Has been cancelled
Lint / Oxlint (push) Has been cancelled
Lint / TypeScript (push) Has been cancelled
2026-07-17 11:39:17 +02:00
klemek 303e8e2dd2 chore: release 1.9.3
Deploy / Build (push) Successful in 1m13s
Lint / ESLint (push) Successful in 2m58s
Deploy / Deploy to Stapler (push) Successful in 3m15s
Lint / Oxlint (push) Successful in 3m36s
Lint / TypeScript (push) Successful in 3m31s
2026-07-17 11:15:09 +02:00
klemek c567a6a9d5 tools(make): release target 2026-07-17 11:13:17 +02:00
klemek f92baf3b82 feat: obfuscate build files
Deploy / Build (push) Has been cancelled
Deploy / Deploy to Stapler (push) Has been cancelled
Lint / ESLint (push) Has been cancelled
Lint / Oxlint (push) Has been cancelled
Lint / TypeScript (push) Has been cancelled
2026-07-17 11:09:43 +02:00
klemek 6680d464c3 ci: detect changes and use actions/stapler-deploy
Lint / Oxlint (push) Successful in 3m36s
Lint / ESLint (push) Successful in 3m36s
Lint / TypeScript (push) Successful in 3m36s
Deploy / Deploy to Stapler (push) Successful in 4m24s
Deploy / Build (push) Successful in 6m3s
2026-05-02 23:50:47 +02:00
klemek b6a5460a04 fix(ci): bug with Type Check job name
Lint / TypeScript (push) Successful in 18m9s
Lint / ESLint (push) Successful in 18m48s
Lint / Oxlint (push) Successful in 18m32s
Deploy / Build (push) Successful in 19m31s
Deploy / Deploy to Stapler (push) Successful in 3m54s
2026-05-02 21:16:42 +02:00
klemek 84c408d149 fix(deploy): stapler fail with body
Lint / Type Check (push) Failing after 7m40s
Lint / Oxlint (push) Successful in 10m30s
Lint / ESLint (push) Successful in 10m36s
Deploy / Build (push) Successful in 11m13s
Deploy / Deploy to Stapler (push) Successful in 3m35s
2026-05-02 20:11:31 +02:00
klemek 53d366f6b6 ci: use local bun action
Lint / Type Check (push) Failing after 2m2s
Lint / Oxlint (push) Successful in 2m14s
Lint / ESLint (push) Successful in 2m57s
Deploy / Build (push) Successful in 2m58s
Deploy / Deploy to Stapler (push) Successful in 3m56s
2026-05-02 19:57:21 +02:00
klemek 6beca83fa3 fix(actions): dont add bun version latest
Lint / Type Check (push) Failing after 5m19s
Lint / Oxlint (push) Successful in 6m57s
Lint / ESLint (push) Successful in 7m25s
Deploy / Deploy to Stapler (push) Successful in 2m53s
Deploy / Build (push) Successful in 8m12s
2026-05-02 00:49:39 +02:00
13 changed files with 693 additions and 295 deletions
+20 -13
View File
@@ -7,17 +7,26 @@ concurrency:
on: on:
push: push:
branches: branches:
- 'main' - "main"
paths:
- '.github/workflows/deploy.yml'
- 'package.json'
- 'bun.lock'
- 'src/**'
- 'index.html'
- 'vite.config.ts'
- 'post-build.ts'
- 'tsconfig.*'
- 'env.d.ts'
- 'vite.d.ts'
jobs: jobs:
build: build:
name: "Build" name: "Build"
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Setup Bun - name: Set up Bun
uses: https://github.com/oven-sh/setup-bun@v2 uses: actions/setup-bun@v2
with:
bun-version: latest
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Install dependencies - name: Install dependencies
@@ -41,18 +50,16 @@ jobs:
name: "Deploy to Stapler" name: "Deploy to Stapler"
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: ${{ vars.STAPLER_TARGET != '' }}
steps: steps:
- name: Download production files - name: Download production files
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3
with: with:
name: production-files name: production-files
path: ./dist path: ./dist
- name: Compress production files
run: tar -czC dist -f dist.tar.gz .
- name: Upload to Stapler server - name: Upload to Stapler server
run: | uses: actions/stapler-deploy@v1
curl -s -X PUT --data-binary "@dist.tar.gz" \ with:
-H 'X-Token: ${{ secrets.STAPLER_TOKEN }}' \ path: dist
${{ vars.STAPLER_CURL_ARGS }} \ token: ${{ secrets.STAPLER_TOKEN }}
${{ vars.STAPLER_TARGET }} target: ${{ github.repository }}
extra_curl_args: ${{ vars.STAPLER_CURL_ARGS }}
+22 -15
View File
@@ -4,17 +4,28 @@ concurrency:
group: lint-${{ github.ref }} group: lint-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
on: [push, workflow_dispatch] on:
workflow_dispatch:
push:
paths:
- '.github/workflows/lint.yml'
- 'package.json'
- 'bun.lock'
- 'src/**'
- 'articles.example/**'
- '.oxlintrc.json'
- 'eslint.config.ts'
- 'tsconfig.*'
- 'env.d.ts'
- 'vite.d.ts'
jobs: jobs:
lint-eslint: lint-eslint:
name: 'ESLint' name: 'ESLint'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Setup Bun - name: Set up Bun
uses: https://github.com/oven-sh/setup-bun@v2 uses: actions/setup-bun@v2
with:
bun-version: latest
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Install dependencies - name: Install dependencies
@@ -28,10 +39,8 @@ jobs:
name: 'Oxlint' name: 'Oxlint'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Setup Bun - name: Set up Bun
uses: https://github.com/oven-sh/setup-bun@v2 uses: actions/setup-bun@v2
with:
bun-version: latest
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Install dependencies - name: Install dependencies
@@ -41,14 +50,12 @@ jobs:
- name: Run Oxlint - name: Run Oxlint
run: bun run lint:oxlint run: bun run lint:oxlint
type-check: tsc:
name: Type Check name: 'TypeScript'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Setup Bun - name: Set up Bun
uses: https://github.com/oven-sh/setup-bun@v2 uses: actions/setup-bun@v2
with:
bun-version: latest
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Install dependencies - name: Install dependencies
-9
View File
@@ -1,9 +0,0 @@
{
"recommendations": [
"Vue.volar",
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"oxc.oxc-vscode",
"esbenp.prettier-vscode"
]
}
+10 -2
View File
@@ -31,8 +31,8 @@ node_modules: bun.lock
.PHONY: install .PHONY: install
install: npm-install ## install project install: npm-install ## install project
.PHONY: install .PHONY: update
install: npm-update ## update project update: npm-update ## update project
.PHONY: build .PHONY: build
build: npm-run-build ## build static site in "dist" build: npm-run-build ## build static site in "dist"
@@ -59,3 +59,11 @@ npm-update: ## npm update
.PHONY: npm-run-% .PHONY: npm-run-%
npm-run-%: node_modules ## npm run (script) npm-run-%: node_modules ## npm run (script)
$(NPM) run $* $(NPM) run $*
.PHONY: release-%
release-%: node_modules ## release major/minor/patch
$(NPM) pm version $* --no-git-tag-version || true
git add package.json
git commit -m "chore: release $$(cat package.json | jq -r .version)"
git tag "release/$$(cat package.json | jq -r .version)" -m "md-blog $$(cat package.json | jq -r .version)"
+2 -1
View File
@@ -11,5 +11,6 @@
"published_on": "Published on", "published_on": "Published on",
"updated_on": "Updated on", "updated_on": "Updated on",
"authored": "By", "authored": "By",
"copyright": "<a style=\"text-decoration:none;color:inherit;\" target=_blank href=\"https://creativecommons.org/licenses/by-nc/4.0/\">CC BY-NC</a>" "copyright": "<a style=\"text-decoration:none;color:inherit;\" target=_blank href=\"https://creativecommons.org/licenses/by-nc/4.0/\">CC BY-NC</a>",
"footer": ""
} }
+543 -171
View File
File diff suppressed because it is too large Load Diff
+17 -16
View File
@@ -1,6 +1,6 @@
{ {
"name": "md-blog", "name": "md-blog",
"version": "1.9.2", "version": "1.9.4",
"private": true, "private": true,
"type": "module", "type": "module",
"repository": "https://git.klemek.fr/klemek/md-blog", "repository": "https://git.klemek.fr/klemek/md-blog",
@@ -21,34 +21,35 @@
"dependencies": { "dependencies": {
"@keithclark/shaderview": "https://github.com/keithclark/shaderview/archive/refs/tags/1.2.0.tar.gz", "@keithclark/shaderview": "https://github.com/keithclark/shaderview/archive/refs/tags/1.2.0.tar.gz",
"highlight.js": "^11.11.1", "highlight.js": "^11.11.1",
"katex": "^0.16.45", "katex": "^0.16.47",
"lucide": "^1.14.0", "lucide": "^1.25.0",
"mermaid": "^11.14.0", "mermaid": "^11.16.0",
"vue": "^3.5.33", "vue": "^3.5.40",
"vue-router": "^5.0.6" "vue-router": "^5.2.0"
}, },
"devDependencies": { "devDependencies": {
"@tsconfig/node24": "^24.0.4", "@tsconfig/node24": "^24.0.4",
"@types/node": "^24.12.2", "@types/node": "^24.13.3",
"@vitejs/plugin-vue": "^6.0.6", "@vitejs/plugin-vue": "^6.0.8",
"@vue/eslint-config-prettier": "^10.2.0", "@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.7.0", "@vue/eslint-config-typescript": "^14.9.0",
"@vue/tsconfig": "^0.9.1", "@vue/tsconfig": "^0.9.1",
"eslint": "^10.3.0", "eslint": "^10.7.0",
"eslint-plugin-oxlint": "~1.60.0", "eslint-plugin-oxlint": "~1.60.0",
"eslint-plugin-vue": "~10.8.0", "eslint-plugin-vue": "~10.8.0",
"feed": "^5.2.1", "feed": "^5.2.1",
"jiti": "^2.6.1", "jiti": "^2.7.0",
"npm-run-all2": "^8.0.4", "npm-run-all2": "^8.0.4",
"oxlint": "~1.60.0", "oxlint": "~1.60.0",
"prettier": "3.8.3", "prettier": "3.8.3",
"sass-embedded": "^1.99.0", "sass-embedded": "^1.100.0",
"tsx": "^4.21.0", "tsx": "^4.23.1",
"typescript": "~6.0.3", "typescript": "~6.0.3",
"vite": "^8.0.10", "vite": "^8.1.5",
"vite-plugin-javascript-obfuscator": "^3.1.0",
"vite-plugin-markdown": "^2.2.0", "vite-plugin-markdown": "^2.2.0",
"vite-plugin-vue-devtools": "^8.1.1", "vite-plugin-vue-devtools": "^8.1.5",
"vue-tsc": "^3.2.7" "vue-tsc": "^3.3.7"
}, },
"engines": { "engines": {
"node": "^20.19.0 || >=22.12.0" "node": "^20.19.0 || >=22.12.0"
+4 -4
View File
@@ -1,12 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { REPOSITORY, NAME, VERSION, TITLE, COPYRIGHT } from '@lib/config' import { REPOSITORY, NAME, VERSION, TITLE, COPYRIGHT, FOOTER } from '@lib/config'
import { stripHTML } from '@lib/strings' import { stripHTML } from '@lib/strings'
</script> </script>
<template> <template>
<footer> <footer>
{{ stripHTML(TITLE) }} &copy; {{ new Date().getFullYear() }}, <span v-html="COPYRIGHT"></span> | {{ stripHTML(TITLE) }} &copy; {{ new Date().getFullYear() }}, <span v-html="COPYRIGHT"></span>
Made with <span v-if="FOOTER">&nbsp;| <span v-html="FOOTER"></span></span>
<a :href="REPOSITORY">{{ NAME }} {{ VERSION }}</a> &nbsp;| Made with <a :href="REPOSITORY">{{ NAME }} {{ VERSION }}</a>
</footer> </footer>
</template> </template>
+18 -17
View File
@@ -1,18 +1,19 @@
import packageJson from '@/../package.json' import packageJson from "@/../package.json";
import articlesConfig from '@articles/config.json' import articlesConfig from "@articles/config.json";
export const NAME: string = packageJson.name export const NAME: string = packageJson.name;
export const VERSION: string = packageJson.version export const VERSION: string = packageJson.version;
export const REPOSITORY: string = packageJson.repository export const REPOSITORY: string = packageJson.repository;
export const TITLE: string = articlesConfig.title export const TITLE: string = articlesConfig.title;
export const SIGNATURE: string = articlesConfig.signature export const SIGNATURE: string = articlesConfig.signature;
export const COPYRIGHT: string = articlesConfig.copyright export const COPYRIGHT: string = articlesConfig.copyright;
export const RSS_LINK: string = articlesConfig.rss_link export const FOOTER: string = articlesConfig.footer;
export const BACK_LINK: string = articlesConfig.back_link export const RSS_LINK: string = articlesConfig.rss_link;
export const ABOUT_LINK: string = articlesConfig.about_link export const BACK_LINK: string = articlesConfig.back_link;
export const HOME_COUNT: number = articlesConfig.home_count export const ABOUT_LINK: string = articlesConfig.about_link;
export const PUBLISHED_ON: string = articlesConfig.published_on export const HOME_COUNT: number = articlesConfig.home_count;
export const UPDATED_ON: string = articlesConfig.updated_on export const PUBLISHED_ON: string = articlesConfig.published_on;
export const AUTHORED: string = articlesConfig.authored export const UPDATED_ON: string = articlesConfig.updated_on;
export const BASE_URL: string = import.meta.env.BASE_URL export const AUTHORED: string = articlesConfig.authored;
export const PROD: boolean = import.meta.env.PROD export const BASE_URL: string = import.meta.env.BASE_URL;
export const PROD: boolean = import.meta.env.PROD;
+6 -6
View File
@@ -32,15 +32,15 @@ onUpdated(updateDynamicContent)
<template v-if="!loading && !article"> <template v-if="!loading && !article">
<NotFoundView /> <NotFoundView />
</template> </template>
<div v-if="!loading" class="article"> <article v-if="!loading" class="article h-entry">
<template v-if="!loading && article"> <template v-if="!loading && article">
<div class="article-header"> <div class="article-header">
<h1 class="article-title" v-html="article.metadata.title"></h1> <h1 class="article-title p-name" v-html="article.metadata.title"></h1>
<div class="article-info"> <div class="article-info">
<span v-if="article.metadata.author" <span v-if="article.metadata.author"
><span v-html="AUTHORED"></span> <span v-html="article.metadata.author"></span> ><span v-html="AUTHORED"></span> <span class="p-author h-card" v-html="article.metadata.author"></span>
</span> </span>
<span v-html="PUBLISHED_ON"></span> {{ simpleDateFormat(article.metadata.date) }} <span v-html="PUBLISHED_ON"></span> <time class="dt-published" :datetime="simpleDateFormat(article.metadata.date)">{{ simpleDateFormat(article.metadata.date) }}</time>
<span v-if="article.metadata.updated" <span v-if="article.metadata.updated"
> <span v-html="UPDATED_ON"></span> > <span v-html="UPDATED_ON"></span>
{{ simpleDateFormat(article.metadata.updated) }}</span {{ simpleDateFormat(article.metadata.updated) }}</span
@@ -53,9 +53,9 @@ onUpdated(updateDynamicContent)
alt="thumbnail" alt="thumbnail"
/> />
</div> </div>
<div class="article-text" v-html="article.html"></div> <div class="article-text e-content" v-html="article.html"></div>
<div class="article-signature" v-html="SIGNATURE"></div> <div class="article-signature" v-html="SIGNATURE"></div>
<BackHomeButton /> <BackHomeButton />
</template> </template>
</div> </article>
</template> </template>
+3 -3
View File
@@ -26,10 +26,10 @@ onUpdated(updateDynamicContent)
<div v-if="!loading" class="home"> <div v-if="!loading" class="home">
<template v-for="(metadata, index) in articles" :key="index"> <template v-for="(metadata, index) in articles" :key="index">
<div v-if="(!metadata.draft || !PROD) && metadata.path" class="article-item"> <div v-if="(!metadata.draft || !PROD) && metadata.path" class="article-item">
<RouterLink :to="metadata.path"> <RouterLink :to="metadata.path" class="h-entry">
<h2 v-html="metadata.title"></h2> <h2 class="p-name" v-html="metadata.title"></h2>
<span class="article-info" <span class="article-info"
><span v-html="PUBLISHED_ON"></span> {{ simpleDateFormat(metadata.date) }}</span ><span v-html="PUBLISHED_ON"></span> <time class="dt-published" :datetime="simpleDateFormat(metadata.date)">{{ simpleDateFormat(metadata.date) }}</time></span
> >
<img <img
v-if="metadata.thumbnail" v-if="metadata.thumbnail"
+47 -22
View File
@@ -1,33 +1,58 @@
import { fileURLToPath, URL } from 'node:url' import { fileURLToPath, URL } from "node:url";
import { defineConfig, loadEnv } from 'vite' import { defineConfig, loadEnv } from "vite";
import vue from '@vitejs/plugin-vue' import vue from "@vitejs/plugin-vue";
import vueDevTools from 'vite-plugin-vue-devtools' import vueDevTools from "vite-plugin-vue-devtools";
import { plugin as mdPlugin, Mode } from 'vite-plugin-markdown' import { plugin as mdPlugin, Mode } from "vite-plugin-markdown";
import obfuscatorPlugin from "vite-plugin-javascript-obfuscator";
import articlesConfig from './articles/config.json' import articlesConfig from "./articles/config.json";
// https://vite.dev/config/ // https://vite.dev/config/
export default ({ mode }: { mode: string }) => { export default ({ mode }: { mode: string }) => {
process.env = { ...process.env, ...loadEnv(mode, process.cwd()) } process.env = { ...process.env, ...loadEnv(mode, process.cwd()) };
process.env.VITE_BASE_URL = articlesConfig.base_url process.env.VITE_BASE_URL = articlesConfig.base_url;
process.env.VITE_APP_TITLE = articlesConfig.title process.env.VITE_APP_TITLE = articlesConfig.title;
process.env.VITE_APP_TITLE_NO_HTML = articlesConfig.title.replace(/(<([^>]+)>)/gi, '').trim() process.env.VITE_APP_TITLE_NO_HTML = articlesConfig.title.replace(/(<([^>]+)>)/gi, "").trim();
process.env.VITE_APP_LANG = articlesConfig.lang process.env.VITE_APP_LANG = articlesConfig.lang;
process.env.VITE_CUSTOM_HEAD = articlesConfig.custom_head process.env.VITE_CUSTOM_HEAD = articlesConfig.custom_head;
return defineConfig({ return defineConfig({
plugins: [vue(), vueDevTools(), mdPlugin({ mode: [Mode.HTML] })], server: {
base: process.env.VITE_BASE_URL, host: "0.0.0.0",
},
plugins: [
vue(),
vueDevTools(),
mdPlugin({ mode: [Mode.HTML] }),
obfuscatorPlugin({
include: [/.*\.md/],
options: { splitStrings: true, stringArrayThreshold: 1 },
}),
],
resolve: { resolve: {
alias: { alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)), "@": fileURLToPath(new URL("./src", import.meta.url)),
'@views': fileURLToPath(new URL('./src/views', import.meta.url)), "@views": fileURLToPath(new URL("./src/views", import.meta.url)),
'@lib': fileURLToPath(new URL('./src/lib', import.meta.url)), "@lib": fileURLToPath(new URL("./src/lib", import.meta.url)),
'@articles': fileURLToPath(new URL('./articles', import.meta.url)), "@articles": fileURLToPath(new URL("./articles", import.meta.url)),
'@interfaces': fileURLToPath(new URL('./src/interfaces.ts', import.meta.url)), "@interfaces": fileURLToPath(new URL("./src/interfaces.ts", import.meta.url)),
'@components': fileURLToPath(new URL('./src/components', import.meta.url)), "@components": fileURLToPath(new URL("./src/components", import.meta.url)),
}, },
}, },
}) build: {
} rolldownOptions: {
output: {
codeSplitting: {
groups: [
{
name: (moduleId: string) => (moduleId.includes("node_modules") ? "libs" : "app"),
maxSize: 1024 * 1024,
},
],
},
},
},
},
});
};
Vendored
+1 -16
View File
@@ -2,26 +2,11 @@ declare module '*.md' {
// "unknown" would be more detailed depends on how you structure frontmatter // "unknown" would be more detailed depends on how you structure frontmatter
const attributes: Record<string, unknown> const attributes: Record<string, unknown>
// When "Mode.TOC" is requested
const toc: { level: string; content: string }[]
// When "Mode.HTML" is requested // When "Mode.HTML" is requested
const html: string const html: string
// When "Mode.RAW" is requested
const raw: string
// When "Mode.React" is requested. VFC could take a generic like React.VFC<{ MyComponent: TypeOfMyComponent }>
import React from 'react'
const ReactComponent: React.VFC
// When "Mode.Vue" is requested
import { ComponentOptions, Component } from 'vue'
const VueComponent: ComponentOptions
const VueComponentWith: (components: Record<string, Component>) => ComponentOptions
// Modify below per your usage // Modify below per your usage
export { attributes, toc, html, ReactComponent, VueComponent, VueComponentWith } export { html }
} }
declare module '*.vue' declare module '*.vue'