pi-studio 0.5.31 → 0.5.32
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/CHANGELOG.md +13 -0
- package/README.md +1 -1
- package/client/studio-client.js +207 -1
- package/client/studio.css +158 -0
- package/index.ts +876 -51
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to `pi-studio` are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.5.32] — 2026-03-25
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- `/studio-pdf <path>` now accepts a curated set of advanced layout controls for file-based exports, including font size, margins, line stretch, main font, paper size, geometry, heading sizes, heading spacing, and footer skip.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Large-font Markdown/QMD Studio PDF exports now switch to a more suitable LaTeX document class and use a safer default footer skip unless you explicitly override the geometry.
|
|
14
|
+
- PDF callout blocks now render more compactly, reducing extra vertical whitespace around note/tip/warning content.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- Studio preview/PDF preparation now treats `.qmd` files like Markdown, strips HTML comments more narrowly, shows standalone LaTeX page-break commands as subtle preview dividers, and supports common Quarto-style callout and `fig-align` patterns in preview/PDF output.
|
|
18
|
+
- Markdown/QMD preview now renders embedded local PDF figures more reliably via `pdf.js`, avoiding grey-box browser embed failures in the Studio preview surface.
|
|
19
|
+
|
|
7
20
|
## [0.5.31] — 2026-03-24
|
|
8
21
|
|
|
9
22
|
### Fixed
|
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ Extension for [pi](https://pi.dev) that opens a local two-pane browser workspace
|
|
|
43
43
|
| `/studio --stop` | Stop studio server |
|
|
44
44
|
| `/studio --help` | Show help |
|
|
45
45
|
| `/studio-current <path>` | Load a file into currently open Studio tab(s) without opening a new browser window |
|
|
46
|
-
| `/studio-pdf <path
|
|
46
|
+
| `/studio-pdf <path> [options]` | Export a local file to `<name>.studio.pdf` via the Studio PDF pipeline, with optional layout controls |
|
|
47
47
|
|
|
48
48
|
## Install
|
|
49
49
|
|
package/client/studio-client.js
CHANGED
|
@@ -188,7 +188,7 @@
|
|
|
188
188
|
const EDITOR_LANGUAGE_STORAGE_KEY = "piStudio.editorLanguage";
|
|
189
189
|
// Single source of truth: language -> file extensions (and display label)
|
|
190
190
|
var LANG_EXT_MAP = {
|
|
191
|
-
markdown: { label: "Markdown", exts: ["md", "markdown", "mdx"] },
|
|
191
|
+
markdown: { label: "Markdown", exts: ["md", "markdown", "mdx", "qmd"] },
|
|
192
192
|
javascript: { label: "JavaScript", exts: ["js", "mjs", "cjs", "jsx"] },
|
|
193
193
|
typescript: { label: "TypeScript", exts: ["ts", "mts", "cts", "tsx"] },
|
|
194
194
|
python: { label: "Python", exts: ["py", "pyw"] },
|
|
@@ -245,6 +245,8 @@
|
|
|
245
245
|
const EMPTY_OVERLAY_LINE = "\u200b";
|
|
246
246
|
const MERMAID_CDN_URL = "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs";
|
|
247
247
|
const MATHJAX_CDN_URL = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js";
|
|
248
|
+
const PDFJS_CDN_URL = "https://cdn.jsdelivr.net/npm/pdfjs-dist@4.10.38/legacy/build/pdf.min.mjs";
|
|
249
|
+
const PDFJS_WORKER_CDN_URL = "https://cdn.jsdelivr.net/npm/pdfjs-dist@4.10.38/legacy/build/pdf.worker.min.mjs";
|
|
248
250
|
const BOOT = (typeof window.__PI_STUDIO_BOOT__ === "object" && window.__PI_STUDIO_BOOT__)
|
|
249
251
|
? window.__PI_STUDIO_BOOT__
|
|
250
252
|
: {};
|
|
@@ -255,9 +257,12 @@
|
|
|
255
257
|
const MERMAID_RENDER_FAIL_MESSAGE = "Mermaid render failed. Showing diagram source text.";
|
|
256
258
|
const MATHJAX_UNAVAILABLE_MESSAGE = "Math fallback unavailable. Some unsupported equations may remain as raw TeX.";
|
|
257
259
|
const MATHJAX_RENDER_FAIL_MESSAGE = "Math fallback could not render some unsupported equations.";
|
|
260
|
+
const PDF_PREVIEW_UNAVAILABLE_MESSAGE = "PDF figure preview unavailable. Inline PDF rendering is not supported in this Studio browser environment.";
|
|
261
|
+
const PDF_PREVIEW_RENDER_FAIL_MESSAGE = "PDF figure preview could not be rendered.";
|
|
258
262
|
let mermaidModulePromise = null;
|
|
259
263
|
let mermaidInitialized = false;
|
|
260
264
|
let mathJaxPromise = null;
|
|
265
|
+
let pdfJsPromise = null;
|
|
261
266
|
|
|
262
267
|
const DEBUG_ENABLED = (() => {
|
|
263
268
|
try {
|
|
@@ -1248,11 +1253,210 @@
|
|
|
1248
1253
|
mathMl: true,
|
|
1249
1254
|
svg: true,
|
|
1250
1255
|
},
|
|
1256
|
+
ADD_TAGS: ["embed"],
|
|
1257
|
+
ADD_ATTR: ["src", "type", "title", "width", "height", "style", "data-fig-align"],
|
|
1258
|
+
ADD_DATA_URI_TAGS: ["embed"],
|
|
1251
1259
|
});
|
|
1252
1260
|
}
|
|
1253
1261
|
return buildPreviewErrorHtml("Preview sanitizer unavailable. Showing plain markdown.", markdown);
|
|
1254
1262
|
}
|
|
1255
1263
|
|
|
1264
|
+
function isPdfPreviewSource(src) {
|
|
1265
|
+
return Boolean(src) && (/^data:application\/pdf(?:;|,)/i.test(src) || /\.pdf(?:$|[?#])/i.test(src));
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
function decoratePdfEmbeds(targetEl) {
|
|
1269
|
+
if (!targetEl || typeof targetEl.querySelectorAll !== "function") {
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
const embeds = targetEl.querySelectorAll("embed[src]");
|
|
1274
|
+
embeds.forEach(function(embedEl) {
|
|
1275
|
+
const src = typeof embedEl.getAttribute === "function" ? (embedEl.getAttribute("src") || "") : "";
|
|
1276
|
+
if (!isPdfPreviewSource(src)) {
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
if (!embedEl.getAttribute("type")) {
|
|
1280
|
+
embedEl.setAttribute("type", "application/pdf");
|
|
1281
|
+
}
|
|
1282
|
+
if (!embedEl.getAttribute("title")) {
|
|
1283
|
+
embedEl.setAttribute("title", "Embedded PDF figure");
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
function decodePdfDataUri(src) {
|
|
1289
|
+
const match = String(src || "").match(/^data:application\/pdf(?:;[^,]*)?,([A-Za-z0-9+/=\s]+)$/i);
|
|
1290
|
+
if (!match) return null;
|
|
1291
|
+
const payload = (match[1] || "").replace(/\s+/g, "");
|
|
1292
|
+
if (!payload) return null;
|
|
1293
|
+
const binary = window.atob(payload);
|
|
1294
|
+
const bytes = new Uint8Array(binary.length);
|
|
1295
|
+
for (let i = 0; i < binary.length; i += 1) {
|
|
1296
|
+
bytes[i] = binary.charCodeAt(i);
|
|
1297
|
+
}
|
|
1298
|
+
return bytes;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
function ensurePdfJs() {
|
|
1302
|
+
if (window.pdfjsLib && typeof window.pdfjsLib.getDocument === "function") {
|
|
1303
|
+
return Promise.resolve(window.pdfjsLib);
|
|
1304
|
+
}
|
|
1305
|
+
if (pdfJsPromise) {
|
|
1306
|
+
return pdfJsPromise;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
pdfJsPromise = import(PDFJS_CDN_URL)
|
|
1310
|
+
.then((module) => {
|
|
1311
|
+
const api = module && typeof module.getDocument === "function"
|
|
1312
|
+
? module
|
|
1313
|
+
: (module && module.default && typeof module.default.getDocument === "function" ? module.default : null);
|
|
1314
|
+
if (!api || typeof api.getDocument !== "function") {
|
|
1315
|
+
throw new Error("pdf.js did not initialize.");
|
|
1316
|
+
}
|
|
1317
|
+
if (api.GlobalWorkerOptions && !api.GlobalWorkerOptions.workerSrc) {
|
|
1318
|
+
api.GlobalWorkerOptions.workerSrc = PDFJS_WORKER_CDN_URL;
|
|
1319
|
+
}
|
|
1320
|
+
window.pdfjsLib = api;
|
|
1321
|
+
return api;
|
|
1322
|
+
})
|
|
1323
|
+
.catch((error) => {
|
|
1324
|
+
pdfJsPromise = null;
|
|
1325
|
+
throw error;
|
|
1326
|
+
});
|
|
1327
|
+
|
|
1328
|
+
return pdfJsPromise;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
function appendPdfPreviewNotice(targetEl, message) {
|
|
1332
|
+
if (!targetEl || typeof targetEl.querySelector !== "function" || typeof targetEl.appendChild !== "function") {
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1335
|
+
if (targetEl.querySelector(".preview-pdf-warning")) {
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
const warningEl = document.createElement("div");
|
|
1339
|
+
warningEl.className = "preview-warning preview-pdf-warning";
|
|
1340
|
+
warningEl.textContent = String(message || PDF_PREVIEW_UNAVAILABLE_MESSAGE);
|
|
1341
|
+
targetEl.appendChild(warningEl);
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
async function loadPdfDocumentSource(src) {
|
|
1345
|
+
const embedded = decodePdfDataUri(src);
|
|
1346
|
+
if (embedded) {
|
|
1347
|
+
return { data: embedded };
|
|
1348
|
+
}
|
|
1349
|
+
const response = await fetch(src);
|
|
1350
|
+
if (!response.ok) {
|
|
1351
|
+
throw new Error("Failed to fetch PDF figure for preview.");
|
|
1352
|
+
}
|
|
1353
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
1354
|
+
return { data: bytes };
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
async function renderSinglePdfPreviewEmbed(embedEl, pdfjsLib) {
|
|
1358
|
+
if (!embedEl || embedEl.dataset.studioPdfPreviewRendered === "1") {
|
|
1359
|
+
return false;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
const src = embedEl.getAttribute("src") || "";
|
|
1363
|
+
if (!isPdfPreviewSource(src)) {
|
|
1364
|
+
return false;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
const measuredWidth = Math.max(1, Math.round(embedEl.getBoundingClientRect().width || 0));
|
|
1368
|
+
const styleText = embedEl.getAttribute("style") || "";
|
|
1369
|
+
const widthAttr = embedEl.getAttribute("width") || "";
|
|
1370
|
+
const figAlign = embedEl.getAttribute("data-fig-align") || "";
|
|
1371
|
+
const pdfSource = await loadPdfDocumentSource(src);
|
|
1372
|
+
const loadingTask = pdfjsLib.getDocument(pdfSource);
|
|
1373
|
+
const pdfDocument = await loadingTask.promise;
|
|
1374
|
+
|
|
1375
|
+
try {
|
|
1376
|
+
const page = await pdfDocument.getPage(1);
|
|
1377
|
+
const baseViewport = page.getViewport({ scale: 1 });
|
|
1378
|
+
const cssWidth = Math.max(1, measuredWidth || Math.round(baseViewport.width));
|
|
1379
|
+
const renderScale = Math.max(0.25, cssWidth / baseViewport.width) * Math.min(window.devicePixelRatio || 1, 2);
|
|
1380
|
+
const viewport = page.getViewport({ scale: renderScale });
|
|
1381
|
+
const canvas = document.createElement("canvas");
|
|
1382
|
+
const context = canvas.getContext("2d", { alpha: false });
|
|
1383
|
+
if (!context) {
|
|
1384
|
+
throw new Error("Canvas 2D context unavailable.");
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
canvas.width = Math.max(1, Math.ceil(viewport.width));
|
|
1388
|
+
canvas.height = Math.max(1, Math.ceil(viewport.height));
|
|
1389
|
+
canvas.style.width = "100%";
|
|
1390
|
+
canvas.style.height = "auto";
|
|
1391
|
+
canvas.setAttribute("aria-label", "PDF figure preview");
|
|
1392
|
+
|
|
1393
|
+
await page.render({
|
|
1394
|
+
canvasContext: context,
|
|
1395
|
+
viewport,
|
|
1396
|
+
}).promise;
|
|
1397
|
+
|
|
1398
|
+
const wrapper = document.createElement("div");
|
|
1399
|
+
wrapper.className = "studio-pdf-preview";
|
|
1400
|
+
if (styleText) {
|
|
1401
|
+
wrapper.style.cssText = styleText;
|
|
1402
|
+
} else if (widthAttr) {
|
|
1403
|
+
wrapper.style.width = /^\d+(?:\.\d+)?$/.test(widthAttr) ? (widthAttr + "px") : widthAttr;
|
|
1404
|
+
} else {
|
|
1405
|
+
wrapper.style.width = "100%";
|
|
1406
|
+
}
|
|
1407
|
+
if (figAlign) {
|
|
1408
|
+
wrapper.setAttribute("data-fig-align", figAlign);
|
|
1409
|
+
}
|
|
1410
|
+
wrapper.title = "PDF figure preview (page 1)";
|
|
1411
|
+
wrapper.appendChild(canvas);
|
|
1412
|
+
embedEl.dataset.studioPdfPreviewRendered = "1";
|
|
1413
|
+
embedEl.replaceWith(wrapper);
|
|
1414
|
+
return true;
|
|
1415
|
+
} finally {
|
|
1416
|
+
if (typeof pdfDocument.cleanup === "function") {
|
|
1417
|
+
try { pdfDocument.cleanup(); } catch {}
|
|
1418
|
+
}
|
|
1419
|
+
if (typeof pdfDocument.destroy === "function") {
|
|
1420
|
+
try { await pdfDocument.destroy(); } catch {}
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
async function renderPdfPreviewsInElement(targetEl) {
|
|
1426
|
+
if (!targetEl || typeof targetEl.querySelectorAll !== "function") {
|
|
1427
|
+
return;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
const embeds = Array.from(targetEl.querySelectorAll("embed[src]"))
|
|
1431
|
+
.filter((embedEl) => isPdfPreviewSource(embedEl.getAttribute("src") || ""));
|
|
1432
|
+
if (embeds.length === 0) {
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
let pdfjsLib;
|
|
1437
|
+
try {
|
|
1438
|
+
pdfjsLib = await ensurePdfJs();
|
|
1439
|
+
} catch (error) {
|
|
1440
|
+
console.error("pdf.js load failed:", error);
|
|
1441
|
+
appendPdfPreviewNotice(targetEl, PDF_PREVIEW_UNAVAILABLE_MESSAGE);
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
let hadFailure = false;
|
|
1446
|
+
for (const embedEl of embeds) {
|
|
1447
|
+
try {
|
|
1448
|
+
await renderSinglePdfPreviewEmbed(embedEl, pdfjsLib);
|
|
1449
|
+
} catch (error) {
|
|
1450
|
+
hadFailure = true;
|
|
1451
|
+
console.error("PDF preview render failed:", error);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
if (hadFailure) {
|
|
1456
|
+
appendPdfPreviewNotice(targetEl, PDF_PREVIEW_RENDER_FAIL_MESSAGE);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1256
1460
|
function appendMathFallbackNotice(targetEl, message) {
|
|
1257
1461
|
if (!targetEl || typeof targetEl.querySelector !== "function" || typeof targetEl.appendChild !== "function") {
|
|
1258
1462
|
return;
|
|
@@ -1901,6 +2105,8 @@
|
|
|
1901
2105
|
|
|
1902
2106
|
finishPreviewRender(targetEl);
|
|
1903
2107
|
targetEl.innerHTML = sanitizeRenderedHtml(renderedHtml, markdown);
|
|
2108
|
+
decoratePdfEmbeds(targetEl);
|
|
2109
|
+
await renderPdfPreviewsInElement(targetEl);
|
|
1904
2110
|
const annotationMode = (pane === "source" || pane === "response")
|
|
1905
2111
|
? (annotationsEnabled ? "highlight" : "hide")
|
|
1906
2112
|
: "none";
|
package/client/studio.css
CHANGED
|
@@ -633,6 +633,91 @@
|
|
|
633
633
|
color: var(--md-quote);
|
|
634
634
|
}
|
|
635
635
|
|
|
636
|
+
.rendered-markdown .callout-note,
|
|
637
|
+
.rendered-markdown .callout-tip,
|
|
638
|
+
.rendered-markdown .callout-warning,
|
|
639
|
+
.rendered-markdown .callout-important,
|
|
640
|
+
.rendered-markdown .callout-caution {
|
|
641
|
+
margin: 1.15em 0;
|
|
642
|
+
padding: 0.8em 1rem 0.95em;
|
|
643
|
+
border: 1px solid var(--border-muted);
|
|
644
|
+
border-left-width: 4px;
|
|
645
|
+
border-radius: 10px;
|
|
646
|
+
background: var(--panel-2);
|
|
647
|
+
color: inherit;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
.rendered-markdown .callout-note::before,
|
|
651
|
+
.rendered-markdown .callout-tip::before,
|
|
652
|
+
.rendered-markdown .callout-warning::before,
|
|
653
|
+
.rendered-markdown .callout-important::before,
|
|
654
|
+
.rendered-markdown .callout-caution::before {
|
|
655
|
+
display: inline-block;
|
|
656
|
+
margin-bottom: 0.45rem;
|
|
657
|
+
font-size: 0.76em;
|
|
658
|
+
font-weight: 700;
|
|
659
|
+
letter-spacing: 0.08em;
|
|
660
|
+
text-transform: uppercase;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
.rendered-markdown .callout-note::before {
|
|
664
|
+
content: "Note";
|
|
665
|
+
color: var(--accent);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
.rendered-markdown .callout-tip::before {
|
|
669
|
+
content: "Tip";
|
|
670
|
+
color: var(--ok);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
.rendered-markdown .callout-warning::before {
|
|
674
|
+
content: "Warning";
|
|
675
|
+
color: var(--warn);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
.rendered-markdown .callout-important::before {
|
|
679
|
+
content: "Important";
|
|
680
|
+
color: var(--error);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
.rendered-markdown .callout-caution::before {
|
|
684
|
+
content: "Caution";
|
|
685
|
+
color: var(--error);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
.rendered-markdown .callout-note {
|
|
689
|
+
border-left-color: var(--accent);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
.rendered-markdown .callout-tip {
|
|
693
|
+
border-left-color: var(--ok);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
.rendered-markdown .callout-warning {
|
|
697
|
+
border-left-color: var(--warn);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
.rendered-markdown .callout-important,
|
|
701
|
+
.rendered-markdown .callout-caution {
|
|
702
|
+
border-left-color: var(--error);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
.rendered-markdown .callout-note > :first-child,
|
|
706
|
+
.rendered-markdown .callout-tip > :first-child,
|
|
707
|
+
.rendered-markdown .callout-warning > :first-child,
|
|
708
|
+
.rendered-markdown .callout-important > :first-child,
|
|
709
|
+
.rendered-markdown .callout-caution > :first-child {
|
|
710
|
+
margin-top: 0;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
.rendered-markdown .callout-note > :last-child,
|
|
714
|
+
.rendered-markdown .callout-tip > :last-child,
|
|
715
|
+
.rendered-markdown .callout-warning > :last-child,
|
|
716
|
+
.rendered-markdown .callout-important > :last-child,
|
|
717
|
+
.rendered-markdown .callout-caution > :last-child {
|
|
718
|
+
margin-bottom: 0;
|
|
719
|
+
}
|
|
720
|
+
|
|
636
721
|
.rendered-markdown pre {
|
|
637
722
|
background: var(--panel-2);
|
|
638
723
|
border: 1px solid var(--md-codeblock-border);
|
|
@@ -765,10 +850,83 @@
|
|
|
765
850
|
margin: 1.25em 0;
|
|
766
851
|
}
|
|
767
852
|
|
|
853
|
+
.rendered-markdown .studio-page-break {
|
|
854
|
+
display: flex;
|
|
855
|
+
align-items: center;
|
|
856
|
+
gap: 0.85rem;
|
|
857
|
+
margin: 1.75em 0;
|
|
858
|
+
color: var(--muted);
|
|
859
|
+
font-size: 0.88em;
|
|
860
|
+
text-transform: uppercase;
|
|
861
|
+
letter-spacing: 0.08em;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
.rendered-markdown .studio-page-break-rule {
|
|
865
|
+
flex: 1 1 auto;
|
|
866
|
+
height: 1px;
|
|
867
|
+
background: var(--md-hr);
|
|
868
|
+
opacity: 0.95;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
.rendered-markdown .studio-page-break-label {
|
|
872
|
+
flex: 0 0 auto;
|
|
873
|
+
white-space: nowrap;
|
|
874
|
+
}
|
|
875
|
+
|
|
768
876
|
.rendered-markdown img {
|
|
769
877
|
max-width: 100%;
|
|
770
878
|
}
|
|
771
879
|
|
|
880
|
+
.rendered-markdown img[data-fig-align="center"],
|
|
881
|
+
.rendered-markdown embed[data-fig-align="center"],
|
|
882
|
+
.rendered-markdown .studio-pdf-preview[data-fig-align="center"] {
|
|
883
|
+
display: block;
|
|
884
|
+
margin-left: auto;
|
|
885
|
+
margin-right: auto;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
.rendered-markdown img[data-fig-align="right"],
|
|
889
|
+
.rendered-markdown embed[data-fig-align="right"],
|
|
890
|
+
.rendered-markdown .studio-pdf-preview[data-fig-align="right"] {
|
|
891
|
+
display: block;
|
|
892
|
+
margin-left: auto;
|
|
893
|
+
margin-right: 0;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
.rendered-markdown embed[type="application/pdf"],
|
|
897
|
+
.rendered-markdown embed[src^="data:application/pdf"],
|
|
898
|
+
.rendered-markdown embed[src$=".pdf"] {
|
|
899
|
+
display: block;
|
|
900
|
+
width: 100%;
|
|
901
|
+
min-height: 18rem;
|
|
902
|
+
border: 1px solid var(--md-table-border);
|
|
903
|
+
border-radius: 10px;
|
|
904
|
+
background: #fff;
|
|
905
|
+
overflow: hidden;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
.rendered-markdown .studio-pdf-preview {
|
|
909
|
+
display: block;
|
|
910
|
+
max-width: 100%;
|
|
911
|
+
border: 1px solid var(--md-table-border);
|
|
912
|
+
border-radius: 10px;
|
|
913
|
+
background: #fff;
|
|
914
|
+
overflow: hidden;
|
|
915
|
+
line-height: 0;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
.rendered-markdown .studio-pdf-preview[data-fig-align="center"] {
|
|
919
|
+
margin-left: auto;
|
|
920
|
+
margin-right: auto;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
.rendered-markdown .studio-pdf-preview canvas {
|
|
924
|
+
display: block;
|
|
925
|
+
width: 100%;
|
|
926
|
+
height: auto;
|
|
927
|
+
max-width: 100%;
|
|
928
|
+
}
|
|
929
|
+
|
|
772
930
|
.rendered-markdown .studio-subfigure-group {
|
|
773
931
|
margin: 1.25em auto;
|
|
774
932
|
}
|