@gitwand/core 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +52 -0
- package/dist/__tests__/bench.bench.d.ts +14 -0
- package/dist/__tests__/bench.bench.d.ts.map +1 -0
- package/dist/__tests__/bench.bench.js +137 -0
- package/dist/__tests__/bench.bench.js.map +1 -0
- package/dist/__tests__/confidence-v14.test.d.ts +13 -0
- package/dist/__tests__/confidence-v14.test.d.ts.map +1 -0
- package/dist/__tests__/confidence-v14.test.js +284 -0
- package/dist/__tests__/confidence-v14.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +2 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +317 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/corpus.d.ts +36 -0
- package/dist/__tests__/corpus.d.ts.map +1 -0
- package/dist/__tests__/corpus.js +541 -0
- package/dist/__tests__/corpus.js.map +1 -0
- package/dist/__tests__/corpus.test.d.ts +17 -0
- package/dist/__tests__/corpus.test.d.ts.map +1 -0
- package/dist/__tests__/corpus.test.js +179 -0
- package/dist/__tests__/corpus.test.js.map +1 -0
- package/dist/__tests__/diff.test.d.ts +10 -0
- package/dist/__tests__/diff.test.d.ts.map +1 -0
- package/dist/__tests__/diff.test.js +178 -0
- package/dist/__tests__/diff.test.js.map +1 -0
- package/dist/__tests__/format-resolvers.test.d.ts +2 -0
- package/dist/__tests__/format-resolvers.test.d.ts.map +1 -0
- package/dist/__tests__/format-resolvers.test.js +577 -0
- package/dist/__tests__/format-resolvers.test.js.map +1 -0
- package/dist/__tests__/imports-extended.test.d.ts +2 -0
- package/dist/__tests__/imports-extended.test.d.ts.map +1 -0
- package/dist/__tests__/imports-extended.test.js +94 -0
- package/dist/__tests__/imports-extended.test.js.map +1 -0
- package/dist/__tests__/lockfile-resolvers.test.d.ts +2 -0
- package/dist/__tests__/lockfile-resolvers.test.d.ts.map +1 -0
- package/dist/__tests__/lockfile-resolvers.test.js +200 -0
- package/dist/__tests__/lockfile-resolvers.test.js.map +1 -0
- package/dist/__tests__/patterns/insertion-at-boundary.test.d.ts +10 -0
- package/dist/__tests__/patterns/insertion-at-boundary.test.d.ts.map +1 -0
- package/dist/__tests__/patterns/insertion-at-boundary.test.js +185 -0
- package/dist/__tests__/patterns/insertion-at-boundary.test.js.map +1 -0
- package/dist/__tests__/patterns/reorder-only.test.d.ts +10 -0
- package/dist/__tests__/patterns/reorder-only.test.d.ts.map +1 -0
- package/dist/__tests__/patterns/reorder-only.test.js +181 -0
- package/dist/__tests__/patterns/reorder-only.test.js.map +1 -0
- package/dist/__tests__/phase-7-2-3b.test.d.ts +6 -0
- package/dist/__tests__/phase-7-2-3b.test.d.ts.map +1 -0
- package/dist/__tests__/phase-7-2-3b.test.js +730 -0
- package/dist/__tests__/phase-7-2-3b.test.js.map +1 -0
- package/dist/__tests__/resolver.test.d.ts +2 -0
- package/dist/__tests__/resolver.test.d.ts.map +1 -0
- package/dist/__tests__/resolver.test.js +927 -0
- package/dist/__tests__/resolver.test.js.map +1 -0
- package/dist/__tests__/resolvers/cargo.test.d.ts +10 -0
- package/dist/__tests__/resolvers/cargo.test.d.ts.map +1 -0
- package/dist/__tests__/resolvers/cargo.test.js +158 -0
- package/dist/__tests__/resolvers/cargo.test.js.map +1 -0
- package/dist/__tests__/resolvers/dockerfile.test.d.ts +8 -0
- package/dist/__tests__/resolvers/dockerfile.test.d.ts.map +1 -0
- package/dist/__tests__/resolvers/dockerfile.test.js +120 -0
- package/dist/__tests__/resolvers/dockerfile.test.js.map +1 -0
- package/dist/__tests__/resolvers/dotenv.test.d.ts +9 -0
- package/dist/__tests__/resolvers/dotenv.test.d.ts.map +1 -0
- package/dist/__tests__/resolvers/dotenv.test.js +113 -0
- package/dist/__tests__/resolvers/dotenv.test.js.map +1 -0
- package/dist/__tests__/resolvers/improvements-v14.test.d.ts +8 -0
- package/dist/__tests__/resolvers/improvements-v14.test.d.ts.map +1 -0
- package/dist/__tests__/resolvers/improvements-v14.test.js +306 -0
- package/dist/__tests__/resolvers/improvements-v14.test.js.map +1 -0
- package/dist/__tests__/validation.test.d.ts +12 -0
- package/dist/__tests__/validation.test.d.ts.map +1 -0
- package/dist/__tests__/validation.test.js +136 -0
- package/dist/__tests__/validation.test.js.map +1 -0
- package/dist/classifier.d.ts +21 -0
- package/dist/classifier.d.ts.map +1 -0
- package/dist/classifier.js +127 -0
- package/dist/classifier.js.map +1 -0
- package/dist/config.d.ts +108 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +200 -0
- package/dist/config.js.map +1 -0
- package/dist/diff.d.ts +69 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +328 -0
- package/dist/diff.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/parser.d.ts +39 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +164 -0
- package/dist/parser.js.map +1 -0
- package/dist/patterns/complex.d.ts +5 -0
- package/dist/patterns/complex.d.ts.map +1 -0
- package/dist/patterns/complex.js +27 -0
- package/dist/patterns/complex.js.map +1 -0
- package/dist/patterns/delete-no-change.d.ts +4 -0
- package/dist/patterns/delete-no-change.d.ts.map +1 -0
- package/dist/patterns/delete-no-change.js +75 -0
- package/dist/patterns/delete-no-change.js.map +1 -0
- package/dist/patterns/insertion-at-boundary.d.ts +22 -0
- package/dist/patterns/insertion-at-boundary.d.ts.map +1 -0
- package/dist/patterns/insertion-at-boundary.js +164 -0
- package/dist/patterns/insertion-at-boundary.js.map +1 -0
- package/dist/patterns/non-overlapping.d.ts +4 -0
- package/dist/patterns/non-overlapping.d.ts.map +1 -0
- package/dist/patterns/non-overlapping.js +28 -0
- package/dist/patterns/non-overlapping.js.map +1 -0
- package/dist/patterns/one-side-change.d.ts +4 -0
- package/dist/patterns/one-side-change.d.ts.map +1 -0
- package/dist/patterns/one-side-change.js +45 -0
- package/dist/patterns/one-side-change.js.map +1 -0
- package/dist/patterns/reorder-only.d.ts +14 -0
- package/dist/patterns/reorder-only.d.ts.map +1 -0
- package/dist/patterns/reorder-only.js +81 -0
- package/dist/patterns/reorder-only.js.map +1 -0
- package/dist/patterns/same-change.d.ts +4 -0
- package/dist/patterns/same-change.d.ts.map +1 -0
- package/dist/patterns/same-change.js +25 -0
- package/dist/patterns/same-change.js.map +1 -0
- package/dist/patterns/utils.d.ts +70 -0
- package/dist/patterns/utils.d.ts.map +1 -0
- package/dist/patterns/utils.js +206 -0
- package/dist/patterns/utils.js.map +1 -0
- package/dist/patterns/value-only-change.d.ts +4 -0
- package/dist/patterns/value-only-change.d.ts.map +1 -0
- package/dist/patterns/value-only-change.js +34 -0
- package/dist/patterns/value-only-change.js.map +1 -0
- package/dist/patterns/whitespace-only.d.ts +4 -0
- package/dist/patterns/whitespace-only.d.ts.map +1 -0
- package/dist/patterns/whitespace-only.js +32 -0
- package/dist/patterns/whitespace-only.js.map +1 -0
- package/dist/resolver/assemble.d.ts +25 -0
- package/dist/resolver/assemble.d.ts.map +1 -0
- package/dist/resolver/assemble.js +170 -0
- package/dist/resolver/assemble.js.map +1 -0
- package/dist/resolver/format-dispatch.d.ts +40 -0
- package/dist/resolver/format-dispatch.d.ts.map +1 -0
- package/dist/resolver/format-dispatch.js +51 -0
- package/dist/resolver/format-dispatch.js.map +1 -0
- package/dist/resolver/generated-detection.d.ts +48 -0
- package/dist/resolver/generated-detection.d.ts.map +1 -0
- package/dist/resolver/generated-detection.js +123 -0
- package/dist/resolver/generated-detection.js.map +1 -0
- package/dist/resolver/index.d.ts +26 -0
- package/dist/resolver/index.d.ts.map +1 -0
- package/dist/resolver/index.js +147 -0
- package/dist/resolver/index.js.map +1 -0
- package/dist/resolver/policy.d.ts +53 -0
- package/dist/resolver/policy.d.ts.map +1 -0
- package/dist/resolver/policy.js +99 -0
- package/dist/resolver/policy.js.map +1 -0
- package/dist/resolver/validation.d.ts +28 -0
- package/dist/resolver/validation.d.ts.map +1 -0
- package/dist/resolver/validation.js +96 -0
- package/dist/resolver/validation.js.map +1 -0
- package/dist/resolver.d.ts +18 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +18 -0
- package/dist/resolver.js.map +1 -0
- package/dist/resolvers/cargo.d.ts +34 -0
- package/dist/resolvers/cargo.d.ts.map +1 -0
- package/dist/resolvers/cargo.js +262 -0
- package/dist/resolvers/cargo.js.map +1 -0
- package/dist/resolvers/css.d.ts +60 -0
- package/dist/resolvers/css.d.ts.map +1 -0
- package/dist/resolvers/css.js +531 -0
- package/dist/resolvers/css.js.map +1 -0
- package/dist/resolvers/dispatcher.d.ts +78 -0
- package/dist/resolvers/dispatcher.d.ts.map +1 -0
- package/dist/resolvers/dispatcher.js +290 -0
- package/dist/resolvers/dispatcher.js.map +1 -0
- package/dist/resolvers/dockerfile.d.ts +24 -0
- package/dist/resolvers/dockerfile.d.ts.map +1 -0
- package/dist/resolvers/dockerfile.js +221 -0
- package/dist/resolvers/dockerfile.js.map +1 -0
- package/dist/resolvers/dotenv.d.ts +27 -0
- package/dist/resolvers/dotenv.d.ts.map +1 -0
- package/dist/resolvers/dotenv.js +114 -0
- package/dist/resolvers/dotenv.js.map +1 -0
- package/dist/resolvers/imports.d.ts +63 -0
- package/dist/resolvers/imports.d.ts.map +1 -0
- package/dist/resolvers/imports.js +513 -0
- package/dist/resolvers/imports.js.map +1 -0
- package/dist/resolvers/json.d.ts +48 -0
- package/dist/resolvers/json.d.ts.map +1 -0
- package/dist/resolvers/json.js +363 -0
- package/dist/resolvers/json.js.map +1 -0
- package/dist/resolvers/lockfile-npm.d.ts +38 -0
- package/dist/resolvers/lockfile-npm.d.ts.map +1 -0
- package/dist/resolvers/lockfile-npm.js +267 -0
- package/dist/resolvers/lockfile-npm.js.map +1 -0
- package/dist/resolvers/lockfile-pnpm.d.ts +44 -0
- package/dist/resolvers/lockfile-pnpm.d.ts.map +1 -0
- package/dist/resolvers/lockfile-pnpm.js +277 -0
- package/dist/resolvers/lockfile-pnpm.js.map +1 -0
- package/dist/resolvers/lockfile-yarn.d.ts +40 -0
- package/dist/resolvers/lockfile-yarn.d.ts.map +1 -0
- package/dist/resolvers/lockfile-yarn.js +184 -0
- package/dist/resolvers/lockfile-yarn.js.map +1 -0
- package/dist/resolvers/markdown.d.ts +64 -0
- package/dist/resolvers/markdown.d.ts.map +1 -0
- package/dist/resolvers/markdown.js +335 -0
- package/dist/resolvers/markdown.js.map +1 -0
- package/dist/resolvers/vue.d.ts +65 -0
- package/dist/resolvers/vue.d.ts.map +1 -0
- package/dist/resolvers/vue.js +258 -0
- package/dist/resolvers/vue.js.map +1 -0
- package/dist/resolvers/yaml.d.ts +65 -0
- package/dist/resolvers/yaml.d.ts.map +1 -0
- package/dist/resolvers/yaml.js +405 -0
- package/dist/resolvers/yaml.js.map +1 -0
- package/dist/types.d.ts +256 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitWand — Résolveur Markdown section-aware
|
|
3
|
+
*
|
|
4
|
+
* Résout les conflits dans les fichiers Markdown en identifiant
|
|
5
|
+
* la structure de sections (headings H1..H6) et en fusionnant
|
|
6
|
+
* section par section lorsque les modifications sont non-overlapping.
|
|
7
|
+
*
|
|
8
|
+
* Stratégie :
|
|
9
|
+
* 1. Détecter les headings dans les trois versions
|
|
10
|
+
* 2. Découper chaque version en sections (heading + contenu jusqu'au prochain heading de niveau ≤)
|
|
11
|
+
* 3. Pour chaque section :
|
|
12
|
+
* a. Si identique dans ours et theirs → garder
|
|
13
|
+
* b. Si modifiée d'un seul côté → accepter la modification
|
|
14
|
+
* c. Si section ajoutée d'un côté → ajouter
|
|
15
|
+
* d. Si modifiée des deux côtés différemment → conflit partiel (insert les deux versions)
|
|
16
|
+
* 4. Gestion du frontmatter YAML (entre --- au début du fichier) : traité séparément
|
|
17
|
+
*
|
|
18
|
+
* Limites :
|
|
19
|
+
* - Ne pas résoudre les conflits intra-section (renvoyés au moteur textuel)
|
|
20
|
+
* - Pas de merge sémantique du contenu riche (listes, tableaux, code)
|
|
21
|
+
*/
|
|
22
|
+
// ─── Frontmatter ─────────────────────────────────────────
|
|
23
|
+
/**
|
|
24
|
+
* Détecte et extrait le frontmatter YAML si présent (--- au début).
|
|
25
|
+
* Retourne { frontmatter: string[], rest: string[] }.
|
|
26
|
+
*/
|
|
27
|
+
export function extractFrontmatter(lines) {
|
|
28
|
+
if (lines.length === 0 || lines[0].trim() !== "---") {
|
|
29
|
+
return { frontmatter: [], rest: lines };
|
|
30
|
+
}
|
|
31
|
+
let end = -1;
|
|
32
|
+
for (let i = 1; i < lines.length; i++) {
|
|
33
|
+
if (lines[i].trim() === "---" || lines[i].trim() === "...") {
|
|
34
|
+
end = i;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (end === -1) {
|
|
39
|
+
// Pas de frontmatter fermant → traiter comme texte normal
|
|
40
|
+
return { frontmatter: [], rest: lines };
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
frontmatter: lines.slice(0, end + 1),
|
|
44
|
+
rest: lines.slice(end + 1),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// ─── Section parsing ──────────────────────────────────────
|
|
48
|
+
/**
|
|
49
|
+
* Détecte le niveau d'un heading ATX (`# ... `).
|
|
50
|
+
* Retourne 0 si la ligne n'est pas un heading.
|
|
51
|
+
*/
|
|
52
|
+
function headingLevel(line) {
|
|
53
|
+
const match = line.match(/^(#{1,6})\s/);
|
|
54
|
+
return match ? match[1].length : 0;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Découpe un tableau de lignes en sections Markdown.
|
|
58
|
+
* Chaque section commence par un heading ATX.
|
|
59
|
+
* Le contenu avant le premier heading forme une section "prologue" (level 0).
|
|
60
|
+
*/
|
|
61
|
+
export function parseSections(lines) {
|
|
62
|
+
const sections = [];
|
|
63
|
+
let currentSection = {
|
|
64
|
+
heading: null,
|
|
65
|
+
level: 0,
|
|
66
|
+
lines: [],
|
|
67
|
+
startIdx: 0,
|
|
68
|
+
};
|
|
69
|
+
for (let i = 0; i < lines.length; i++) {
|
|
70
|
+
const level = headingLevel(lines[i]);
|
|
71
|
+
if (level > 0) {
|
|
72
|
+
// Nouveau heading → sauvegarder la section courante, en commencer une nouvelle
|
|
73
|
+
sections.push(currentSection);
|
|
74
|
+
currentSection = {
|
|
75
|
+
heading: lines[i],
|
|
76
|
+
level,
|
|
77
|
+
lines: [],
|
|
78
|
+
startIdx: i,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
currentSection.lines.push(lines[i]);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Sauvegarder la dernière section
|
|
86
|
+
sections.push(currentSection);
|
|
87
|
+
return sections;
|
|
88
|
+
}
|
|
89
|
+
// ─── Section key ─────────────────────────────────────────
|
|
90
|
+
/**
|
|
91
|
+
* Retourne une clé unique pour identifier une section par son heading.
|
|
92
|
+
* Les sections sans heading utilisent "__prologue__".
|
|
93
|
+
*/
|
|
94
|
+
function sectionKey(section) {
|
|
95
|
+
return section.heading ?? "__prologue__";
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Compare deux sections (heading + contenu) pour égalité textuelle.
|
|
99
|
+
*/
|
|
100
|
+
function sectionsEqual(a, b) {
|
|
101
|
+
if (a.heading !== b.heading)
|
|
102
|
+
return false;
|
|
103
|
+
if (a.lines.length !== b.lines.length)
|
|
104
|
+
return false;
|
|
105
|
+
return a.lines.every((line, i) => line === b.lines[i]);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Fusionne deux versions Markdown section par section avec une base commune.
|
|
109
|
+
*
|
|
110
|
+
* @param baseLines - Lignes de la version base
|
|
111
|
+
* @param oursLines - Lignes de la version ours
|
|
112
|
+
* @param theirsLines - Lignes de la version theirs
|
|
113
|
+
*/
|
|
114
|
+
export function tryResolveMarkdownConflict(baseLines, oursLines, theirsLines) {
|
|
115
|
+
// Extraire frontmatter de chaque version
|
|
116
|
+
const baseFm = extractFrontmatter(baseLines);
|
|
117
|
+
const oursFm = extractFrontmatter(oursLines);
|
|
118
|
+
const theirsFm = extractFrontmatter(theirsLines);
|
|
119
|
+
// Résoudre le frontmatter séparément
|
|
120
|
+
const mergedFrontmatter = resolveFrontmatter(baseFm.frontmatter, oursFm.frontmatter, theirsFm.frontmatter);
|
|
121
|
+
if (mergedFrontmatter === null) {
|
|
122
|
+
return {
|
|
123
|
+
mergedLines: null,
|
|
124
|
+
conflictedSections: ["frontmatter"],
|
|
125
|
+
resolvedSections: 0,
|
|
126
|
+
reason: "Conflit dans le frontmatter YAML — fusion manuelle requise.",
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// Découper en sections
|
|
130
|
+
const baseSections = parseSections(baseFm.rest);
|
|
131
|
+
const oursSections = parseSections(oursFm.rest);
|
|
132
|
+
const theirsSections = parseSections(theirsFm.rest);
|
|
133
|
+
// Indexer par clé
|
|
134
|
+
const baseMap = new Map(baseSections.map((s) => [sectionKey(s), s]));
|
|
135
|
+
const oursMap = new Map(oursSections.map((s) => [sectionKey(s), s]));
|
|
136
|
+
const theirsMap = new Map(theirsSections.map((s) => [sectionKey(s), s]));
|
|
137
|
+
// Ordre des sections : union de toutes les clés dans l'ordre d'apparition
|
|
138
|
+
const orderedKeys = buildSectionOrder(baseSections, oursSections, theirsSections);
|
|
139
|
+
const mergedLines = [...mergedFrontmatter];
|
|
140
|
+
const conflictedSections = [];
|
|
141
|
+
let resolvedSections = 0;
|
|
142
|
+
for (const key of orderedKeys) {
|
|
143
|
+
const baseSection = baseMap.get(key);
|
|
144
|
+
const oursSection = oursMap.get(key);
|
|
145
|
+
const theirsSection = theirsMap.get(key);
|
|
146
|
+
const resolution = resolveSectionConflict(baseSection, oursSection, theirsSection, key);
|
|
147
|
+
if (resolution.resolved) {
|
|
148
|
+
const lines = resolution.lines;
|
|
149
|
+
mergedLines.push(...lines);
|
|
150
|
+
resolvedSections++;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
// Conflit non résolvable → insérer les deux versions avec marqueurs de section
|
|
154
|
+
conflictedSections.push(key);
|
|
155
|
+
if (oursSection) {
|
|
156
|
+
if (oursSection.heading)
|
|
157
|
+
mergedLines.push(oursSection.heading);
|
|
158
|
+
mergedLines.push(...oursSection.lines);
|
|
159
|
+
}
|
|
160
|
+
if (theirsSection && !sectionsEqual(oursSection ?? emptySectionFor(key), theirsSection)) {
|
|
161
|
+
// Ajouter la version theirs avec un commentaire d'avertissement
|
|
162
|
+
mergedLines.push(`<!-- ⚠️ GitWand: section "${key}" modifiée des deux côtés -->`);
|
|
163
|
+
if (theirsSection.heading)
|
|
164
|
+
mergedLines.push(theirsSection.heading);
|
|
165
|
+
mergedLines.push(...theirsSection.lines);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Si des conflits partiels → le contenu est produit mais marqué
|
|
170
|
+
if (conflictedSections.length > 0) {
|
|
171
|
+
return {
|
|
172
|
+
mergedLines: null, // Force resolution manuelle si des sections ont conflicté
|
|
173
|
+
conflictedSections,
|
|
174
|
+
resolvedSections,
|
|
175
|
+
reason: `Fusion Markdown partielle : ${resolvedSections} section(s) résolue(s), ${conflictedSections.length} en conflit (${conflictedSections.join(", ")}).`,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
mergedLines,
|
|
180
|
+
conflictedSections: [],
|
|
181
|
+
resolvedSections,
|
|
182
|
+
reason: `Fusion Markdown réussie : ${resolvedSections} section(s) fusionnée(s) automatiquement.`,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// ─── Helpers ──────────────────────────────────────────────
|
|
186
|
+
function emptySectionFor(key) {
|
|
187
|
+
return { heading: key === "__prologue__" ? null : key, level: 0, lines: [], startIdx: 0 };
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Résout le frontmatter : simple comparaison textuelle.
|
|
191
|
+
* Si ours = base → prendre theirs. Si theirs = base → prendre ours.
|
|
192
|
+
* Si same → prendre ours. Sinon null (conflit).
|
|
193
|
+
*/
|
|
194
|
+
function resolveFrontmatter(base, ours, theirs) {
|
|
195
|
+
if (base.length === 0 && ours.length === 0 && theirs.length === 0)
|
|
196
|
+
return [];
|
|
197
|
+
const arrEq = (a, b) => a.length === b.length && a.every((l, i) => l === b[i]);
|
|
198
|
+
if (arrEq(ours, theirs))
|
|
199
|
+
return ours;
|
|
200
|
+
if (arrEq(ours, base))
|
|
201
|
+
return theirs; // ours n'a pas changé → prendre theirs
|
|
202
|
+
if (arrEq(theirs, base))
|
|
203
|
+
return ours; // theirs n'a pas changé → prendre ours
|
|
204
|
+
return null; // conflit
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Détermine l'ordre de fusion des sections en combinant les ordres de ours et theirs.
|
|
208
|
+
* Utilise une heuristique simple : préserver l'ordre de ours, insérer les nouvelles
|
|
209
|
+
* sections de theirs après leur section précédente dans theirs.
|
|
210
|
+
*/
|
|
211
|
+
function buildSectionOrder(base, ours, theirs) {
|
|
212
|
+
const oursKeys = ours.map(sectionKey);
|
|
213
|
+
const theirsKeys = theirs.map(sectionKey);
|
|
214
|
+
const baseKeys = new Set(base.map(sectionKey));
|
|
215
|
+
// Sections présentes dans ours en premier
|
|
216
|
+
const result = [...oursKeys];
|
|
217
|
+
const resultSet = new Set(result);
|
|
218
|
+
// Ajouter les sections de theirs absentes de ours (sections ajoutées par theirs)
|
|
219
|
+
for (let i = 0; i < theirsKeys.length; i++) {
|
|
220
|
+
const key = theirsKeys[i];
|
|
221
|
+
if (!resultSet.has(key)) {
|
|
222
|
+
// Trouver la bonne position : après la section précédente dans theirs
|
|
223
|
+
const prevKey = i > 0 ? theirsKeys[i - 1] : null;
|
|
224
|
+
const insertIdx = prevKey ? result.indexOf(prevKey) + 1 : 0;
|
|
225
|
+
result.splice(insertIdx, 0, key);
|
|
226
|
+
resultSet.add(key);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Retirer les sections supprimées des deux côtés
|
|
230
|
+
return result.filter((key) => {
|
|
231
|
+
const inOurs = oursKeys.includes(key);
|
|
232
|
+
const inTheirs = theirsKeys.includes(key);
|
|
233
|
+
const inBase = baseKeys.has(key);
|
|
234
|
+
// Garder si présent dans au moins une branche active
|
|
235
|
+
return inOurs || inTheirs || !inBase;
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
// ─── Bullet list merge (v1.4) ─────────────────────────────
|
|
239
|
+
const RE_BULLET = /^(\s*)[*-]\s/;
|
|
240
|
+
/**
|
|
241
|
+
* Vérifie si un ensemble de lignes est une liste à puces cohérente.
|
|
242
|
+
* Toutes les lignes non-vides doivent commencer par `- ` ou `* ` à l'indentation de base.
|
|
243
|
+
*/
|
|
244
|
+
function isBulletList(lines) {
|
|
245
|
+
const contentLines = lines.filter((l) => l.trim() !== "");
|
|
246
|
+
if (contentLines.length === 0)
|
|
247
|
+
return false;
|
|
248
|
+
return contentLines.every((l) => RE_BULLET.test(l));
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Fusionne deux listes à puces Markdown en union d'items (ours order preserved,
|
|
252
|
+
* items de theirs absents de ours ajoutés à la fin).
|
|
253
|
+
* Retourne null si les items sont en conflit irréductible (même item différent).
|
|
254
|
+
*/
|
|
255
|
+
function mergeBulletLists(baseLines, oursLines, theirsLines) {
|
|
256
|
+
// Normaliser : retirer trailing whitespace des items
|
|
257
|
+
const normalize = (l) => l.trimEnd();
|
|
258
|
+
const oursNorm = oursLines.map(normalize);
|
|
259
|
+
const theirsNorm = theirsLines.map(normalize);
|
|
260
|
+
if (oursNorm.join("\n") === theirsNorm.join("\n"))
|
|
261
|
+
return oursNorm;
|
|
262
|
+
const baseNorm = baseLines.map(normalize);
|
|
263
|
+
if (oursNorm.join("\n") === baseNorm.join("\n"))
|
|
264
|
+
return theirsNorm;
|
|
265
|
+
if (theirsNorm.join("\n") === baseNorm.join("\n"))
|
|
266
|
+
return oursNorm;
|
|
267
|
+
// Union par valeur d'item (text after bullet marker)
|
|
268
|
+
const stripBullet = (l) => l.replace(/^\s*[*-]\s+/, "").trimEnd();
|
|
269
|
+
const oursSet = new Set(oursNorm.map(stripBullet));
|
|
270
|
+
const extra = theirsNorm.filter((l) => !oursSet.has(stripBullet(l)));
|
|
271
|
+
return [...oursNorm, ...extra];
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Résout un conflit pour une section donnée.
|
|
275
|
+
*/
|
|
276
|
+
function resolveSectionConflict(base, ours, theirs, key) {
|
|
277
|
+
const empty = emptySectionFor(key);
|
|
278
|
+
const b = base ?? empty;
|
|
279
|
+
const o = ours ?? empty;
|
|
280
|
+
const t = theirs ?? empty;
|
|
281
|
+
const toLines = (s) => {
|
|
282
|
+
const lines = [];
|
|
283
|
+
if (s.heading)
|
|
284
|
+
lines.push(s.heading);
|
|
285
|
+
lines.push(...s.lines);
|
|
286
|
+
return lines;
|
|
287
|
+
};
|
|
288
|
+
// Section absente de ours et de base, présente dans theirs → ajout theirs
|
|
289
|
+
if (!ours && !base && theirs) {
|
|
290
|
+
return { resolved: true, lines: toLines(t) };
|
|
291
|
+
}
|
|
292
|
+
// Section absente de theirs et de base, présente dans ours → ajout ours
|
|
293
|
+
if (!theirs && !base && ours) {
|
|
294
|
+
return { resolved: true, lines: toLines(o) };
|
|
295
|
+
}
|
|
296
|
+
// Section supprimée des deux côtés (présente dans base)
|
|
297
|
+
if (base && !ours && !theirs) {
|
|
298
|
+
return { resolved: true, lines: [] };
|
|
299
|
+
}
|
|
300
|
+
// Ours a supprimé, theirs n'a pas changé
|
|
301
|
+
if (base && !ours && theirs && sectionsEqual(b, t)) {
|
|
302
|
+
return { resolved: true, lines: [] };
|
|
303
|
+
}
|
|
304
|
+
// Theirs a supprimé, ours n'a pas changé
|
|
305
|
+
if (base && ours && !theirs && sectionsEqual(b, o)) {
|
|
306
|
+
return { resolved: true, lines: [] };
|
|
307
|
+
}
|
|
308
|
+
// Les deux ont fait la même modification
|
|
309
|
+
if (sectionsEqual(o, t)) {
|
|
310
|
+
return { resolved: true, lines: toLines(o) };
|
|
311
|
+
}
|
|
312
|
+
// Seul ours a changé (theirs = base ou theirs absent)
|
|
313
|
+
if (base && theirs && sectionsEqual(b, t)) {
|
|
314
|
+
return { resolved: true, lines: toLines(o) };
|
|
315
|
+
}
|
|
316
|
+
// Seul theirs a changé (ours = base ou ours absent)
|
|
317
|
+
if (base && ours && sectionsEqual(b, o)) {
|
|
318
|
+
return { resolved: true, lines: toLines(t) };
|
|
319
|
+
}
|
|
320
|
+
// Les deux ont changé différemment
|
|
321
|
+
// v1.4 — Tenter un merge bullet-list si les deux sections sont des listes à puces
|
|
322
|
+
if (isBulletList(o.lines) && isBulletList(t.lines)) {
|
|
323
|
+
const merged = mergeBulletLists(b.lines, o.lines, t.lines);
|
|
324
|
+
if (merged !== null) {
|
|
325
|
+
const resultLines = [];
|
|
326
|
+
if (o.heading)
|
|
327
|
+
resultLines.push(o.heading);
|
|
328
|
+
resultLines.push(...merged);
|
|
329
|
+
return { resolved: true, lines: resultLines };
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// Conflit non résolvable
|
|
333
|
+
return { resolved: false, lines: [] };
|
|
334
|
+
}
|
|
335
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/resolvers/markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAeH,4DAA4D;AAE5D;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAe;IAIhD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;QACpD,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;YAC3D,GAAG,GAAG,CAAC,CAAC;YACR,MAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QACf,0DAA0D;QAC1D,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED,OAAO;QACL,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC;QACpC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;KAC3B,CAAC;AACJ,CAAC;AAED,6DAA6D;AAE7D;;;GAGG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAe;IAC3C,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,IAAI,cAAc,GAAoB;QACpC,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,EAAE;QACT,QAAQ,EAAE,CAAC;KACZ,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAErC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,+EAA+E;YAC/E,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC9B,cAAc,GAAG;gBACf,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;gBACjB,KAAK;gBACL,KAAK,EAAE,EAAE;gBACT,QAAQ,EAAE,CAAC;aACZ,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAE9B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,4DAA4D;AAE5D;;;GAGG;AACH,SAAS,UAAU,CAAC,OAAwB;IAC1C,OAAO,OAAO,CAAC,OAAO,IAAI,cAAc,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,CAAkB,EAAE,CAAkB;IAC3D,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC1C,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACpD,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAeD;;;;;;GAMG;AACH,MAAM,UAAU,0BAA0B,CACxC,SAAmB,EACnB,SAAmB,EACnB,WAAqB;IAErB,yCAAyC;IACzC,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAEjD,qCAAqC;IACrC,MAAM,iBAAiB,GAAG,kBAAkB,CAC1C,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,WAAW,EAClB,QAAQ,CAAC,WAAW,CACrB,CAAC;IAEF,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,kBAAkB,EAAE,CAAC,aAAa,CAAC;YACnC,gBAAgB,EAAE,CAAC;YACnB,MAAM,EAAE,6DAA6D;SACtE,CAAC;IACJ,CAAC;IAED,uBAAuB;IACvB,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEpD,kBAAkB;IAClB,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAC5C,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAC5C,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,GAAG,CACvB,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAC9C,CAAC;IAEF,0EAA0E;IAC1E,MAAM,WAAW,GAAG,iBAAiB,CAAC,YAAY,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;IAElF,MAAM,WAAW,GAAa,CAAC,GAAG,iBAAiB,CAAC,CAAC;IACrD,MAAM,kBAAkB,GAAa,EAAE,CAAC;IACxC,IAAI,gBAAgB,GAAG,CAAC,CAAC;IAEzB,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEzC,MAAM,UAAU,GAAG,sBAAsB,CAAC,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;QAExF,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;YAC/B,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;YAC3B,gBAAgB,EAAE,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,+EAA+E;YAC/E,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,WAAW,EAAE,CAAC;gBAChB,IAAI,WAAW,CAAC,OAAO;oBAAE,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;gBAC/D,WAAW,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YACzC,CAAC;YACD,IAAI,aAAa,IAAI,CAAC,aAAa,CAAC,WAAW,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC;gBACxF,gEAAgE;gBAChE,WAAW,CAAC,IAAI,CAAC,6BAA6B,GAAG,+BAA+B,CAAC,CAAC;gBAClF,IAAI,aAAa,CAAC,OAAO;oBAAE,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;gBACnE,WAAW,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,WAAW,EAAE,IAAI,EAAE,0DAA0D;YAC7E,kBAAkB;YAClB,gBAAgB;YAChB,MAAM,EAAE,+BAA+B,gBAAgB,2BAA2B,kBAAkB,CAAC,MAAM,gBAAgB,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;SAC7J,CAAC;IACJ,CAAC;IAED,OAAO;QACL,WAAW;QACX,kBAAkB,EAAE,EAAE;QACtB,gBAAgB;QAChB,MAAM,EAAE,6BAA6B,gBAAgB,2CAA2C;KACjG,CAAC;AACJ,CAAC;AAED,6DAA6D;AAE7D,SAAS,eAAe,CAAC,GAAW;IAClC,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AAC5F,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CACzB,IAAc,EACd,IAAc,EACd,MAAgB;IAEhB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE7E,MAAM,KAAK,GAAG,CAAC,CAAW,EAAE,CAAW,EAAE,EAAE,CACzC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzD,IAAI,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,uCAAuC;IAC7E,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,uCAAuC;IAC7E,OAAO,IAAI,CAAC,CAAC,UAAU;AACzB,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CACxB,IAAuB,EACvB,IAAuB,EACvB,MAAyB;IAEzB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;IAE/C,0CAA0C;IAC1C,MAAM,MAAM,GAAa,CAAC,GAAG,QAAQ,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAElC,iFAAiF;IACjF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,sEAAsE;YACtE,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACjD,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5D,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;YACjC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,qDAAqD;QACrD,OAAO,MAAM,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC;AAOD,6DAA6D;AAE7D,MAAM,SAAS,GAAG,cAAc,CAAC;AAEjC;;;GAGG;AACH,SAAS,YAAY,CAAC,KAAe;IACnC,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1D,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CACvB,SAAmB,EACnB,SAAmB,EACnB,WAAqB;IAErB,qDAAqD;IACrD,MAAM,SAAS,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IAC7C,MAAM,QAAQ,GAAK,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAE9C,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEnE,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1C,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,UAAU,CAAC;IACnE,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEnE,qDAAqD;IACrD,MAAM,WAAW,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;IAC1E,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;IACnD,MAAM,KAAK,GAAK,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvE,OAAO,CAAC,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAC7B,IAAiC,EACjC,IAAiC,EACjC,MAAmC,EACnC,GAAW;IAEX,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAEnC,MAAM,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;IACxB,MAAM,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;IACxB,MAAM,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC;IAE1B,MAAM,OAAO,GAAG,CAAC,CAAkB,EAAY,EAAE;QAC/C,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,0EAA0E;IAC1E,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC;QAC7B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,CAAC;IAED,wEAAwE;IACxE,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QAC7B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,CAAC;IAED,wDAAwD;IACxD,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACvC,CAAC;IAED,yCAAyC;IACzC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACnD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACvC,CAAC;IAED,yCAAyC;IACzC,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACnD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACvC,CAAC;IAED,yCAAyC;IACzC,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,CAAC;IAED,sDAAsD;IACtD,IAAI,IAAI,IAAI,MAAM,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAC1C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,CAAC;IAED,oDAAoD;IACpD,IAAI,IAAI,IAAI,IAAI,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACxC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,CAAC;IAED,mCAAmC;IACnC,kFAAkF;IAClF,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,MAAM,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QAC3D,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,MAAM,WAAW,GAAa,EAAE,CAAC;YACjC,IAAI,CAAC,CAAC,OAAO;gBAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC3C,WAAW,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;YAC5B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;QAChD,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitWand — Résolveur Vue SFC (Single File Component)
|
|
3
|
+
*
|
|
4
|
+
* Résout les conflits dans les fichiers `.vue` en reconnaissant la structure
|
|
5
|
+
* SFC et en traitant chaque bloc indépendamment.
|
|
6
|
+
*
|
|
7
|
+
* Structure d'un fichier Vue SFC :
|
|
8
|
+
* <template> - HTML du composant
|
|
9
|
+
* <script> - Logique (JS ou TS, avec possibles sous-blocs)
|
|
10
|
+
* <script setup> - Composition API
|
|
11
|
+
* <style> - CSS/SCSS/Less
|
|
12
|
+
* <style scoped> - CSS scopé
|
|
13
|
+
* <custom-block> - Blocs personnalisés (i18n, docs, etc.)
|
|
14
|
+
*
|
|
15
|
+
* Stratégie :
|
|
16
|
+
* 1. Découper chaque version en blocs SFC identifiés par leur balise ouvrante
|
|
17
|
+
* 2. Pour chaque bloc : appliquer la logique 3-way standard
|
|
18
|
+
* - Bloc non modifié → garder base
|
|
19
|
+
* - Seul un côté a changé → accepter le changement
|
|
20
|
+
* - Same change → accepter
|
|
21
|
+
* - Conflit réel → fallback textuel (null)
|
|
22
|
+
* 3. Reconstruire le fichier dans l'ordre des blocs de `ours`
|
|
23
|
+
* (en insérant les nouveaux blocs de `theirs` à la bonne position)
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Un bloc SFC parsé.
|
|
27
|
+
*/
|
|
28
|
+
export interface SfcBlock {
|
|
29
|
+
/** Tag d'ouverture complet (ex: `<template>`, `<script setup lang="ts">`) */
|
|
30
|
+
openTag: string;
|
|
31
|
+
/** Nom du bloc (ex: 'template', 'script', 'style') */
|
|
32
|
+
name: string;
|
|
33
|
+
/** Attributs bruts (ex: 'setup lang="ts"') */
|
|
34
|
+
attrs: string;
|
|
35
|
+
/** Lignes de contenu (sans le tag d'ouverture et de fermeture) */
|
|
36
|
+
lines: string[];
|
|
37
|
+
/** Tag de fermeture (ex: `</template>`) */
|
|
38
|
+
closeTag: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Découpe un fichier Vue SFC en blocs.
|
|
42
|
+
* Les lignes hors blocs reconnus (commentaires HTML, attributs en tête…)
|
|
43
|
+
* sont regroupées dans un bloc virtuel "preamble".
|
|
44
|
+
*/
|
|
45
|
+
export declare function parseSfcBlocks(lines: string[]): SfcBlock[];
|
|
46
|
+
/** Résultat du merge Vue SFC */
|
|
47
|
+
export interface VueMergeResult {
|
|
48
|
+
/** Lignes fusionnées (null = conflit non résolvable) */
|
|
49
|
+
mergedLines: string[] | null;
|
|
50
|
+
/** Description de la fusion */
|
|
51
|
+
reason: string;
|
|
52
|
+
/** Blocs résolus automatiquement */
|
|
53
|
+
resolvedBlocks: number;
|
|
54
|
+
/** Blocs en conflit */
|
|
55
|
+
conflictedBlocks: string[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Tente de résoudre un conflit Vue SFC en fusionnant bloc par bloc.
|
|
59
|
+
*
|
|
60
|
+
* @param baseLines - Lignes de la version base
|
|
61
|
+
* @param oursLines - Lignes de la version ours
|
|
62
|
+
* @param theirsLines - Lignes de la version theirs
|
|
63
|
+
*/
|
|
64
|
+
export declare function tryResolveVueConflict(baseLines: string[], oursLines: string[], theirsLines: string[]): VueMergeResult;
|
|
65
|
+
//# sourceMappingURL=vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue.d.ts","sourceRoot":"","sources":["../../src/resolvers/vue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAUD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CA4E1D;AAID,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7B,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AA6BD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EAAE,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,WAAW,EAAE,MAAM,EAAE,GACpB,cAAc,CA6HhB"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitWand — Résolveur Vue SFC (Single File Component)
|
|
3
|
+
*
|
|
4
|
+
* Résout les conflits dans les fichiers `.vue` en reconnaissant la structure
|
|
5
|
+
* SFC et en traitant chaque bloc indépendamment.
|
|
6
|
+
*
|
|
7
|
+
* Structure d'un fichier Vue SFC :
|
|
8
|
+
* <template> - HTML du composant
|
|
9
|
+
* <script> - Logique (JS ou TS, avec possibles sous-blocs)
|
|
10
|
+
* <script setup> - Composition API
|
|
11
|
+
* <style> - CSS/SCSS/Less
|
|
12
|
+
* <style scoped> - CSS scopé
|
|
13
|
+
* <custom-block> - Blocs personnalisés (i18n, docs, etc.)
|
|
14
|
+
*
|
|
15
|
+
* Stratégie :
|
|
16
|
+
* 1. Découper chaque version en blocs SFC identifiés par leur balise ouvrante
|
|
17
|
+
* 2. Pour chaque bloc : appliquer la logique 3-way standard
|
|
18
|
+
* - Bloc non modifié → garder base
|
|
19
|
+
* - Seul un côté a changé → accepter le changement
|
|
20
|
+
* - Same change → accepter
|
|
21
|
+
* - Conflit réel → fallback textuel (null)
|
|
22
|
+
* 3. Reconstruire le fichier dans l'ordre des blocs de `ours`
|
|
23
|
+
* (en insérant les nouveaux blocs de `theirs` à la bonne position)
|
|
24
|
+
*/
|
|
25
|
+
// ─── Parser SFC ───────────────────────────────────────────
|
|
26
|
+
const RE_OPEN_TAG = /^<([\w-]+)((?:\s+[\w-]+(?:="[^"]*")?)*)\s*>$/;
|
|
27
|
+
const RE_CLOSE_TAG = /^<\/([\w-]+)>$/;
|
|
28
|
+
/** Tags racines reconnus comme blocs SFC (les autres sont ignorés comme texte) */
|
|
29
|
+
const SFC_ROOT_TAGS = new Set(["template", "script", "style"]);
|
|
30
|
+
/**
|
|
31
|
+
* Découpe un fichier Vue SFC en blocs.
|
|
32
|
+
* Les lignes hors blocs reconnus (commentaires HTML, attributs en tête…)
|
|
33
|
+
* sont regroupées dans un bloc virtuel "preamble".
|
|
34
|
+
*/
|
|
35
|
+
export function parseSfcBlocks(lines) {
|
|
36
|
+
const blocks = [];
|
|
37
|
+
let i = 0;
|
|
38
|
+
// Lignes de préambule avant le premier bloc racine
|
|
39
|
+
const preamble = [];
|
|
40
|
+
while (i < lines.length) {
|
|
41
|
+
const line = lines[i];
|
|
42
|
+
const openMatch = line.trim().match(RE_OPEN_TAG);
|
|
43
|
+
if (openMatch) {
|
|
44
|
+
const name = openMatch[1].toLowerCase();
|
|
45
|
+
const attrs = openMatch[2].trim();
|
|
46
|
+
// Reconnaître les blocs racines SFC et les custom blocks
|
|
47
|
+
// On accepte tout tag au niveau racine (i18n, docs, etc.)
|
|
48
|
+
if (preamble.length > 0 && blocks.length === 0) {
|
|
49
|
+
// Sauvegarder le préambule comme bloc virtuel
|
|
50
|
+
blocks.push({
|
|
51
|
+
openTag: "",
|
|
52
|
+
name: "__preamble__",
|
|
53
|
+
attrs: "",
|
|
54
|
+
lines: [...preamble],
|
|
55
|
+
closeTag: "",
|
|
56
|
+
});
|
|
57
|
+
preamble.length = 0;
|
|
58
|
+
}
|
|
59
|
+
const closeTagStr = `</${name}>`;
|
|
60
|
+
const contentLines = [];
|
|
61
|
+
i++;
|
|
62
|
+
while (i < lines.length) {
|
|
63
|
+
const inner = lines[i];
|
|
64
|
+
const closeMatch = inner.trim().match(RE_CLOSE_TAG);
|
|
65
|
+
if (closeMatch && closeMatch[1].toLowerCase() === name) {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
contentLines.push(inner);
|
|
69
|
+
i++;
|
|
70
|
+
}
|
|
71
|
+
blocks.push({
|
|
72
|
+
openTag: line.trim(),
|
|
73
|
+
name,
|
|
74
|
+
attrs,
|
|
75
|
+
lines: contentLines,
|
|
76
|
+
closeTag: closeTagStr,
|
|
77
|
+
});
|
|
78
|
+
i++; // passer le closeTag
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
// Ligne hors bloc → préambule ou texte entre blocs
|
|
82
|
+
preamble.push(line);
|
|
83
|
+
i++;
|
|
84
|
+
}
|
|
85
|
+
// Préambule résiduel
|
|
86
|
+
if (preamble.length > 0) {
|
|
87
|
+
if (blocks.length === 0) {
|
|
88
|
+
blocks.push({
|
|
89
|
+
openTag: "",
|
|
90
|
+
name: "__preamble__",
|
|
91
|
+
attrs: "",
|
|
92
|
+
lines: [...preamble],
|
|
93
|
+
closeTag: "",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Ajouter au dernier bloc (espace avant EOF)
|
|
98
|
+
blocks[blocks.length - 1].lines.push(...preamble);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return blocks;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Clé d'identification d'un bloc : nom + attributs.
|
|
105
|
+
* Deux blocs avec la même clé représentent le même bloc SFC.
|
|
106
|
+
*/
|
|
107
|
+
function blockKey(block) {
|
|
108
|
+
return `${block.name}:${block.attrs}`;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Compare le contenu de deux blocs pour égalité textuelle.
|
|
112
|
+
*/
|
|
113
|
+
function blocksContentEqual(a, b) {
|
|
114
|
+
return (a.openTag === b.openTag &&
|
|
115
|
+
a.lines.length === b.lines.length &&
|
|
116
|
+
a.lines.every((l, i) => l === b.lines[i]));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Sérialise un bloc SFC en lignes.
|
|
120
|
+
*/
|
|
121
|
+
function blockToLines(block) {
|
|
122
|
+
if (block.name === "__preamble__")
|
|
123
|
+
return [...block.lines];
|
|
124
|
+
return [block.openTag, ...block.lines, block.closeTag];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Tente de résoudre un conflit Vue SFC en fusionnant bloc par bloc.
|
|
128
|
+
*
|
|
129
|
+
* @param baseLines - Lignes de la version base
|
|
130
|
+
* @param oursLines - Lignes de la version ours
|
|
131
|
+
* @param theirsLines - Lignes de la version theirs
|
|
132
|
+
*/
|
|
133
|
+
export function tryResolveVueConflict(baseLines, oursLines, theirsLines) {
|
|
134
|
+
const baseBlocks = parseSfcBlocks(baseLines);
|
|
135
|
+
const oursBlocks = parseSfcBlocks(oursLines);
|
|
136
|
+
const theirsBlocks = parseSfcBlocks(theirsLines);
|
|
137
|
+
// Indexer par clé
|
|
138
|
+
const baseMap = new Map(baseBlocks.map((b) => [blockKey(b), b]));
|
|
139
|
+
const oursMap = new Map(oursBlocks.map((b) => [blockKey(b), b]));
|
|
140
|
+
const theirsMap = new Map(theirsBlocks.map((b) => [blockKey(b), b]));
|
|
141
|
+
// Ordre : ours first, puis nouveaux blocs de theirs
|
|
142
|
+
const oursOrder = oursBlocks.map(blockKey);
|
|
143
|
+
const theirsOrder = theirsBlocks.map(blockKey);
|
|
144
|
+
const allKeys = [...oursOrder];
|
|
145
|
+
for (const k of theirsOrder) {
|
|
146
|
+
if (!allKeys.includes(k))
|
|
147
|
+
allKeys.push(k);
|
|
148
|
+
}
|
|
149
|
+
const resultLines = [];
|
|
150
|
+
let resolvedBlocks = 0;
|
|
151
|
+
const conflictedBlocks = [];
|
|
152
|
+
for (const key of allKeys) {
|
|
153
|
+
const base = baseMap.get(key);
|
|
154
|
+
const ours = oursMap.get(key);
|
|
155
|
+
const theirs = theirsMap.get(key);
|
|
156
|
+
// Bloc absent de base → ajout d'un côté ou des deux
|
|
157
|
+
if (!base) {
|
|
158
|
+
if (ours && theirs) {
|
|
159
|
+
if (blocksContentEqual(ours, theirs)) {
|
|
160
|
+
resultLines.push(...blockToLines(ours));
|
|
161
|
+
resolvedBlocks++;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// Deux versions différentes d'un nouveau bloc → conflit
|
|
165
|
+
conflictedBlocks.push(key);
|
|
166
|
+
return {
|
|
167
|
+
mergedLines: null,
|
|
168
|
+
conflictedBlocks,
|
|
169
|
+
resolvedBlocks,
|
|
170
|
+
reason: `Conflit sur le bloc <${ours.name}> — ajouté différemment des deux côtés.`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else if (ours) {
|
|
175
|
+
resultLines.push(...blockToLines(ours));
|
|
176
|
+
resolvedBlocks++;
|
|
177
|
+
}
|
|
178
|
+
else if (theirs) {
|
|
179
|
+
resultLines.push(...blockToLines(theirs));
|
|
180
|
+
resolvedBlocks++;
|
|
181
|
+
}
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const oursChanged = ours ? !blocksContentEqual(base, ours) : true;
|
|
185
|
+
const theirsChanged = theirs ? !blocksContentEqual(base, theirs) : true;
|
|
186
|
+
// Suppression des deux côtés
|
|
187
|
+
if (!ours && !theirs) {
|
|
188
|
+
resolvedBlocks++;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
// Ours supprimé
|
|
192
|
+
if (!ours) {
|
|
193
|
+
if (!theirsChanged) {
|
|
194
|
+
resolvedBlocks++; // theirs = base, ours supprimé → supprimer
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
conflictedBlocks.push(key);
|
|
198
|
+
return {
|
|
199
|
+
mergedLines: null,
|
|
200
|
+
conflictedBlocks,
|
|
201
|
+
resolvedBlocks,
|
|
202
|
+
reason: `Conflit sur le bloc <${base.name}> — ours l'a supprimé, theirs l'a modifié.`,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
// Theirs supprimé
|
|
208
|
+
if (!theirs) {
|
|
209
|
+
if (!oursChanged) {
|
|
210
|
+
resolvedBlocks++; // ours = base, theirs supprimé → supprimer
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
conflictedBlocks.push(key);
|
|
214
|
+
return {
|
|
215
|
+
mergedLines: null,
|
|
216
|
+
conflictedBlocks,
|
|
217
|
+
resolvedBlocks,
|
|
218
|
+
reason: `Conflit sur le bloc <${base.name}> — theirs l'a supprimé, ours l'a modifié.`,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
// Les deux présents
|
|
224
|
+
if (!oursChanged && !theirsChanged) {
|
|
225
|
+
resultLines.push(...blockToLines(base));
|
|
226
|
+
resolvedBlocks++;
|
|
227
|
+
}
|
|
228
|
+
else if (blocksContentEqual(ours, theirs)) {
|
|
229
|
+
resultLines.push(...blockToLines(ours));
|
|
230
|
+
resolvedBlocks++;
|
|
231
|
+
}
|
|
232
|
+
else if (!oursChanged) {
|
|
233
|
+
resultLines.push(...blockToLines(theirs));
|
|
234
|
+
resolvedBlocks++;
|
|
235
|
+
}
|
|
236
|
+
else if (!theirsChanged) {
|
|
237
|
+
resultLines.push(...blockToLines(ours));
|
|
238
|
+
resolvedBlocks++;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
// Les deux ont modifié le même bloc différemment → conflit
|
|
242
|
+
conflictedBlocks.push(key);
|
|
243
|
+
return {
|
|
244
|
+
mergedLines: null,
|
|
245
|
+
conflictedBlocks,
|
|
246
|
+
resolvedBlocks,
|
|
247
|
+
reason: `Conflit sur le bloc <${ours.name}> — modifié des deux côtés de façon incompatible.`,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
mergedLines: resultLines,
|
|
253
|
+
conflictedBlocks: [],
|
|
254
|
+
resolvedBlocks,
|
|
255
|
+
reason: `Fusion Vue SFC réussie : ${resolvedBlocks} bloc(s) fusionné(s).`,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=vue.js.map
|