mabuseif commited on
Commit
d5922f7
·
verified ·
1 Parent(s): e9cd3a9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -203
app.py CHANGED
@@ -18,8 +18,7 @@ def load_css():
18
  text-align: center;
19
  margin-bottom: 2rem;
20
  }
21
-
22
- .citation-output {
23
  background: #f8f8f8;
24
  border: 1px solid #e0e0e0;
25
  border-radius: 4px;
@@ -27,65 +26,13 @@ def load_css():
27
  margin: 1rem 0;
28
  font-family: 'Courier New', monospace;
29
  }
30
-
31
- .warning-box {
32
- background: #f8f8f8;
33
- border: 1px solid #e0e0e0;
34
- border-radius: 4px;
35
- padding: 1rem;
36
- margin: 1rem 0;
37
- }
38
-
39
- .success-box {
40
- background: #f8f8f8;
41
- border: 1px solid #e0e0e0;
42
- border-radius: 4px;
43
- padding: 1rem;
44
- margin: 1rem 0;
45
- }
46
-
47
- .info-card {
48
- background: white;
49
- border-radius: 4px;
50
- padding: 1.5rem;
51
- margin: 1rem 0;
52
- border-left: 1px solid #e0e0e0;
53
- }
54
-
55
  .footer {
56
  text-align: center;
57
  padding: 2rem;
58
- margin-top: 2rem;
59
- border-top: 1px solid #e0e0e0;
60
  font-size: 0.9rem;
61
  }
62
-
63
- .hash-display {
64
- background: #f8f8f8;
65
- border: 1px solid #e0e0e0;
66
- border-radius: 4px;
67
- padding: 1rem;
68
- font-family: 'Courier New', monospace;
69
- font-size: 0.85rem;
70
- word-break: break-all;
71
- margin: 0.5rem 0;
72
- }
73
-
74
- .tab-content {
75
- padding: 2rem 0;
76
- }
77
-
78
  .datetime-display {
79
- background: #f8f8f8;
80
- border-radius: 4px;
81
- padding: 0.8rem;
82
- margin: 0.5rem 0;
83
- border-left: 1px solid #e0e0e0;
84
- }
85
-
86
- .rendered-citation {
87
- margin: 1rem 0;
88
- font-size: 1rem;
89
  }
90
  </style>
91
  """, unsafe_allow_html=True)
@@ -127,32 +74,6 @@ def parse_metadata_hash(metadata_html):
127
  return scc_hash, username, task_name, date, time
128
  return None, None, None, None, None
129
 
130
- # --- JavaScript for capturing pasted links ---
131
- def verification_js():
132
- return """
133
- <script>
134
- function updateCitationData(inputId, outputId) {
135
- const input = document.getElementById(inputId);
136
- const output = document.getElementById(outputId);
137
- if (input && output) {
138
- const link = input.querySelector('a');
139
- output.value = link ? link.outerHTML : '';
140
- // Dispatch input event to trigger Streamlit update
141
- const event = new Event('input', { bubbles: true });
142
- output.dispatchEvent(event);
143
- }
144
- }
145
-
146
- document.getElementById('citation_input').addEventListener('paste', function(e) {
147
- setTimeout(() => updateCitationData('citation_input', 'citation_output'), 100);
148
- });
149
-
150
- document.getElementById('hash_input').addEventListener('paste', function(e) {
151
- setTimeout(() => updateCitationData('hash_input', 'hash_output'), 100);
152
- });
153
- </script>
154
- """
155
-
156
  # --- Live Clock JavaScript ---
157
  def live_clock():
158
  return """
@@ -189,10 +110,8 @@ def live_clock():
189
  # --- Streamlit App ---
190
  st.set_page_config(layout="wide", page_title="Smart Context Citation Tool")
191
 
192
- # Load custom CSS
193
  load_css()
194
 
195
- # Main header
196
  st.markdown("""
197
  <div class="main-header">
198
  <h1>Smart Context Citation (SCC) Tool</h1>
@@ -200,93 +119,57 @@ st.markdown("""
200
  </div>
201
  """, unsafe_allow_html=True)
202
 
203
- # Expandable section for About and Example
204
  with st.expander("About SCC and Example Citation"):
205
  st.markdown("""
206
  <div class="info-card">
207
  <h3>About SCC</h3>
208
  The Smart Context Citation (SCC) style is a next-generation digital referencing system designed for the age of Generative AI. It embeds citation context directly in the document, uses cryptographic hash signatures for integrity, and eliminates traditional reference lists.
209
-
210
- <strong>Purpose:</strong> Transparency, integrity, and digital fluency in citations.
211
-
212
- <strong>Structure:</strong>
213
- - Inline general author name and date style citation
214
- - Hyperlinked URL with text fragment (#:~:text=)
215
- - SHA-256 hash for verification
216
-
217
- <strong>Benefits:</strong> Enhances fairness, integrates with source contexts, promotes digital fluency, prevents fabrication, and eliminates traditional reference lists.
218
-
219
- <strong>Technical Legitimacy:</strong> Referencing the <a href="https://wicg.github.io/scroll-to-text-fragment/" target="_blank">Text Fragments WICG specification</a> for technical legitimacy.
220
  </div>
221
-
222
  <div class="info-card">
223
  <h3>Example Citation</h3>
224
- <strong>Input:</strong><br>
225
- - Author: <code>Abuseif et al.</code><br>
226
- - Year: <code>2025</code><br>
227
- - URL: <code>https://www.sciencedirect.com/science/article/pii/S2772411523000046</code><br>
228
- - Text: <code>A proposed design framework for green roof settings in general and trees on buildings</code><br>
229
-
230
- <strong>Output (Start of Text):</strong><br>
231
- <div class="rendered-citation">
232
- Abuseif et al. (2025)
233
- </div>
234
- <strong>Output (End of Text):</strong><br>
235
- <div class="rendered-citation">
236
- (Abuseif et al., 2025)
237
- </div>
238
  </div>
239
  """, unsafe_allow_html=True)
240
 
241
  tabs = st.tabs(["Citation Generator", "Verify Citation"])
242
 
 
243
  with tabs[0]:
244
  st.markdown('<div class="tab-content">', unsafe_allow_html=True)
245
  st.header("Generate New Citation")
246
 
247
- # User Information Section
248
  st.subheader("User Information")
249
  col1, col2 = st.columns(2)
250
- with col1:
251
- username = st.text_input("Username", help="Your username for tracking purposes", placeholder="e.g., john_doe")
252
- with col2:
253
- task_name = st.text_input("Task Name", help="The name of the task or project", placeholder="e.g., Literature Review Assignment")
254
 
255
- # Citation Info Section
256
  st.subheader("Citation Info")
257
  col3, col4 = st.columns(2)
258
- with col3:
259
- author_name = st.text_input("Author(s) Name", help="The author(s) of the source", placeholder="e.g., Smith or Smith et al.")
260
- with col4:
261
- publication_year = st.text_input("Publication Year", help="The year of publication", placeholder="e.g., 2023")
262
-
263
  col5, col6 = st.columns(2)
264
- with col5:
265
- source_url = st.text_input("Source URL", help="The full URL of the source", placeholder="https://example.com/article")
266
- with col6:
267
- annotated_text = st.text_input("Annotated Text", help="The text quoted or paraphrased from the source", placeholder="e.g., Thermal comfort thresholds...")
268
 
269
- # Live date and time display
270
  st.markdown("### Current Date and Time")
271
  components.html(live_clock(), height=50)
272
 
273
- # Get current date and time in Melbourne timezone for hash generation
274
  melbourne_tz = pytz.timezone(MELBOURNE_TIMEZONE)
275
  current_datetime_melbourne = datetime.now(melbourne_tz)
276
  current_date = current_datetime_melbourne.strftime("%Y-%m-%d")
277
  current_time = current_datetime_melbourne.strftime("%H:%M:%S")
278
 
279
- generate_button = st.button("Generate Citation", type="primary", use_container_width=True)
280
-
281
- if generate_button:
282
  if not all([username, task_name, author_name, publication_year, source_url, annotated_text]):
283
- st.error("Please fill in all fields before generating a citation.")
284
  elif check_for_fragment(source_url):
285
  st.markdown("""
286
  <div class="warning-box">
287
- <strong>Warning:</strong> It seems like your URL already contains a text fragment (<code>#:~:text=</code>).
288
- This suggests you may have used AI assistance in generating this link. Please go back to the original source,
289
- read the context carefully, and copy the source link again without any existing fragment.
290
  </div>
291
  """, unsafe_allow_html=True)
292
  else:
@@ -295,111 +178,61 @@ with tabs[0]:
295
  citation_link_end = f'<a href="{source_url}#:~:text={urllib.parse.quote(annotated_text)}" data-hash="{scc_hash}">({author_name}, {publication_year})</a>'
296
  metadata_link = format_metadata_html(source_url, author_name, publication_year, scc_hash, username, task_name, current_date, current_time)
297
 
298
- st.markdown("## Generated Citations")
299
  col_html1, col_html2 = st.columns(2)
300
 
301
- # HTML Citation - Start of Text
302
  with col_html1:
303
  st.markdown("### Citation (Start of Text)")
304
- st.markdown('<div class="rendered-citation">', unsafe_allow_html=True)
305
- st.markdown(citation_link_start, unsafe_allow_html=True)
306
- st.markdown('</div>', unsafe_allow_html=True)
307
 
308
- # HTML Citation - End of Text
309
  with col_html2:
310
  st.markdown("### Citation (End of Text)")
311
- st.markdown('<div class="rendered-citation">', unsafe_allow_html=True)
312
- st.markdown(citation_link_end, unsafe_allow_html=True)
313
- st.markdown('</div>', unsafe_allow_html=True)
314
 
315
- # SCC Ledger
316
  st.markdown("### SCC Ledger")
317
- st.markdown('<div class="hash-display">', unsafe_allow_html=True)
318
- st.markdown(metadata_link, unsafe_allow_html=True)
319
- st.markdown('</div>', unsafe_allow_html=True)
320
-
321
  st.markdown('</div>', unsafe_allow_html=True)
322
 
 
323
  with tabs[1]:
324
  st.markdown('<div class="tab-content">', unsafe_allow_html=True)
325
  st.header("Verify Citation")
326
- st.markdown("""
327
- <div class="info-card">
328
- Paste the rendered citation and hash links (e.g., "Author (Year)" and "Author (Year). Hash") directly from the 'Citation Generator' tab to verify the citation's authenticity.
329
- </div>
330
- """, unsafe_allow_html=True)
331
-
332
- # Input fields for citation and hash
333
- st.markdown("""
334
- <div>
335
- <label>Paste Citation (with embedded link)</label>
336
- <div id="citation_input" contenteditable="true" style="border: 1px solid #e0e0e0; border-radius: 4px; padding: 0.5rem; min-height: 50px; margin-bottom: 1rem;"></div>
337
- <input type="hidden" id="citation_output" name="citation_output" value="">
338
- <label>Paste Hash (with embedded link)</label>
339
- <div id="hash_input" contenteditable="true" style="border: 1px solid #e0e0e0; border-radius: 4px; padding: 0.5rem; min-height: 50px; margin-bottom: 1rem;"></div>
340
- <input type="hidden" id="hash_output" name="hash_output" value="">
341
- </div>
342
- """, unsafe_allow_html=True)
343
-
344
- # Add JavaScript to capture pasted link data
345
- components.html(verification_js(), height=0)
346
-
347
- # Initialize session state
348
- if 'citation_html' not in st.session_state:
349
- st.session_state.citation_html = ''
350
- if 'hash_html' not in st.session_state:
351
- st.session_state.hash_html = ''
352
-
353
- # Hidden text inputs to capture JavaScript data
354
- citation_html = st.text_input("Citation HTML", key="citation_output", value=st.session_state.citation_html, label_visibility="collapsed")
355
- hash_html = st.text_input("Hash HTML", key="hash_output", value=st.session_state.hash_html, label_visibility="collapsed")
356
 
357
- # Update session state
358
- if citation_html != st.session_state.citation_html:
359
- st.session_state.citation_html = citation_html
360
- if hash_html != st.session_state.hash_html:
361
- st.session_state.hash_html = hash_html
362
 
363
- verify_button = st.button("Verify Citation", type="primary", use_container_width=True)
364
-
365
- if verify_button:
366
- if not (st.session_state.citation_html and st.session_state.hash_html):
367
  st.error("Please paste both the citation and hash links before verifying.")
368
  else:
369
- # Parse citation
370
- author, year, url, fragment_text, citation_hash = parse_citation(st.session_state.citation_html)
371
- # Parse hash and metadata
372
- scc_hash, username, task_name, date, time = parse_metadata_hash(st.session_state.hash_html)
373
 
374
  if not all([author, year, url, fragment_text, scc_hash, username, task_name, date, time]):
375
- st.error("Invalid citation or hash format. Please ensure both inputs are correctly pasted links from the generated output.")
376
  else:
377
- # Recompute hash
378
- recomputed_hash = generate_citation_hash(
379
- author, year, url, fragment_text, fragment_text, username, task_name, date, time
380
- )
381
-
382
  if recomputed_hash == scc_hash:
383
  st.markdown("""
384
  <div class="success-box">
385
- <strong>Hash verified successfully!</strong> The citation is authentic and hasn't been tampered with.
386
  </div>
387
  """, unsafe_allow_html=True)
388
  else:
389
  st.markdown("""
390
  <div class="warning-box">
391
- <strong>Hash verification failed!</strong> The citation may have been altered or is not authentic.
392
  </div>
393
  """, unsafe_allow_html=True)
394
 
395
  st.markdown('</div>', unsafe_allow_html=True)
396
 
397
- # Footer
398
  st.markdown("""
399
  <div class="footer">
400
  Developed by: Dr Majed Abuseif<br>
401
- School of Architecture and Built Environment<br>
402
- Deakin University<br>
403
  © 2025
404
  </div>
405
- """, unsafe_allow_html=True)
 
18
  text-align: center;
19
  margin-bottom: 2rem;
20
  }
21
+ .citation-output, .warning-box, .success-box, .info-card, .footer, .hash-display, .tab-content, .datetime-display, .rendered-citation {
 
22
  background: #f8f8f8;
23
  border: 1px solid #e0e0e0;
24
  border-radius: 4px;
 
26
  margin: 1rem 0;
27
  font-family: 'Courier New', monospace;
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  .footer {
30
  text-align: center;
31
  padding: 2rem;
 
 
32
  font-size: 0.9rem;
33
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  .datetime-display {
35
+ font-family: sans-serif;
 
 
 
 
 
 
 
 
 
36
  }
37
  </style>
38
  """, unsafe_allow_html=True)
 
74
  return scc_hash, username, task_name, date, time
75
  return None, None, None, None, None
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  # --- Live Clock JavaScript ---
78
  def live_clock():
79
  return """
 
110
  # --- Streamlit App ---
111
  st.set_page_config(layout="wide", page_title="Smart Context Citation Tool")
112
 
 
113
  load_css()
114
 
 
115
  st.markdown("""
116
  <div class="main-header">
117
  <h1>Smart Context Citation (SCC) Tool</h1>
 
119
  </div>
120
  """, unsafe_allow_html=True)
121
 
 
122
  with st.expander("About SCC and Example Citation"):
123
  st.markdown("""
124
  <div class="info-card">
125
  <h3>About SCC</h3>
126
  The Smart Context Citation (SCC) style is a next-generation digital referencing system designed for the age of Generative AI. It embeds citation context directly in the document, uses cryptographic hash signatures for integrity, and eliminates traditional reference lists.
 
 
 
 
 
 
 
 
 
 
 
127
  </div>
 
128
  <div class="info-card">
129
  <h3>Example Citation</h3>
130
+ Author: <code>Abuseif et al.</code> <br>
131
+ Year: <code>2025</code><br>
132
+ URL: <code>https://www.sciencedirect.com/science/article/pii/S2772411523000046</code><br>
133
+ Text: <code>A proposed design framework for green roof settings in general and trees on buildings</code>
 
 
 
 
 
 
 
 
 
 
134
  </div>
135
  """, unsafe_allow_html=True)
136
 
137
  tabs = st.tabs(["Citation Generator", "Verify Citation"])
138
 
139
+ # --- Citation Generator ---
140
  with tabs[0]:
141
  st.markdown('<div class="tab-content">', unsafe_allow_html=True)
142
  st.header("Generate New Citation")
143
 
 
144
  st.subheader("User Information")
145
  col1, col2 = st.columns(2)
146
+ username = col1.text_input("Username", placeholder="e.g., john_doe")
147
+ task_name = col2.text_input("Task Name", placeholder="e.g., Literature Review")
 
 
148
 
 
149
  st.subheader("Citation Info")
150
  col3, col4 = st.columns(2)
151
+ author_name = col3.text_input("Author(s) Name", placeholder="e.g., Smith et al.")
152
+ publication_year = col4.text_input("Publication Year", placeholder="e.g., 2023")
153
+
 
 
154
  col5, col6 = st.columns(2)
155
+ source_url = col5.text_input("Source URL", placeholder="https://example.com/article")
156
+ annotated_text = col6.text_input("Annotated Text", placeholder="e.g., Thermal comfort thresholds...")
 
 
157
 
 
158
  st.markdown("### Current Date and Time")
159
  components.html(live_clock(), height=50)
160
 
 
161
  melbourne_tz = pytz.timezone(MELBOURNE_TIMEZONE)
162
  current_datetime_melbourne = datetime.now(melbourne_tz)
163
  current_date = current_datetime_melbourne.strftime("%Y-%m-%d")
164
  current_time = current_datetime_melbourne.strftime("%H:%M:%S")
165
 
166
+ if st.button("Generate Citation", type="primary", use_container_width=True):
 
 
167
  if not all([username, task_name, author_name, publication_year, source_url, annotated_text]):
168
+ st.error("Please fill in all fields.")
169
  elif check_for_fragment(source_url):
170
  st.markdown("""
171
  <div class="warning-box">
172
+ <strong>Warning:</strong> Your URL already includes a text fragment. Please use the original source URL.
 
 
173
  </div>
174
  """, unsafe_allow_html=True)
175
  else:
 
178
  citation_link_end = f'<a href="{source_url}#:~:text={urllib.parse.quote(annotated_text)}" data-hash="{scc_hash}">({author_name}, {publication_year})</a>'
179
  metadata_link = format_metadata_html(source_url, author_name, publication_year, scc_hash, username, task_name, current_date, current_time)
180
 
 
181
  col_html1, col_html2 = st.columns(2)
182
 
 
183
  with col_html1:
184
  st.markdown("### Citation (Start of Text)")
185
+ st.markdown('<div class="rendered-citation">' + citation_link_start + '</div>', unsafe_allow_html=True)
 
 
186
 
 
187
  with col_html2:
188
  st.markdown("### Citation (End of Text)")
189
+ st.markdown('<div class="rendered-citation">' + citation_link_end + '</div>', unsafe_allow_html=True)
 
 
190
 
 
191
  st.markdown("### SCC Ledger")
192
+ st.markdown('<div class="hash-display">' + metadata_link + '</div>', unsafe_allow_html=True)
193
+
 
 
194
  st.markdown('</div>', unsafe_allow_html=True)
195
 
196
+ # --- Verify Citation ---
197
  with tabs[1]:
198
  st.markdown('<div class="tab-content">', unsafe_allow_html=True)
199
  st.header("Verify Citation")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
+ st.subheader("Paste Citation and Hash (as generated above)")
202
+ citation_html = st.text_area("Paste Citation (with embedded link)", height=150)
203
+ hash_html = st.text_area("Paste Hash (with embedded link)", height=150)
 
 
204
 
205
+ if st.button("Verify Citation", type="primary", use_container_width=True):
206
+ if not (citation_html and hash_html):
 
 
207
  st.error("Please paste both the citation and hash links before verifying.")
208
  else:
209
+ author, year, url, fragment_text, citation_hash = parse_citation(citation_html)
210
+ scc_hash, username, task_name, date, time = parse_metadata_hash(hash_html)
 
 
211
 
212
  if not all([author, year, url, fragment_text, scc_hash, username, task_name, date, time]):
213
+ st.error("Invalid format. Please check both the citation and hash inputs.")
214
  else:
215
+ recomputed_hash = generate_citation_hash(author, year, url, fragment_text, fragment_text, username, task_name, date, time)
 
 
 
 
216
  if recomputed_hash == scc_hash:
217
  st.markdown("""
218
  <div class="success-box">
219
+ <strong>Hash verified successfully!</strong> The citation is authentic and untampered.
220
  </div>
221
  """, unsafe_allow_html=True)
222
  else:
223
  st.markdown("""
224
  <div class="warning-box">
225
+ <strong>Hash verification failed!</strong> Citation may have been altered.
226
  </div>
227
  """, unsafe_allow_html=True)
228
 
229
  st.markdown('</div>', unsafe_allow_html=True)
230
 
231
+ # --- Footer ---
232
  st.markdown("""
233
  <div class="footer">
234
  Developed by: Dr Majed Abuseif<br>
235
+ School of Architecture and Built Environment, Deakin University<br>
 
236
  © 2025
237
  </div>
238
+ """, unsafe_allow_html=True)