Is it possible for markdown export to link to other files?

This post was last updated for 292 days ago, and the information may already be changed

I exported a notebook to markdown (which is great), but I found that the files don't have links to other files like they were in Siyuan.

So, is there anyway to make markdown exports have links to other files?

    Welcome to here!

    Here we can learn from each other how to use SiYuan, give feedback and suggestions, and build SiYuan together.

    Signup About
    Please input reply content ...
    • giovannipollo

      Thanks a lot for the solution. It works really. I actively write python code for my PhD. If I have time, I will for sure look into extending it with blocks.

    • MiscReply
    • adham 1
      Author

      I was able to do it (for documents only, not blocks, as I don't know how to find out if the link is of a block or a document, and I don't want to mutate the linked documents anyway).

      Here's the Python script:

      import os
      import re
      import requests
      
      # Replace 'YOUR_API_ENDPOINT' with the actual Siyuan API endpoint
      SIYUAN_API_ENDPOINT = "http://localhost:6806"
      
      
      # Function to make a SQL query to Siyuan API
      def query_block_details(block_id):
          query = {"stmt": f"SELECT * FROM blocks WHERE id='{block_id}'"}
          response = requests.post(f"{SIYUAN_API_ENDPOINT}/api/query/sql", json=query)
          return response.json()
      
      
      # Function to process each markdown file
      def process_markdown_file(file_path):
          with open(file_path, "r", encoding="utf-8") as file:
              content = file.read()
      
              # Use regex to find instances of [Anchor text](siyuan://blocks/block-id)
              matches = re.findall(r"\[.*?\]\(siyuan://blocks/(.*?)\)", content)
      
              for block_id in matches:
                  # Query Siyuan API to get block details
                  result = query_block_details(block_id)
      
                  # Assumes ref is of a document, not a block
                  if result:
                      hpath_value = result["data"][0].get("hpath")
      
                      # Replace the siyuan://blocks/block-id with hpath_value.md
                      new_link = f"({hpath_value}.md)"
      
                      # Replace the old link in the content
                      content = content.replace(f"(siyuan://blocks/{block_id})", new_link)
      
          # Write the updated content back to the file
          with open(file_path, "w", encoding="utf-8") as file:
              file.write(content)
      
      
      def process_markdown_directory(directory_path):
          for root, _, files in os.walk(directory_path):
              for file_name in files:
                  if file_name.endswith(".md"):
                      file_path = os.path.join(root, file_name)
                      process_markdown_file(file_path)
      
      
      # Replace 'YOUR_MARKDOWN_DIRECTORY_PATH' with the actual path to your exported markdown files
      markdown_directory_path = "YOUR_MARKDOWN_DIRECTORY_PATH"
      
      # Process each markdown file in the specified path
      process_markdown_directory(markdown_directory_path)
      
      
    • sagar 2
      VIP Warrior

      I think there is a fairly simple solution to this, which I will describe below. I think it can be implemented as a simple Python script that does some post-processing of the exported markdown files. I will try to create a proof-of-concept script, but it will take me a few days because I am not a programmer and will need to learn some Python programming first.

      Solution description

      1. In Settings > Export configure 'Ref' to 'Anchor text with block URL'. After doing this, a link to another block in a SiYuan note appears in the exported Markdown file as [Anchor text](siyuan://blocks/block-id).

      2. Write a Python script that opens each exported markdown file and uses regex matching to identify all instances of [Anchor text](siyuan://blocks/block-id). For each instance,

      3. Use the /api/query/sql API endpoint to get details of the block-id by making a query like:

        { "stmt": "SELECT * FROM blocks WHERE id='block-id'" }

      4. In the query result, you can find the hpath key whose value is a human readable path.

        1. If the block-id is for a block of type document (which would be the case for a link to another document), then the Python script just needs to replace siyuan://blocks/block-id with hpath_value.md which would be the relative path to the exported markdown file that the link points to.
        2. If the block-id is for a block inside a document (e.g. to some arbitrary paragraph block in the document), all you need to do is to open the exported markdown document containing that paragraph (from the value of hpath for that block-id), find the start of the paragraph and add an <a name="block-id"></a> anchor at the start of the paragraph. Then, the siyuan://blocks/block-id in the exported markdown file can be replaced by hpath_value.md#block-id

      This would basically solve the problem of having correct links in the exported markdown files and additionally the exported notes can easily be converted to HTML and published e.g. with a static site generator like Hugo.

      @88250 Do you see any problems with this approach? I don't understand why SiYuan does not do this already when exporting to markdown.. but in any case, a Python script that does the above can post-process the exported markdown files from SiYuan and fix all the links. What do you think?

      1 Reply
      1 Operate
      sagar updated this reply at 2023-12-01 08:25:07
    • sagar
      VIP Warrior

      @adham Wow 😍 You are a master programmer indeed! I was still trying to figure out how to use Python to open all .md files in a directory, by copy/pasting code from Stackoverflow 😄 This solution is exactly what I meant.

      I do believe it can be extended to include references to any arbitrary block, not just a document block. You did say that you don't want to mutate the linked documents, but I am just laying out the approach in case any other master programmers want to try it 😄. You wrote,

      I don't know how to find out if the link is of a block or a document,

      I see a few different possible checks for this

      • Look at the 'type' field in the response of the SQL query. If it is a document block, the type value will be 'd'. Other type values are given in the documentation at /Please Start Here/Advanced search/Type filtering
      • I believe that if the block is of type document, then the 'root_id' will be the same as 'id'. See the documentation of the SQL table fields at /Please Start Here/Advanced search/Database table

      So one or both of the above checks can be used to determine if the block is of type 'document' or something else.

      If the block is of type something else, then the way to link to it would be

      1. Open the target document that contains the block (i.e. the hpath)
      2. Search for the occurrence of the content in the 'markdown' field of the SQL query response. This will place the "cursor" inside the document to the start of the paragraph (or whatever other content) the block points to
      3. At this cursor position, insert an HTML anchor text like: <a name="block-id"></a>
      4. Then, update the siyuan://blocks/block-id part of the link to hpath_value.md#block-id

      This approach enables having links in the markdown files to any other markdown files or parts inside markdown files.

      @adham Thank you once again for your example code 🙏

      3 Operate
      sagar updated this reply at 2023-12-02 01:22:47
      sagar updated this reply at 2023-12-02 01:21:03
      sagar updated this reply at 2023-12-02 01:18:06
    • Visit all replies