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-editorPeer 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 Point | Location | Use Case |
|---|---|---|
clauseToolbar | Next to each operative clause | Amendment buttons, comment toggles |
clauseAnnotations | Overlay on each clause | Diff highlights, amendment badges |
previewHeader | Top of preview | Custom metadata, voting info |
previewFooter | Bottom of preview | Signatures, timestamps |