Skip to content

Commit 6cc0c21

Browse files
authored
feat: rewrite to export into universal folder + support linking
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.
1 parent 09dcd2d commit 6cc0c21

File tree

29 files changed

+835
-538
lines changed

29 files changed

+835
-538
lines changed

.github/workflows/release.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ name: goreleaser
44
on:
55
pull_request:
66
push:
7+
branches:
8+
- main
79

810
jobs:
911
goreleaser:
@@ -29,4 +31,4 @@ jobs:
2931
env:
3032
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3133
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
32-
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
34+
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

.github/workflows/test.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# taken from https://github.com/mvdan/github-actions-golang/blob/master/.github/workflows/test.yml
2-
on: [push, pull_request]
2+
on:
3+
pull_request:
4+
push:
5+
branches:
6+
- main
7+
38
name: Test
49
jobs:
510
test:

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
logseq-export
2-
export-*
2+
export-*
3+
test/test-output

.goreleaser.yaml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,6 @@ builds:
88
- linux
99
- windows
1010
- darwin
11-
archives:
12-
- replacements:
13-
darwin: Darwin
14-
linux: Linux
15-
windows: Windows
16-
386: i386
17-
amd64: x86_64
1811
checksum:
1912
name_template: 'checksums.txt'
2013
snapshot:

Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
APP=logseq-export
2+
3+
.PHONY: build
4+
build:
5+
go build ./...
6+
# go build -o ${APP} main.go
7+
8+
.PHONY: test
9+
test:
10+
go test ./...
11+
12+
.PHONY: watch
13+
watch:
14+
fswatch --exclude 'test/test-output' -o ./ | xargs -n1 -I{} go test ./...
15+
16+
.PHONY: clean
17+
clean:
18+
go clean

README.md

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
11
# logseq-export
22

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

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

8+
**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.**
9+
810
## Install
911

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

1315
## Usage
1416

15-
### Command
17+
The `logseq-export` utility will export the pages into an export folder that can then be imported into your static site generator.
18+
19+
```mermaid
20+
graph LR;
21+
LS[Logseq graph] --"logseq-export"--> EF[export folder]
22+
EF --"import_to_hugo.sh"--> HU[Hugo static site generator]
23+
```
24+
25+
### Export
1626

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

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

2737
```yml
38+
# list of logseq page properties that won't be quoted in the markdown front matter
2839
unquotedProperties:
2940
- date
3041
- tags
31-
assetsRelativePath: "static/images/logseq"
32-
webAssetsPathPrefix: "/images/logseq"
3342
```
3443
35-
- `assetsRelativePath` relative path within blogFolder where the assets (images) should be stored (e.g. 'static/images/logseq'). Default is logseq-images (default "logseq-images")
36-
- `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")
37-
- `unquotedProperties` list of logseq page properties that won't be quoted in the markdown frontmatter
38-
3944
#### Command example
4045
4146
This is how I run the command on my machine:
4247
4348
```sh
4449
logseq-export \
4550
--logseqFolder /Users/tomas/workspace/private/notes \
46-
--outputFolder /Users/tomas/workspace/private/blog \
51+
--outputFolder /tmp/logseq-export \
4752
```
4853

49-
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)`).
54+
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)`).
55+
56+
#### Constraints
57+
58+
- `logseq-export` assumes that all the pages you want to export are in `pages/` folder inside your `logseqFolder`.
59+
60+
61+
### Import
62+
63+
```sh
64+
# these environment variables are optional
65+
# the values in this example are default values
66+
export BLOG_CONTENT_FODLER="/graph"
67+
export BLOG_IMAGES_FOLDER="/assets/graph"
68+
69+
# copies pages from `/tmp/logseq/export/logseq-pages` to `~/workspace/private/blog/content/graph`
70+
# copies assets from `/tmp/logseq/export/logseq-assets` to `~/workspace/private/blog/static/assets/graph`
71+
# replaces all `/logseq-assets` in all image URLs with `/assets/graph`
72+
./import_to_hugo.sh \
73+
/tmp/logseq-export
74+
~/workspace/private/blog
75+
```
5076

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

5379
- `public` - as soon as this page property is present (regardless of value), the page gets exported
80+
- `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:`
5481
- `slug` used as a file name
5582
- `date` it's used as a file name prefix
56-
- `folder` the page is going to be exported in this subfolder e.g. `content/posts`
57-
- the `folder` property always uses `/` (forward slash) but on Windows, it gets translated to `\` in folder path
58-
- 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
59-
- `image` The value of this property behaves the same way as all Markdown images.
60-
- 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.
83+
- if your logseq `date::` attributes contains the link brackets e.g. `[[2023-07-30]]`, `logseq-export` will remove them
6184

6285
## From
6386

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

6689
## To
6790

68-
`content/posts/2022-09-25-test-page.md` :
91+
`content/graph/2022-09-25-test-page.md` :
6992

7093
~~~md
7194
---
72-
date: 2022-09-25
73-
categories: "category"
95+
date: "2022-09-25"
7496
public: true
75-
slug: test-page
76-
folder: "content/posts"
97+
slug: "test-page"
98+
title: "Test page"
7799
---
78100

79101
This is an example paragraph
80102

81103
- Second level means bullet points
82-
83-
- `logseq-export` also supports multi-level bullet points
104+
- `logseq-export` also supports multi-level bullet points
84105

85106
```ts
86107
const v = "Hello world"

config.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"flag"
66
"fmt"
77
"log"
8-
"path"
8+
"path/filepath"
99

1010
"github.com/knadh/koanf/parsers/yaml"
1111
"github.com/knadh/koanf/providers/basicflag"
@@ -14,11 +14,9 @@ import (
1414
)
1515

1616
type Config struct {
17-
LogseqFolder string
18-
OutputFolder string
19-
UnquotedProperties []string
20-
AssetsRelativePath string
21-
WebAssetsPathPrefix string
17+
LogseqFolder string
18+
OutputFolder string
19+
UnquotedProperties []string
2220
}
2321

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

6462
logseqFolder := k.String("logseqFolder")
6563
// Load YAML config and merge into the previously loaded config (because we can).
66-
configPath := path.Join(logseqFolder, "export.yaml")
64+
configPath := filepath.Join(logseqFolder, "export.yaml")
6765
if err := k.Load(file.Provider(configPath), yaml.Parser()); err != nil {
6866
log.Printf("Failed to read config file %q. Using default config.", configPath)
6967
}

config_test.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package main
22

33
import (
4-
"path"
4+
"path/filepath"
55
"reflect"
66
"testing"
77
)
@@ -35,7 +35,7 @@ func TestParseMandatoryFlags(t *testing.T) {
3535
}
3636

3737
func TestTestParsingOptionalFlags(t *testing.T) {
38-
configFolderPath := path.Join(path.Dir(t.Name()), "test/config")
38+
configFolderPath := filepath.Join(filepath.Dir(t.Name()), "test/config")
3939
args := []string{
4040
"script-name",
4141
"--logseqFolder",
@@ -61,12 +61,4 @@ func TestTestParsingOptionalFlags(t *testing.T) {
6161
if !reflect.DeepEqual(config.UnquotedProperties, []string{"date", "tags"}) {
6262
t.Fatalf("incorrectly parsed unquotedProperties. Expected date, tags, got %v", config.UnquotedProperties)
6363
}
64-
65-
if config.AssetsRelativePath != "static/images/logseq" {
66-
t.Fatalf("incorrectly parsed assetsRelativePath. Expected 'static/images/logseq' got %v", config.AssetsRelativePath)
67-
}
68-
69-
if config.WebAssetsPathPrefix != "/images/logseq" {
70-
t.Fatalf("incorrectly parsed webAssetsPathPrefix. Expected '/images/logseq' got %v", config.WebAssetsPathPrefix)
71-
}
7264
}

docs/assets/logseq-teset-page.png

-2.98 KB
Loading

import_to_hugo.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
##!/bin/bash
2+
3+
set -e
4+
5+
# Check if the correct number of arguments is provided
6+
if [ "$#" -ne 2 ]; then
7+
echo "Usage: move_logseq_content.sh <export_folder> <blog_folder>"
8+
exit 1
9+
fi
10+
11+
# Extract arguments
12+
export_folder="$1"
13+
blog_folder="$2"
14+
15+
# Check if the export folder exists
16+
if [ ! -d "$export_folder" ]; then
17+
echo "Error: The export folder does not exist."
18+
exit 1
19+
fi
20+
21+
# Check if the blog folder exists
22+
if [ ! -d "$blog_folder" ]; then
23+
echo "Error: The blog folder does not exist."
24+
exit 1
25+
fi
26+
27+
blog_content_folder="${BLOG_CONTENT_FODLER:-/graph}"
28+
images_folder="${BLOG_IMAGES_FOLDER:-/assets/graph}"
29+
30+
# by default the files get copied as follows
31+
# - /logseq-pages -> /content/graph
32+
# - /logseq-assets -> /static/assets/graph
33+
pages_destination="$blog_folder/content$blog_content_folder"
34+
assets_destination="$blog_folder/static$images_folder"
35+
36+
# delete existing pages and assets
37+
rm -rf "$pages_destination"
38+
rm -rf "$assets_destination"
39+
40+
# prepare the directories
41+
mkdir -p "$pages_destination"
42+
mkdir -p "$assets_destination"
43+
44+
# Move the content of logseq-pages to the new destination
45+
cp -R "$export_folder/logseq-pages"/* "$pages_destination/"
46+
47+
# Move the content of logseq-assets to the new destination
48+
cp -R "$export_folder/logseq-assets"/* "$assets_destination/"
49+
50+
# replace the /logseq-asstes/ paths with the hugo image folder
51+
find "$pages_destination" -type f -exec sed -i '' -e "s@/logseq-assets/@$images_folder/@g" {} \;
52+
find "$pages_destination" -type f -exec sed -i '' -e "s@/logseq-pages/@$blog_content_folder/@g" {} \;
53+
54+
echo "Content moved successfully."

0 commit comments

Comments
 (0)