Skip to content

refmdio/plugin-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@refmdio/plugin-sdk

Minimal, framework-agnostic SDK for building RefMD plugins.

Status

  • v0.1.x: API surface is small and focused on DOM primitives, a tiny UI kit, and host bridging helpers.
  • No external deps, designed to be imported directly by plugins in the browser.

Install (npm)

npm i @refmdio/plugin-sdk

Then in your plugin code:

import { createKit, resolveDocId } from '@refmdio/plugin-sdk'

export default async function mount(container: Element, host: any) {
  const kit = createKit(host)
  const state = { docId: host?.context?.docId || resolveDocId(), text: '' }

  kit.store({
    container,
    initialState: state,
    render: (s, set) => kit.card({
      title: 'SDK Demo',
      body: kit.fragment(
        kit.input({ value: s.text, onInput: (v) => set({ text: v }) }),
        kit.button({ label: 'Preview', onClick: async () => {
          const out = document.createElement('div')
          container.appendChild(out)
          await kit.markdownPreview(s.text, out, { sanitize: true, absolute_attachments: true, doc_id: s.docId, base_origin: host.origin })
        }})
      )
    })
  })
}

API (v0.1)

  • Core: h, fragment, render, store
  • UI: button, card, input, textarea, tokens
  • Utils: markdownPreview(host, { text, options, target }), resolveDocId, escapeHtml
  • Host bridges: createHostContext, normalizeExec, createRecordStore, createMarkdownRenderer, createMarkdownEditor, createUploader
  • Split editor bridge (v0.1.9+): host.ui.mountSplitEditor(container, { docId, token, preview: { delegate }, document: { onReady } })
  • Record store pagination (v0.1.10+): createRecordStore(...).list({ limit, offset }) passes pagination through host.records.list.
  • Document editor actions (v0.1.11+): ctx.actions.exec(action, payload) runs a plugin-defined backend action. Use backend action effects for plugin state changes.
  • Document editor pane bridge: optional canActivateDocumentEditor(ctx) and activateDocumentEditor(ctx) exports can attach plugin behavior to the standard RefMD document editor. Use ctx.documentPanes.register(...) for Backlinks-style right pane UI and ctx.editor for selection, insertion, reveal, content, and decorations.

Document editor API notes:

  • ctx.editor.setDecorations(ownerId, ...) and ctx.editor.setHiddenRanges(ownerId, ...) use plugin-local owner IDs. RefMD scopes those IDs by plugin internally.
  • ctx.records.list(kind, { limit, offset }) supports pagination.
  • ctx.kv.get(key) resolves to the stored value for document editor plugins.
  • ctx.actions.exec(action, payload) is the write path for document editor plugins. Expose plugin-specific backend actions instead of mutating generic records or KV from the frontend.
  • ctx.documentPanes.register({ icon }) accepts a host-defined icon name string. Unknown values fall back to the host default.

Document editor pane plugins export named lifecycle functions:

import type { DocumentEditorActivationContext } from '@refmdio/plugin-sdk'

export async function canActivateDocumentEditor(ctx: { document?: { type?: string | null } }) {
  return ctx.document?.type === 'markdown'
}

export async function activateDocumentEditor(ctx: DocumentEditorActivationContext) {
  const pane = ctx.documentPanes.register({
    id: 'comments',
    title: 'Comments',
    icon: 'message-square',
    render(container) {
      container.textContent = ctx.document.getContent()
      return () => {
        container.textContent = ''
      }
    },
  })

  return () => pane.dispose()
}

WC are not intended to be used directly by plugin authors; markdownPreview calls the host hydration routines under the hood.

Build

npm run build

Outputs ESM + CJS + d.ts to dist/.

Release workflow (suggested)

  • Tag v0.1.x → GitHub Actions builds and publishes to npm.

About

Plugin SDK for RefMD

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors