vyasa 0.3.6__tar.gz → 0.3.8__tar.gz
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.
- {vyasa-0.3.6/vyasa.egg-info → vyasa-0.3.8}/PKG-INFO +1 -1
- {vyasa-0.3.6 → vyasa-0.3.8}/pyproject.toml +1 -1
- {vyasa-0.3.6 → vyasa-0.3.8}/settings.ini +1 -1
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa/__init__.py +1 -1
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa/core.py +125 -1
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa/static/scripts.js +81 -0
- {vyasa-0.3.6 → vyasa-0.3.8/vyasa.egg-info}/PKG-INFO +1 -1
- {vyasa-0.3.6 → vyasa-0.3.8}/LICENSE +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/MANIFEST.in +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/README.md +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/setup.cfg +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/setup.py +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa/agent.py +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa/build.py +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa/config.py +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa/helpers.py +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa/layout_helpers.py +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa/main.py +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa/static/sidenote.css +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa.egg-info/SOURCES.txt +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa.egg-info/dependency_links.txt +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa.egg-info/entry_points.txt +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa.egg-info/not-zip-safe +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa.egg-info/requires.txt +0 -0
- {vyasa-0.3.6 → vyasa-0.3.8}/vyasa.egg-info/top_level.txt +0 -0
|
@@ -67,6 +67,8 @@ def span_token(name, pat, attr, prec=5):
|
|
|
67
67
|
self.caption = match.group(2) if match.group(2) else None
|
|
68
68
|
elif name == 'MermaidEmbed':
|
|
69
69
|
self.option = match.group(2) if match.group(2) else None
|
|
70
|
+
elif name == 'IframeEmbed':
|
|
71
|
+
self.options = match.group(2) if match.group(2) else None
|
|
70
72
|
T.__name__ = name
|
|
71
73
|
return T
|
|
72
74
|
|
|
@@ -77,6 +79,12 @@ YoutubeEmbed = span_token(
|
|
|
77
79
|
'video_id',
|
|
78
80
|
6
|
|
79
81
|
)
|
|
82
|
+
IframeEmbed = span_token(
|
|
83
|
+
'IframeEmbed',
|
|
84
|
+
r'\[iframe:([^\|\]]+)(?:\|(.+))?\]',
|
|
85
|
+
'src',
|
|
86
|
+
6
|
|
87
|
+
)
|
|
80
88
|
|
|
81
89
|
# Superscript and Subscript tokens with higher precedence
|
|
82
90
|
class Superscript(mst.span_token.SpanToken):
|
|
@@ -221,6 +229,7 @@ class ContentRenderer(FrankenRenderer):
|
|
|
221
229
|
self.current_path = current_path # Current post path for resolving relative links and images
|
|
222
230
|
self.heading_counts = {}
|
|
223
231
|
self.mermaid_counter = 0
|
|
232
|
+
self.iframe_counter = 0
|
|
224
233
|
|
|
225
234
|
def render_list_item(self, token):
|
|
226
235
|
"""Render list items with task list checkbox support"""
|
|
@@ -273,6 +282,86 @@ class ContentRenderer(FrankenRenderer):
|
|
|
273
282
|
if caption:
|
|
274
283
|
return iframe + f'<p class="text-sm text-slate-500 dark:text-slate-400 text-center mt-2">{caption}</p>'
|
|
275
284
|
return iframe
|
|
285
|
+
|
|
286
|
+
def render_iframe_embed(self, token):
|
|
287
|
+
src = token.src.strip()
|
|
288
|
+
options_raw = getattr(token, 'options', None)
|
|
289
|
+
|
|
290
|
+
# Defaults
|
|
291
|
+
width = '65vw'
|
|
292
|
+
height = '400px'
|
|
293
|
+
title = 'Embedded content'
|
|
294
|
+
allow = 'clipboard-read; clipboard-write; fullscreen'
|
|
295
|
+
allowfullscreen = True
|
|
296
|
+
caption = None
|
|
297
|
+
popup = False
|
|
298
|
+
|
|
299
|
+
# Parse options: key=value;key=value
|
|
300
|
+
if options_raw:
|
|
301
|
+
for part in options_raw.split(';'):
|
|
302
|
+
if not part.strip() or '=' not in part:
|
|
303
|
+
continue
|
|
304
|
+
key, value = part.split('=', 1)
|
|
305
|
+
key = key.strip().lower()
|
|
306
|
+
value = value.strip()
|
|
307
|
+
if key == 'width':
|
|
308
|
+
width = value
|
|
309
|
+
elif key == 'height':
|
|
310
|
+
height = value
|
|
311
|
+
elif key == 'title':
|
|
312
|
+
title = value
|
|
313
|
+
elif key == 'allow':
|
|
314
|
+
allow = value
|
|
315
|
+
elif key == 'fullscreen':
|
|
316
|
+
allowfullscreen = value.lower() in ('1', 'true', 'yes', 'on')
|
|
317
|
+
elif key == 'caption':
|
|
318
|
+
caption = value
|
|
319
|
+
elif key == 'popup':
|
|
320
|
+
popup = value.lower() in ('1', 'true', 'yes', 'on')
|
|
321
|
+
|
|
322
|
+
# Break out of normal content flow for viewport widths
|
|
323
|
+
break_out = 'vw' in str(width).lower()
|
|
324
|
+
if break_out:
|
|
325
|
+
container_style = f"width: {width}; position: relative; left: 50%; transform: translateX(-50%);"
|
|
326
|
+
else:
|
|
327
|
+
container_style = f"width: {width};"
|
|
328
|
+
|
|
329
|
+
self.iframe_counter += 1
|
|
330
|
+
iframe_id = f"iframe-{abs(hash(src)) & 0xFFFFFF}-{self.iframe_counter}"
|
|
331
|
+
|
|
332
|
+
fullscreen_button = ''
|
|
333
|
+
if popup:
|
|
334
|
+
fullscreen_button = (
|
|
335
|
+
'<div class="iframe-controls absolute top-2 right-2 z-10 flex gap-1 '
|
|
336
|
+
'bg-white/80 dark:bg-slate-800/80 backdrop-blur-sm rounded">'
|
|
337
|
+
f'<button data-iframe-fullscreen-toggle="true" '
|
|
338
|
+
f'data-iframe-src="{src}" '
|
|
339
|
+
f'data-iframe-title="{title}" '
|
|
340
|
+
f'data-iframe-allow="{allow}" '
|
|
341
|
+
f'data-iframe-allowfullscreen="{str(allowfullscreen).lower()}" '
|
|
342
|
+
'class="px-2 py-1 text-xs border rounded hover:bg-slate-100 '
|
|
343
|
+
'dark:hover:bg-slate-700" title="Fullscreen">⛶</button>'
|
|
344
|
+
'</div>'
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
iframe = f'''
|
|
348
|
+
<div class="relative my-6 rounded-lg overflow-hidden border border-slate-200 dark:border-slate-800" style="{container_style}">
|
|
349
|
+
{fullscreen_button}
|
|
350
|
+
<iframe
|
|
351
|
+
id="{iframe_id}"
|
|
352
|
+
src="{src}"
|
|
353
|
+
title="{title}"
|
|
354
|
+
frameborder="0"
|
|
355
|
+
allow="{allow}"
|
|
356
|
+
{'allowfullscreen' if allowfullscreen else ''}
|
|
357
|
+
style="width: 100%; height: {height};">
|
|
358
|
+
</iframe>
|
|
359
|
+
</div>
|
|
360
|
+
'''
|
|
361
|
+
|
|
362
|
+
if caption:
|
|
363
|
+
return iframe + f'<p class="text-sm text-slate-500 dark:text-slate-400 text-center mt-2">{caption}</p>'
|
|
364
|
+
return iframe
|
|
276
365
|
|
|
277
366
|
def render_footnote_ref(self, token):
|
|
278
367
|
self.fn_counter += 1
|
|
@@ -613,7 +702,7 @@ def from_md(content, img_dir=None, current_path=None):
|
|
|
613
702
|
'table': 'uk-table uk-table-striped uk-table-hover uk-table-divider uk-table-middle my-6'}
|
|
614
703
|
|
|
615
704
|
# Register custom tokens with renderer context manager
|
|
616
|
-
with ContentRenderer(YoutubeEmbed, InlineCodeAttr, Strikethrough, FootnoteRef, Superscript, Subscript, img_dir=img_dir, footnotes=footnotes, current_path=current_path) as renderer:
|
|
705
|
+
with ContentRenderer(YoutubeEmbed, IframeEmbed, InlineCodeAttr, Strikethrough, FootnoteRef, Superscript, Subscript, img_dir=img_dir, footnotes=footnotes, current_path=current_path) as renderer:
|
|
617
706
|
doc = mst.Document(content)
|
|
618
707
|
html = renderer.render(doc)
|
|
619
708
|
|
|
@@ -818,6 +907,41 @@ hdrs = (
|
|
|
818
907
|
height: calc(100vh - 6rem) !important;
|
|
819
908
|
}
|
|
820
909
|
|
|
910
|
+
/* Iframe fullscreen overlay */
|
|
911
|
+
body.iframe-fullscreen-open {
|
|
912
|
+
overflow: hidden;
|
|
913
|
+
}
|
|
914
|
+
.iframe-fullscreen-overlay {
|
|
915
|
+
position: fixed;
|
|
916
|
+
inset: 0;
|
|
917
|
+
z-index: 1000;
|
|
918
|
+
background: rgba(2, 6, 23, 0.85);
|
|
919
|
+
display: flex;
|
|
920
|
+
flex-direction: column;
|
|
921
|
+
}
|
|
922
|
+
.iframe-fullscreen-header {
|
|
923
|
+
display: flex;
|
|
924
|
+
align-items: center;
|
|
925
|
+
justify-content: space-between;
|
|
926
|
+
gap: 1rem;
|
|
927
|
+
padding: 0.75rem 1rem;
|
|
928
|
+
color: #e2e8f0;
|
|
929
|
+
font-size: 0.9rem;
|
|
930
|
+
background: rgba(15, 23, 42, 0.9);
|
|
931
|
+
border-bottom: 1px solid rgba(148, 163, 184, 0.3);
|
|
932
|
+
}
|
|
933
|
+
.iframe-fullscreen-body {
|
|
934
|
+
flex: 1;
|
|
935
|
+
padding: 0.75rem;
|
|
936
|
+
}
|
|
937
|
+
.iframe-fullscreen-frame {
|
|
938
|
+
width: 100%;
|
|
939
|
+
height: 100%;
|
|
940
|
+
border: 0;
|
|
941
|
+
border-radius: 0.5rem;
|
|
942
|
+
background: #0f172a;
|
|
943
|
+
}
|
|
944
|
+
|
|
821
945
|
.layout-fluid {
|
|
822
946
|
--layout-breakpoint: 1280px;
|
|
823
947
|
--layout-blend: 240px;
|
|
@@ -1174,6 +1174,86 @@ function initPdfFocusToggle() {
|
|
|
1174
1174
|
});
|
|
1175
1175
|
}
|
|
1176
1176
|
|
|
1177
|
+
function openIframeFullscreen(button) {
|
|
1178
|
+
const src = button.getAttribute('data-iframe-src');
|
|
1179
|
+
const title = button.getAttribute('data-iframe-title') || 'Embedded content';
|
|
1180
|
+
const allow = button.getAttribute('data-iframe-allow') || '';
|
|
1181
|
+
const allowfullscreen = button.getAttribute('data-iframe-allowfullscreen') === 'true';
|
|
1182
|
+
|
|
1183
|
+
let overlay = document.querySelector('.iframe-fullscreen-overlay');
|
|
1184
|
+
if (!overlay) {
|
|
1185
|
+
overlay = document.createElement('div');
|
|
1186
|
+
overlay.className = 'iframe-fullscreen-overlay';
|
|
1187
|
+
overlay.innerHTML = `
|
|
1188
|
+
<div class="iframe-fullscreen-header">
|
|
1189
|
+
<div class="iframe-fullscreen-title"></div>
|
|
1190
|
+
<button type="button" class="iframe-fullscreen-close px-2 py-1 text-xs border rounded hover:bg-slate-700">
|
|
1191
|
+
Close
|
|
1192
|
+
</button>
|
|
1193
|
+
</div>
|
|
1194
|
+
<div class="iframe-fullscreen-body">
|
|
1195
|
+
<iframe class="iframe-fullscreen-frame" frameborder="0"></iframe>
|
|
1196
|
+
</div>
|
|
1197
|
+
`;
|
|
1198
|
+
document.body.appendChild(overlay);
|
|
1199
|
+
|
|
1200
|
+
overlay.addEventListener('click', (event) => {
|
|
1201
|
+
if (event.target.classList.contains('iframe-fullscreen-overlay')) {
|
|
1202
|
+
closeIframeFullscreen();
|
|
1203
|
+
}
|
|
1204
|
+
});
|
|
1205
|
+
|
|
1206
|
+
overlay.querySelector('.iframe-fullscreen-close').addEventListener('click', () => {
|
|
1207
|
+
closeIframeFullscreen();
|
|
1208
|
+
});
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
overlay.querySelector('.iframe-fullscreen-title').textContent = title;
|
|
1212
|
+
const frame = overlay.querySelector('.iframe-fullscreen-frame');
|
|
1213
|
+
frame.setAttribute('src', src);
|
|
1214
|
+
frame.setAttribute('title', title);
|
|
1215
|
+
frame.setAttribute('allow', allow);
|
|
1216
|
+
if (allowfullscreen) {
|
|
1217
|
+
frame.setAttribute('allowfullscreen', '');
|
|
1218
|
+
} else {
|
|
1219
|
+
frame.removeAttribute('allowfullscreen');
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
document.body.classList.add('iframe-fullscreen-open');
|
|
1223
|
+
overlay.style.display = 'flex';
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
function closeIframeFullscreen() {
|
|
1227
|
+
const overlay = document.querySelector('.iframe-fullscreen-overlay');
|
|
1228
|
+
if (!overlay) {
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
const frame = overlay.querySelector('.iframe-fullscreen-frame');
|
|
1232
|
+
if (frame) {
|
|
1233
|
+
frame.setAttribute('src', 'about:blank');
|
|
1234
|
+
}
|
|
1235
|
+
overlay.style.display = 'none';
|
|
1236
|
+
document.body.classList.remove('iframe-fullscreen-open');
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
function initIframeFullscreenToggle() {
|
|
1240
|
+
document.addEventListener('click', (event) => {
|
|
1241
|
+
const button = event.target.closest('[data-iframe-fullscreen-toggle]');
|
|
1242
|
+
if (!button) {
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
event.preventDefault();
|
|
1246
|
+
openIframeFullscreen(button);
|
|
1247
|
+
});
|
|
1248
|
+
|
|
1249
|
+
document.addEventListener('keydown', (event) => {
|
|
1250
|
+
if (event.key !== 'Escape') {
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
closeIframeFullscreen();
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1177
1257
|
// Initialize on page load
|
|
1178
1258
|
document.addEventListener('DOMContentLoaded', () => {
|
|
1179
1259
|
updateActivePostLink();
|
|
@@ -1183,6 +1263,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
1183
1263
|
initFolderChevronState();
|
|
1184
1264
|
initKeyboardShortcuts();
|
|
1185
1265
|
initPdfFocusToggle();
|
|
1266
|
+
initIframeFullscreenToggle();
|
|
1186
1267
|
initSearchPlaceholderCycle(document);
|
|
1187
1268
|
initPostsSearchPersistence(document);
|
|
1188
1269
|
initCodeBlockCopyButtons(document);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|