Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions docs/dist/v1/chartifact-toolbar.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,25 @@

/* Base styles for the toolbar */
.chartifact-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.5em 1em;
font-weight: bold;
font-family: sans-serif;
}

.chartifact-toolbar a {
text-decoration: none;
color: inherit;
}

.chartifact-toolbar button, .chartifact-toolbar select {
font-size: 9pt;
}

/* Remove margin from all toolbar divs by default */
.chartifact-toolbar > div {
display: inline-block;
}

/* Default (OS light theme) */
Expand All @@ -37,7 +54,7 @@
/* OS dark theme fallback */
@media (prefers-color-scheme: dark) {
.chartifact-toolbar {
background-color: #1e1e1e;
background-color: #2e2e2e;
color: #ffffff;
border-bottom-color: rgba(255, 255, 255, 0.1);
}
Expand Down
111 changes: 85 additions & 26 deletions docs/dist/v1/chartifact.host.umd.js
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ ${guardedJs}
return;
}
let docIndex = 0;
const folderSpan = host.toolbar.toolbarElement.querySelector("#folderSpan");
const { folderSpan } = host.toolbar;
folderSpan.style.display = "";
folderSpan.innerText = `Folder: ${folder.title} (${folder.docs.length} documents)`;
const prevBtn = document.createElement("button");
Expand Down Expand Up @@ -941,7 +941,8 @@ ${guardedJs}
prevBtn.disabled = docIndex === 0;
nextBtn.disabled = docIndex === folder.docs.length - 1;
pageSelect.value = (docIndex + 1).toString();
resolveUrl(folderUrl, folder.docs[docIndex].href, host);
const title = folder.docs[docIndex].title || `Page ${docIndex + 1}`;
resolveUrl(title, folderUrl, folder.docs[docIndex].href, host);
}
pageSelect.onchange = () => {
const selectedPage = parseInt(pageSelect.value, 10);
Expand Down Expand Up @@ -979,7 +980,7 @@ ${guardedJs}
folderSpan.appendChild(pageSelect);
folderSpan.appendChild(nextBtn);
}
async function resolveUrl(base, relativeOrAbsolute, host) {
async function resolveUrl(title, base, relativeOrAbsolute, host) {
let url;
try {
url = base ? new URL(relativeOrAbsolute, base).href : relativeOrAbsolute;
Expand All @@ -999,19 +1000,19 @@ ${guardedJs}
return;
}
if (result.idoc) {
host.render(void 0, result.idoc);
host.render(title, void 0, result.idoc);
} else if (result.markdown) {
host.render(result.markdown, void 0);
host.render(title, result.markdown, void 0);
} else if (result.folder) {
host.render("Nested folders are not supported", void 0);
host.render("Error", "Nested folders are not supported", void 0);
} else {
host.errorHandler(
"Invalid document format",
"The document could not be loaded from the folder."
);
}
}
function determineContent(url, content, host, handle) {
function determineContent(urlOrTitle, content, host, handle) {
const result = _determineContent(content);
if (handle) {
if (result.error) {
Expand All @@ -1021,16 +1022,16 @@ ${guardedJs}
);
return;
} else if (result.idoc) {
host.render(void 0, result.idoc);
host.render(urlOrTitle, void 0, result.idoc);
} else if (result.folder) {
loadFolder(url, result.folder, host);
loadFolder(urlOrTitle, result.folder, host);
} else if (result.markdown) {
host.render(result.markdown, void 0);
host.render(urlOrTitle, result.markdown, void 0);
}
}
return result;
}
function _determineContent(content, host) {
function _determineContent(content) {
if (!content) {
return {
error: "Content is empty",
Expand Down Expand Up @@ -1107,7 +1108,7 @@ ${guardedJs}
);
return;
}
determineContent(null, content, host, true);
determineContent(file.name, content, host, true);
};
reader.onerror = (e) => {
host.errorHandler(
Expand Down Expand Up @@ -1152,7 +1153,7 @@ ${guardedJs}
);
return;
}
determineContent(null, content, host, true);
determineContent("clipboard-content", content, host, true);
});
handled = true;
break;
Expand Down Expand Up @@ -1206,7 +1207,7 @@ ${guardedJs}
);
return;
}
determineContent(null, content, host, true);
determineContent("dropped-content", content, host, true);
} else {
host.errorHandler(
"Unsupported drop content",
Expand Down Expand Up @@ -1259,9 +1260,9 @@ ${guardedJs}
const message = event.data;
if (message.type == "hostRenderRequest") {
if (message.markdown) {
host.render(message.markdown, void 0);
host.render(message.title, message.markdown, void 0);
} else if (message.interactiveDocument) {
host.render(void 0, message.interactiveDocument);
host.render(message.title, void 0, message.interactiveDocument);
} else {
}
}
Expand Down Expand Up @@ -1394,7 +1395,7 @@ ${guardedJs}
${message}

${details}`;
this.render(markdown, void 0);
this.render("Error", markdown, void 0);
} else {
this.previewDiv.innerHTML = "";
const h1 = document.createElement("h1");
Expand All @@ -1408,7 +1409,10 @@ ${details}`;
this.previewDiv.appendChild(pDetails);
}
}
render(markdown, interactiveDocument) {
render(title, markdown, interactiveDocument) {
if (this.toolbar) {
this.toolbar.filename = title;
}
if (interactiveDocument) {
this.onSetMode("json", null, interactiveDocument);
this.renderInteractiveDocument(interactiveDocument);
Expand Down Expand Up @@ -1461,26 +1465,69 @@ ${details}`;
constructor(toolbarElementOrSelector, options = {}) {
__publicField(this, "options");
__publicField(this, "toolbarElement");
__publicField(this, "folderSpan");
__publicField(this, "tweakButton");
__publicField(this, "downloadButton");
__publicField(this, "mode");
__publicField(this, "filename");
var _a, _b;
this.options = options;
this.filename = options.filename || "sample";
this.mode = options.mode || "markdown";
this.toolbarElement = typeof toolbarElementOrSelector === "string" ? document.querySelector(toolbarElementOrSelector) : toolbarElementOrSelector;
if (!this.toolbarElement) {
throw new Error("Toolbar element not found");
}
const html = `<a href="https://microsoft.github.io/chartifact" target="_blank">Chartifact</a> viewer
<button type="button" id="tweak" style="display: none;">tweak</button>
<span id="folderSpan" style="display: none;"></span>
const html = `
<div>
<a href="https://microsoft.github.io/chartifact" target="_blank">Chartifact</a> viewer
</div>
<div id="folderSpan" style="display: none;"></div>
<div>
<button type="button" id="tweak" style="display: none;">tweak</button>
<button type="button" id="download" style="display: none;">download</button>
</div>
`;
this.toolbarElement.innerHTML = html;
this.tweakButton = this.toolbarElement.querySelector("#tweak");
this.folderSpan = this.toolbarElement.querySelector("#folderSpan");
this.downloadButton = this.toolbarElement.querySelector("#download");
if (this.options.tweakButton) {
this.showTweakButton();
}
}
showTweakButton() {
const tweakButton = this.toolbarElement.querySelector("#tweak");
tweakButton.style.display = "";
tweakButton == null ? void 0 : tweakButton.addEventListener("click", () => {
if (this.options.downloadButton) {
this.showDownloadButton();
}
(_a = this.tweakButton) == null ? void 0 : _a.addEventListener("click", () => {
this.options.textarea.style.display = this.options.textarea.style.display === "none" ? "" : "none";
});
(_b = this.downloadButton) == null ? void 0 : _b.addEventListener("click", () => {
const textarea = this.options.textarea;
if (!textarea)
return;
const content = textarea.value;
const ext = this.mode === "markdown" ? "idoc.md" : "idoc.json";
const filename = `${filenameWithoutPathOrExtension(this.filename)}.${ext}`;
const blob = new Blob([content], {
type: this.mode === "markdown" ? "text/markdown" : "application/json"
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
}, 0);
});
}
showTweakButton() {
this.tweakButton.style.display = "";
}
showDownloadButton() {
this.downloadButton.style.display = "";
}
manageTextareaVisibilityForAgents() {
const { textarea } = this.options;
Expand All @@ -1498,6 +1545,18 @@ ${details}`;
}, 300);
}
}
function filenameWithoutPathOrExtension(filename) {
const base = filename.split(/[\\/]/).pop() || filename;
const idocIdx = base.indexOf(".idoc");
if (idocIdx !== -1) {
return base.substring(0, idocIdx);
}
const lastDot = base.lastIndexOf(".");
if (lastDot > 0) {
return base.substring(0, lastDot);
}
return base;
}
function create(toolbarElementOrSelector, options = {}) {
const toolbar = new Toolbar(toolbarElementOrSelector, options);
toolbar.manageTextareaVisibilityForAgents();
Expand Down
2 changes: 1 addition & 1 deletion docs/dist/v1/chartifact.markdown.umd.js
Original file line number Diff line number Diff line change
Expand Up @@ -2202,6 +2202,7 @@ ${reconstitutedRules.join("\n\n")}
}
}
async beginListening() {
this.active = true;
this.log("beginListening", "begin initial batch", this.signalDeps);
for (const peer of this.peers) {
const batch = {};
Expand Down Expand Up @@ -2246,7 +2247,6 @@ ${reconstitutedRules.join("\n\n")}
this.log(peer.id, "No shared signals");
}
}
this.active = true;
}
deactivate() {
if (this.signalDeps) {
Expand Down
71 changes: 63 additions & 8 deletions docs/dist/v1/chartifact.sandbox.umd.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,26 +322,69 @@ document.addEventListener('DOMContentLoaded', () => {
constructor(toolbarElementOrSelector, options = {}) {
__publicField(this, "options");
__publicField(this, "toolbarElement");
__publicField(this, "folderSpan");
__publicField(this, "tweakButton");
__publicField(this, "downloadButton");
__publicField(this, "mode");
__publicField(this, "filename");
var _a, _b;
this.options = options;
this.filename = options.filename || "sample";
this.mode = options.mode || "markdown";
this.toolbarElement = typeof toolbarElementOrSelector === "string" ? document.querySelector(toolbarElementOrSelector) : toolbarElementOrSelector;
if (!this.toolbarElement) {
throw new Error("Toolbar element not found");
}
const html = `<a href="https://microsoft.github.io/chartifact" target="_blank">Chartifact</a> viewer
<button type="button" id="tweak" style="display: none;">tweak</button>
<span id="folderSpan" style="display: none;"></span>
const html = `
<div>
<a href="https://microsoft.github.io/chartifact" target="_blank">Chartifact</a> viewer
</div>
<div id="folderSpan" style="display: none;"></div>
<div>
<button type="button" id="tweak" style="display: none;">tweak</button>
<button type="button" id="download" style="display: none;">download</button>
</div>
`;
this.toolbarElement.innerHTML = html;
this.tweakButton = this.toolbarElement.querySelector("#tweak");
this.folderSpan = this.toolbarElement.querySelector("#folderSpan");
this.downloadButton = this.toolbarElement.querySelector("#download");
if (this.options.tweakButton) {
this.showTweakButton();
}
}
showTweakButton() {
const tweakButton = this.toolbarElement.querySelector("#tweak");
tweakButton.style.display = "";
tweakButton == null ? void 0 : tweakButton.addEventListener("click", () => {
if (this.options.downloadButton) {
this.showDownloadButton();
}
(_a = this.tweakButton) == null ? void 0 : _a.addEventListener("click", () => {
this.options.textarea.style.display = this.options.textarea.style.display === "none" ? "" : "none";
});
(_b = this.downloadButton) == null ? void 0 : _b.addEventListener("click", () => {
const textarea = this.options.textarea;
if (!textarea)
return;
const content = textarea.value;
const ext = this.mode === "markdown" ? "idoc.md" : "idoc.json";
const filename = `${filenameWithoutPathOrExtension(this.filename)}.${ext}`;
const blob = new Blob([content], {
type: this.mode === "markdown" ? "text/markdown" : "application/json"
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
}, 0);
});
}
showTweakButton() {
this.tweakButton.style.display = "";
}
showDownloadButton() {
this.downloadButton.style.display = "";
}
manageTextareaVisibilityForAgents() {
const { textarea } = this.options;
Expand All @@ -359,6 +402,18 @@ document.addEventListener('DOMContentLoaded', () => {
}, 300);
}
}
function filenameWithoutPathOrExtension(filename) {
const base = filename.split(/[\\/]/).pop() || filename;
const idocIdx = base.indexOf(".idoc");
if (idocIdx !== -1) {
return base.substring(0, idocIdx);
}
const lastDot = base.lastIndexOf(".");
if (lastDot > 0) {
return base.substring(0, lastDot);
}
return base;
}
function create(toolbarElementOrSelector, options = {}) {
const toolbar = new Toolbar(toolbarElementOrSelector, options);
toolbar.manageTextareaVisibilityForAgents();
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type SandboxApprovalMessage = {

export interface HostRenderRequestMessage {
type: 'hostRenderRequest';
title: string;
markdown?: string;
interactiveDocument?: InteractiveDocument
}
Expand Down
1 change: 1 addition & 0 deletions packages/host-test/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ window.addEventListener('message', (event) => {
if (hostStatusMessage.type === 'hostStatus' && hostStatusMessage.hostStatus === 'ready') {
const message: Chartifact.common.HostRenderRequestMessage = {
type: 'hostRenderRequest',
title: 'sample',
markdown: `# Auto-loaded Content

This markdown was automatically sent when the iframe became ready.
Expand Down
Loading