joplin <=> obsidian completed

ref: GitHub - rxliuli/mami: cross-tool document converter


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