Resolution Editor

A Svelte 5 component library for creating and editing UN-style resolutions. Built for Model United Nations conferences.

Full Resolution Editor

Complete editing experience for UN resolutions with preamble and operative clauses. Block-based structure supporting nested subclauses up to 4 levels deep.

Phrase Validation

Validate clause openings against official UN resolution vocabulary. Inline autocomplete suggestions help users write proper resolutions.

Import from Text

Parse plain text or LLM-formatted resolutions. Smart detection of numbered lists, lettered subclauses, and nested structures.

Preview Mode

Render resolutions in official UN document format with proper formatting, italicized phrases, and correct punctuation.

Fully Customizable

Complete i18n support with all labels customizable. Provide custom phrase dictionaries for different languages or conferences.

Extension Points

Svelte 5 snippet-based extension points allow adding custom UI elements like amendment buttons, vote indicators, or diff highlighting.

Installation

bun add @deutschemodelunitednations/munify-resolution-editor

Peer Dependencies

  • svelte ^5.0.0
  • TailwindCSS and DaisyUI for styling (configure in your project)

Basic Usage

<script lang="ts">
  import {
    ResolutionEditor,
    englishPreamblePhrases,
    englishOperativePhrases,
    type Resolution
  } from '@deutschemodelunitednations/munify-resolution-editor';

  let resolution: Resolution = $state({
    committeeName: 'General Assembly',
    preamble: [],
    operative: []
  });

  function handleChange(updated: Resolution) {
    resolution = updated;
  }
</script>

<ResolutionEditor
  committeeName="General Assembly"
  {resolution}
  editable={true}
  preamblePhrases={englishPreamblePhrases}
  operativePhrases={englishOperativePhrases}
  onResolutionChange={handleChange}
/>

Extension Points

The editor supports Svelte 5 snippet-based extension points for customization:

import {
  ResolutionEditor,
  ResolutionDocumentHeader,
  ResolutionDocumentFooter
} from '@deutschemodelunitednations/munify-resolution-editor';

<ResolutionEditor {...props}>
  {#snippet clauseToolbar({ clause, index })}
    <button onclick={() => addAmendment(clause)}>
      Add Amendment
    </button>
  {/snippet}

  {#snippet clauseAnnotations({ clause, index })}
    {#if hasAmendments(clause)}
      <div class="badge badge-warning">Has amendments</div>
    {/if}
  {/snippet}

  {#snippet previewHeader({ resolution, headerData })}
    <!-- Use default header + custom content -->
    <ResolutionDocumentHeader {headerData} {resolution} />
    <div class="custom-banner">Draft Resolution</div>
  {/snippet}

  {#snippet previewFooter({ resolution })}
    <ResolutionDocumentFooter {resolution} {headerData} />
  {/snippet}
</ResolutionEditor>

Available Extension Points

Extension PointLocationUse Case
clauseToolbarNext to each operative clauseAmendment buttons, comment toggles
clauseAnnotationsOverlay on each clauseDiff highlights, amendment badges
previewHeaderTop of previewCustom metadata, voting info
previewFooterBottom of previewSignatures, timestamps