From 68f81d03a95fb56365eb69a03430c70e785a571a Mon Sep 17 00:00:00 2001 From: jdrydn Date: Fri, 3 Apr 2026 20:26:10 +0100 Subject: [PATCH 1/4] ci: Updated workflows --- .github/workflows/{deploy.yml => cd.yml} | 12 ++++++----- .github/workflows/ci.yml | 27 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) rename .github/workflows/{deploy.yml => cd.yml} (82%) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/cd.yml similarity index 82% rename from .github/workflows/deploy.yml rename to .github/workflows/cd.yml index 136094e..9043911 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/cd.yml @@ -1,4 +1,4 @@ -name: Main Deploy +name: CD on: push: @@ -11,14 +11,13 @@ permissions: pages: write id-token: write -concurrency: - group: pages - cancel-in-progress: false - jobs: build: name: Build runs-on: ubuntu-latest + concurrency: + group: cd-build + cancel-in-progress: true steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 @@ -38,6 +37,9 @@ jobs: name: Deploy needs: build runs-on: ubuntu-latest + concurrency: + group: deploy-github-pages + cancel-in-progress: false environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..81c0534 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: CI + +on: + pull_request: + +permissions: + contents: read + pages: write + id-token: write + +jobs: + build: + name: Build + runs-on: ubuntu-latest + concurrency: + group: pr-${{ github.event.number }}-build + cancel-in-progress: true + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: pnpm + + - run: pnpm install --frozen-lockfile + - run: pnpm build From a8f999b0e64230a8c3f8b5665c17e45bd6c6a70d Mon Sep 17 00:00:00 2001 From: jdrydn Date: Fri, 3 Apr 2026 20:26:17 +0100 Subject: [PATCH 2/4] fix: Formatting --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 04f4486..d84362f 100644 --- a/package.json +++ b/package.json @@ -22,4 +22,4 @@ "vitepress": "2.0.0-alpha.17", "vitepress-sidebar": "^1.33.1" } -} \ No newline at end of file +} From 1b089c92a8e23da1a1bf0682cdf094e8a9f06dc1 Mon Sep 17 00:00:00 2001 From: jdrydn Date: Fri, 3 Apr 2026 21:27:51 +0100 Subject: [PATCH 3/4] docs: Archived --- archived/aws-api-gateway-vuejs.md | 54 +++ archived/ideas-calendar-platform.md | 697 ++++++++++++++++++++++++++++ archived/index.data.ts | 6 +- archived/js-inline-loader.md | 6 +- archived/lua-hincrallby.md | 15 + archived/nodejs-cluster.md | 47 ++ archived/nodejs-http-proxy-sni.md | 50 ++ archived/svn-extending-cli.md | 6 +- 8 files changed, 868 insertions(+), 13 deletions(-) create mode 100644 archived/aws-api-gateway-vuejs.md create mode 100644 archived/ideas-calendar-platform.md create mode 100644 archived/lua-hincrallby.md create mode 100644 archived/nodejs-cluster.md create mode 100644 archived/nodejs-http-proxy-sni.md diff --git a/archived/aws-api-gateway-vuejs.md b/archived/aws-api-gateway-vuejs.md new file mode 100644 index 0000000..6cc2ad1 --- /dev/null +++ b/archived/aws-api-gateway-vuejs.md @@ -0,0 +1,54 @@ +# AWS API-Gateway → VueJS + +Serve a Vue SPA through API-Gateway. + +```sh +aws cloudformation deploy \ + --stack-name vue-frontend-prod \ + --template-file ./cloudformation.yml +``` + +```yml +Description: Vue HTTP API-Gateway +Resources: + FrontendApi: + Type: AWS::ApiGatewayV2::Api + Properties: + Name: vue-prod-frontend + ProtocolType: HTTP + DisableExecuteApiEndpoint: true + Tags: + Environment: production + FrontendIntegration: + Type: AWS::ApiGatewayV2::Integration + Properties: + ApiId: + Ref: FrontendApi + IntegrationType: HTTP_PROXY + IntegrationMethod: GET + IntegrationUri: https://vue-prod-frontend.s3.amazonaws.com/index.html + PayloadFormatVersion: 1.0 + FrontendStage: + Type: AWS::ApiGatewayV2::Stage + Properties: + ApiId: + Ref: FrontendApi + StageName: $default + AutoDeploy: true + FrontendRootRoute: + Type: AWS::ApiGatewayV2::Route + Properties: + ApiId: + Ref: FrontendApi + RouteKey: GET / + Target: + Fn::Join: ['/', ['integrations', { Ref: FrontendIntegration }]] + FrontendAnyRoute: + Type: AWS::ApiGatewayV2::Route + Properties: + ApiId: + Ref: FrontendApi + RouteKey: GET /{any+} + Target: + Fn::Join: ['/', ['integrations', { Ref: FrontendIntegration }]] +``` diff --git a/archived/ideas-calendar-platform.md b/archived/ideas-calendar-platform.md new file mode 100644 index 0000000..8bdb1e0 --- /dev/null +++ b/archived/ideas-calendar-platform.md @@ -0,0 +1,697 @@ +# Calendar Platform (Idea) + +The following are some example usage queries to how I think a GraphQL Backend-API should work for a Calendar App. +Properties and names are not fixed, and feedback on any of this is welcome! + +```graphql +{ + profile { + id + name + emailAddress + avatar + } + + calendar { + id + type + title + color + } + + events(where: { startAt: "2020-04-01", endAt: "2020-04-30" }, order: STARTING_ASC) { + id + title + location { + name + } + startAt + endAt + color + } + + event(where: { id: "SOME-LONG-EVENT-ID" }) { + id + title + location { + name + address + latlon + } + startAt + endAt + color # Event could have a color? Fall back to calendar color by default? + url + notes + repeats + + calendar { + id + title + color + } + + attendees { + name + emailAddress + avatar + + member { + id + name + emailAddress + avatar + } + + isOrganiser + rsvp # ATTENDING, TENTATIVE, DECLINED + } + + thread { + # One + id + } + } + + threads { + id + + event { + id + } + + messages(limit: 20, order: CREATED_DESC) { + id + } + } + + message(where: { id: "SOME-MESSAGE-ID" }) { + id + author { + emailAddress + avatar + } + text + createdAt + } +} +``` + +- Events listed by week with latest message + +```graphql +{ + events(where: { startAt: "2020-04-06", endAt: "2020-04-12" }, order: STARTING_ASC) { + id + title + startAt + endAt + isAllDay + isManyDays + location { + name + } + color + + thread { + id + messages(limit: 1, order: CREATED_DESC) { + id + text + author { + avatar + } + } + } + } +} +``` + +- Events listed by month + +```graphql +{ + events(where: { startAt: "2020-04-01", endAt: "2020-04-30" }, order: STARTING_ASC) { + id + title + startAt + endAt + location { + name + } + color + } +} +``` + +- Message thread with event + +```graphql +{ + thread(where: { id: "SOME-THREAD-ID" }) { + id + startAt + total + + event { + id + title + startAt + endAt + location { + name + } + color + } + + messages(page: 1, limit: 20, order: CREATED_DESC) { + id + author { + # One + emailAddress + avatar + } + text + createdAt + } + } +} +``` + +- Event details, ready to edit the event + +```graphql +query EditEvent { + event(where: { id: "SOME-EVENT-ID" }) { + id + title + startAt + endAt + + location { + # One + name + address + latlon + } + + color # Inherit from calendar, but could an event have it's own color? + repeats # NEVER (null), DAILY, WEEKLY, FORTNIGHTLY, MONTHLY, YEARLY + url # Clever support for URLs, MAILTO or TEL prefixes in-app? + notes + + calendar { + # One + id # Compare with calendars[*].id to choose a calendar + } + + attendees { + # Many + name + emailAddress + avatar # Pulled from Gravatar? + member { + id + name + emailAddress + } + + isOrganiser # Boolean to determine if this attendee created the event? + rsvp # ATTENDING, TENTATIVE, DECLINED + } + } + + profile { + id # Compare with events.attendees.id to find "YOU" + } + + calendars { + # Many + id + title + color + } +} +``` + +- Activity view (list of threads ordered by last updated) + +```graphql +query Activity { + threads(order: UPDATED_DESC) { + id + startAt + total + + event { + id + title + location { + name + } + color + } + + messages(page: 1, limit: 20, order: CREATED_DESC) { + id + author { + # One + emailAddress + avatar + } + text + createdAt + } + } +} +``` + +- Searching for "Coffee" + +```graphql +query Search { + events(where: { title: "%coffee%" }) { + id + title + startAt + endAt + location { + name + } + color + } +} +``` + +- Creating an event + +```graphql +mutation createEvent { + createEvent( + create: { + title: "Tuesday stand-up" + # 8AM UTC, 9AM BST + startDate: "2020-04-07T08:00:00.000Z" + # 9AM UTC, 10AM BST + endDate: "2020-04-07T09:00:00.000Z" + # Perhaps right now, single-calendar setup, we don't need this? + # I think we should, even if we're not displaying multiple calendars in the app + calendar: { id: "496baec6-cc5f-4c54-944d-18c2bfe18598" } + # Manual location + location: { name: "Office", address: "WeWork, Aldgate Tower, London E1 8FA", latlon: "51.513582,-0.0762422" } + # Just throw a latlon at the API, and it could lookup a location from it? + # Unsure which 3rd party service we'd need to support this feature though.. + location: { latlon: "51.513582,-0.0762422" } + # Or perhaps an online meet? + conference: { + # TBD, a unified way of creating/generating conference-call data! + type: "hangouts" + # Ideally the app would make a request to fetch "new" conference data & send it up to the API + } + attendees: [ + { id: "0220743c-c9b2-40a6-a478-e168cfc005c4", isOrganiser: true } + { name: "Alex", emailAddress: "alex@hotmail.com" } + { name: "James", emailAddress: "james@gmail.com" } + ] + } + options: { + # In this case the app wants to control whether or not to send emails + # Obviously this would default to true! + sendCreateEmail: false + } + ) { + id + title + startDate + endDate + location { + name + } + } +} +``` + +- Updating events + +```graphql +mutation updateEvent { + updateEvent( + update: { + # Ideally the App would know what properties of the form have been updated + # And just send the diff, but if you send an entire event object we can work with that too + location: { name: "Office", address: "WeWork, Aldgate Tower, London E1 8FA" } + } + where: { + # The where & updates are seperate for full flexibility + id: "SOME-EVENT-ID" + } + ) { + id + } +} + +mutation updateLotsOfEvents { + updateManyEvents( + update: { + # This would "unset" the location property of events + location: null + } + where: { + # IMO this would be a neat "trick" to select an entire day + startDate: ">= 2020-04-02" + # If no TIME is present on the startDate then assume start-of-day + endDate: "<= 2020-04-02" + # If no TIME is present on the endDate then assume end-of-day + } + ) { + # Array of Events affected returned, so this would be [{ id: 22 }] + id + # Returning IDs of those events affected + } +} + +mutation rsvpToEvent { + replyToEvent( + update: { + # Simply replying YES + rsvp: ATTENDING + # What if we want to suggest a new start time? + rsvp: TENTATIVE + suggestStartDate: "2020-04-02T09:00:00.000Z" + suggestEndDate: "2020-04-02T10:00:00.000Z" + # Really though, this should mark your attendance but not edit the event + # Instead, it should put a message in the chat to suggest a new time + # With some sort of one-click approve? TBD + } + where: { + # The where & updates are seperate for full flexibility + id: "SOME-EVENT-ID" + } + ) { + id + } +} +``` + +- Write a new message + +```graphql +mutation createTextMessage { + createMessage( + create: { + # Attach a message to a thread + thread: { id: "SOME-THREAD-ID" } + # Or why not to a specific event + thread: { event: { id: "SOME-EVENT-ID" } } + # Because an event has one thread right? + + # A text message just needs text + text: "Quick coffee to discuss my YC application?" + } + ) { + id + thread { + # To get event information about the thread we just added to + event { + id + title + } + } + text + } +} + +query GetThreadMessages { + thread(where: { id: "SOME-THREAD-ID" }) { + messages(page: 1, limit: 20, order: CREATED_DESC) { + id + author { + name + emailAddress + avatar + } + text + createdAt + } + } +} +``` + +In the future we'll have more types of chat, so I see this format above being flexible enough to support other types: + +```graphql +# GraphQL cannot handle incoming file types, so instead we need two mutations: +# First to get a set of upload credentials, so the app can upload direct to S3 +# Second to mark an upload as complete, and get back an assetID to use in other mutations + +mutation getImageUploadCredentials { + createAsset( + create: { + type: IMAGE + # The name of the image + fileName: "IMG_0932.JPG" + # The mimetype of the image + fileMime: "image/jpeg" + # The file size of the image, in bytes + fileSize: 20420492 + # Sha1 hash so we can verify the image was uploaded correctly + fileSha1: "mkldsfv8jq32rfjkarnvkq34nf9u" + } + ) { + token # Used to confirm the upload was finished + url + headers + body + } +} + +# Then the client uploads the image to upload.url with upload.headers & upload.body +# Once done, the client notifies the server that the image has been uploaded, so the server can perform final checks +# Use `fileSha1` to verify the image is correct, trigger moderation, etc. etc. + +mutation finallyFinishedUploadingImage($token: String!) { + uploadedAsset(token: $token) { + id # The ID of the image + fileName + fileLocation # The final URL this image will be available at + fileMime + fileSize + fileSha1 + } +} + +mutation createImageMessage { + createMessage( + create: { + thread: { id: "SOME-THREAD-ID" } + text: "Sat downstairs at table 15, see you in bit!" + image: { id: $imageID } + } + ) { + id + author { + emailAddress + avatar + } + text + image { + fileName + fileLocation + fileSize # "${fileName} is greater than 2MB, tap to show" + } + createdAt + } +} + +mutation createEmbedMessage { + createMessage( + create: { + thread: { id: "SOME-THREAD-ID" } + text: "Lol, what about this" + # Provide a URL to expand + url: "https://vm.tiktok.com/nCGxS3/" + } + ) { + id + author { + emailAddress + avatar + } + text + # For an example, check out https://github.com/someimportantcompany/yoem + embed { + title # Due to the wide-ranging nature of embeds + description # Literally any one of these fields could be NULL + url # Except `url`, that guy is super reliable 🤦‍♂️ + provider { + name + url + } + author { + name + url + } + thumbnail { + url + height + width + } + iframe { + html + height + width + } + } + createdAt + } +} + +mutation getDocumentUploadCredentials { + createAsset( + create: { + type: DOCUMENT + # The name of the document + fileName: "Paperwork.docx" + # The mimetype of the document + fileMime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + # The file size of the document, in bytes + fileSize: 20420492 + # Sha1 hash so we can verify the document was uploaded correctly + fileSha1: "dfvsdfvwrfsfvqrfafsv4wdec" + } + ) { + token # Used to confirm the upload was finished + url + headers + body + } +} + +# Then the client uploads the document to upload.url with upload.headers & upload.body +# Once done, the client notifies the server that the document has been uploaded, so the server can perform final checks +# Use `fileSha1` to verify the document is correct, trigger moderation, etc. etc. + +mutation finallyFinishedUploadingImage($token: String!) { + uploadedAsset(token: $token) { + id # The ID of the document + fileName + fileLocation # The final URL this document will be available at + fileMime + fileSize + fileSha1 + } +} + +mutation createDocumentMessage($documentID: ID!) { + createMessage( + create: { + thread: { id: "SOME-THREAD-ID" } + text: "Could you please read over this before we catch-up? Thanks" + document: { id: $documentID } + } + ) { + id + author { + emailAddress + avatar + } + text + document { + fileName + fileLocation + fileSize # "${fileName} is greater than 2MB, tap to show" + } + createdAt + } +} + +mutation createLocationMessage { + createMessage( + create: { + thread: { id: "SOME-THREAD-ID" } + text: "How about we meet here?" + location: { name: "Pret, Aldgate East", latlon: "51.513582,-0.0762422" } + } + ) { + id + author { + emailAddress + avatar + } + text + location { + latlon + } + createdAt + } +} + +query EverythingIsNamespacedSoItAllFitsTogether { + thread(where: { id: "SOME-THREAD-ID" }) { + messages(page: 1, limit: 20, order: CREATED_DESC) { + id + author { + emailAddress + avatar + } + text + image { + fileName + fileLocation + fileSize # "${fileName} is greater than 2MB, tap to show" + } + embed { + title + description + url + } + document { + fileName + fileLocation + fileSize # "${fileName} is greater than 2MB, tap to show" + } + location { + name + latlon + } + createdAt + } + } +} +``` + +## Potential Subscriptions + +```graphql +{ + createdEvent { + # EVENT_CREATED + id + } + updatedEvent { + # EVENT_UPDATED + id + } + updatedThread { + # THREAD_UPDATED + id + } + updatedMessage { + # MESSAGE_UPDATED + id + } +} +``` + +## Questions + +- Event locations need to consider online meetups, Google Meet or Microsoft Teams + - Support more types? Slack? Zoom? +- Event alerts? Email alerts? +- Event timezone support? +- Only time when on-device account management fails is when you want to switch an event between calendars... that would + technically involve deleting from one provider & creating in another? +- Messages have color? +- When a message is sent, the thread should be updated. But not the event? +- When the event is updated, a new context/status message should be generated so the thread should get an update + triggered too? diff --git a/archived/index.data.ts b/archived/index.data.ts index f64b1cf..6d1a313 100644 --- a/archived/index.data.ts +++ b/archived/index.data.ts @@ -3,14 +3,14 @@ import { createContentLoader } from 'vitepress'; export default createContentLoader(path.resolve(__dirname, '../archived/*.md'), { includeSrc: false, - render: false, - excerpt: true, + render: true, + excerpt: false, transform: (items) => items .filter((item) => item.url !== '/archived/') .map((item) => { const filename = path.basename(item.url, path.extname(item.url)); - const firstTitle = item.excerpt?.match(/]*>(.*?)<\/h1>/s)?.[1]; + const firstTitle = item.html?.slice(0, 500).match(/]*>(.*?)<\/h1>/s)?.[1]; item.frontmatter.title = item.frontmatter.title || firstTitle || filename; return item; }), diff --git a/archived/js-inline-loader.md b/archived/js-inline-loader.md index c51ec31..296b665 100644 --- a/archived/js-inline-loader.md +++ b/archived/js-inline-loader.md @@ -1,8 +1,4 @@ ---- -title: JS - An inline loader ---- - -# {{ $frontmatter.title }} +# JS - An inline loader One upon a time, this was needed to load Javascript files on the frontend, after the page had fully loaded. diff --git a/archived/lua-hincrallby.md b/archived/lua-hincrallby.md new file mode 100644 index 0000000..db8ee2c --- /dev/null +++ b/archived/lua-hincrallby.md @@ -0,0 +1,15 @@ +# Lua - HINCRALLBY + +Grab your shovels, that Redis instance won't be around much longer. + +```lua +-- Usage: HINCRALLBY AKeyOfYourChoice 1 +-- HKEYS AKeyOfYourChoice +-- HINCRBY AKeyOfYourChoice KEY 1 +local keys = redis.call("HKEYS", ARGV[1]) +local results = {} +for i,k in ipairs(keys) do + results[i] = redis.call("HINCRBY", ARGV[1], keys[i], ARGV[2]) +end +return results +``` diff --git a/archived/nodejs-cluster.md b/archived/nodejs-cluster.md new file mode 100644 index 0000000..094d932 --- /dev/null +++ b/archived/nodejs-cluster.md @@ -0,0 +1,47 @@ +# NodeJS - Cluster + +```js +if (require('cluster').isMaster) { + const cluster = require('cluster'); + const CPU = require('os').cpus(); + + const LIMIT = process.env.LIMIT || CPU.length; + const start = Date.now(); + + // Generate a list of MAX numbers to loop through + const LIST = new Array(parseInt(process.env.MAX || 10, 10)).fill(null).map((v, k) => k + 1); + + // Fork a new worker + function createWorker() { + const nextItem = LIST.shift(); + if (nextItem) { + const worker = cluster.fork(); + // worker.on('message', message => console.log(`Worker ${worker.process.pid}: ${message}`)); + worker.send(`${nextItem}`); + } + } + + // Initialise LIMIT workers + for (let i = 0; i < LIMIT; i++) { + createWorker(); + } + + // After each worker, spawn a new one if required + cluster.on('exit', (worker) => { + // console.log(`Worker ${worker.process.pid} died`); + createWorker(); + + if (!LIST.length) { + console.log(`Took: ${Math.ceil((Date.now() - start) / 1000)}s`); + } + }); +} else { + // console.log(`Worker ${process.pid} started`); + + process.on('message', (nextItem) => { + console.log(`Worker ${process.pid}: ${nextItem}`); + process.send(`${nextItem}`); + process.exit(); + }); +} +``` diff --git a/archived/nodejs-http-proxy-sni.md b/archived/nodejs-http-proxy-sni.md new file mode 100644 index 0000000..765b7b2 --- /dev/null +++ b/archived/nodejs-http-proxy-sni.md @@ -0,0 +1,50 @@ +# NodeJS - HTTP Proxy (SNI) + +NodeJS HTTPS server to handle SaaS levels of traffic, managing HTTPS certs & proxying to your application. + +```js +const fs = require('fs'); +const path = require('path'); +const proxy = require('http-proxy'); + +const server = proxy.createProxyServer({ + target: 'https://backend-services-prod-772187446.eu-west-2.elb.amazonaws.com', + secure: false, + ssl: { + // Certs need to cover the domains in question + key: fs.readFileSync(path.resolve(__dirname, './server.key')), + cert: fs.readFileSync(path.resolve(__dirname, './server.cert')), + SNICallback(domain, callback) { + console.log(domain); + // localhost + // jdrydn.com + // api.dev.jdrydn.com + // api.dev.jdrydn.someimportantcompany.com + callback(); + }, + }, +}); + +/* istanbul ignore next */ +if (!module.parent) { + if (process.env.NODE_ENV === 'production') { + process.on('uncaughtException', (err) => { + logger.fatal(err); + process.kill(process.pid); + }); + } + + // Start the HTTP server! + server.listen(process.env.HTTP_PORT || 8088, process.env.HTTP_HOST || 'localhost'); + console.log(`Server listening on http://${process.env.HTTP_HOST || 'localhost'}:${process.env.HTTP_PORT || 8088}`); +} +``` + +When testing: + +```bash +curl -k -I \ + --resolve wiki.jdrydn.com:80:127.0.0.1 \ + --resolve wiki.jdrydn.com:443:127.0.0.1 \ + https://wiki.jdrydn.com +``` diff --git a/archived/svn-extending-cli.md b/archived/svn-extending-cli.md index 82dff9b..b6a65df 100644 --- a/archived/svn-extending-cli.md +++ b/archived/svn-extending-cli.md @@ -1,8 +1,4 @@ ---- -title: SVN - Extending the CLI ---- - -# {{ $frontmatter.title }} +# SVN - Extending the CLI Extending SVN's features to include common tasks such as tagging. From 694b714747727405ba284abbf3a2227bb10f1a17 Mon Sep 17 00:00:00 2001 From: jdrydn Date: Fri, 3 Apr 2026 21:27:57 +0100 Subject: [PATCH 4/4] fix: Updates --- .vitepress/config.mts | 2 +- entries/index.data.ts | 6 +++--- entries/terminal-one-liners.md | 8 ++------ package.json | 5 ++--- public/assets/icon-iterm2.svg | 1 + 5 files changed, 9 insertions(+), 13 deletions(-) create mode 100644 public/assets/icon-iterm2.svg diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 595b4b5..92efe56 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -28,7 +28,7 @@ export default defineConfig({ scanStartPath: 'archived', basePath: '/archived/', resolvePath: '/archived/', - useTitleFromFrontmatter: true, + useTitleFromFileHeading: true, }, ]), diff --git a/entries/index.data.ts b/entries/index.data.ts index a62e44d..25d6347 100644 --- a/entries/index.data.ts +++ b/entries/index.data.ts @@ -3,14 +3,14 @@ import { createContentLoader } from 'vitepress'; export default createContentLoader(path.resolve(__dirname, '../entries/*.md'), { includeSrc: false, - render: false, - excerpt: true, + render: true, + excerpt: false, transform: (items) => items .filter((item) => item.url !== '/entries/') .map((item) => { const filename = path.basename(item.url, path.extname(item.url)); - const firstTitle = item.excerpt?.match(/]*>(.*?)<\/h1>/s)?.[1]; + const firstTitle = item.html?.slice(0, 500).match(/]*>(.*?)<\/h1>/s)?.[1]; item.frontmatter.title = item.frontmatter.title || firstTitle || filename; return item; }), diff --git a/entries/terminal-one-liners.md b/entries/terminal-one-liners.md index 5eddab6..516eb70 100644 --- a/entries/terminal-one-liners.md +++ b/entries/terminal-one-liners.md @@ -1,12 +1,8 @@ ---- -title: Terminal One-Liners ---- - -# {{ $frontmatter.title }} +# Terminal One Liners A handy page to list useful command-line one-liners! - + ## Create a MongoDB Object ID, fast! diff --git a/package.json b/package.json index d84362f..4c0ddc5 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,7 @@ { - "name": "docs", + "name": "@jdrydn/wiki", "version": "1.0.0", - "description": "", - "main": "index.js", + "private": true, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "vitepress dev", diff --git a/public/assets/icon-iterm2.svg b/public/assets/icon-iterm2.svg new file mode 100644 index 0000000..1aa6b96 --- /dev/null +++ b/public/assets/icon-iterm2.svg @@ -0,0 +1 @@ +iTerm2 \ No newline at end of file