Skip to content

Commit

Permalink
Improved UX for embeds #1496
Browse files Browse the repository at this point in the history
  • Loading branch information
miteshashar committed Dec 7, 2022
1 parent f551782 commit 67fb0af
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 62 deletions.
10 changes: 5 additions & 5 deletions funnel/assets/js/utils/initembed.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import MarkmapEmbed from './markmap';
import MermaidEmbed from './mermaid';
import PrismEmbed from './prism';

export default function initEmbed(markdownElem = '') {
export default function initEmbed(parentContainer = '') {
addVegaSupport();
if (markdownElem) TypeformEmbed.init(markdownElem);
MarkmapEmbed.init();
MermaidEmbed.init();
PrismEmbed.init(markdownElem);
if (parentContainer) TypeformEmbed.init(parentContainer);
MarkmapEmbed.init(parentContainer);
MermaidEmbed.init(parentContainer);
PrismEmbed.init(parentContainer);
}
32 changes: 22 additions & 10 deletions funnel/assets/js/utils/markmap.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
const MarkmapEmbed = {
addMarkmap() {
$('.md-embed-markmap').each(function embedMarkmap() {
$(this).find('.embed-content').addClass('markmap');
});
window.markmap.autoLoader.renderAll();
$('.md-embed-markmap').each(function embedMarkmap() {
$(this).addClass('activated');
});
const self = this;
self.container
.find('.md-embed-markmap:not(.activating):not(.activated)')
.each(function embedMarkmap() {
$(this).addClass('activating');
const current = $(this).find('.embed-container');
current
.addClass('markmap')
.append(
`<script type="text/template">${$(this)
.find('.embed-content')
.text()}</script>`
);
window.markmap.autoLoader.renderAllUnder(this);
$(this).addClass('activated').removeClass('activating');
});
},
resizeTimer: null,
resizeMarkmapContainers() {
Expand Down Expand Up @@ -65,9 +74,12 @@ const MarkmapEmbed = {
self.addMarkmap();
}
},
init(containerDiv) {
this.containerDiv = containerDiv;
if ($('.md-embed-markmap:not(.activated)').length > 0) {
init(container) {
this.container = $(container || 'body');
if (
this.container.find('.md-embed-markmap:not(.activated):not(.activated)').length >
0
) {
this.loadMarkmap();
}
},
Expand Down
25 changes: 16 additions & 9 deletions funnel/assets/js/utils/mermaid.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
const MermaidEmbed = {
addMermaid() {
const instances = $('.md-embed-mermaid:not(.activating):not(.activated)');
const self = this;
let idCount = $('.md-embed-mermaid.activating, .md-embed-mermaid.activated').length;
const idMarker = 'mermaid_elem_';
const instances = self.container.find(
'.md-embed-mermaid:not(.activating):not(.activated)'
);
instances.each(function embedMarkmap() {
const root = $(this);
root.addClass('activating');
const elem = root.find('.embed-content');
const definition = elem.text();
let elemId = elem.attr('id');
const contentElem = root.find('.embed-content');
const containerElem = root.find('.embed-container');
const definition = contentElem.text();
let elemId = containerElem.attr('id');
if (!elemId) {
elemId = `${idMarker}${idCount}`;
do {
idCount += 1;
} while ($(`#${idMarker}${idCount}`).length > 0);
}
window.mermaid.render(elemId, definition, (svg) => {
elem.html(svg);
root.addClass('activated');
root.removeClass('activating');
containerElem.html(svg);
root.addClass('activated').removeClass('activating');
});
});
},
Expand All @@ -37,8 +40,12 @@ const MermaidEmbed = {
self.addMermaid();
}
},
init() {
if ($('.md-embed-mermaid:not(.activated)').length > 0) {
init(container) {
this.container = $(container || 'body');
if (
this.container.find('.md-embed-mermaid:not(.activating):not(.activated)').length >
0
) {
this.loadMermaid();
}
},
Expand Down
51 changes: 29 additions & 22 deletions funnel/assets/js/utils/vegaembed.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
/* global vegaEmbed */

function addVegaChart() {
$('.md-embed-vega-lite:not(.activated)').each(async function embedVegaChart() {
const root = $(this);
const embedded = await vegaEmbed(
this,
JSON.parse($(this).find('.embed-content').text()),
{
renderer: 'svg',
actions: {
source: false,
editor: false,
compiled: false,
},
}
);
embedded.view.runAfter(() => {
root.addClass('activated');
function addVegaChart(parentElement) {
parentElement
.find('.md-embed-vega-lite:not(.activating):not(.activated)')
.each(async function embedVegaChart() {
const root = $(this);
root.addClass('activating');
const embedded = await vegaEmbed(
root.find('.embed-container')[0],
JSON.parse(root.find('.embed-content').text()),
{
renderer: 'svg',
actions: {
source: false,
editor: false,
compiled: false,
},
}
);
embedded.view.runAfter(() => {
root.addClass('activated').removeClass('activating');
});
});
});
}

function addVegaSupport() {
if ($('.md-embed-vega-lite:not(.activated)').length > 0) {
function addVegaSupport(container) {
const parentElement = $(container || 'body');
if (
parentElement.find('.md-embed-vega-lite:not(.activating):not(.activated)').length >
0
) {
const vegaliteCDN = [
'https://cdn.jsdelivr.net/npm/vega@5',
'https://cdn.jsdelivr.net/npm/vega-lite@5',
Expand All @@ -42,13 +49,13 @@ function addVegaSupport() {
}
// Once all vega js is loaded, initialize vega visualization on all pre tags with class 'md-embed-vega-lite'
if (vegaliteUrl === vegaliteCDN.length) {
addVegaChart();
addVegaChart(parentElement);
}
});
};
loadVegaScript();
} else {
addVegaChart();
addVegaChart(parentElement);
}
}
}
Expand Down
43 changes: 32 additions & 11 deletions funnel/assets/sass/_layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -861,32 +861,53 @@
}

.md-embed {
visibility: hidden;
border: 1px solid black;
background: linear-gradient(45deg, #bbb, #eee);
canvas,
svg {
width: 100% !important;
max-width: 100% !important;
background-color: transparent !important;
}
.embed-content {
white-space: pre;
display: none;
}
.embed-loading {
padding: 5px 2.5%;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
align-content: center;
}
.embed-container {
display: none;
canvas,
svg {
width: 100% !important;
max-width: 100% !important;
background-color: transparent !important;
}
}
&.activating .embed-container {
visibility: hidden;
display: block;
}
&.activated {
visibility: visible;
.embed-loading {
display: none;
}
.embed-container {
visibility: visible;
display: block;
}
}
&.md-embed-markmap {
margin-bottom: 0px;
.embed-content {
.embed-container {
width: 100%;
aspect-ratio: 4 / 3;
svg {
height: 100%;
}
}
}
&.md-embed-vega-lite.vega-embed {
&.md-embed-vega-lite .vega-embed {
padding: 2.5%;
display: block !important;
svg.marks {
Expand Down
16 changes: 11 additions & 5 deletions funnel/utils/markdown/mdit_plugins/embeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
from markdown_it.common.utils import charCodeAt
from markdown_it.rules_block import StateBlock

LOADING_TEXT = {
'markmap': 'mindmap',
'mermaid': 'visualization',
'vega-lite': 'visualization',
}


def embeds_plugin(
md: MarkdownIt,
Expand All @@ -25,13 +31,13 @@ def validate(params: str, *args):
def render(self, tokens, idx, _options, env):
token = tokens[idx]
content = md.utils.escapeHtml(token.content)

loading = LOADING_TEXT.get(name, '')
return (
'<div'
+ (f' class="md-embed md-embed-{name}" ')
+ '><div class="embed-content">'
f'<div class="md-embed md-embed-{name}">'
+ '<div class="embed-loading">'
+ f'Loading {loading}…</div><div class="embed-content">'
+ content
+ '</div></div>\n'
+ '</div><div class="embed-container"></div></div>\n'
)

min_markers = 3
Expand Down

0 comments on commit 67fb0af

Please sign in to comment.