DGS WeChat Publisher

approved

by d0u9

Create a WeChat Official Account draft from the current Markdown note. - This plugin has not been manually reviewed by Obsidian staff.

24 downloadsUpdated 19d agoMIT

DGS WeChat Publisher for Obsidian

中文说明

Turn the Markdown note you are editing into a WeChat Official Account draft, formatted with the inline HTML the WeChat editor accepts. Typography comes from dgs-wechat-publisher.

The plugin only ever creates a draft. It never publishes an article and never sends a mass message.

Desktop only, and Chinese-facing by nature: the runtime messages are in Chinese, because the people writing these articles are.

Getting started

  1. Put your Official Account credentials in a .env file outside your vault:

    WECHAT_APP_ID=wx…
    WECHAT_APP_SECRET=…
    WECHAT_AUTHOR=Your name   # optional
    

    In Settings → Community plugins → DGS WeChat Publisher, set Credentials file to that file's full path — written out in full, since ~ is not expanded — then press Check. This is the only way to give the plugin credentials: nothing secret is written into your vault.

  2. In the WeChat admin console, whitelist this machine's public IP address and confirm the account has permission to use the material and draft APIs.

  3. Give the note some frontmatter:

    ---
    title: An article
    description: The summary readers see in the subscription list
    cover: ./images/cover.jpg # optional — you are asked when it is missing
    author: A name            # optional
    lang: zh                  # zh (default) or en; picks the typography
    ---
    
  4. Run 预检并预览当前笔记 (preview) to check the rendering, then 发布当前笔记到公众号草稿箱 (publish) to create the draft.

What it handles

Images. Standard Markdown (![](./images/photo.jpg)) and Obsidian wiki embeds (![[photo.jpg]]) both work, in the body and for the cover. Relative references (./, ../) resolve against the note's folder, a leading / against the vault root, and remote http(s) images are downloaded and re-uploaded. JPEG and PNG under WeChat's 1 MB limit are uploaded untouched, so quality and transparency survive; anything larger is scaled and re-encoded. Covers are cropped to the 900×500 thumbnail WeChat wants. The body endpoint takes no GIF, so an animated one is uploaded as its first frame.

Missing pieces. A note without a title, digest, author or cover is not rejected. The cover picker offers candidates best guess first — the bundle's own images, then the note's pictures, then its folder, then the vault — each with a thumbnail. The confirmation dialog asks for whatever text is still missing, within WeChat's own length limits. With Remember what you fill in enabled (the default), your answers are written back to the note's frontmatter, so the next publish asks nothing.

Bundles. An article can be a folder rather than a single note, matching the layout the base library publishes from the command line:

my-article/
├── index.md      shared, language-independent frontmatter — the cover in particular
├── zh.md         title and description, which are per-language by nature
├── en.md
└── images/
    └── cover.jpg

Running the command on a translation picks up the index.md beside it, and anything the translation names itself wins. Running it on index.md asks which translation to publish. The filename decides the typography, ahead of any lang in the frontmatter. A cover at images/cover.* is used without asking. Write-back always goes to the translation you published.

Failures. If the draft cannot be created, the cover's permanent-material slot is given back rather than left orphaned in your account. If any image reference was not replaced with the URL WeChat returned, publishing aborts instead of shipping a draft whose pictures only load in your vault.

Why the plugin reads a file outside the vault

Storing the AppSecret in the plugin's data.json would put it wherever your vault syncs — iCloud, Obsidian Sync, a git remote — and Obsidian gives plugins no sandbox from one another, so any other installed plugin could read it. The AppSecret is the account's master credential: it can send mass messages, rewrite menus and enumerate followers, far beyond what this plugin needs. Keeping it in a file you control, and whitelisting your IP in the WeChat console, are the two things that actually contain the damage if it leaks.

Reading that file is the only thing the plugin does outside your vault, and it does it through Obsidian's own FileSystemAdapter.readLocalFile — the plugin imports no Node filesystem module, and the build fails if one ever reappears in the bundle. Everything else lives in src/local-file.ts: recognising an absolute path and reading that one file. Nothing is written outside the vault, ever, and the plugin never reads your environment — which is why the path has to be written out in full rather than starting with ~.

Covers are offered from the folders the article already points at — the bundle's images/, the note's own pictures, its folder — rather than from a listing of every file in your vault.

Development

npm install
npm test        # unit tests for the pure logic
npm run lint    # the same rules the plugin directory's review runs
npm run build

npm run deploy copies the build into the vaults listed in scripts/deploy.mjs.

Releasing

Bump the version in manifest.json, package.json and versions.json, then push a tag that matches it exactly:

git tag -a 0.1.2 -m 0.1.2 && git push origin main 0.1.2

GitHub Actions checks the tag against the manifest, runs the tests, builds, and opens a draft release with main.js, manifest.json and styles.css attached. Publishing it stays a manual step.

License

MIT — see LICENSE.

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.