Skip to content

Commit

Permalink
feat: tags will get enclosed with []
Browse files Browse the repository at this point in the history
  • Loading branch information
viktomas committed Aug 4, 2023
1 parent a9bc58e commit f701a62
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 44 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ logseq-export
# list of logseq page properties that won't be quoted in the markdown front matter
unquotedProperties:
- date
- tags
```
#### Command example
Expand Down Expand Up @@ -80,6 +79,7 @@ export BLOG_IMAGES_FOLDER="/assets/graph"

- `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:`
- `tags` - Logseq uses comma separated values (`tags:: tag1, tag2`) but valid `yaml` in the front matter has to surround the value with square brackets (`tags: [tag1, tag2]`). The `tags` attribute is **always unquoted**.
- `slug` used as a file name
- `date` it's used as a file name prefix
- if your logseq `date::` attributes contains the link brackets e.g. `[[2023-07-30]]`, `logseq-export` will remove them
Expand Down
30 changes: 16 additions & 14 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func Run(args []string) error {
err = afero.WriteFile(
appFS,
exportPath,
[]byte(render(page.pc.attributes, contentWithAssets, config.UnquotedProperties)),
[]byte(render(transformAttributes(page.pc.attributes, config.UnquotedProperties), contentWithAssets)),
0644,
)
if err != nil {
Expand All @@ -153,6 +153,19 @@ func Run(args []string) error {
return nil
}

func transformAttributes(attributes map[string]string, dontQuote []string) map[string]string {
dontQuote = append(dontQuote, "tags")
if _, ok := attributes["tags"]; ok {
attributes["tags"] = fmt.Sprintf("[%s]", attributes["tags"])
}
for name, value := range attributes {
if !slices.Contains(dontQuote, name) {
attributes[name] = fmt.Sprintf("%q", value)
}
}
return attributes
}

func detectPageLinks(content string) []string {
result := regexp.MustCompile(`\[\[([^\/\n\r]+?)]]`).FindAllStringSubmatch(content, -1)
links := make([]string, 0, len(result))
Expand Down Expand Up @@ -204,26 +217,15 @@ func replaceAssetPaths(p parsedPage) string {
return newContent
}

func parseUnquotedProperties(param string) []string {
if param == "" {
return []string{}
}
return strings.Split(param, ",")
}

func render(attributes map[string]string, content string, dontQuote []string) string {
func render(attributes map[string]string, content string) string {
sortedKeys := make([]string, 0, len(attributes))
for k := range attributes {
sortedKeys = append(sortedKeys, k)
}
slices.Sort(sortedKeys)
attributeBuilder := strings.Builder{}
for _, key := range sortedKeys {
if slices.Contains(dontQuote, key) {
attributeBuilder.WriteString(fmt.Sprintf("%s: %s\n", key, attributes[key]))
} else {
attributeBuilder.WriteString(fmt.Sprintf("%s: %q\n", key, attributes[key]))
}
attributeBuilder.WriteString(fmt.Sprintf("%s: %s\n", key, attributes[key]))
}
return fmt.Sprintf("---\n%s---\n%s", attributeBuilder.String(), content)
}
47 changes: 25 additions & 22 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ var expectedPages = []string{
filepath.Join("logseq-pages", "b.md"),
}

func TestTransformAttributes(t *testing.T) {
attributes := map[string]string{
"tags": "tag1, another-tag",
"quoted": "quoted",
"unquoted": "unquoted",
}

result := transformAttributes(attributes, []string{"unquoted"})

require.Equal(t, map[string]string{
"tags": "[tag1, another-tag]",
"quoted": "\"quoted\"",
"unquoted": "unquoted",
}, result)
}

func TestFullTransformation(t *testing.T) {
deleteTestOutputFolder(t)
testLogseqFolder := filepath.Join(testDir, "test", "logseq-folder")
Expand Down Expand Up @@ -129,10 +145,10 @@ func TestRender(t *testing.T) {
"second": "2",
}
content := "page text"
result := render(attributes, content, []string{})
result := render(attributes, content)
require.Equal(t, `---
first: "1"
second: "2"
first: 1
second: 2
---
page text`, result)
})
Expand All @@ -145,26 +161,13 @@ page text`, result)
"a": "1",
}
content := "page text"
result := render(attributes, content, []string{})
require.Equal(t, `---
a: "1"
b: "1"
c: "1"
d: "1"
e: "1"
---
page text`, result)
})
t.Run("it renders attributes without quotes", func(t *testing.T) {
attributes := map[string]string{
"first": "1",
"second": "2",
}
content := "page text"
result := render(attributes, content, []string{"first", "second"})
result := render(attributes, content)
require.Equal(t, `---
first: 1
second: 2
a: 1
b: 1
c: 1
d: 1
e: 1
---
page text`, result)
})
Expand Down
7 changes: 1 addition & 6 deletions parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,8 @@ func firstBulletPointsToParagraphs(from string) string {
return regexp.MustCompile(`(?m:^- )`).ReplaceAllString(from, "\n")
}

func secondToFirstBulletPoints(from string) string {
return regexp.MustCompile(`(?m:^\t-)`).ReplaceAllString(from, "\n-")
}

func removeTabFromMultiLevelBulletPoints(from string) string {
return regexp.MustCompile(`(?m:^\t{2,}-)`).ReplaceAllStringFunc(from, func(s string) string {
return regexp.MustCompile(`(?m:^\t{1,}-)`).ReplaceAllStringFunc(from, func(s string) string {
return s[1:]
})
}
Expand Down Expand Up @@ -152,7 +148,6 @@ func parseContent(rawContent string) parsedContent {
removeEmptyBulletPoints,
unindentMultilineStrings,
firstBulletPointsToParagraphs,
secondToFirstBulletPoints,
removeTabFromMultiLevelBulletPoints,
)
return parsedContent{
Expand Down
2 changes: 1 addition & 1 deletion parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func TestParseContent(t *testing.T) {

t.Run("turns second level bullet points into first level", func(t *testing.T) {
result := parseContent("\t- hello\n\t- world")
require.Equal(t, "\n- hello\n\n- world", result.content) // TODO: maybe remove the duplicated new line
require.Equal(t, "- hello\n- world", result.content)
})

t.Run("removes one tab from multi-level bullet points", func(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions test/expected-output/logseq-pages/b.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
public: true
slug: "b"
tags: [tag1, another-tag]
title: "Hello World"
---

Expand Down
1 change: 1 addition & 0 deletions test/logseq-folder/pages/B.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
title:: Hello World
public:: true
tags:: tag1, another-tag

- ![pngimg](../assets/picture-2.png)
- ![test that we don't fail on non-existing-image](../assets/image-that-doesnt-exist.png)
Expand Down

0 comments on commit f701a62

Please sign in to comment.