Files
decision/frontend/app/components/texts/ClauseVersionDiff.vue
T
YvvandClaude Fable 5 e164b5f6c1 v2 : les 14 écrans — le tour complet de la démocratie d'exercice
- Aujourd'hui (Fil 13 sections + capture sticky) + Le chemin (tunnel 2 gestes,
  Q0 inline, 3 chips, dérogation asymétrique, alternatives réglage/consignation)
- Registre + fiche décision (timeline, périmètre premier/second lieu auditable,
  affluence non-ignorable, S'instruire condensé, éléments + cartographie de
  clôture, épreuve du réel, Remettre en question, PV A4, gravure)
- Salle de vote 5 modalités (consentement, nuancé+histogramme, binaire hérité
  avec jauge inertielle, Réglage collectif complet — faisceau, médiane basse,
  Pour moi, Explorer, cristallisation-geste —, élection à départage humain)
- Textes (Pacte en clair, document vivant, diff, vue projetée, Atelier des
  formules porté du v1 sur le moteur unique) + Mandats (faits comptés, feux
  de la rampe, wizard 3 étapes) + Observatoire (consigner→observer→protocoliser)
- Onboarding 7 gabarits + Données locales (export/import, attributs, atelier)
- voting→framing gardé (Reformuler d'un réglage figé non cristallisé)
- Pages v1 supprimées (login, documents, mandates, protocols, sanctuary,
  tools, decisions/new) — 342 tests verts, build zéro erreur

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 13:47:20 +02:00

115 lines
3.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
// <!-- ld-v2 --> Diff inline +/ entre la version courante et une version
// proposée — contenu d'abord, calculé localement (LCS ligne à ligne, sans lib).
const props = defineProps<{
current: string
proposed: string
}>()
interface DiffLine {
text: string
type: 'kept' | 'removed' | 'added'
}
/** Line-based LCS diff — texts are clause-sized, the DP table stays tiny. */
function lineDiff(a: string[], b: string[]): DiffLine[] {
const n = a.length
const m = b.length
// lcs[i][j] = LCS length of a[i:] / b[j:]
const lcs: number[][] = Array.from({ length: n + 1 }, () => new Array<number>(m + 1).fill(0))
for (let i = n - 1; i >= 0; i--) {
for (let j = m - 1; j >= 0; j--) {
lcs[i]![j] = a[i] === b[j]
? lcs[i + 1]![j + 1]! + 1
: Math.max(lcs[i + 1]![j]!, lcs[i]![j + 1]!)
}
}
const out: DiffLine[] = []
let i = 0
let j = 0
while (i < n && j < m) {
if (a[i] === b[j]) {
out.push({ text: a[i]!, type: 'kept' })
i++
j++
} else if (lcs[i + 1]![j]! >= lcs[i]![j + 1]!) {
out.push({ text: a[i]!, type: 'removed' })
i++
} else {
out.push({ text: b[j]!, type: 'added' })
j++
}
}
while (i < n) out.push({ text: a[i++]!, type: 'removed' })
while (j < m) out.push({ text: b[j++]!, type: 'added' })
return out
}
const lines = computed(() => {
const a = props.current.split('\n')
const b = props.proposed.split('\n')
return lineDiff(a, b).filter(l => !(l.type === 'kept' && l.text.trim() === ''))
})
const changedCount = computed(() => lines.value.filter(l => l.type !== 'kept').length)
</script>
<template>
<!-- ld-v2 -->
<div class="clause-diff">
<div v-if="changedCount === 0" class="clause-diff__same">
Aucun changement de texte les deux versions sont identiques.
</div>
<div
v-for="(line, index) in lines"
v-else
:key="index"
class="clause-diff__line"
:class="`clause-diff__line--${line.type}`"
>
<span class="clause-diff__marker" aria-hidden="true">
{{ line.type === 'added' ? '+' : line.type === 'removed' ? '' : '' }}
</span>
<span class="clause-diff__text">{{ line.text }}</span>
</div>
</div>
</template>
<style scoped>
.clause-diff {
border-radius: var(--r-input);
overflow: hidden;
background: color-mix(in srgb, var(--mood-text) 3%, var(--mood-surface));
font-size: 0.8125rem;
line-height: 1.55;
}
.clause-diff__same {
padding: 0.6rem 0.9rem;
color: var(--mood-text-muted);
font-style: italic;
}
.clause-diff__line {
display: flex;
gap: 0.5rem;
padding: 0.15rem 0.9rem;
}
.clause-diff__line--removed {
background: color-mix(in srgb, var(--mood-error) 10%, transparent);
color: color-mix(in srgb, var(--mood-error) 80%, var(--mood-text));
text-decoration: line-through;
text-decoration-thickness: 1px;
}
.clause-diff__line--added {
background: color-mix(in srgb, var(--mood-success) 11%, transparent);
color: color-mix(in srgb, var(--mood-success) 75%, var(--mood-text));
}
.clause-diff__marker {
flex-shrink: 0;
width: 0.9rem;
font-weight: 800;
font-family: monospace;
text-align: center;
}
.clause-diff__text { white-space: pre-wrap; word-break: break-word; }
</style>