An idea for a more standard-Markdown property syntax

The problem

The syntax for properties:

- key:: value

has three issues:

  1. It’s confusing about how values are parsed (see documentation here): you can choose between multiple values or longer text with commas, but not both at the same time. It is limiting and very developer-oriented. Sometimes text is turned into pages and the user needs to figure out why; when you experience it it seems a bug.
  2. To use a block as a property value you need to save the block somewhere else and reference it with ((block-id)), and this leads to even more issues especially with queries:
- Block A
  id:: 12345-12345-12345-12345
- Block B
  property:: ((12345-12345-12345-12345))
  1. When you open Logseq Markdown files in another editor, properties make them unusable.

The solution

Here there is an idea for a better properties syntax that:

  1. Support multiple values, mixing text and page references without ambiguities.
  2. Support blocks as values
  3. Looks good in Markdown editors

The idea is to use asterisk (*) bullet points for properties (as opposed to dash (-) bullet points used for blocks):

- Block A
  * key:: single value

For multiple values use blocks again:

- Block A
  * key::
    - First value
    - Second value

rendered it looks like this:

  • Block A
    • key::
      • First value
      • Second value

Since blocks can have their own properties, this means it’s possible to store structured data more or less like JSON:

- Oscar Wilde
  * Description:: Oscar Wilde was an Irish poet and playwright. After writing in different forms throughout the 1880s, he became one of the most popular playwrights in London in the early 1890s.
  * Books::
    - The Picture of Dorian Gray
      * Year:: 1891
	- The Importance of Being Earnest
	  * Year:: 1895
- Lewis Carroll
  * Books:: [[Alice in Wonderland]]

Rendered:

  • Oscar Wilde
    • Description:: Oscar Wilde was an Irish poet and playwright. After writing in different forms throughout the 1880s, he became one of the most popular playwrights in London in the early 1890s.
    • Books::
      • The Picture of Dorian Gray
        • Year:: 1891
      • The Importance of Being Earnest
        • Year:: 1895
  • Lewis Carroll
    • Books:: [[Alice in Wonderland]]

To make it even better when rendered, the key:: syntax could be replaced by **key:** and support spaces (**foo bar:**):

- Oscar Wilde
  * **Description:** Oscar Wilde was an Irish poet and playwright. After writing in different forms throughout the 1880s, he became one of the most popular playwrights in London in the early 1890s.
  * **Books:**
    - The Picture of Dorian Gray
      * **Year:** 1891
	- The Importance of Being Earnest
	  * **Year:** 1895
- Lewis Carroll
  * **Books:** [[Alice in Wonderland]]

Rendered:

  • Oscar Wilde
    • Description: Oscar Wilde was an Irish poet and playwright. After writing in different forms throughout the 1880s, he became one of the most popular playwrights in London in the early 1890s.
    • Books:
      • The Picture of Dorian Gray
        • Year: 1891
      • The Importance of Being Earnest
        • Year: 1895
  • Lewis Carroll
    • Books: [[Alice in Wonderland]]

Since we are at it, I think it would be better if it’s the user that specifies if a property key is also a page, like this:

- Block A
  * **[[Key A]]:** value

It may looks complex to type but this could be just the syntax to store in Markdown files: the Logseq UI could present this in a more WYSIWYG way.

CC @FlorianF

8 Likes

Not sure how I feel about this particular implementation but I agree that properties need a little love, especially when it comes to supporting lists of values. I think the YAML-looking approach you suggested is not bad, but maybe plain old YAML, with a marker to indicate we’re in “properties mode”, would be preferable? This is what most apps do and I think it works just fine.

Oscar Wilde
---
Description: Oscar Wilde was an Irish poet and playwright. After writing in different forms throughout the 1880s, he became one of the most popular playwrights in London in the early 1890s.
Books:
  The Picture of Dorian Gray:
     Year: 1891
  The Importance of Being Earnest:
     Year: 1895
---

This would correspond to the JSON

{
  "Description": "Oscar Wilde was an Irish poet and playwright. After writing in different forms throughout the 1880s, he became one of the most popular playwrights in London in the early 1890s.",
  "Books": {
    "The Picture of Dorian Gray": {
      "Year": 1891
    },
    "The Importance of Being Earnest": {
      "Year": 1895
    }
  }
}

To differentiate between regular old properties and objects, maybe two colons could be used:

Oscar Wilde
---
Description:: Oscar Wilde was an Irish poet and playwright. After writing in different forms throughout the 1880s, he became one of the most popular playwrights in London in the early 1890s.
Books::
  The Picture of Dorian Gray:
     Year:: 1891
  The Importance of Being Earnest:
     Year:: 1895
---

So now Description and Books would be bona fide properties, which could be queried, whereas The Picture of Dorian Gray and The Importance of Being Earnest are the names (in the sense of a Logseq page title) of the objects being described.

Your approach is the same of the current one: a syntax other than Markdown to store properties. In my case I am looking for a Markdown way to do that.

Your example here renders like this:

Oscar Wilde

Description: Oscar Wilde was an Irish poet and playwright. After writing in different forms throughout the 1880s, he became one of the most popular playwrights in London in the early 1890s.
Books:
The Picture of Dorian Gray:
Year: 1891
The Importance of Being Earnest:
Year: 1895

In Markdown you need - or * lists to indent, so anything that doesn’t use them won’t look right.

Logseq uses Markdown indented lists in the first place to nest pieces of informations one inside the other. The problem of properties here is the same: how do we nest properties and blocks together? With my idea you can nest them indefinitely deep, with properties having blocks as values that have their own properties that have blocks as values that have their own properties and so on.

1 Like

I am also interested in a Markdown-friendly way to hide some properties from rendering. I use properties to add comments on blocks, timestamps, etc that I don’t want rendered. Right now Logseq expects Properties after the first paragraph and inserts its hidden properties (“collapsed::”) after the last property of the Block.
I would suggest Logseq inserts its automated/hidden properties at the begining of the list and have a way to allow user-defined hidden as well as user-defined visible properties.
This can be a bit much to swallow and I am not a software engineer so bear with me on this one.
ATM if I have:

- block paragraph 1
  property1:: value1
  property2:: value2
  Second paragraph of the Block, followed by -maybe- a list, etc ...

and I want these to be hidden from the Markdown file rendering in an external editor I have to post-process the file and get the following:

- block paragraph 1 <!--
  property1:: value1
  property2:: value2
  -->
  Second paragraph of the Block, followed by -maybe- a list, etc ...

Now this is a hack and I will have the <!-- and --> visible in Logseq, but at least I would have these propertties hidden in Markdown. Of course the above is an HTML comment but Markdown doesn’t natively have anything to hide text, apart from another hack I use which is the Null-Anchor Link, which would look like:

- block paragraph 1 [](# '
  property1:: value1
  property2:: value2
  ')
  Second paragraph of the Block, followed by -maybe- a list, etc ...

because the above properties are one per line and they are starting from just under the first paragraph of the block, Logseq will see them and show them in the app, which is great.

Now for user defined hidden properties in Logseq I would use the .property like so:

- block paragraph 1
  .property1:: value1
  property2:: value2
  Second paragraph of the Block, followed by -maybe- a list, etc ...

Now I still have to post-process the file and get the user-defined hidden property enclosed in a HTML comment or in a multi-line Markdown Link pointing to an empty anchor:

- block paragraph 1 <!--
  .property1:: value1
  -->
  property2:: value2
  Second paragraph of the Block, followed by -maybe- a list, etc ...

But this doesn’t play well with Logseq because there can’t be any other lines in between properties so the HTML comment ending --> will break the Logseq way of working with properties. MOreover, If I collapse the block, I would get:

- block paragraph 1
  .property1:: value1
  property2:: value2
  .collapsed::true
  Second paragraph of the Block, followed by -maybe- a list, etc ...

so even if the .property would be addopted, placing the hidden property after the user-defined visible property will break the flow. SO Logseq automated hidden properties should be inserted at the top of the properties list while the visible and user-defied visible properties should be left for the subsequent ones:

- block paragraph 1
  .collapsed::true
  .property1:: value1
  property2:: value2
  Second paragraph of the Block, followed by -maybe- a list, etc ...

Now I can post-process the block and get:

- block paragraph 1 <!--
  .collapsed::true
  .property1:: value1
  -->
  property2:: value2
  Second paragraph of the Block, followed by -maybe- a list, etc ...

But for this to work, Logseq should allow properties to appear not in continuous rows.

I know my approach is hackish but if you can understand what I mean maybe you can adapt these suggestions into your “more standard-markdown” suggestion.

If I take your suggestion and add some Hidden Properties :

- Oscar Wilde
  * **.Note:** Add maximum 3 more Books and maybe a section for best quotes from each book!!
  * **.Edited:** 20230726
  * **Description:** Oscar Wilde was an Irish poet and playwright. After writing in different forms throughout the 1880s, he became one of the most popular playwrights in London in the early 1890s.
  * **Books:**
    - The Picture of Dorian Gray
      * **Year:** 1891
	- The Importance of Being Earnest
	  * **Year:** 1895
- Lewis Carroll
  * **Books:** [[Alice in Wonderland]]

, then, for my hidden & visible properties suggestion, something like the following should have to be achieved (assuming Logseq will insert its hidden properties atop of the stack, above the first property and not at the bottom and also allow some other lines -like the --> in between properties’ definitions):

- Oscar Wilde
  <!--
  * **.Note:** Add maximum 3 more Books and maybe a section for best quotes from each book!!
  * **.Edited:** 20230726
  -->
  * **Description:** Oscar Wilde was an Irish poet and playwright. After writing in different forms throughout the 1880s, he became one of the most popular playwrights in London in the early 1890s.
  * **Books:**
    - The Picture of Dorian Gray
      * **Year:** 1891
	- The Importance of Being Earnest
	  * **Year:** 1895
- Lewis Carroll
  * **Books:** [[Alice in Wonderland]]

and the HTML comment markers should be hidden from Logseq, maybe with CSS (if possible).

I have suggested in the past to use a dot as prefix to hide properties with no luck… in that case it would be easy to programmatically remove all the lines containing * **. without other marks.

Sadly Markdown doesn’t support comments, it’s one of the reasons I’d prefer Djot to Markdown.

I don’t think properties should be deleted, they are important data that I put into the files and I’d like them to remain in the file. I just want the rendering to not show some of them.

Properties are nice to use as they can contain links, LaTEX, paragrapghs, maybe even pictures and can be queried and shown in table format to get better insight into stuff. I don’t know how the same can be achieved without properties. Maybe there is a way, I don’t know that well Logseq …

I mean “exporting” Logseq Markdown files without the hidden properties so that they are not rendered in other programs.

If instead you mean hiding some properties from Logseq UI only, you can use the option in config.edn for that.

I mean having the exact same data in the markdown files but with a way to hide some of it from rendering, by using either html comments or markdown links multi-line titles, just as I exemplified, as I know of no other way to achieve this.

If by “rendering” you mean in Logseq, you can set which properties should be hidden in config.edn.

I know tht… it is so annoying. I need to be able to set those hidden properties whenever I am creating them, just as I type them.
And I mean rendering in an external Markdown Editor. I am doing my test with VSCodium and some Web editors.

Awesome Props plugin has an option to hide dotted properties:

Hmm, very interestig, will give it a try. I wonder how the markdown looks. I usually avoid plugins because they often drop out of favor or stop being maintained etc … As few plugins as possible is the best.

Right now, without any effort, I can Hide all properties from the Markdown rendering in an external editor while Logseq will still work with them as usual, as they are one per line under the Block’s First Paragraph:

  • block paragraph 1
    Second paragraph of the Block, followed by -maybe- a list, etc …

image
image3030×682 292 KB

If I only could hide, withc CSS, the from view it would be awesome.

Zettlr also uses YAML for its ‘frontmatter’ block and they render OK in Logseq:

Cf. Typora

Obsidian seems to turn everything monospaced.

Zettlr

1 Like

The point is block properties. I am not against YAML for page properties.

3 Likes

Come to think of it, I’d personally prefer Logseq Properties to be encased in markdown syntax like this -for example:

- test block
  [id:]([[ID]] "64c752b0-d33b-4448-a261-e4dc2bbe12d3")
  [property-name:]([[property-name]] "property value: URL, long text, etc")
  -->
  Block Body Text ...

This way the property name is clickable and pointing to a Logseq Link and, even in for an external editor the [[ID]] makes no sense, it will at least render correctly. If I want the property to be invisible I would just leave the [] empty and so it will not be rendered at all in an external editor while in Logseq it can be also hidden should Logseq respect the Markdown syntax (atm, if [] is empty, it will show the link of what’s in between [[ ]]):

image

I understand that ID and other hidden properties are special cases that may need some kind of ad-hoc syntax to be hidden in other editors. But the properties I am talking about here are not editor metadata, but actual user content, so I want them to render well in Markdown tools.

By the way as I already mentioned elsewhere, it would be way better for Logseq to move from Markdown to Djot, because it is basically a better flavour of Markdown and Logseq’s .md files are useless in other tools anyway.

I know hearing a new name like “Djot” may scary, but it really is Markdown 2.0 and it is by one of the authors of Commonmark (the most common Markdown flavour that we are using also here on Discourse) and author of Pandoc (the universal document converter).

2 Likes

If it is an in-place replacement for Markdown I am quite ok with such a move. I mostly care about FOSS, future-proofing and code/files readability -which Markdown kind of excels at, for being so simple you can actually print the files and be able to understand everything, unlike HTML/etc.

My previous response was written by giving an example of Logseq Metadata but, along with logseq metadata, which I’d like hidden (BUT NOT REMOVED), I want to be able to define myself hidden metadata (like timestamps of edits, etc) as well as visible metadata.

So, a block using my previous suggestion would look like this:

- test block
  []([[ID]] "64c752b0-d33b-4448-a261-e4dc2bbe12d3"); <-- Logseq Metadata Hidden property
  []([[edited-on]] "/date /time");  <-- User-defined hidden Metadata
  [status:]([[status]] "Ongoing"); <-- User-Defined visible Metadata
  Block Body Text ...

This would look like this in Logseq:


In external Editor:

1 Like

I like the ideas presented here. For me most importantly is that the plain text and Logseq works well.
I don’t use other editors (unless we want to count Notepad++ lol), so Logseq’s rendering is most important to me.
Therefore I especially like what @alex0 suggested in the original post. I just hope it would play well with queries and the like. But that is probably dependent on how such a thing is stored in the database.

1 Like

I’ll throw in what I always thought was going to be the way to include “metadata” into markdown, but feel free to ignore it, what is proposed here seems to be good.

My thought was to use triple backticks with a custom type, so

(picture backticks instead of single quotes)
'''logseq
Any syntax could go here
'''

This would make it trivial to exclude or parse differently or even use a specific language, or multiple, if json is desirable logseqjson could be used, while logseq is for nornal text properties in the format described by the OP.