I rewrote the joplin-blog and it is now separated into the mami project

If you don't know what joplin-blog is, let me briefly introduce it: it is a cli tool for converting joplin notes into other forms of content, supporting blog/wiki frameworks such as hexo, vuepress, docsify, jeykll. ref: https://discourse.joplinapp.org/t/joplin-note-sharing-tool/13480

Motivation

Why started this rewrite?

The main reason is that some frameworks are currently supported, but it is still not enough. In my case, I have come into contact with the vitepress documentation generator. I plan to use it to replace vuepress, but this requires some modifications to joplin-blog, which actually does not not very convenient. Some people have also mentioned how to generate more customized files, such as adding additional yaml meta information to the generated markdown (ref: https://github.com/rxliuli/joplin-utils/issues/55), which It's actually a bit cumbersome without extension points, the temporary solution given at that time was to use joplin-blog in the form of a lib, and insert some custom logic to do it. There is also mention of supporting hugo, but it is not shown that all is implemented in joplin-blog.

after

Later, I realized that a plugin system is needed to support generating arbitrary framework files, and further, I can even add input sources such as joplin as plugins, just like pandoc, to connect different note-taking, blogging and wiki tools. One of the current attempts is mami, which intends to use markdown as an intermediate format for conversion.
At present, this project has just been created, and only supports joplin as input source and hexo/local-dir as output source, but I have already used it in my own blog, reference: <GitHub - rxliuli/blog: 个人博客 blob/master/mami.config.ts>

GitHub: https://github.com/rxliuli/mami

PS

The origin of the name mami is [Mami Tomoe] in Puella Magi Madoka Magica (Mami Tomoe - Wikipedia), her magic is a ribbon that can connect various things , and can even form a musket (:

8 Likes

@mami/plugin-hugo-output It has been simply implemented, it can generate the files required by hugo from joplin notes, basically just make some simple modifications to hexo, refer to the example project: mami/mami.config.ts at master · rxliuli/mami · GitHub


2 Likes

joplin <=> obsidian completed

ref: GitHub - rxliuli/mami


Usage

Requirements

Step 1: Create a new project

The following uses pnpm as the package manager, but you can replace it with npm

Create a new directory and enter

mkdir mami-starter && cd mami-starter

Then use your favorite package manager to initialize

pnpm init

Step 2: Install mami

Add @mami/cli and typescript as development dependencies of the project

pnpm i -D @mami/cli typescript

Add some scripts to package.json

{
  ...
  "scripts": {
    "gen": "mami"
  },
  ...
}

Create your config file mami.config.ts

import { defineConfig } from '@mami/cli'

export default defineConfig({
  input: [],
  output: [],
})

then run

$ pnpm run gen

> joplin2obsidian-demo@1.0.0 gen
> mami

start
end

Well, nothing happens because you have no input or output plugin defined. Continue to the next step.

Step 3: Install the required plugins

Install the required plug-ins to connect the required tools. Here we use joplin => obsidian as an example

pnpm i -D @mami/plugin-joplin @mami/plugin-obsidian

Modify your config file mami.config.ts

The token required by the joplin plugin here comes from the web clipper service

import { defineConfig } from '@mami/cli'
import * as joplin from '@mami/plugin-joplin'
import * as obsidian from '@mami/plugin-obsidian'
import path from 'path'

export default defineConfig({
  input: [
    joplin.input({
      baseUrl: 'http://localhost:41184',
      token:
        '5bcfa49330788dd68efea27a0a133d2df24df68c3fd78731eaa9914ef34811a34a782233025ed8a651677ec303de6a04e54b57a27d48898ff043fd812d8e0b31',
      tag: '',
    }),
  ],
  output: [
    obsidian.output({
      root: path.resolve(__dirname, 'dist'),
    }),
  ],
})

Step 4: Perform the conversion

Then you can rerun the following command

pnpm run gen

Now you will see the converted obsidian file in dist

example

plugins

API Documentation

Roughly speaking, plugins are divided into input and output plugins. The input plugin will return an AsyncGenerator, while the output plugin will return an AsyncGenerator will consume it in the handle hook function.

design

Intermediate format

{
  "id": "0e2510c9272449dbafe3e0f3fba12d74",
  "title": "Welcome to Joplin!",
  "content": "content body",
  "createAt": 1666288266591,
  "updateAt": 1666288266591,
  "path": ["Welcome! (Desktop)"],
  "tags": [
    {
      "id": "04dfa5cf19e4435f9f3f09a73a7edfb2",
      "title": "blog"
    }
  ],
  "resources": [
    {
      "id": "63b83e548b7b4adfae18544b7038b0bc",
      "title": "AllClients.png",
      "raw": "<nodejs buffer>"
    }
  ]
}

Writing plugins involves some markdown ast operations. For example, you may need to convert links in markdown. It is recommended to use mdast to handle it.

3 Likes

mami-cli.exe demo

Publishing a mami-cli binary, I tried making an exe that doesn't require installing nodejs or npm dependencies, see if anyone is interested.

Instructions

  1. Download mami-cli.exe

  2. Put it in the directory that needs to be manipulated

  3. Add a config file, basically of the form [name, config], an example of converting from joplin to hexo

    {
      "input": [
        [
          "joplin",
          {
            "baseUrl": "http://127.0.0.1:27583",
            "token": "5bcfa49330788dd68efea27a0a133d2df24df68c3fd78731eaa9914ef34811a34a782233025ed8a651677ec303de6a04e54b57a27d48898ff043fd812d8e0b31",
            "tag": "blog"
          }
        ]
      ],
      "output": [["hugo", { "baseUrl": "/demo/joplin2hugo-for-release/" }]]
    }
    
  4. Run the command ./mami-cli

An example project is https://github.com/rxliuli/mami/tree/master/demos/joplin2hugo-for-release-demo

release: Release mami-cli.exe · rxliuli/mami · GitHub

3 Likes

Implement the docsify plugin,ref: mami/demos/joplin2docsify-demo at master · rxliuli/mami · GitHub

demo: https://mami.rxliuli.com/demo/joplin2docsify/

3 Likes

Conversion from joplin to other formats is much faster than I expected, so nice!

The Obsidian output is nicer to work with than Hexo or Hugo because the filenames are the page titles instead of Hex ID string.

Is it possible to select a particular Joplin notebook to export instead of everything? I have a lot of notes that aren't suitable for web publishing. (Though it is comforting to have an quick and easy external backup of all of it.)

Pictures seem to be broken in the output files. The links I'm getting look like
src=":/2373913a38e3428eba18192417db21dd"
instead of
src="../resources/2373913a38e3428eba18192417db21dd.jpg"

Update: it's only pictures using html tags that break, regular markdown pics are okay.

The Obsidian output is nicer to work with than Hexo or Hugo because the filenames are the page titles instead of Hex ID string.

Not exactly, because hexo/hugo essentially expects no manual editing after the output, so directly using id as the file name is a convenient method, and it does not affect the final rendering of hexo/hugo. You can refer to the example: mami/demos/joplin2hexo-demo at master · rxliuli/mami · GitHub

Is it possible to select a particular Joplin notebook to export instead of everything? I have a lot of notes that aren't suitable for web publishing. (Though it is comforting to have an quick and easy external backup of all of it.)

Yes, you can filter using the tag field, for example the following configurations are supported

{
  baseUrl: 'http://127.0.0.1:27583',
  token:
    '',
  tag: 'blog',
}

it's only pictures using html tags that break, regular markdown pics are okay

Yes, html is not supported yet, and I'm still not sure if I should support it, because html parser is another thing, and I should not add support for it for the time being, but anyway, the plugin can handle converting html in markdown by itself.

ps: The main reason why joplin to other formats is fast is that the intermediate format uses joplin. Although some problems have been found, the main problem is that the attachments and links cannot be distinguished, especially when the notes of attachments or links do not exist, it is impossible to judge

thanks for the extra info!

Published @mami/plugin-vuepress, support to generate vuepress files, refer to the example

1 Like

Published @mami/plugin-vitepress, support to generate vitepress files, refer to the example

1 Like