Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate from topic notes to atomic notes #3

Merged
merged 26 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5300e5a
header: highlight "notes" when on a bookmark page
ooloth Dec 22, 2024
fadedfe
comments: only show on post pages
ooloth Dec 22, 2024
b42ce2f
slug: render bookmark routes
ooloth Dec 22, 2024
00cb515
notes: render bookmarks + drafts + notes on index page
ooloth Dec 22, 2024
f955898
collections: add Bookmark type
ooloth Dec 22, 2024
238a4b0
isPathnameInCollection: ignore leading/trailing slashes when comparin…
ooloth Dec 22, 2024
a5e73dd
notes: add tag helpers
ooloth Dec 22, 2024
6743b80
bookmarks: add helpers
ooloth Dec 22, 2024
39dbe6c
tags: add cleaning helper
ooloth Dec 22, 2024
d12f6e1
Merge branch 'main' into flat-notes
ooloth Dec 22, 2024
6260cae
Merge branch 'main' into flat-notes
ooloth Dec 23, 2024
73a4458
Merge branch 'main' into flat-notes
ooloth Dec 23, 2024
54aed5a
remark: get last modified date of content files in submodule
ooloth Dec 23, 2024
7d420a0
header: highlight notes nav link when on a draft page
ooloth Dec 23, 2024
35adcc2
base: block indexing drafts and bookmarks
ooloth Dec 23, 2024
5e7ae12
related: extract to separate component
ooloth Dec 23, 2024
76e9325
tag: extract markup (may not be necessary)
ooloth Dec 23, 2024
3911155
css: add todo re selection styles
ooloth Dec 23, 2024
7f8911e
bookmark: fix path to tags for privacy detection
ooloth Dec 23, 2024
213abd2
tags: find matching entries
ooloth Dec 23, 2024
27366ad
drafts: move to notes page
ooloth Dec 23, 2024
caf69e4
notes: show notes, drafts and bookmarks by last modified date
ooloth Dec 23, 2024
8f0a42c
remark: generate youtube embed markup from obsidian youtube image links
ooloth Dec 23, 2024
50c99cd
markdown: style hr color and vertical spacing
ooloth Dec 23, 2024
65d93f5
tags: make text a little smaller
ooloth Dec 23, 2024
485abc4
hr: ensure border color will take
ooloth Dec 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions lib/remark/last-modified.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// see: https://docs.astro.build/en/recipes/modified-time/

import { execSync } from 'child_process'
import { resolve } from 'path'

function remarkModifiedTime() {
return function (tree, file) {

Check failure on line 7 in lib/remark/last-modified.ts

View workflow job for this annotation

GitHub Actions / Format, lint and check types

Parameter 'tree' implicitly has an 'any' type.

Check failure on line 7 in lib/remark/last-modified.ts

View workflow job for this annotation

GitHub Actions / Format, lint and check types

Parameter 'file' implicitly has an 'any' type.
const filepath = file.history[0]

try {
// Resolve the absolute path of the file
const absoluteFilePath = resolve(filepath)

// Get the root directory of the repository
const repoRoot = execSync('git rev-parse --show-toplevel').toString().trim()

// Get the relative path of the file from the repository root
const relativeFilePath = absoluteFilePath.replace(`${repoRoot}/`, '')

// Check if the file is within a submodule
const submodulePath = execSync(`git submodule foreach --quiet 'echo $path'`)
.toString()
.trim()
.split('\n')
.find(submodule => relativeFilePath.startsWith(submodule))

let result
if (submodulePath) {
// Navigate to the submodule directory and get the last modified time
const submoduleAbsolutePath = resolve(repoRoot, submodulePath)
const submoduleRelativeFilePath = absoluteFilePath.replace(`${submoduleAbsolutePath}/`, '')
result = execSync(
`cd ${submoduleAbsolutePath} && git log -1 --pretty="format:%cI" "${submoduleRelativeFilePath}"`,
)
.toString()
.trim()
} else {
// Get the last modified time in the main repository
result = execSync(`git log -1 --pretty="format:%cI" "${relativeFilePath}"`).toString().trim()
}

file.data.astro.frontmatter.lastModified = result
} catch (error) {
console.error('Error getting last modified time:', error)
}
}
}

export default remarkModifiedTime
4 changes: 4 additions & 0 deletions lib/remark/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import remarkUnwrapImages from 'remark-unwrap-images'
import remarkWikiLink from '@portaljs/remark-wiki-link'

import remarkLastModified from './last-modified'
import remarkRemoveTags from './remove-tags'
import remarkYouTubeEmbedFromImageLink from './youtube-embed-from-image-link'

export default [
remarkLastModified,
remarkRemoveTags,
remarkUnwrapImages,
[
Expand All @@ -15,4 +18,5 @@ export default [
wikiLinkResolver: (slug: string): string[] => [`${slug}/`], // expects all pages to have root-level paths
},
],
remarkYouTubeEmbedFromImageLink,
]
40 changes: 40 additions & 0 deletions lib/remark/youtube-embed-from-image-link.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Obsidian uses ![](<video link>) for embedding videos responsively, so I need to convert those to YouTube embeds.
// see: https://www.ryanfiller.com/blog/remark-and-rehype-plugins
// see: https://github.com/syntax-tree/mdast

import type { RemarkPlugin } from '@astrojs/markdown-remark'
import type { Data, Image } from 'mdast'
import { visit } from 'unist-util-visit'
import type { Node } from 'unist'

/**
* Convert markdown image link containing a YouTube video link to a YouTube iFrame embed.
*/
const convertImageLinkToIframe = (url: string): string => {
const videoId = url.split('v=')[1]
const embedUrl = `https://www.youtube.com/embed/${videoId}`
return `<iframe width="560" height="315" src="${embedUrl}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>`
}

type Transformer = (tree: Node<Data>) => Promise<void>

/**
* Convert markdown image links containing Youtube video links to YouTube embeds.
*/
const remarkYouTubeEmbedFromImageLink: RemarkPlugin =
(): Transformer =>
async (tree: Node<Data>): Promise<void> => {
// Identify the type of node I want to modify ("text" in this case) here: https://astexplorer.net
visit(tree, 'image', (node: Image) => {
if (!node.url.includes('youtube.com')) return

// Use Object.assign to replace the exact same object instead of triggering an infinite loop by creating new objects
Object.assign(node, {
type: 'html',
value: convertImageLinkToIframe(node.url),
position: node.position,
})
})
}

export default remarkYouTubeEmbedFromImageLink
11 changes: 8 additions & 3 deletions src/components/Header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,27 @@
import nav, { type NavItem } from '../data/nav'
import site from '../data/site'
import { isPathnameInCollection } from '../utils/collections'
import { getPosts } from '../utils/posts'
import { getDrafts, getPosts } from '../utils/posts'
import { getNotes } from '../utils/notes'
import { getTILs } from '../utils/tils'
import { getBookmarks } from '../utils/bookmarks'

const posts = await getPosts()
const notes = await getNotes()
const tils = await getTILs()
const drafts = await getDrafts()
const notes = await getNotes()
const bookmarks = await getBookmarks()

const { pathname } = Astro.url

// see: https://docs.astro.build/en/reference/api-reference/#astrourl
const isCurrentPage = (item: NavItem): boolean =>
item.url === pathname ||
(isPathnameInCollection(pathname, posts) && item.url === '/') ||
(isPathnameInCollection(pathname, tils) && item.url === '/til/') ||
(isPathnameInCollection(pathname, drafts) && item.url === '/notes/') ||
(isPathnameInCollection(pathname, notes) && item.url === '/notes/') ||
(isPathnameInCollection(pathname, tils) && item.url === '/til/')
(isPathnameInCollection(pathname, bookmarks) && item.url === '/notes/')
---

<header class="mb-12">
Expand Down
57 changes: 57 additions & 0 deletions src/components/Related.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
import { type Draft, isPathnameInCollection, type Writing } from '../utils/collections'
import { getNotes } from '../utils/notes'
import { getDrafts, getPosts } from '../utils/posts'
import { getHumanReadableDate, getMachineReadableDate } from '../utils/dates'
import { getTILs } from '../utils/tils'
import { getBookmarks } from '../utils/bookmarks'
import { getEntriesWithTags as getEntriesWithSameTags } from '../utils/tags'

type Props = {
entry: Writing | Draft
}

const { entry } = Astro.props
const { pathname } = Astro.url

const posts = await getPosts()
const tils = await getTILs()
const bookmarks = await getBookmarks()
const drafts = await getDrafts()
const notes = await getNotes()

const isPost = isPathnameInCollection(pathname, posts)

const entriesWithSameTags = await getEntriesWithSameTags(entry, [...posts, ...tils, ...drafts, ...notes, ...bookmarks])

const hasRelated = Object.keys(entriesWithSameTags).length > 0
---

{
isPost || !hasRelated ? null : (
<footer class="markdown mt-12 border-t-2 border-zinc-600 pb-8">
{Object.entries(entriesWithSameTags).map(([tag, entriesWithTag]) => (
<>
<h2 class="text-red-500">
Related to <span class="text-zinc-400">#{tag}</span>
</h2>
<ul>
{entriesWithTag.map(item => (
<li>
<a href={`/${item.slug}/`}>{item.data.title}</a>

{item.data.date ? (
<time datetime={getMachineReadableDate(item.data.date)} class="timestamp ml-3">
{getHumanReadableDate(item.data.date)}
</time>
) : (
isPathnameInCollection(pathname, posts) && <span class="timestamp ml-3">draft</span>
)}
</li>
))}
</ul>
</>
))}
</footer>
)
}
9 changes: 9 additions & 0 deletions src/components/Tag.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
const { tag } = Astro.props

/* <li class="rounded border-[1px] border-[--moonlight-red] hover:bg-[--moonlight-red] px-2 leading-relaxed text-[--moonlight-red] hover:text-zinc-950"> */
---

<p class="rounded border-[1px] border-[--moonlight-red] px-2 leading-relaxed text-[0.95rem] text-[--moonlight-red]">
{tag}
</p>
27 changes: 22 additions & 5 deletions src/layouts/Base.astro
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
---
import '../styles/global.css'
import site from '../data/site'
import { getPosts } from '../utils/posts'
import { getDrafts, getPosts } from '../utils/posts'
import { getNotes } from '../utils/notes'
import { isPathnameInCollection } from '../utils/collections'
import { getTILs } from '../utils/tils'
import { getBookmarks } from '../utils/bookmarks'

export type BaseProps = {
description?: string
Expand All @@ -19,7 +20,15 @@ const { pathname } = Astro.url

const posts = await getPosts()
const tils = await getTILs()
const drafts = await getDrafts()
const notes = await getNotes()
const bookmarks = await getBookmarks()

const isPost = isPathnameInCollection(pathname, posts)
const isTIL = isPathnameInCollection(pathname, tils)
const isDraft = isPathnameInCollection(pathname, drafts)
const isNote = isPathnameInCollection(pathname, notes)
const isBookmark = isPathnameInCollection(pathname, bookmarks)

const isHome = pathname === '/'

Expand Down Expand Up @@ -73,12 +82,16 @@ const pageTitleWithSuffix = pageTitle + (isHome ? '' : ` • ${site.title}`)

const pageDescription = description
? description
: isPathnameInCollection(pathname, notes)
? `Notes about ${title} by ${site.author.name}.`
: isPathnameInCollection(pathname, posts)
: isPost
? `Blog post by ${site.author.name}.`
: isPathnameInCollection(pathname, tils)
: isTIL
? `Something ${site.author.name} learned about today.`
: isDraft
? `Notes for a future blog post by ${site.author.name}.`
: isNote
? `Notes about ${title} by ${site.author.name}.`
: isBookmark
? `Notes about ${title}.`
: site.description.site

const borderWidth = 0
Expand Down Expand Up @@ -160,6 +173,10 @@ const socialImage = ogImage

<!--- Feeds --->
<link rel="alternate" type="application/rss+xml" href={site.url + 'rss.xml'} title={site.title} />

<!-- Block indexing drafts and bookmarks -->
<!-- See: https://developers.google.com/search/docs/crawling-indexing/block-indexing -->
{isDraft || isBookmark ? <meta name="robots" content="noindex" /> : null}
</head>

<body>
Expand Down
Loading
Loading