Viewers, editors and actions

What the registry offers for a kind, and the order it picks among them.

app.resources.registerViewer({
  id: 'markdown', title: 'Markdown', kinds: ['file.markdown'],
  component: 'MarkdownViewer', priority: 100,
});

app.resources.registerViewer({
  id: 'unknown', title: 'Details', kinds: [],
  component: 'FallbackViewer', fallback: true,
});

app.resources.registerEditor({
  id: 'text-edit', title: 'Edit', kinds: ['file.text'],
  component: 'TextEditor', saves: true,
});

app.resources.registerAction({
  id: 'file.delete', title: 'Delete', kinds: ['file'],
  slots: ['context'],
  run: (args, ctx) => void ctx.app.execute('file.delete', { uri: String(args.uri) }),
});

An action’s run reaches the world through ctx.app. Note what the registry itself forwards: stat, list, read and write, and nothing else. A provider may also implement delete, rename and watch, but there is no registry passthrough for those, so an action needing one has to go through a command the host registered - which is what the delete above does.

Selection order: an explicit viewerId, then an editor when edit was asked for, then the best-priority viewer for the kind or an ancestor, then a fallback viewer, then any component that declared opens for the kind.

A component can declare that it opens a kind, which is how the shipped viewers work without an application registering anything:

{
  component: 'MarkdownViewer',
  opens: { resourceKinds: ['file.markdown'], title: 'Markdown', priority: 50 },
  renderer: { kind: 'function', render: MarkdownViewer },
}

Back to top

MIT licensed. Pre-1.0 - the surface is still moving.