Skip to content

Commit

Permalink
feat: rewrite to export into universal folder + support linking
Browse files Browse the repository at this point in the history
This commit rewrites logseq-export to be more opinionated with the idea that you'll dedicate a whole folder to all your interlinked notes instead of trying to transform logseq notes into customised blog articles.
New features

- supports interlinking - If you link between pages with [[title]], this will be transformed into [title](/logseq-pages/slug) in your pages
- more opinionated about where the files will go - the idea is that each CMS system will require a small bash script that will move the files in the right place. I tried to decouple this tool from Hugo, but I haven't tried any other static site generators
- better Windows support




BREAKING CHANGE: complete rewrite, use version `0.0.3` for the old functionality.
  • Loading branch information
viktomas authored Jul 31, 2023
1 parent 09dcd2d commit 6cc0c21
Show file tree
Hide file tree
Showing 29 changed files with 835 additions and 538 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ name: goreleaser
on:
pull_request:
push:
branches:
- main

jobs:
goreleaser:
Expand All @@ -29,4 +31,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
7 changes: 6 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# taken from https://github.com/mvdan/github-actions-golang/blob/master/.github/workflows/test.yml
on: [push, pull_request]
on:
pull_request:
push:
branches:
- main

name: Test
jobs:
test:
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
logseq-export
export-*
export-*
test/test-output
7 changes: 0 additions & 7 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@ builds:
- linux
- windows
- darwin
archives:
- replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
checksum:
name_template: 'checksums.txt'
snapshot:
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
APP=logseq-export

.PHONY: build
build:
go build ./...
# go build -o ${APP} main.go

.PHONY: test
test:
go test ./...

.PHONY: watch
watch:
fswatch --exclude 'test/test-output' -o ./ | xargs -n1 -I{} go test ./...

.PHONY: clean
clean:
go clean
67 changes: 44 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
# logseq-export

Tool to export raw [Logseq](https://github.com/logseq/logseq) Markdown files (with `public::` page property) into Markdown blog posts with front matter.
Tool to export raw [Logseq](https://github.com/logseq/logseq) Markdown pages (with `public::` page property) into Markdown blog posts with front matter.

- Takes Logseq page properties (`title:: Hello world`) and turns them into [Front Matter properties](https://gohugo.io/content-management/front-matter/) `title: Hello World`.
- Changes the Markdown syntax to remove the top-level bullet points.

**Note: I completely reworked `logseq-export` to be a bit more versatile and universal. See the [version `v0.0.3`](https://github.com/viktomas/logseq-export/tree/v0.0.3) if you are not ready to move on.**

## Install

- Download the latest binary for your OS in the [Releases](https://github.com/viktomas/logseq-export/releases) page
- `go install github.com/viktomas/logseq-export@latest` if you have Go installed

## Usage

### Command
The `logseq-export` utility will export the pages into an export folder that can then be imported into your static site generator.

```mermaid
graph LR;
LS[Logseq graph] --"logseq-export"--> EF[export folder]
EF --"import_to_hugo.sh"--> HU[Hugo static site generator]
```

### Export

```
logseq-export
Expand All @@ -22,65 +32,76 @@ logseq-export
[MANDATORY] Path to the root of your logseq graph containing /pages and /journals directories.
```

This command also expects you have a file called `export.yaml` in your logseq folder.
*Optional* configuration is in a file called `export.yaml` in your logseq folder.

```yml
# list of logseq page properties that won't be quoted in the markdown front matter
unquotedProperties:
- date
- tags
assetsRelativePath: "static/images/logseq"
webAssetsPathPrefix: "/images/logseq"
```
- `assetsRelativePath` relative path within blogFolder where the assets (images) should be stored (e.g. 'static/images/logseq'). Default is logseq-images (default "logseq-images")
- `webAssetsPathPrefix` path that the images are going to be served on on the web (e.g. '/public/images/logseq'). Default is /logseq-images (default "/logseq-images")
- `unquotedProperties` list of logseq page properties that won't be quoted in the markdown frontmatter

#### Command example
This is how I run the command on my machine:
```sh
logseq-export \
--logseqFolder /Users/tomas/workspace/private/notes \
--outputFolder /Users/tomas/workspace/private/blog \
--outputFolder /tmp/logseq-export \
```

This will take my logseq notes and copies them to blog, it will also copy all the images to `/Users/tomas/workspace/private/blog/static/images/logseq`, but the image links themselves are going to have `/images/logseq` prefix (`![alt](/images/logseq/image.png)`).
This will take my logseq notes and copies them to the export folder, it will also copy all the images to `/tmp/logseq-export/logseq-assets`, but the image links themselves are going to have `/logseq-asstes/` prefix (`![alt](/logseq/assets/image.png)`).

#### Constraints

- `logseq-export` assumes that all the pages you want to export are in `pages/` folder inside your `logseqFolder`.


### Import

```sh
# these environment variables are optional
# the values in this example are default values
export BLOG_CONTENT_FODLER="/graph"
export BLOG_IMAGES_FOLDER="/assets/graph"

# copies pages from `/tmp/logseq/export/logseq-pages` to `~/workspace/private/blog/content/graph`
# copies assets from `/tmp/logseq/export/logseq-assets` to `~/workspace/private/blog/static/assets/graph`
# replaces all `/logseq-assets` in all image URLs with `/assets/graph`
./import_to_hugo.sh \
/tmp/logseq-export
~/workspace/private/blog
```

### Logseq page properties with a special meaning (all optional)

- `public` - as soon as this page property is present (regardless of value), the page gets exported
- `title` - either the `title::` is present and used as `title:` front matter attribute, or the page file name is unescaped (e.g. `%3A` changes to `:`) and used as the `title:`
- `slug` used as a file name
- `date` it's used as a file name prefix
- `folder` the page is going to be exported in this subfolder e.g. `content/posts`
- the `folder` property always uses `/` (forward slash) but on Windows, it gets translated to `\` in folder path
- if the base export folder is `a` and the `folder` page property is `b/c`, then the resulting page will be in `a/b/c` folder
- `image` The value of this property behaves the same way as all Markdown images.
- if the `image` property contains `../assets/post-image.jpg`, and we run the `logseq-extract` with `--webAssetsPathPrefix /images/logseq -assetsRelativePath static/images/logseq` flags, the resulting Markdown post will have front-matter attribute `image: /images/logseq/post-image.jpg` and the image will be copied to `static/images/logseq/post-image.jpg` in the blog folder.
- if your logseq `date::` attributes contains the link brackets e.g. `[[2023-07-30]]`, `logseq-export` will remove them

## From

![logseq test page](./docs/assets/logseq-teset-page.png)

## To

`content/posts/2022-09-25-test-page.md` :
`content/graph/2022-09-25-test-page.md` :

~~~md
---
date: 2022-09-25
categories: "category"
date: "2022-09-25"
public: true
slug: test-page
folder: "content/posts"
slug: "test-page"
title: "Test page"
---

This is an example paragraph

- Second level means bullet points

- `logseq-export` also supports multi-level bullet points
- `logseq-export` also supports multi-level bullet points

```ts
const v = "Hello world"
Expand Down
12 changes: 5 additions & 7 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"flag"
"fmt"
"log"
"path"
"path/filepath"

"github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/basicflag"
Expand All @@ -14,11 +14,9 @@ import (
)

type Config struct {
LogseqFolder string
OutputFolder string
UnquotedProperties []string
AssetsRelativePath string
WebAssetsPathPrefix string
LogseqFolder string
OutputFolder string
UnquotedProperties []string
}

func (c *Config) Validate() error {
Expand Down Expand Up @@ -63,7 +61,7 @@ func parseConfig(args []string) (*Config, error) {

logseqFolder := k.String("logseqFolder")
// Load YAML config and merge into the previously loaded config (because we can).
configPath := path.Join(logseqFolder, "export.yaml")
configPath := filepath.Join(logseqFolder, "export.yaml")
if err := k.Load(file.Provider(configPath), yaml.Parser()); err != nil {
log.Printf("Failed to read config file %q. Using default config.", configPath)
}
Expand Down
12 changes: 2 additions & 10 deletions config_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package main

import (
"path"
"path/filepath"
"reflect"
"testing"
)
Expand Down Expand Up @@ -35,7 +35,7 @@ func TestParseMandatoryFlags(t *testing.T) {
}

func TestTestParsingOptionalFlags(t *testing.T) {
configFolderPath := path.Join(path.Dir(t.Name()), "test/config")
configFolderPath := filepath.Join(filepath.Dir(t.Name()), "test/config")
args := []string{
"script-name",
"--logseqFolder",
Expand All @@ -61,12 +61,4 @@ func TestTestParsingOptionalFlags(t *testing.T) {
if !reflect.DeepEqual(config.UnquotedProperties, []string{"date", "tags"}) {
t.Fatalf("incorrectly parsed unquotedProperties. Expected date, tags, got %v", config.UnquotedProperties)
}

if config.AssetsRelativePath != "static/images/logseq" {
t.Fatalf("incorrectly parsed assetsRelativePath. Expected 'static/images/logseq' got %v", config.AssetsRelativePath)
}

if config.WebAssetsPathPrefix != "/images/logseq" {
t.Fatalf("incorrectly parsed webAssetsPathPrefix. Expected '/images/logseq' got %v", config.WebAssetsPathPrefix)
}
}
Binary file modified docs/assets/logseq-teset-page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 54 additions & 0 deletions import_to_hugo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
##!/bin/bash

set -e

# Check if the correct number of arguments is provided
if [ "$#" -ne 2 ]; then
echo "Usage: move_logseq_content.sh <export_folder> <blog_folder>"
exit 1
fi

# Extract arguments
export_folder="$1"
blog_folder="$2"

# Check if the export folder exists
if [ ! -d "$export_folder" ]; then
echo "Error: The export folder does not exist."
exit 1
fi

# Check if the blog folder exists
if [ ! -d "$blog_folder" ]; then
echo "Error: The blog folder does not exist."
exit 1
fi

blog_content_folder="${BLOG_CONTENT_FODLER:-/graph}"
images_folder="${BLOG_IMAGES_FOLDER:-/assets/graph}"

# by default the files get copied as follows
# - /logseq-pages -> /content/graph
# - /logseq-assets -> /static/assets/graph
pages_destination="$blog_folder/content$blog_content_folder"
assets_destination="$blog_folder/static$images_folder"

# delete existing pages and assets
rm -rf "$pages_destination"
rm -rf "$assets_destination"

# prepare the directories
mkdir -p "$pages_destination"
mkdir -p "$assets_destination"

# Move the content of logseq-pages to the new destination
cp -R "$export_folder/logseq-pages"/* "$pages_destination/"

# Move the content of logseq-assets to the new destination
cp -R "$export_folder/logseq-assets"/* "$assets_destination/"

# replace the /logseq-asstes/ paths with the hugo image folder
find "$pages_destination" -type f -exec sed -i '' -e "s@/logseq-assets/@$images_folder/@g" {} \;
find "$pages_destination" -type f -exec sed -i '' -e "s@/logseq-pages/@$blog_content_folder/@g" {} \;

echo "Content moved successfully."
Loading

0 comments on commit 6cc0c21

Please sign in to comment.