mabuseif commited on
Commit
b2b9458
·
verified ·
1 Parent(s): 5a70603

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +253 -283
app.py CHANGED
@@ -9,87 +9,76 @@ import json
9
  # --- Constants ---
10
  MELBOURNE_TIMEZONE = 'Australia/Melbourne'
11
 
12
- # --- Custom CSS for enhanced UI ---
13
  def load_css():
14
  st.markdown("""
15
  <style>
16
  .main-header {
17
- background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
18
  padding: 2rem;
19
- border-radius: 10px;
20
- color: white;
21
  text-align: center;
22
  margin-bottom: 2rem;
23
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
24
  }
25
 
26
  .citation-output {
27
- background: #f8f9fa;
28
- border: 2px solid #e9ecef;
29
- border-radius: 8px;
30
  padding: 1rem;
31
  margin: 1rem 0;
32
  font-family: 'Courier New', monospace;
33
- position: relative;
34
  }
35
 
36
  .copy-button {
37
- background: #28a745;
38
- color: white;
39
  border: none;
40
  padding: 0.5rem 1rem;
41
- border-radius: 5px;
42
  cursor: pointer;
43
  font-size: 0.9rem;
44
  margin-top: 0.5rem;
45
- transition: background-color 0.3s;
46
  }
47
 
48
  .copy-button:hover {
49
- background: #218838;
50
  }
51
 
52
  .warning-box {
53
- background: #fff3cd;
54
- border: 1px solid #ffeaa7;
55
- border-radius: 8px;
56
  padding: 1rem;
57
  margin: 1rem 0;
58
- color: #856404;
59
  }
60
 
61
  .success-box {
62
- background: #d4edda;
63
- border: 1px solid #c3e6cb;
64
- border-radius: 8px;
65
  padding: 1rem;
66
  margin: 1rem 0;
67
- color: #155724;
68
  }
69
 
70
  .info-card {
71
  background: white;
72
- border-radius: 10px;
73
  padding: 1.5rem;
74
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
75
  margin: 1rem 0;
76
- border-left: 4px solid #667eea;
77
  }
78
 
79
- .creator-info {
80
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
81
- color: white;
82
- padding: 1rem;
83
- border-radius: 8px;
84
  text-align: center;
85
- margin: 2rem 0;
 
 
86
  font-size: 0.9rem;
87
  }
88
 
89
  .hash-display {
90
- background: #f1f3f4;
91
- border: 1px solid #dadce0;
92
- border-radius: 6px;
93
  padding: 1rem;
94
  font-family: 'Courier New', monospace;
95
  font-size: 0.85rem;
@@ -101,27 +90,18 @@ def load_css():
101
  padding: 2rem 0;
102
  }
103
 
104
- .form-section {
105
- background: white;
106
- padding: 2rem;
107
- border-radius: 10px;
108
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
109
- margin: 1rem 0;
110
- }
111
-
112
  .datetime-display {
113
- background: #e3f2fd;
114
- border-radius: 6px;
115
  padding: 0.8rem;
116
  margin: 0.5rem 0;
117
- border-left: 4px solid #2196f3;
118
  }
119
 
120
  .verification-table {
121
  margin: 1rem 0;
122
- border-radius: 8px;
123
  overflow: hidden;
124
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
125
  }
126
  </style>
127
  """, unsafe_allow_html=True)
@@ -134,10 +114,10 @@ def generate_citation_hash(author, year, url, fragment_text, cited_text, usernam
134
  def format_citation_html(url, fragment_text, author, year, scc_hash):
135
  encoded_fragment = urllib.parse.quote(fragment_text)
136
  full_url = f"{url}#:~:text={encoded_fragment}"
137
- return f'<a href="{full_url}" data-hash="{scc_hash}">Full Guidelines</a>'
138
 
139
  def format_citation_plaintext(author, year, scc_hash):
140
- return f'Full Guidelines [hash: {scc_hash[:12]}...]'
141
 
142
  def check_for_fragment(url):
143
  return '#:~:text=' in url
@@ -148,22 +128,22 @@ def copy_to_clipboard_js(text, button_id):
148
  <script>
149
  function copyToClipboard_{button_id}() {{
150
  navigator.clipboard.writeText(`{text}`).then(function() {{
151
- document.getElementById('copy_status_{button_id}').innerHTML = 'Copied!';
152
  setTimeout(function() {{
153
  document.getElementById('copy_status_{button_id}').innerHTML = '';
154
  }}, 2000);
155
  }}, function(err) {{
156
- document.getElementById('copy_status_{button_id}').innerHTML = 'Copy failed';
157
  console.error('Could not copy text: ', err);
158
  }});
159
  }}
160
  </script>
161
- <button onclick="copyToClipboard_{button_id}()" class="copy-button">📋 Copy to Clipboard</button>
162
- <span id="copy_status_{button_id}" style="margin-left: 10px; color: green; font-weight: bold;"></span>
163
  """
164
 
165
  # --- Streamlit App ---
166
- st.set_page_config(layout="wide", page_title="Smart Context Citation Tool", page_icon="📚")
167
 
168
  # Load custom CSS
169
  load_css()
@@ -171,177 +151,162 @@ load_css()
171
  # Main header
172
  st.markdown("""
173
  <div class="main-header">
174
- <h1>📚 Smart Context Citation (SCC) Tool</h1>
175
  <p>Next-generation digital referencing system for the age of Generative AI</p>
176
  </div>
177
  """, unsafe_allow_html=True)
178
 
179
- # Creator information
180
- st.markdown("""
181
- <div class="creator-info">
182
- <strong>Developed by:</strong> Dr Majed Abuseif<br>
183
- School of Architecture and Built Environment<br>
184
- Deakin University<br>
185
- © 2025
186
- </div>
187
- """, unsafe_allow_html=True)
188
-
189
- st.sidebar.header("📖 About SCC")
190
- st.sidebar.markdown("""
191
- <div class="info-card">
192
- 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.
193
-
194
- <strong>🎯 Purpose:</strong> Transparency, integrity, and digital fluency in citations.
195
 
196
- <strong>🏗️ Structure:</strong>
197
- • Inline general author name and date style citation
198
- • Hyperlinked URL with text fragment (#:~:text=)
199
- • SHA-256 hash for verification
200
 
201
- <strong>✨ Benefits:</strong> Enhances fairness, integrates with source contexts, promotes digital fluency, prevents fabrication, and eliminates traditional reference lists.
 
 
 
202
 
203
- <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.
204
- </div>
205
- """, unsafe_allow_html=True)
206
 
207
- st.sidebar.header("💡 Example Citation")
208
- st.sidebar.markdown("""
209
- <div class="info-card">
210
- <strong>📝 Input:</strong><br>
211
- • Author: <code>Abuseif et al.</code><br>
212
- • Year: <code>2025</code><br>
213
- URL: <code>https://www.sciencedirect.com/science/article/pii/S2772411523000046</code><br>
214
- Text: <code>A proposed design framework for green roof settings in general and trees on buildings</code>
215
-
216
- <strong>📤 Output (HTML - example hash):</strong><br>
217
- <div class="hash-display">
218
- &lt;a href="https://www.sciencedirect.com/science/article/pii/S2772411523000046#:~:text=A%20proposed%20design%20framework%20for%20green%20roof%20settings%20in%20general%20and%20trees%20on%20buildings" data-hash="[GENERATED_HASH]"&gt;Full Guidelines&lt;/a&gt;
219
- </div>
220
- </div>
221
- """, unsafe_allow_html=True)
 
 
222
 
223
- tabs = st.tabs(["🔧 Citation Generator", "Verify Citation"])
224
 
225
  with tabs[0]:
226
  st.markdown('<div class="tab-content">', unsafe_allow_html=True)
227
- st.header("🔧 Generate New Citation")
228
 
229
- with st.container():
230
- st.markdown('<div class="form-section">', unsafe_allow_html=True)
231
-
232
- col1, col2 = st.columns(2)
233
-
234
- with col1:
235
- username = st.text_input("👤 Username", help="Your username for tracking purposes", placeholder="e.g., john_doe")
236
- task_name = st.text_input("📋 Task Name", help="The name of the task or project", placeholder="e.g., Literature Review Assignment")
237
- author_name = st.text_input("✍️ Author Name", help="The author(s) of the source", placeholder="e.g., Smith or Smith et al.")
238
-
239
- with col2:
240
- publication_year = st.text_input("📅 Publication Year", help="The year of publication", placeholder="e.g., 2023")
241
- source_url = st.text_input("🔗 Source URL", help="The full URL of the source", placeholder="https://example.com/article")
242
-
243
- cited_text = st.text_area("📝 Quoted or Paraphrased Text",
244
- help="The exact text quoted or paraphrased from the source",
245
- placeholder="e.g., Thermal comfort thresholds are exceeded frequently in Australian schools",
246
- height=100)
247
-
248
- # Get current date and time in Melbourne timezone
249
- melbourne_tz = pytz.timezone(MELBOURNE_TIMEZONE)
250
- current_datetime_melbourne = datetime.now(melbourne_tz)
251
- current_date = current_datetime_melbourne.strftime("%Y-%m-%d")
252
- current_time = current_datetime_melbourne.strftime("%H:%M:%S")
253
-
254
- st.markdown(f"""
255
- <div class="datetime-display">
256
- <strong>🕐 Current Date & Time (Melbourne, Australia):</strong><br>
257
- 📅 Date: {current_date}<br>
258
- ⏰ Time: {current_time}
259
- </div>
260
- """, unsafe_allow_html=True)
261
-
262
- generate_button = st.button("🚀 Generate Citation", type="primary", use_container_width=True)
263
-
264
- st.markdown('</div>', unsafe_allow_html=True)
265
-
266
- if generate_button:
267
- if not all([username, task_name, author_name, publication_year, source_url, cited_text]):
268
- st.error("⚠️ Please fill in all fields before generating a citation.")
269
- elif check_for_fragment(source_url):
270
- st.markdown("""
271
- <div class="warning-box">
272
- <strong>⚠️ Warning:</strong> It seems like your URL already contains a text fragment (<code>#:~:text=</code>).
273
- This suggests you may have used AI assistance in generating this link. Please go back to the original source,
274
- read the context carefully, and copy the source link again without any existing fragment.
275
- </div>
276
- """, unsafe_allow_html=True)
277
- else:
278
- scc_hash = generate_citation_hash(author_name, publication_year, source_url, cited_text, cited_text, username, task_name, current_date, current_time)
279
 
280
- st.markdown("## 🎉 Generated Citations")
281
-
282
- # HTML Citation - Start of text
283
- st.markdown("### 📝 HTML Citation (Start of Text)")
284
- html_citation_start = f'"{cited_text}" ' + format_citation_html(source_url, cited_text, author_name, publication_year, scc_hash)
285
-
286
- st.markdown('<div class="citation-output">', unsafe_allow_html=True)
287
- st.code(html_citation_start, language='html')
288
- st.markdown(copy_to_clipboard_js(html_citation_start.replace('`', '\\`'), "html_start"), unsafe_allow_html=True)
289
- st.markdown('</div>', unsafe_allow_html=True)
290
-
291
- # HTML Citation - End of text
292
- st.markdown("### 📝 HTML Citation (End of Text)")
293
- html_citation_end = format_citation_html(source_url, cited_text, author_name, publication_year, scc_hash) + f' "{cited_text}"'
294
-
295
- st.markdown('<div class="citation-output">', unsafe_allow_html=True)
296
- st.code(html_citation_end, language='html')
297
- st.markdown(copy_to_clipboard_js(html_citation_end.replace('`', '\\`'), "html_end"), unsafe_allow_html=True)
298
- st.markdown('</div>', unsafe_allow_html=True)
299
-
300
- # Plaintext Citation
301
- st.markdown("### 📄 Plaintext Citation")
302
- plaintext_citation = format_citation_plaintext(author_name, publication_year, scc_hash)
303
-
304
- st.markdown('<div class="citation-output">', unsafe_allow_html=True)
305
- st.code(plaintext_citation)
306
- st.markdown(copy_to_clipboard_js(plaintext_citation, "plaintext"), unsafe_allow_html=True)
307
- st.markdown('</div>', unsafe_allow_html=True)
308
-
309
- # Citation Hash Details
310
- st.markdown("### 🔐 Citation Hash Details (for Verification)")
311
- hash_details = {
312
- "author": author_name,
313
- "year": publication_year,
314
- "url": source_url,
315
- "fragment_text": cited_text,
316
- "cited_text": cited_text,
317
- "username": username,
318
- "task_name": task_name,
319
- "date": current_date,
320
- "time": current_time,
321
- "hash": scc_hash
322
- }
323
-
324
- st.markdown('<div class="hash-display">', unsafe_allow_html=True)
325
- st.json(hash_details)
326
- st.markdown('</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327
 
328
  # Instructions section
329
- st.markdown("## 📋 Instructions for Copying to Word")
330
  st.markdown("""
331
  <div class="info-card">
332
  <strong>To use the generated HTML citation in Microsoft Word:</strong><br><br>
333
- 1. 📋 Copy the desired HTML citation (Start or End of Text) using the 'Copy to Clipboard' button<br>
334
- 2. 📄 In Word, go to the 'Insert' tab<br>
335
- 3. 🔗 Click on 'Object' → 'Text from File...'<br>
336
- 4. 📁 Select 'HTML Document' from the file type dropdown<br>
337
- 5. 💾 Paste the copied HTML into a new text file (e.g., using Notepad) and save it with a <code>.html</code> extension<br>
338
- 6. Select this <code>.html</code> file in the 'Text from File...' dialog<br><br>
339
 
340
  <strong>Alternative method:</strong> You might be able to paste directly into Word and then right-click and choose 'Keep Source Formatting' or 'Merge Formatting' if available, but the 'Text from File' method is more reliable for preserving hyperlinks and data attributes.
341
  </div>
342
  """, unsafe_allow_html=True)
343
 
344
- st.markdown("## 🔍 Guidance on Verifying Citations")
345
  st.markdown("""
346
  <div class="info-card">
347
  To verify a citation, you can recompute the hash using the original input data and compare it to the embedded hash.
@@ -353,7 +318,7 @@ with tabs[0]:
353
 
354
  with tabs[1]:
355
  st.markdown('<div class="tab-content">', unsafe_allow_html=True)
356
- st.header("Verify Citation")
357
  st.markdown("""
358
  <div class="info-card">
359
  Enter the citation details below to recompute and verify the hash. This ensures the citation hasn't been tampered with or fabricated.
@@ -364,87 +329,82 @@ with tabs[1]:
364
  if 'verified_hashes' not in st.session_state:
365
  st.session_state.verified_hashes = []
366
 
367
- with st.container():
368
- st.markdown('<div class="form-section">', unsafe_allow_html=True)
369
-
370
- col1, col2 = st.columns(2)
371
-
372
- with col1:
373
- verify_username = st.text_input("👤 Username (for verification)", placeholder="e.g., john_doe")
374
- verify_task_name = st.text_input("📋 Task Name (for verification)", placeholder="e.g., Literature Review Assignment")
375
- verify_author_name = st.text_input("✍️ Author Name (for verification)", placeholder="e.g., Smith or Smith et al.")
376
- verify_publication_year = st.text_input("📅 Publication Year (for verification)", placeholder="e.g., 2023")
377
-
378
- with col2:
379
- verify_source_url = st.text_input("🔗 Source URL (for verification)", placeholder="https://example.com/article")
380
- verify_date = st.text_input("📅 Date (YYYY-MM-DD) (for verification)", placeholder="e.g., 2025-01-08")
381
- verify_time = st.text_input(" Time (HH:MM:SS) (for verification)", placeholder="e.g., 14:30:25")
382
- expected_hash = st.text_input("🔐 Expected Hash (from the citation)", placeholder="Enter the full hash from the citation")
383
-
384
- verify_cited_text = st.text_area("📝 Quoted or Paraphrased Text (for verification)",
385
- placeholder="e.g., Thermal comfort thresholds are exceeded frequently in Australian schools",
386
- height=100)
387
-
388
- verify_button = st.button("🔍 Verify Hash", type="primary", use_container_width=True)
389
-
390
- st.markdown('</div>', unsafe_allow_html=True)
391
-
392
- if verify_button:
393
- if not all([verify_username, verify_task_name, verify_author_name, verify_publication_year,
394
- verify_source_url, verify_cited_text, verify_date, verify_time, expected_hash]):
395
- st.error("⚠️ Please fill in all fields before verifying the hash.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
  else:
397
- recomputed_hash = generate_citation_hash(
398
- verify_author_name, verify_publication_year, verify_source_url,
399
- verify_cited_text, verify_cited_text, verify_username, verify_task_name,
400
- verify_date, verify_time
401
- )
402
-
403
- if recomputed_hash == expected_hash:
404
- st.markdown("""
405
- <div class="success-box">
406
- <strong>✅ Hash verified successfully!</strong> The citation is authentic and hasn't been tampered with.
407
- </div>
408
- """, unsafe_allow_html=True)
409
-
410
- st.session_state.verified_hashes.append({
411
- "Author": verify_author_name,
412
- "Year": verify_publication_year,
413
- "URL": verify_source_url,
414
- "Fragment text": verify_cited_text,
415
- "Cited text": verify_cited_text,
416
- "Username": verify_username,
417
- "Task name": verify_task_name,
418
- "Date": verify_date,
419
- "Time": verify_time,
420
- "Original Hash": expected_hash,
421
- "Recomputed Hash": recomputed_hash,
422
- "Status": "✅ Verified"
423
- })
424
- else:
425
- st.markdown("""
426
- <div class="warning-box">
427
- <strong>❌ Hash verification failed!</strong> The citation may have been altered or is not authentic.
428
- </div>
429
- """, unsafe_allow_html=True)
430
-
431
- st.session_state.verified_hashes.append({
432
- "Author": verify_author_name,
433
- "Year": verify_publication_year,
434
- "URL": verify_source_url,
435
- "Fragment text": verify_cited_text,
436
- "Cited text": verify_cited_text,
437
- "Username": verify_username,
438
- "Task name": verify_task_name,
439
- "Date": verify_date,
440
- "Time": verify_time,
441
- "Original Hash": expected_hash,
442
- "Recomputed Hash": recomputed_hash,
443
- "Status": "❌ Failed"
444
- })
445
 
446
  if st.session_state.verified_hashes:
447
- st.markdown("## 📊 Verification History")
448
  df = pd.DataFrame(st.session_state.verified_hashes)
449
 
450
  st.markdown('<div class="verification-table">', unsafe_allow_html=True)
@@ -459,7 +419,7 @@ with tabs[1]:
459
  csv = convert_df_to_csv(df)
460
 
461
  st.download_button(
462
- label="📥 Download Verification History as CSV",
463
  data=csv,
464
  file_name="scc_verification_history.csv",
465
  mime="text/csv",
@@ -467,8 +427,18 @@ with tabs[1]:
467
  )
468
 
469
  # Clear history button
470
- if st.button("🗑️ Clear Verification History", type="secondary"):
471
  st.session_state.verified_hashes = []
472
  st.experimental_rerun()
473
 
474
- st.markdown('</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
9
  # --- Constants ---
10
  MELBOURNE_TIMEZONE = 'Australia/Melbourne'
11
 
12
+ # --- Custom CSS for simplified UI ---
13
  def load_css():
14
  st.markdown("""
15
  <style>
16
  .main-header {
 
17
  padding: 2rem;
 
 
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;
26
  padding: 1rem;
27
  margin: 1rem 0;
28
  font-family: 'Courier New', monospace;
 
29
  }
30
 
31
  .copy-button {
32
+ background: #e0e0e0;
33
+ color: black;
34
  border: none;
35
  padding: 0.5rem 1rem;
36
+ border-radius: 4px;
37
  cursor: pointer;
38
  font-size: 0.9rem;
39
  margin-top: 0.5rem;
 
40
  }
41
 
42
  .copy-button:hover {
43
+ background: #d0d0d0;
44
  }
45
 
46
  .warning-box {
47
+ background: #f8f8f8;
48
+ border: 1px solid #e0e0e0;
49
+ border-radius: 4px;
50
  padding: 1rem;
51
  margin: 1rem 0;
 
52
  }
53
 
54
  .success-box {
55
+ background: #f8f8f8;
56
+ border: 1px solid #e0e0e0;
57
+ border-radius: 4px;
58
  padding: 1rem;
59
  margin: 1rem 0;
 
60
  }
61
 
62
  .info-card {
63
  background: white;
64
+ border-radius: 4px;
65
  padding: 1.5rem;
 
66
  margin: 1rem 0;
67
+ border-left: 1px solid #e0e0e0;
68
  }
69
 
70
+ .footer {
 
 
 
 
71
  text-align: center;
72
+ padding: 2rem;
73
+ margin-top: 2rem;
74
+ border-top: 1px solid #e0e0e0;
75
  font-size: 0.9rem;
76
  }
77
 
78
  .hash-display {
79
+ background: #f8f8f8;
80
+ border: 1px solid #e0e0e0;
81
+ border-radius: 4px;
82
  padding: 1rem;
83
  font-family: 'Courier New', monospace;
84
  font-size: 0.85rem;
 
90
  padding: 2rem 0;
91
  }
92
 
 
 
 
 
 
 
 
 
93
  .datetime-display {
94
+ background: #f8f8f8;
95
+ border-radius: 4px;
96
  padding: 0.8rem;
97
  margin: 0.5rem 0;
98
+ border-left: 1px solid #e0e0e0;
99
  }
100
 
101
  .verification-table {
102
  margin: 1rem 0;
103
+ border-radius: 4px;
104
  overflow: hidden;
 
105
  }
106
  </style>
107
  """, unsafe_allow_html=True)
 
114
  def format_citation_html(url, fragment_text, author, year, scc_hash):
115
  encoded_fragment = urllib.parse.quote(fragment_text)
116
  full_url = f"{url}#:~:text={encoded_fragment}"
117
+ return f'<a href="{full_url}" data-hash="{scc_hash}">({author}, {year})</a>'
118
 
119
  def format_citation_plaintext(author, year, scc_hash):
120
+ return f'({author}, {year}) [hash: {scc_hash[:12]}...]'
121
 
122
  def check_for_fragment(url):
123
  return '#:~:text=' in url
 
128
  <script>
129
  function copyToClipboard_{button_id}() {{
130
  navigator.clipboard.writeText(`{text}`).then(function() {{
131
+ document.getElementById('copy_status_{button_id}').innerHTML = 'Copied!';
132
  setTimeout(function() {{
133
  document.getElementById('copy_status_{button_id}').innerHTML = '';
134
  }}, 2000);
135
  }}, function(err) {{
136
+ document.getElementById('copy_status_{button_id}').innerHTML = 'Copy failed';
137
  console.error('Could not copy text: ', err);
138
  }});
139
  }}
140
  </script>
141
+ <button onclick="copyToClipboard_{button_id}()" class="copy-button">Copy to Clipboard</button>
142
+ <span id="copy_status_{button_id}" style="margin-left: 10px; font-weight: bold;"></span>
143
  """
144
 
145
  # --- Streamlit App ---
146
+ st.set_page_config(layout="wide", page_title="Smart Context Citation Tool")
147
 
148
  # Load custom CSS
149
  load_css()
 
151
  # Main header
152
  st.markdown("""
153
  <div class="main-header">
154
+ <h1>Smart Context Citation (SCC) Tool</h1>
155
  <p>Next-generation digital referencing system for the age of Generative AI</p>
156
  </div>
157
  """, unsafe_allow_html=True)
158
 
159
+ # Expandable section for About and Example
160
+ with st.expander("About SCC and Example Citation"):
161
+ st.markdown("""
162
+ <div class="info-card">
163
+ <h3>About SCC</h3>
164
+ 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.
 
 
 
 
 
 
 
 
 
 
165
 
166
+ <strong>Purpose:</strong> Transparency, integrity, and digital fluency in citations.
 
 
 
167
 
168
+ <strong>Structure:</strong>
169
+ - Inline general author name and date style citation
170
+ - Hyperlinked URL with text fragment (#:~:text=)
171
+ - SHA-256 hash for verification
172
 
173
+ <strong>Benefits:</strong> Enhances fairness, integrates with source contexts, promotes digital fluency, prevents fabrication, and eliminates traditional reference lists.
 
 
174
 
175
+ <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.
176
+ </div>
177
+
178
+ <div class="info-card">
179
+ <h3>Example Citation</h3>
180
+ <strong>Input:</strong><br>
181
+ - Author: <code>Abuseif et al.</code><br>
182
+ - Year: <code>2025</code><br>
183
+ - URL: <code>https://www.sciencedirect.com/science/article/pii/S2772411523000046</code><br>
184
+ - Text: <code>A proposed design framework for green roof settings in general and trees on buildings</code>
185
+
186
+ <strong>Output (HTML - example hash):</strong><br>
187
+ <div class="hash-display">
188
+ &lt;a href="https://www.sciencedirect.com/science/article/pii/S2772411523000046#:~:text=A%20proposed%20design%20framework%20for%20green%20roof%20settings%20in%20general%20and%20trees%20on%20buildings" data-hash="[GENERATED_HASH]"&gt;(Abuseif et al., 2025)&lt;/a&gt;
189
+ </div>
190
+ </div>
191
+ """, unsafe_allow_html=True)
192
 
193
+ tabs = st.tabs(["Citation Generator", "Verify Citation"])
194
 
195
  with tabs[0]:
196
  st.markdown('<div class="tab-content">', unsafe_allow_html=True)
197
+ st.header("Generate New Citation")
198
 
199
+ col1, col2 = st.columns(2)
200
+
201
+ with col1:
202
+ username = st.text_input("Username", help="Your username for tracking purposes", placeholder="e.g., john_doe")
203
+ task_name = st.text_input("Task Name", help="The name of the task or project", placeholder="e.g., Literature Review Assignment")
204
+ author_name = st.text_input("Author Name", help="The author(s) of the source", placeholder="e.g., Smith or Smith et al.")
205
+
206
+ with col2:
207
+ publication_year = st.text_input("Publication Year", help="The year of publication", placeholder="e.g., 2023")
208
+ source_url = st.text_input("Source URL", help="The full URL of the source", placeholder="https://example.com/article")
209
+
210
+ cited_text = st.text_area("Quoted or Paraphrased Text",
211
+ help="The exact text quoted or paraphrased from the source",
212
+ placeholder="e.g., Thermal comfort thresholds are exceeded frequently in Australian schools",
213
+ height=100)
214
+
215
+ # Get current date and time in Melbourne timezone
216
+ melbourne_tz = pytz.timezone(MELBOURNE_TIMEZONE)
217
+ current_datetime_melbourne = datetime.now(melbourne_tz)
218
+ current_date = current_datetime_melbourne.strftime("%Y-%m-%d")
219
+ current_time = current_datetime_melbourne.strftime("%H:%M:%S")
220
+
221
+ st.markdown(f"""
222
+ <div class="datetime-display">
223
+ <strong>Current Date & Time (Melbourne, Australia):</strong><br>
224
+ Date: {current_date}<br>
225
+ Time: {current_time}
226
+ </div>
227
+ """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
 
229
+ generate_button = st.button("Generate Citation", type="primary", use_container_width=True)
230
+
231
+ if generate_button:
232
+ if not all([username, task_name, author_name, publication_year, source_url, cited_text]):
233
+ st.error("Please fill in all fields before generating a citation.")
234
+ elif check_for_fragment(source_url):
235
+ st.markdown("""
236
+ <div class="warning-box">
237
+ <strong>Warning:</strong> It seems like your URL already contains a text fragment (<code>#:~:text=</code>).
238
+ This suggests you may have used AI assistance in generating this link. Please go back to the original source,
239
+ read the context carefully, and copy the source link again without any existing fragment.
240
+ </div>
241
+ """, unsafe_allow_html=True)
242
+ else:
243
+ scc_hash = generate_citation_hash(author_name, publication_year, source_url, cited_text, cited_text, username, task_name, current_date, current_time)
244
+
245
+ st.markdown("## Generated Citations")
246
+
247
+ # HTML Citation - Start of text
248
+ st.markdown("### HTML Citation (Start of Text)")
249
+ html_citation_start = f'"{cited_text}" ' + format_citation_html(source_url, cited_text, author_name, publication_year, scc_hash)
250
+
251
+ st.markdown('<div class="citation-output">', unsafe_allow_html=True)
252
+ st.code(html_citation_start, language='html')
253
+ st.markdown(copy_to_clipboard_js(html_citation_start.replace('`', '\\`'), "html_start"), unsafe_allow_html=True)
254
+ st.markdown('</div>', unsafe_allow_html=True)
255
+
256
+ # HTML Citation - End of text
257
+ st.markdown("### HTML Citation (End of Text)")
258
+ html_citation_end = format_citation_html(source_url, cited_text, author_name, publication_year, scc_hash) + f' "{cited_text}"'
259
+
260
+ st.markdown('<div class="citation-output">', unsafe_allow_html=True)
261
+ st.code(html_citation_end, language='html')
262
+ st.markdown(copy_to_clipboard_js(html_citation_end.replace('`', '\\`'), "html_end"), unsafe_allow_html=True)
263
+ st.markdown('</div>', unsafe_allow_html=True)
264
+
265
+ # Plaintext Citation
266
+ st.markdown("### Plaintext Citation")
267
+ plaintext_citation = format_citation_plaintext(author_name, publication_year, scc_hash)
268
+
269
+ st.markdown('<div class="citation-output">', unsafe_allow_html=True)
270
+ st.code(plaintext_citation)
271
+ st.markdown(copy_to_clipboard_js(plaintext_citation, "plaintext"), unsafe_allow_html=True)
272
+ st.markdown('</div>', unsafe_allow_html=True)
273
+
274
+ # Citation Hash Details
275
+ st.markdown("### Citation Hash Details (for Verification)")
276
+ hash_details = {
277
+ "author": author_name,
278
+ "year": publication_year,
279
+ "url": source_url,
280
+ "fragment_text": cited_text,
281
+ "cited_text": cited_text,
282
+ "username": username,
283
+ "task_name": task_name,
284
+ "date": current_date,
285
+ "time": current_time,
286
+ "hash": scc_hash
287
+ }
288
+
289
+ st.markdown('<div class="hash-display">', unsafe_allow_html=True)
290
+ st.json(hash_details)
291
+ st.markdown('</div>', unsafe_allow_html=True)
292
 
293
  # Instructions section
294
+ st.markdown("## Instructions for Copying to Word")
295
  st.markdown("""
296
  <div class="info-card">
297
  <strong>To use the generated HTML citation in Microsoft Word:</strong><br><br>
298
+ 1. Copy the desired HTML citation (Start or End of Text) using the 'Copy to Clipboard' button<br>
299
+ 2. In Word, go to the 'Insert' tab<br>
300
+ 3. Click on 'Object' → 'Text from File...'<br>
301
+ 4. Select 'HTML Document' from the file type dropdown<br>
302
+ 5. Paste the copied HTML into a new text file (e.g., using Notepad) and save it with a <code>.html</code> extension<br>
303
+ 6. Select this <code>.html</code> file in the 'Text from File...' dialog<br><br>
304
 
305
  <strong>Alternative method:</strong> You might be able to paste directly into Word and then right-click and choose 'Keep Source Formatting' or 'Merge Formatting' if available, but the 'Text from File' method is more reliable for preserving hyperlinks and data attributes.
306
  </div>
307
  """, unsafe_allow_html=True)
308
 
309
+ st.markdown("## Guidance on Verifying Citations")
310
  st.markdown("""
311
  <div class="info-card">
312
  To verify a citation, you can recompute the hash using the original input data and compare it to the embedded hash.
 
318
 
319
  with tabs[1]:
320
  st.markdown('<div class="tab-content">', unsafe_allow_html=True)
321
+ st.header("Verify Citation")
322
  st.markdown("""
323
  <div class="info-card">
324
  Enter the citation details below to recompute and verify the hash. This ensures the citation hasn't been tampered with or fabricated.
 
329
  if 'verified_hashes' not in st.session_state:
330
  st.session_state.verified_hashes = []
331
 
332
+ col1, col2 = st.columns(2)
333
+
334
+ with col1:
335
+ verify_username = st.text_input("Username (for verification)", placeholder="e.g., john_doe")
336
+ verify_task_name = st.text_input("Task Name (for verification)", placeholder="e.g., Literature Review Assignment")
337
+ verify_author_name = st.text_input("Author Name (for verification)", placeholder="e.g., Smith or Smith et al.")
338
+ verify_publication_year = st.text_input("Publication Year (for verification)", placeholder="e.g., 2023")
339
+
340
+ with col2:
341
+ verify_source_url = st.text_input("Source URL (for verification)", placeholder="https://example.com/article")
342
+ verify_date = st.text_input("Date (YYYY-MM-DD) (for verification)", placeholder="e.g., 2025-01-08")
343
+ verify_time = st.text_input("Time (HH:MM:SS) (for verification)", placeholder="e.g., 14:30:25")
344
+ expected_hash = st.text_input("Expected Hash (from the citation)", placeholder="Enter the full hash from the citation")
345
+
346
+ verify_cited_text = st.text_area("Quoted or Paraphrased Text (for verification)",
347
+ placeholder="e.g., Thermal comfort thresholds are exceeded frequently in Australian schools",
348
+ height=100)
349
+
350
+ verify_button = st.button("Verify Hash", type="primary", use_container_width=True)
351
+
352
+ if verify_button:
353
+ if not all([verify_username, verify_task_name, verify_author_name, verify_publication_year,
354
+ verify_source_url, verify_cited_text, verify_date, verify_time, expected_hash]):
355
+ st.error("Please fill in all fields before verifying the hash.")
356
+ else:
357
+ recomputed_hash = generate_citation_hash(
358
+ verify_author_name, verify_publication_year, verify_source_url,
359
+ verify_cited_text, verify_cited_text, verify_username, verify_task_name,
360
+ verify_date, verify_time
361
+ )
362
+
363
+ if recomputed_hash == expected_hash:
364
+ st.markdown("""
365
+ <div class="success-box">
366
+ <strong>Hash verified successfully!</strong> The citation is authentic and hasn't been tampered with.
367
+ </div>
368
+ """, unsafe_allow_html=True)
369
+
370
+ st.session_state.verified_hashes.append({
371
+ "Author": verify_author_name,
372
+ "Year": verify_publication_year,
373
+ "URL": verify_source_url,
374
+ "Fragment text": verify_cited_text,
375
+ "Cited text": verify_cited_text,
376
+ "Username": verify_username,
377
+ "Task name": verify_task_name,
378
+ "Date": verify_date,
379
+ "Time": verify_time,
380
+ "Original Hash": expected_hash,
381
+ "Recomputed Hash": recomputed_hash,
382
+ "Status": "Verified"
383
+ })
384
  else:
385
+ st.markdown("""
386
+ <div class="warning-box">
387
+ <strong>Hash verification failed!</strong> The citation may have been altered or is not authentic.
388
+ </div>
389
+ """, unsafe_allow_html=True)
390
+
391
+ st.session_state.verified_hashes.append({
392
+ "Author": verify_author_name,
393
+ "Year": verify_publication_year,
394
+ "URL": verify_source_url,
395
+ "Fragment text": verify_cited_text,
396
+ "Cited text": verify_cited_text,
397
+ "Username": verify_username,
398
+ "Task name": verify_task_name,
399
+ "Date": verify_date,
400
+ "Time": verify_time,
401
+ "Original Hash": expected_hash,
402
+ "Recomputed Hash": recomputed_hash,
403
+ "Status": "Failed"
404
+ })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
 
406
  if st.session_state.verified_hashes:
407
+ st.markdown("## Verification History")
408
  df = pd.DataFrame(st.session_state.verified_hashes)
409
 
410
  st.markdown('<div class="verification-table">', unsafe_allow_html=True)
 
419
  csv = convert_df_to_csv(df)
420
 
421
  st.download_button(
422
+ label="Download Verification History as CSV",
423
  data=csv,
424
  file_name="scc_verification_history.csv",
425
  mime="text/csv",
 
427
  )
428
 
429
  # Clear history button
430
+ if st.button("Clear Verification History", type="secondary"):
431
  st.session_state.verified_hashes = []
432
  st.experimental_rerun()
433
 
434
+ st.markdown('</div>', unsafe_allow_html=True)
435
+
436
+ # Footer
437
+ st.markdown("""
438
+ <div class="footer">
439
+ Developed by: Dr Majed Abuseif<br>
440
+ School of Architecture and Built Environment<br>
441
+ Deakin University<br>
442
+ © 2025
443
+ </div>
444
+ """, unsafe_allow_html=True)