om4r932 commited on
Commit
28face5
·
1 Parent(s): 48c68c7

Update document handling

Browse files
Files changed (3) hide show
  1. app.py +110 -11
  2. static/script.js +45 -51
  3. static/style.css +5 -0
app.py CHANGED
@@ -128,6 +128,114 @@ def get_latest_version(spec: str) -> str:
128
  else:
129
  raise HTTPException(req.status_code, "An error has occured while getting latest version")
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  class SpecRequest(BaseModel):
132
  specification: str
133
  version: Optional[str] = None
@@ -137,7 +245,7 @@ def main_page():
137
  return FileResponse(os.path.join("templates", "index.html"))
138
 
139
  @app.post("/from-search")
140
- def get_file_from_spec_id_version(req: SpecRequest) -> Dict[str, str]:
141
  spec = req.specification
142
  version = req.version
143
  if not version:
@@ -176,13 +284,4 @@ def get_file_from_spec_id_version(req: SpecRequest) -> Dict[str, str]:
176
  except ValueError as e:
177
  real_toc_indexes[chapter] = -float("inf")
178
 
179
- document = {}
180
- toc = list(real_toc_indexes.keys())
181
- index_toc = list(real_toc_indexes.values())
182
- curr_index = 0
183
- for x in range(1, len(toc)):
184
- document[toc[curr_index].replace("\t", " ")] = re.sub(r"[\ \t]+", " ", "\n".join(text[index_toc[curr_index]+1:index_toc[x]]))
185
- curr_index = x
186
-
187
- document[toc[curr_index].replace("\t"," ")] = re.sub(r"\s+", " ", " ".join(text[index_toc[curr_index]+1:]))
188
- return document
 
128
  else:
129
  raise HTTPException(req.status_code, "An error has occured while getting latest version")
130
 
131
+ def create_nested_structure(chapters, text, real_toc_indexes):
132
+ """Crée une structure hiérarchique où les sous-sections sont imbriquées dans leurs sections parentes."""
133
+ result = {}
134
+
135
+ # Trier les chapitres par numéro de section
136
+ sorted_chapters = sorted(chapters, key=lambda x: [int(p) if p.isdigit() else p for p in x.split()[0].split('.')])
137
+
138
+ # Préparer les contenus des chapitres
139
+ chapter_contents = {}
140
+ for i, chapter in enumerate(sorted_chapters):
141
+ current_index = real_toc_indexes[chapter]
142
+
143
+ # Déterminer l'index de fin
144
+ end_index = len(text)
145
+ if i < len(sorted_chapters) - 1:
146
+ next_chapter = sorted_chapters[i + 1]
147
+ end_index = real_toc_indexes[next_chapter]
148
+
149
+ # Extraire et nettoyer le contenu
150
+ content = text[current_index + 1:end_index]
151
+ cleaned_content = "\n".join(content).strip()
152
+ chapter_contents[chapter] = cleaned_content
153
+
154
+ # Fonction récursive pour construire la structure hiérarchique
155
+ def insert_section(root, section_path, title, content):
156
+ """Insère une section dans l'arborescence hiérarchique."""
157
+ parts = section_path.split('.')
158
+
159
+ # Ignorer les sections sans titre réel (seulement si le titre est vide ou juste des espaces)
160
+ if not title.strip():
161
+ # Si c'est une section sans titre mais avec du contenu, on peut le fusionner avec sa première sous-section
162
+ # ou simplement l'ignorer selon votre besoin
163
+ return None
164
+
165
+ # Cas de base: section de premier niveau
166
+ if len(parts) == 1:
167
+ key = section_path + " " + title
168
+ if key not in root:
169
+ root[key] = {"content": content, "subsections": {}}
170
+ else:
171
+ root[key]["content"] = content
172
+ return root[key]
173
+
174
+ # Trouver ou créer le parent
175
+ parent_path = '.'.join(parts[:-1])
176
+ for key in root.keys():
177
+ if key.startswith(parent_path + " "):
178
+ # Parent trouvé, insérer dans ses sous-sections
179
+ section_key = section_path + " " + title
180
+ if section_key not in root[key]["subsections"]:
181
+ root[key]["subsections"][section_key] = {"content": content, "subsections": {}}
182
+ else:
183
+ root[key]["subsections"][section_key]["content"] = content
184
+ return root[key]["subsections"][section_key]
185
+
186
+ # Parent non trouvé, il faut le créer d'abord
187
+ # Rechercher le titre du parent
188
+ parent_title = ""
189
+ for chapter in sorted_chapters:
190
+ if chapter.split()[0] == parent_path:
191
+ parts = chapter.split(maxsplit=1)
192
+ parent_title = parts[1] if len(parts) > 1 else ""
193
+ break
194
+
195
+ # Si le parent n'a pas de titre, on cherche un parent plus haut
196
+ if not parent_title.strip():
197
+ # On peut soit ignorer cette branche, soit essayer de trouver un parent valide plus haut
198
+ grand_parent_parts = parent_path.split('.')
199
+ if len(grand_parent_parts) > 1:
200
+ grand_parent_path = '.'.join(grand_parent_parts[:-1])
201
+ for key in root.keys():
202
+ if key.startswith(grand_parent_path + " "):
203
+ # On a trouvé un grand-parent valide, on insère directement dedans
204
+ section_key = section_path + " " + title
205
+ if section_key not in root[key]["subsections"]:
206
+ root[key]["subsections"][section_key] = {"content": content, "subsections": {}}
207
+ return root[key]["subsections"][section_key]
208
+ # Si on n'a pas trouvé de grand-parent valide, on insère à la racine
209
+ section_key = section_path + " " + title
210
+ root[section_key] = {"content": content, "subsections": {}}
211
+ return root[section_key]
212
+
213
+ # Créer le parent récursivement
214
+ parent_section = insert_section(root, parent_path, parent_title, "")
215
+
216
+ # Si le parent n'a pas pu être créé (car sans titre), on insère à la racine
217
+ if parent_section is None:
218
+ section_key = section_path + " " + title
219
+ root[section_key] = {"content": content, "subsections": {}}
220
+ return root[section_key]
221
+
222
+ # Maintenant insérer cette section dans le parent nouvellement créé
223
+ section_key = section_path + " " + title
224
+ parent_section["subsections"][section_key] = {"content": content, "subsections": {}}
225
+ return parent_section["subsections"][section_key]
226
+
227
+ # Traiter chaque chapitre
228
+ for chapter in sorted_chapters:
229
+ parts = chapter.split(maxsplit=1)
230
+ section_num = parts[0]
231
+ section_title = parts[1] if len(parts) > 1 else ""
232
+
233
+ # Ne traiter que les sections avec un titre
234
+ if section_title.strip():
235
+ insert_section(result, section_num, section_title, chapter_contents[chapter])
236
+
237
+ return result
238
+
239
  class SpecRequest(BaseModel):
240
  specification: str
241
  version: Optional[str] = None
 
245
  return FileResponse(os.path.join("templates", "index.html"))
246
 
247
  @app.post("/from-search")
248
+ def get_file_from_spec_id_version(req: SpecRequest) -> Dict:
249
  spec = req.specification
250
  version = req.version
251
  if not version:
 
284
  except ValueError as e:
285
  real_toc_indexes[chapter] = -float("inf")
286
 
287
+ return create_nested_structure(chapters, text, real_toc_indexes)
 
 
 
 
 
 
 
 
 
static/script.js CHANGED
@@ -25,12 +25,6 @@ function handleSpecSearch(){
25
  let body = {"specification": document.getElementById("specInput").value};
26
  if(versCheck && document.getElementById("versionInput").value.length > 0){
27
  body["version"] = document.getElementById("versionInput").value;
28
- } else {
29
- fetch("https://organizedprogrammers-3gppdocfinder.hf.space/find",
30
- {method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({"doc_id": body.specification})}
31
- ).then(data => data.json())
32
- .then(resp => body['version'] = resp.version)
33
- .catch(error => console.error(error))
34
  }
35
 
36
  fetch("/from-search", {
@@ -91,57 +85,57 @@ function handleFileSelect(event) {
91
  reader.readAsText(file);
92
  }
93
 
94
- function renderDocument(tab, jsonContent) {
95
  const container = document.querySelector(`#${tab} #document-container`);
96
  container.innerHTML = '';
97
-
98
- // Parcourir tous les éléments du JSON
99
- Object.entries(jsonContent).forEach(([key, value]) => {
100
- // Déterminer le niveau de titre basé sur la clé
101
- if (key.match(/^\d+$/)) {
102
- // Section principale (ex: "1 Scope")
103
- const section = document.createElement('div');
104
- section.className = 'section';
105
-
106
- const title = document.createElement('h2');
107
- title.textContent = key;
108
- section.appendChild(title);
109
-
110
- const content = document.createElement('div');
111
- content.innerHTML = formatText(value);
112
- section.appendChild(content);
113
-
114
- container.appendChild(section);
115
- } else if (key.match(/^\d+\.\d+$/)) {
116
- // Sous-section (ex: "3.1 Definitions")
117
- const subsection = document.createElement('div');
118
- subsection.className = 'subsection';
119
-
120
- const title = document.createElement('h3');
121
- title.textContent = key;
122
- subsection.appendChild(title);
123
-
124
- const content = document.createElement('div');
125
- content.innerHTML = formatText(value);
126
- subsection.appendChild(content);
127
-
128
- container.appendChild(subsection);
129
- } else {
130
- // Autres éléments
131
- const div = document.createElement('div');
132
- const title = document.createElement('h3');
133
- title.textContent = key;
134
- div.appendChild(title);
135
-
136
  const content = document.createElement('div');
137
- content.innerHTML = formatText(value);
138
- div.appendChild(content);
139
-
140
- container.appendChild(div);
 
 
 
 
 
 
 
 
 
 
 
 
141
  }
142
- });
 
 
 
 
 
 
 
 
143
  }
144
 
 
 
145
  function formatText(text) {
146
  if (!text) return '';
147
 
 
25
  let body = {"specification": document.getElementById("specInput").value};
26
  if(versCheck && document.getElementById("versionInput").value.length > 0){
27
  body["version"] = document.getElementById("versionInput").value;
 
 
 
 
 
 
28
  }
29
 
30
  fetch("/from-search", {
 
85
  reader.readAsText(file);
86
  }
87
 
88
+ function renderDocument(tab, data) {
89
  const container = document.querySelector(`#${tab} #document-container`);
90
  container.innerHTML = '';
91
+
92
+ function renderSection(sectionKey, sectionData, level) {
93
+ const sectionDiv = document.createElement('div');
94
+ sectionDiv.className = `section level-${level}`;
95
+
96
+ // Extraire le numéro et le titre de la clé
97
+ const parts = sectionKey.split(/\s(.+)/); // Divise à partir du premier espace
98
+ const sectionNumber = parts[0];
99
+ const sectionTitle = parts[1] || "";
100
+
101
+ // Créer l'en-tête de section
102
+ const header = document.createElement(`h${Math.min(level + 1, 6)}`);
103
+ header.textContent = sectionKey; // Utiliser la clé complète comme titre
104
+ sectionDiv.appendChild(header);
105
+
106
+ // Ajouter le contenu
107
+ if (sectionData.content) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  const content = document.createElement('div');
109
+ content.className = 'content';
110
+ content.textContent = sectionData.content;
111
+ sectionDiv.appendChild(content);
112
+ }
113
+
114
+ // Ajouter les sous-sections récursivement
115
+ if (sectionData.subsections && Object.keys(sectionData.subsections).length > 0) {
116
+ const subsectionsDiv = document.createElement('div');
117
+ subsectionsDiv.className = 'subsections';
118
+
119
+ for (const [subKey, subData] of Object.entries(sectionData.subsections)) {
120
+ const subSection = renderSection(subKey, subData, level + 1);
121
+ subsectionsDiv.appendChild(subSection);
122
+ }
123
+
124
+ sectionDiv.appendChild(subsectionsDiv);
125
  }
126
+
127
+ return sectionDiv;
128
+ }
129
+
130
+ // Parcourir les sections de premier niveau
131
+ for (const [sectionKey, sectionData] of Object.entries(data)) {
132
+ const sectionElement = renderSection(sectionKey, sectionData, 1);
133
+ container.appendChild(sectionElement);
134
+ }
135
  }
136
 
137
+
138
+
139
  function formatText(text) {
140
  if (!text) return '';
141
 
static/style.css CHANGED
@@ -7,6 +7,11 @@ body {
7
  color: #333;
8
  }
9
 
 
 
 
 
 
10
  .header {
11
  margin-bottom: 30px;
12
  padding-bottom: 15px;
 
7
  color: #333;
8
  }
9
 
10
+ div[class^='section level']{
11
+ padding: 10px;
12
+ border: 1px solid #bbb;
13
+ }
14
+
15
  .header {
16
  margin-bottom: 30px;
17
  padding-bottom: 15px;