diff --git a/dist/plugins/iwsy.js b/dist/plugins/iwsy.js
index 636c08a..a725f07 100644
--- a/dist/plugins/iwsy.js
+++ b/dist/plugins/iwsy.js
@@ -1,9 +1,9 @@
const EasyCoder_IWSY = {
- name: `EasyCoder_IWSY`,
+ name: `EasyCoder_IWSY`,
- iwsy: {
- },
+ iwsy: {
+ },
IWSY: {
@@ -12,138 +12,148 @@ const EasyCoder_IWSY = {
const lino = compiler.getLino();
const action = compiler.nextToken();
switch (action) {
- case `load`:
- if (compiler.nextIsSymbol()) {
- const playerRecord = compiler.getSymbolRecord();
- if (playerRecord.keyword === `div`) {
- const script = compiler.getNextValue();
- compiler.addCommand({
- domain: `iwsy`,
- keyword: `iwsy`,
- lino,
- action,
- player: playerRecord.name,
- script
- });
- return true;
- }
- }
- break;
- case `init`:
- case `stop`:
- compiler.next();
- compiler.addCommand({
- domain: `iwsy`,
- keyword: `iwsy`,
- lino,
- action
- });
- return true;
- case `remove`:
- if (compiler.nextTokenIs(`styles`)) {
- compiler.next();
+ case `load`:
+ if (compiler.nextIsSymbol()) {
+ const playerRecord = compiler.getSymbolRecord();
+ if (playerRecord.keyword === `div`) {
+ const script = compiler.getNextValue();
compiler.addCommand({
domain: `iwsy`,
keyword: `iwsy`,
lino,
- action: `removeStyles`
+ action,
+ player: playerRecord.name,
+ script
});
return true;
}
- return false;
- case `path`:
- const path = compiler.getNextValue();
- compiler.addCommand({
- domain: `iwsy`,
- keyword: `iwsy`,
- lino,
- action,
- path
- });
- return true;
- case `script`:
- const script = compiler.getNextValue();
- compiler.addCommand({
- domain: `iwsy`,
- keyword: `iwsy`,
- lino,
- action,
- script
- });
- return true;
- case `goto`:
- const target = compiler.getNextValue();
- compiler.addCommand({
- domain: `iwsy`,
- keyword: `iwsy`,
- lino,
- action,
- target
- });
- return true;
- case `block`:
- const block = compiler.getNextValue();
+ }
+ break;
+ case `init`:
+ case `stop`:
+ compiler.next();
+ compiler.addCommand({
+ domain: `iwsy`,
+ keyword: `iwsy`,
+ lino,
+ action
+ });
+ return true;
+ case `remove`:
+ if (compiler.nextTokenIs(`styles`)) {
+ compiler.next();
compiler.addCommand({
domain: `iwsy`,
keyword: `iwsy`,
lino,
- action,
- block
+ action: `removeStyles`
});
return true;
- case `run`:
- const pc = compiler.getPc();
- let mode = `normal`;
- let startMode = `wait`;
- if (compiler.nextToken() === `fullscreen`) {
- mode = compiler.getToken();
- if ([`auto`, `manual`].includes(compiler.nextToken())) {
- startMode = compiler.getToken();
- compiler.next();
- }
+ }
+ return false;
+ case `path`:
+ const path = compiler.getNextValue();
+ compiler.addCommand({
+ domain: `iwsy`,
+ keyword: `iwsy`,
+ lino,
+ action,
+ path
+ });
+ return true;
+ case `script`:
+ const script = compiler.getNextValue();
+ compiler.addCommand({
+ domain: `iwsy`,
+ keyword: `iwsy`,
+ lino,
+ action,
+ script
+ });
+ return true;
+ case `goto`:
+ const target = compiler.getNextValue();
+ compiler.addCommand({
+ domain: `iwsy`,
+ keyword: `iwsy`,
+ lino,
+ action,
+ target
+ });
+ return true;
+ case `block`:
+ const block = compiler.getNextValue();
+ compiler.addCommand({
+ domain: `iwsy`,
+ keyword: `iwsy`,
+ lino,
+ action,
+ block
+ });
+ return true;
+ case `run`:
+ const pc = compiler.getPc();
+ let mode = `normal`;
+ let startMode = `wait`;
+ if (compiler.nextToken() === `fullscreen`) {
+ mode = compiler.getToken();
+ if ([`auto`, `manual`].includes(compiler.nextToken())) {
+ startMode = compiler.getToken();
+ compiler.next();
}
+ }
+ compiler.addCommand({
+ domain: `iwsy`,
+ keyword: `iwsy`,
+ lino,
+ action,
+ mode,
+ startMode,
+ then: 0
+ });
+ // Get the 'then' code, if any
+ if (compiler.tokenIs(`then`)) {
+ const goto = compiler.getPc();
+ // Add a 'goto' to skip the 'then'
compiler.addCommand({
- domain: `iwsy`,
- keyword: `iwsy`,
- lino,
- action,
- mode,
- startMode,
- then: 0
+ domain: `core`,
+ keyword: `goto`,
+ goto: 0
});
- // Get the 'then' code, if any
- if (compiler.tokenIs(`then`)) {
- const goto = compiler.getPc();
- // Add a 'goto' to skip the 'then'
- compiler.addCommand({
- domain: `core`,
- keyword: `goto`,
- goto: 0
- });
- // Fixup the link to the 'then' branch
- compiler.getCommandAt(pc).then = compiler.getPc();
- // Process the 'then' branch
- compiler.next();
- compiler.compileOne(true);
- compiler.addCommand({
- domain: `core`,
- keyword: `stop`
- });
- // Fixup the 'goto'
- compiler.getCommandAt(goto).goto = compiler.getPc();
- }
- return true;
- case `onstep`:
+ // Fixup the link to the 'then' branch
+ compiler.getCommandAt(pc).then = compiler.getPc();
+ // Process the 'then' branch
compiler.next();
+ compiler.compileOne(true);
compiler.addCommand({
- domain: `iwsy`,
- keyword: `iwsy`,
- lino,
- action
+ domain: `core`,
+ keyword: `stop`
});
- return compiler.completeHandler();
- default:
- break;
+ // Fixup the 'goto'
+ compiler.getCommandAt(goto).goto = compiler.getPc();
+ }
+ return true;
+ case `onstep`:
+ compiler.next();
+ compiler.addCommand({
+ domain: `iwsy`,
+ keyword: `iwsy`,
+ lino,
+ action
+ });
+ return compiler.completeHandler();
+ case `panzoom`:
+ const spec = compiler.getNextValue();
+ compiler.addCommand({
+ domain: `iwsy`,
+ keyword: `iwsy`,
+ lino,
+ action,
+ spec
+ });
+ return true;
+ default:
+ break;
}
return false;
},
@@ -153,83 +163,88 @@ const EasyCoder_IWSY = {
const action = command.action;
let script;
switch (action) {
- case `init`:
- program.require(`js`, `iwsy.js`,
+ case `init`:
+ program.require(`js`, `iwsy.js`,
function () {
program.run(command.pc + 1);
});
+ return 0;
+ case `load`:
+ // if (program.iwsyFunctions) {
+ // throw Error(`IWSY has already been set up`);
+ // }
+ const playerRecord = program.getSymbolRecord(command.player);
+ const player = playerRecord.element[playerRecord.index];
+ player.innerHTML = ``;
+ player.style.background = `none`;
+ player.style.border = `none`;
+ script = program.getValue(command.script);
+ try {
+ script = JSON.parse(script);
+ } catch (err) {
+ alert(`iwsy load: Badly formatted script`);
+ }
+ program.iwsyFunctions = IWSY(player, script);
+ break;
+ case `path`:
+ if (program.iwsyFunctions) {
+ program.iwsyFunctions.setPath(program.getValue(command.path));
+ }
+ break;
+ case `script`:
+ script = program.getValue(command.script);
+ try {
+ script = JSON.parse(script);
+ } catch (err) {
+ alert(`iwsy script: Badly formatted script`);
+ }
+ if (program.iwsyFunctions) {
+ program.iwsyFunctions.setScript(script);
+ }
+ break;
+ case `goto`:
+ if (program.iwsyFunctions) {
+ program.iwsyFunctions.gotoStep(program.getValue(command.target));
+ }
+ break;
+ case `block`:
+ if (program.iwsyFunctions) {
+ program.iwsyFunctions.block(program.getValue(command.block));
+ }
+ break;
+ case `run`:
+ if (program.iwsyFunctions) {
+ program.iwsyFunctions.run(command.mode, command.startMode, () => {
+ program.run(command.then);
+ });
return 0;
- case `load`:
- if (program.iwsyFunctions) {
- throw Error(`IWSY has already been set up`);
- }
- const playerRecord = program.getSymbolRecord(command.player);
- const player = playerRecord.element[playerRecord.index];
- player.innerHTML = ``;
- player.style.background = `none`;
- player.style.border = `none`;
- script = program.getValue(command.script);
- try {
- script = JSON.parse(script);
- } catch (err) {
- alert(`iwsy load: Badly formatted script`);
- }
- program.iwsyFunctions = IWSY(player, script);
- break;
- case `path`:
- if (program.iwsyFunctions) {
- program.iwsyFunctions.setPath(program.getValue(command.path));
- }
- break;
- case `script`:
- script = program.getValue(command.script);
- try {
- script = JSON.parse(script);
- } catch (err) {
- alert(`iwsy script: Badly formatted script`);
- }
- if (program.iwsyFunctions) {
- program.iwsyFunctions.setScript(script);
- }
- break;
- case `goto`:
- if (program.iwsyFunctions) {
- program.iwsyFunctions.gotoStep(program.getValue(command.target));
- }
- break;
- case `block`:
- if (program.iwsyFunctions) {
- program.iwsyFunctions.block(program.getValue(command.block));
- }
- break;
- case `run`:
- if (program.iwsyFunctions) {
- program.iwsyFunctions.run(command.mode, command.startMode, () => {
- program.run(command.then);
- });
- return 0;
- }
- break;
- case `stop`:
- if (program.iwsyFunctions) {
- program.iwsyFunctions.stop();
- delete program.iwsyFunctions;
- }
- break;
- case `removeStyles`:
- if (program.iwsyFunctions) {
- program.iwsyFunctions.removeStyles();
- }
- break;
- case `onstep`:
- const cb = command.pc + 2;
- if (program.iwsyFunctions) {
- program.iwsyFunctions.onStep(function(step) {
- program.iwsyStep = step;
- program.run(cb);
- });
- }
- break;
+ }
+ break;
+ case `stop`:
+ if (program.iwsyFunctions) {
+ program.iwsyFunctions.stop();
+ // delete program.iwsyFunctions;
+ }
+ break;
+ case `removeStyles`:
+ if (program.iwsyFunctions) {
+ program.iwsyFunctions.removeStyles();
+ }
+ break;
+ case `onstep`:
+ const cb = command.pc + 2;
+ if (program.iwsyFunctions) {
+ program.iwsyFunctions.onStep(function(step) {
+ program.iwsyStep = step;
+ program.run(cb);
+ });
+ }
+ break;
+ case `panzoom`:
+ const spec = program.getValue(command.spec);
+ if (program.iwsyFunctions) {
+ program.iwsyFunctions.panzoom(spec);
+ }
}
return command.pc + 1;
}
@@ -237,10 +252,10 @@ const EasyCoder_IWSY = {
getHandler: (name) => {
switch (name) {
- case `iwsy`:
- return EasyCoder_IWSY.IWSY;
- default:
- return null;
+ case `iwsy`:
+ return EasyCoder_IWSY.IWSY;
+ default:
+ return null;
}
},
@@ -281,7 +296,7 @@ const EasyCoder_IWSY = {
type: `constant`,
numeric: false,
content: JSON.stringify(script)
- }
+ };
}
break;
case `step`:
diff --git a/iwsy/iwsy.js b/iwsy/iwsy.js
index 3c14873..f892de3 100644
--- a/iwsy/iwsy.js
+++ b/iwsy/iwsy.js
@@ -1,675 +1,793 @@
-// IWSY
-
+// eslint-disable-next-line no-unused-vars
const IWSY = (playerElement, scriptObject) => {
- let player = playerElement;
- let script = scriptObject;
- let homeScript;
- let afterRun;
- let path;
+ let player = playerElement;
+ let script = scriptObject;
+ let homeScript = script;
+ let afterRun;
+ let path;
+ let plugins;
+ const timeouts = [];
+ const intervals = [];
- // Set up all the blocks
- const setupBlocks = () => {
- for (const block of script.blocks) {
- const current = {};
- for (const name in block.defaults) {
- current[name] = block.defaults[name];
- }
- block.current = current;
- }
- };
+ // Set up all the blocks
+ const setupBlocks = () => {
+ for (const block of script.blocks) {
+ const current = {};
+ for (const name in block.defaults) {
+ current[name] = block.defaults[name];
+ }
+ block.current = current;
+ }
+ };
- const pause = step => {
- if (script.speed === `scan`) {
- step.next();
- return;
- }
- setTimeout(() => {
- step.next();
- }, script.runMode === `manual` ? 0 : step.duration * 1000);
- };
+ const pause = step => {
+ if (script.speed === `scan`) {
+ step.next();
+ return;
+ }
+ addTimeoutTimer(setTimeout(() => {
+ step.next();
+ }, script.runMode === `manual` ? 0 : step.duration * 1000));
+ };
- // Get the bounding rectangle of a block
- const getBlockRect = (block, r) => {
- const left = block.defaults.left;
- const top = block.defaults.top;
- const width = block.defaults.width;
- const height = block.defaults.height;
- if (isNaN(left) || isNaN(top) || isNaN(width) || isNaN(height)) {
- return rect;
- }
- const w = r.width / 1000;
- const h = r.height / 1000;
- const rect = {};
- rect.width = width * w;
- rect.height = height * h;
- rect.left = left * w;
- rect.top = top * h;
- return rect;
- };
+ // Get the bounding rectangle of a block
+ const getBlockRect = (block, r) => {
+ const left = block.defaults.left;
+ const top = block.defaults.top;
+ const width = block.defaults.width;
+ const height = block.defaults.height;
+ if (isNaN(left) || isNaN(top) || isNaN(width) || isNaN(height)) {
+ return rect;
+ }
+ const w = r.width / 1000;
+ const h = r.height / 1000;
+ const rect = {};
+ rect.width = width * w;
+ rect.height = height * h;
+ rect.left = left * w;
+ rect.top = top * h;
+ return rect;
+ };
- // Create a block
- const createBlock = block => {
- let rect = {
- width: player.clientWidth,
- height: player.clientHeight,
- left: 0,
- top: 0
- }
- if (block.defaults.parent) {
- for (b of script.blocks) {
- if (b.defaults.name === block.defaults.parent) {
- rect = getBlockRect(b, rect);
- break;
- }
- }
- };
- const w = rect.width / 1000;
- const h = rect.height / 1000;
- const l = rect.left;
- const t = rect.top;
- const defaults = block.defaults;
- const element = document.createElement(`div`);
- player.appendChild(element);
- block.element = element;
- if (script.speed === `scan`) {
- element.style.display = `none`;
- }
- element.style.position = `absolute`;
- element.style.opacity = `0.0`;
- let val = defaults.left;
- if (isNaN(val)) {
- element.style.left = val;
- } else {
- val *= w;
- element.style.left = `calc(${l}px + ${val}px)`;
- }
- val = defaults.top;
- if (isNaN(val)) {
- element.style.left = val;
- } else {
- val *= h;
- element.style.top = `calc(${t}px + ${val}px)`;
- }
- val = defaults.width;
- if (!isNaN(val)) {
- val = `${val * w}px`;
- }
- element.style.width = val;
- val = defaults.height;
- if (!isNaN(val)) {
- val = `${val * h}px`;
- }
- element.style.height = val;
- if (defaults.background) {
- element.style.background = defaults.background;
- }
- element.style[`background-size`] = `cover`;
- element.style.border = defaults.border;
- element.style[`overflow`] = `hidden`;
- element.style[`display`] = `none`;
- element.style[`opacity`] = `0`;
- val = defaults.textMarginLeft;
- if (!isNaN(val)) {
- val *= w;
- }
- const marginLeft = val;
- val = defaults.textMarginTop;
- if (!isNaN(val)) {
- val *= h;
- }
- const marginTop = val;
- const text = document.createElement(`div`);
- element.appendChild(text);
- block.textPanel = text;
- text.style.position = `absolute`;
- text.style.left = marginLeft;
- text.style.top = marginTop;
- text.style.width = `calc(100% - ${marginLeft}px - ${marginLeft}px)`;
- text.style.height = `calc(100% - ${marginTop}px - ${marginTop}px)`;
- text.style[`font-family`] = defaults.fontFamily;
- val = defaults.fontSize;
- if (!isNaN(val)) {
- val *= h;
- }
- text.style[`font-size`] = `${val}px`;
- text.style[`font-weight`] = defaults.fontWeight;
- text.style[`font-style`] = defaults.fontStyle;
- text.style.color = defaults.fontColor;
- text.style[`text-align`] = defaults.textAlign;
- };
+ // Create a block
+ const createBlock = block => {
+ let rect = {
+ width: player.clientWidth,
+ height: player.clientHeight,
+ left: 0,
+ top: 0
+ };
+ if (block.defaults.parent) {
+ for (b of script.blocks) {
+ if (b.defaults.name === block.defaults.parent) {
+ rect = getBlockRect(b, rect);
+ break;
+ }
+ }
+ }
+ const w = rect.width / 1000;
+ const h = rect.height / 1000;
+ const l = rect.left;
+ const t = rect.top;
+ const defaults = block.defaults;
+ const element = document.createElement(`div`);
+ player.appendChild(element);
+ block.element = element;
+ if (script.speed === `scan`) {
+ element.style.display = `none`;
+ }
+ element.style.position = `absolute`;
+ element.style.opacity = `0.0`;
+ let val = defaults.left;
+ if (isNaN(val)) {
+ element.style.left = val;
+ } else {
+ val *= w;
+ element.style.left = `calc(${l}px + ${val}px)`;
+ }
+ val = defaults.top;
+ if (isNaN(val)) {
+ element.style.left = val;
+ } else {
+ val *= h;
+ element.style.top = `calc(${t}px + ${val}px)`;
+ }
+ val = defaults.width;
+ if (!isNaN(val)) {
+ val = `${val * w}px`;
+ }
+ element.style.width = val;
+ val = defaults.height;
+ if (!isNaN(val)) {
+ val = `${val * h}px`;
+ }
+ element.style.height = val;
+ if (defaults.background) {
+ element.style.background = defaults.background;
+ }
+ element.style[`background-size`] = `cover`;
+ element.style.border = defaults.border;
+ element.style[`overflow`] = `hidden`;
+ element.style[`display`] = `none`;
+ element.style[`opacity`] = `0`;
+ val = defaults.textMarginLeft;
+ if (!isNaN(val)) {
+ val *= w;
+ }
+ const marginLeft = val;
+ val = defaults.textMarginTop;
+ if (!isNaN(val)) {
+ val *= h;
+ }
+ const marginTop = val;
+ const text = document.createElement(`div`);
+ element.appendChild(text);
+ block.textPanel = text;
+ text.style.position = `absolute`;
+ text.style.left = marginLeft;
+ text.style.top = marginTop;
+ text.style.width = `calc(100% - ${marginLeft}px - ${marginLeft}px)`;
+ text.style.height = `calc(100% - ${marginTop}px - ${marginTop}px)`;
+ text.style[`font-family`] = defaults.fontFamily;
+ val = defaults.fontSize;
+ if (!isNaN(val)) {
+ val *= h;
+ }
+ text.style[`font-size`] = `${val}px`;
+ text.style[`font-weight`] = defaults.fontWeight;
+ text.style[`font-style`] = defaults.fontStyle;
+ text.style.color = defaults.fontColor;
+ text.style[`text-align`] = defaults.textAlign;
+ };
- // Set the content of one or more blocks
- const setcontent = step => {
- for (const item of step.blocks)
- {
- for (const block of script.blocks) {
- if (block.defaults.name === item.block) {
- if (!block.element) {
- createBlock(block);
- }
- for (const text of script.content) {
- if (text.name === item.content) {
- const converter = new showdown.Converter({
- extensions: [`IWSY`]
- });
- block.textPanel.innerHTML =
+ // Set the content of one or more blocks
+ const setcontent = step => {
+ for (const item of step.blocks)
+ {
+ for (const block of script.blocks) {
+ if (block.defaults.name === item.block) {
+ if (!block.element) {
+ createBlock(block);
+ }
+ for (const text of script.content) {
+ if (text.name === item.content) {
+ const converter = new showdown.Converter({
+ extensions: [`IWSY`]
+ });
+ block.textPanel.innerHTML =
converter.makeHtml(text.content.split(`%0a`).join(`\n`));
- break;
- }
- }
- break;
- }
- }
- }
- step.next();
- };
+ break;
+ }
+ }
+ const vfxElements = block.textPanel.getElementsByClassName(`iwsy-vfx`);
+ // Save all the vfx items in this step
+ for (const vfxElement of vfxElements) {
+ script.vfxElements.push({
+ block,
+ vfxElement
+ });
+ }
+ break;
+ }
+ }
+ }
+ step.next();
+ };
- // Show or hide a block
- const doShowHide = (step, showHide) => {
- for (const name of step.blocks)
- {
- for (const block of script.blocks) {
- if (block.defaults.name === name) {
- block.element.style.opacity = showHide ? `1.0` : `0.0`;
- block.element.style.display = showHide ? `block` : `none`;
- break;
- }
- }
- }
- if (script.runMode === `manual`) {
- enterManualMode(step);
- } else {
- step.next();
- }
- };
+ // Set the visibility of a block
+ const setVisibility = (block, showHide) => {
+ if (showHide) {
+ block.element.style.opacity = `1.0`;
+ block.element.style.display = `block`;
+ } else {
+ block.element.style.opacity = `0.0`;
+ block.element.style.display = `none`;
+ }
+ };
- const show = step => {
- doShowHide(step, true);
- };
+ // Show or hide a block
+ const doShowHide = (step, showHide) => {
+ for (const name of step.blocks)
+ {
+ for (const block of script.blocks) {
+ if (block.defaults.name === name) {
+ if (!block.element) {
+ createBlock(block);
+ }
+ setVisibility(block, showHide);
+ break;
+ }
+ }
+ }
+ if (script.runMode === `manual`) {
+ enterManualMode(step);
+ } else {
+ step.next();
+ }
+ };
+
+ const show = step => {
+ doShowHide(step, true);
+ };
+
+ const hide = step => {
+ doShowHide(step, false);
+ };
+
+ addIntervalTimer = (interval) => {
+ intervals.push(interval);
+ };
+
+ clearIntervalTimer = interval => {
+ clearInterval(interval);
+ const pos = intervals.indexOf(interval);
+ intervals.splice(pos, 1);
+ };
+
+ addTimeoutTimer = (interval) => {
+ intervals.push(interval);
+ };
+
+ clearAllTimers = () => {
+ while (intervals.length) {
+ clearInterval(intervals[0]);
+ intervals.splice(0, 1);
+ }
+ while (timeouts.length) {
+ clearTimeout(timeouts[0]);
+ timeouts.splice(0, 1);
+ }
+ };
- const hide = step => {
- doShowHide(step, false);
- };
+ // Fade up or down
+ const doFade = (step, upDown) => {
+ const stepBlocks = [];
+ for (const name of step.blocks) {
+ script.blocks.every((block) => {
+ if (block.defaults.name === name) {
+ stepBlocks.push(block);
+ if (!block.element) {
+ createBlock(block);
+ }
+ return false;
+ }
+ return true;
+ });
+ }
+ if (script.speed === `scan`) {
+ for (const block of stepBlocks)
+ {
+ setVisibility(step, block, showHide);
+ }
+ step.next();
+ } else {
+ const animSteps = Math.round(step.duration * 25);
+ const continueFlag = step.continue;
+ for (const block of stepBlocks)
+ {
+ block.element.style.display = `block`;
+ }
+ let animStep = 0;
+ const interval = setInterval(() => {
+ try {
+ if (animStep < animSteps) {
+ const ratio = 0.5 - Math.cos(Math.PI * animStep / animSteps) / 2;
+ for (const block of stepBlocks)
+ {
+ // if (block.element) {
+ block.element.style.opacity = upDown ? ratio : 1.0 - ratio;
+ // }
+ }
+ animStep++;
+ } else {
+ for (const block of stepBlocks)
+ {
+ // if (block.element) {
+ block.element.style.opacity = upDown ? 1 : 0;
+ block.element.style.display = upDown ? `block` :`none`;
+ // }
+ }
+ clearIntervalTimer(interval);
+ if (!continueFlag) {
+ if (script.runMode === `manual`) {
+ enterManualMode(step);
+ } else {
+ step.next();
+ }
+ }
+ }
+ } catch(err) {
+ clearIntervalTimer(interval);
+ throw Error(err);
+ }
+ }, 40);
+ addIntervalTimer(interval);
+ if (continueFlag) {
+ step.next();
+ }
+ }
+ };
- // Fade up or down
- const doFade = (step, upDown) => {
- const stepBlocks = [];
- for (const name of step.blocks) {
- script.blocks.every((block, index) => {
- if (block.defaults.name === name) {
- stepBlocks.push(block);
- if (!block.element) {
- createBlock(block);
- }
- return false;
- }
- return true;
- });
- }
- if (script.speed === `scan`) {
- for (const block of stepBlocks)
- {
- block.element.style.opacity = upDown ? 1.0 : 0.0;
- block.element.style.display = upDown ? `block` : `none`;
- }
- step.next();
- } else {
- const animSteps = Math.round(step.duration * 25);
- const continueFlag = step.continue;
- for (const block of stepBlocks)
- {
- block.element.style.display = `block`;
- }
- let animStep = 0;
- const interval = setInterval(() => {
- try {
- if (animStep < animSteps) {
- const ratio = 0.5 - Math.cos(Math.PI * animStep / animSteps) / 2;
- for (const block of stepBlocks)
- {
- if (block.element) {
- block.element.style.opacity = upDown ? ratio : 1.0 - ratio;
- }
- }
- animStep++;
- } else {
- for (const block of stepBlocks)
- {
- if (block.element) {
- block.element.style.opacity = upDown ? 1 : 0;
- block.element.style.display = upDown ? `block` :`none`;
- }
- }
- clearInterval(interval);
- if (!continueFlag) {
- if (script.runMode === `manual`) {
- enterManualMode(step);
- } else {
- step.next();
- }
- }
- }
- } catch(err) {
- clearInterval(interval);
- throw Error(err);
- }
- }, 40);
- if (continueFlag) {
- step.next();
- }
- }
- };
+ const fadeup = step => {
+ doFade(step, true);
+ };
- const fadeup = step => {
- doFade(step, true);
- };
+ const fadedown = step => {
+ doFade(step, false);
+ };
- const fadedown = step => {
- doFade(step, false);
- };
+ // This is where the vfx animations are started
+ const startVFX = (step, vfxElement) => {
+ vfxElement.style.position = `relative`;
+ vfxElement.style.display = `inline-block`;
+ const slide = vfxElement.dataset.slide;
+ const vfx = script.vfx;
+ for (const item of vfx) {
+ if (item.name === slide) {
+ step.vfxRunning.push(vfxElement);
+ doPanzoom(vfxElement, item, () => {
+ if (step.continue !== `yes`) {
+ const index = step.vfxRunning.indexOf(vfxElement);
+ if (index > -1) {
+ step.vfxRunning.splice(index, 1);
+ }
+ if (step.vfxRunning.length === 0) {
+ step.next();
+ }
+ }
+ });
+ }
+ }
+ };
- // Handle a crossfade
- const crossfade = step => {
- for (const content of script.content) {
- if (content.name === step.target) {
- const converter = new showdown.Converter({
- extensions: [`IWSY`]
- });
- const newText = converter.makeHtml(content.content.split(`%0a`).join(`\n`));
- for (const block of script.blocks) {
- if (block.defaults.name === step.block) {
- if (script.speed === `scan`) {
- block.textPanel.innerHTML = newText;
- step.next();
- } else {
- const element = document.createElement(`div`);
- player.appendChild(element);
- element.style.position = `absolute`;
- element.style.opacity = `0.0`;
- element.style.left = block.element.style.left;
- element.style.top = block.element.style.top;
- element.style.width = block.element.style.width;
- element.style.height = block.element.style.height;
- if (block.element.style.background) {
- element.style.background = block.element.style.background;
- }
- element.style.border = block.element.style.border
- element.style[`border-radius`] = block.element.style[`border-radius`]
- const text = document.createElement(`div`);
- element.appendChild(text);
- text.style.position = `absolute`;
- text.style.left = block.textPanel.style.left;
- text.style.top = block.textPanel.style.top;
- text.style.width = block.textPanel.style.width;
- text.style[`font-family`] = block.textPanel.style[`font-family`];
- text.style[`font-size`] = block.textPanel.style[`font-size`];
- text.style[`font-weight`] = block.textPanel.style[`font-weight`];
- text.style[`font-style`] = block.textPanel.style[`font-style`];
- text.style[`text-align`] = block.textPanel.style[`text-align`];
- text.style.color = block.textPanel.style.color;
- text.innerHTML = newText;
+ // Animate blocks
+ const animate = step => {
+ const continueFlag = step.continue === `yes`;
+ for (const name of step.blocks)
+ {
+ for (const block of script.blocks) {
+ if (block.defaults.name === name) {
+ if (!block.element) {
+ createBlock(block);
+ setVisibility(block, true);
+ }
+ for (const item of script.vfxElements) {
+ if (item.block === block) {
+ startVFX(step, item.vfxElement);
+ }
+ }
+ break;
+ }
+ }
+ }
+ if (script.runMode === `manual`) {
+ enterManualMode(step);
+ } else if (continueFlag || step.vfxRunning.length === 0) {
+ step.next();
+ }
+ };
+
+ // Handle a crossfade
+ const crossfade = step => {
+ for (const content of script.content) {
+ if (content.name === step.target) {
+ const converter = new showdown.Converter({
+ extensions: [`IWSY`]
+ });
+ const newText = converter.makeHtml(content.content.split(`%0a`).join(`\n`));
+ for (const block of script.blocks) {
+ if (block.defaults.name === step.block) {
+ if (script.speed === `scan`) {
+ block.textPanel.innerHTML = newText;
+ step.next();
+ } else {
+ const element = document.createElement(`div`);
+ player.appendChild(element);
+ element.style.position = `absolute`;
+ element.style.opacity = `0.0`;
+ element.style.left = block.element.style.left;
+ element.style.top = block.element.style.top;
+ element.style.width = block.element.style.width;
+ element.style.height = block.element.style.height;
+ if (block.element.style.background) {
+ element.style.background = block.element.style.background;
+ }
+ element.style.border = block.element.style.border;
+ element.style[`border-radius`] = block.element.style[`border-radius`];
+ const text = document.createElement(`div`);
+ element.appendChild(text);
+ text.style.position = `absolute`;
+ text.style.left = block.textPanel.style.left;
+ text.style.top = block.textPanel.style.top;
+ text.style.width = block.textPanel.style.width;
+ text.style[`font-family`] = block.textPanel.style[`font-family`];
+ text.style[`font-size`] = block.textPanel.style[`font-size`];
+ text.style[`font-weight`] = block.textPanel.style[`font-weight`];
+ text.style[`font-style`] = block.textPanel.style[`font-style`];
+ text.style[`text-align`] = block.textPanel.style[`text-align`];
+ text.style.color = block.textPanel.style.color;
+ text.innerHTML = newText;
- const animSteps = Math.round(step.duration * 25);
- const continueFlag = step.continue;
- let animStep = 0;
- const interval = setInterval(() => {
- if (animStep < animSteps) {
- const ratio = 0.5 - Math.cos(Math.PI * animStep / animSteps) / 2;
- block.element.style.opacity = 1.0 - ratio;
- element.style.opacity = ratio;
- animStep++;
- } else {
- clearInterval(interval);
- block.textPanel.innerHTML = newText;
- if (content.url) {
- block.element.style.background = `url("${content.url}")`;
- }
- block.element.style[`background-size`] = `cover`;
- block.element.style.opacity = 1.0 ;
- removeElement(element);
- if (!continueFlag) {
- if (script.runMode === `manual`) {
- enterManualMode(step);
- } else {
- step.next();
- }
- }
- }
- }, 40);
- if (continueFlag) {
- step.next();
- }
- }
- break;
- }
- }
- break;
- }
- }
- };
+ const animSteps = Math.round(step.duration * 25);
+ const continueFlag = step.continue === `yes`;
+ let animStep = 0;
+ const interval = setInterval(() => {
+ if (animStep < animSteps) {
+ const ratio = 0.5 - Math.cos(Math.PI * animStep / animSteps) / 2;
+ block.element.style.opacity = 1.0 - ratio;
+ element.style.opacity = ratio;
+ animStep++;
+ } else {
+ clearIntervalTimer(interval);
+ block.textPanel.innerHTML = newText;
+ if (content.url) {
+ block.element.style.background = `url("${content.url}")`;
+ }
+ block.element.style[`background-size`] = `cover`;
+ block.element.style.opacity = 1.0 ;
+ removeElement(element);
+ if (!continueFlag) {
+ if (script.runMode === `manual`) {
+ enterManualMode(step);
+ } else {
+ step.next();
+ }
+ }
+ }
+ }, 40);
+ addIntervalTimer(interval);
+ if (continueFlag) {
+ step.next();
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ };
- // Compute a block size
- const setComputedBlockSize = (block, target, ratio) => {
- const boundingRect = player.getBoundingClientRect();
- const w = boundingRect.width / 1000;
- const h = boundingRect.height / 1000;
- let width = block.current.width;
- if (!isNaN(width)) {
- width *= w;
- }
- let height = block.current.height;
- if (!isNaN(height)) {
- height *= h;
- }
- let endWidth = target.defaults.width;
- if (!isNaN(endWidth)) {
- endWidth *= w;
- }
- let endHeight = target.defaults.height;
- if (!isNaN(endHeight)) {
- endHeight *= h;
- }
- block.element.style.width =
+ // Compute a block size
+ const setComputedBlockSize = (block, target, ratio) => {
+ const boundingRect = player.getBoundingClientRect();
+ const w = boundingRect.width / 1000;
+ const h = boundingRect.height / 1000;
+ let width = block.current.width;
+ if (!isNaN(width)) {
+ width *= w;
+ }
+ let height = block.current.height;
+ if (!isNaN(height)) {
+ height *= h;
+ }
+ let endWidth = target.defaults.width;
+ if (!isNaN(endWidth)) {
+ endWidth *= w;
+ }
+ let endHeight = target.defaults.height;
+ if (!isNaN(endHeight)) {
+ endHeight *= h;
+ }
+ block.element.style.width =
`${width + (endWidth - width) * ratio}px`;
- block.element.style.height =
+ block.element.style.height =
`${height + (endHeight - height) * ratio}px`;
- };
+ };
- // Compute a block position
- const setComputedBlockPosition = (block, target, ratio) => {
- const boundingRect = player.getBoundingClientRect();
- const w = boundingRect.width / 1000;
- const h = boundingRect.height / 1000;
- let left = block.current.left;
- if (!isNaN(left)) {
- left *= w;
- }
- let top = block.current.top;
- if (!isNaN(top)) {
- top *= h;
- }
- let endLeft = target.defaults.left;
- if (!isNaN(endLeft)) {
- endLeft *= w;
- }
- let endTop = target.defaults.top;
- if (!isNaN(endTop)) {
- endTop *= h;
- }
- block.element.style.left = left + (endLeft - left) * ratio;
- block.element.style.top = top + (endTop - top) * ratio;
- };
+ // Compute a block position
+ const setComputedBlockPosition = (block, target, ratio) => {
+ const boundingRect = player.getBoundingClientRect();
+ const w = boundingRect.width / 1000;
+ const h = boundingRect.height / 1000;
+ let left = block.current.left;
+ if (!isNaN(left)) {
+ left *= w;
+ }
+ let top = block.current.top;
+ if (!isNaN(top)) {
+ top *= h;
+ }
+ let endLeft = target.defaults.left;
+ if (!isNaN(endLeft)) {
+ endLeft *= w;
+ }
+ let endTop = target.defaults.top;
+ if (!isNaN(endTop)) {
+ endTop *= h;
+ }
+ block.element.style.left = left + (endLeft - left) * ratio;
+ block.element.style.top = top + (endTop - top) * ratio;
+ };
- // Compute a font size
- const setComputedFontSize = (block, target, ratio) => {
- const h = Math.round(player.getBoundingClientRect().height) / 1000;
- let size = block.current.fontSize;
- if (!isNaN(size)) {
- size *= h;
- }
- let endSize = target.defaults.fontSize;
- if (!isNaN(endSize)) {
- endSize *= h;
- }
- block.textPanel.style[`font-size`] =
+ // Compute a font size
+ const setComputedFontSize = (block, target, ratio) => {
+ const h = Math.round(player.getBoundingClientRect().height) / 1000;
+ let size = block.current.fontSize;
+ if (!isNaN(size)) {
+ size *= h;
+ }
+ let endSize = target.defaults.fontSize;
+ if (!isNaN(endSize)) {
+ endSize *= h;
+ }
+ block.textPanel.style[`font-size`] =
`${size + (endSize - size) * ratio}px`;
- };
+ };
- // Compute a font color
- const setComputedFontColor = (block, target, ratio) => {
- const color = block.current.fontColor;
- const endColor = target.defaults.fontColor;
- const rStart = parseInt(color.slice(1, 3), 16);
- const gStart = parseInt(color.slice(3, 5), 16);
- const bStart = parseInt(color.slice(5, 7), 16);
- const rFinish = parseInt(endColor.slice(1, 3), 16);
- const gFinish = parseInt(endColor.slice(3, 5), 16);
- const bFinish = parseInt(endColor.slice(5, 7), 16);
- const red = rStart + Math.round((rFinish - rStart) * ratio);
- const green = gStart + Math.round((gFinish - gStart) * ratio);
- const blue = bStart + Math.round((bFinish - bStart) * ratio);
- const r = ("0" + red.toString(16)).slice(-2);
- const g = ("0" + green.toString(16)).slice(-2);
- const b = ("0" + blue.toString(16)).slice(-2);
- block.textPanel.style.color = `#${r}${g}${b}`;
- };
+ // Compute a font color
+ const setComputedFontColor = (block, target, ratio) => {
+ const color = block.current.fontColor;
+ const endColor = target.defaults.fontColor;
+ const rStart = parseInt(color.slice(1, 3), 16);
+ const gStart = parseInt(color.slice(3, 5), 16);
+ const bStart = parseInt(color.slice(5, 7), 16);
+ const rFinish = parseInt(endColor.slice(1, 3), 16);
+ const gFinish = parseInt(endColor.slice(3, 5), 16);
+ const bFinish = parseInt(endColor.slice(5, 7), 16);
+ const red = rStart + Math.round((rFinish - rStart) * ratio);
+ const green = gStart + Math.round((gFinish - gStart) * ratio);
+ const blue = bStart + Math.round((bFinish - bStart) * ratio);
+ const r = (`0` + red.toString(16)).slice(-2);
+ const g = (`0` + green.toString(16)).slice(-2);
+ const b = (`0` + blue.toString(16)).slice(-2);
+ block.textPanel.style.color = `#${r}${g}${b}`;
+ };
- // Handle a single step of a transition
- const doTransitionStep = (block, target, ratio) => {
- setComputedBlockSize(block, target, ratio);
- setComputedBlockPosition(block, target, ratio);
- setComputedFontSize(block, target, ratio);
- setComputedFontColor(block, target, ratio);
- };
+ // Handle a single step of a transition
+ const doTransitionStep = (block, target, ratio) => {
+ setComputedBlockSize(block, target, ratio);
+ setComputedBlockPosition(block, target, ratio);
+ setComputedFontSize(block, target, ratio);
+ setComputedFontColor(block, target, ratio);
+ };
- // Set the final state of a transition
- const setFinalState = (block, target) =>
- {
- block.current.width = target.defaults.width;
- block.current.height = target.defaults.height;
- block.current.left = target.defaults.left;
- block.current.top = target.defaults.top;
- block.current.fontColor = target.defaults.fontColor;
- block.current.fontSize = target.defaults.fontSize;
- };
+ // Set the final state of a transition
+ const setFinalState = (block, target) =>
+ {
+ block.current.width = target.defaults.width;
+ block.current.height = target.defaults.height;
+ block.current.left = target.defaults.left;
+ block.current.top = target.defaults.top;
+ block.current.fontColor = target.defaults.fontColor;
+ block.current.fontSize = target.defaults.fontSize;
+ };
- // Handle a transition
- const transition = step => {
- let block = null;
- let target = null;
- script.blocks.every(item => {
- if (item.defaults.name === step.block) {
- block = item;
- }
- if (item.defaults.name === step.target) {
- target = item;
- }
- return true;
- });
- if (typeof block.element === `undefined`) {
- throw Error(`Block '${block.defaults.name}' has not been set up`);
- }
- block.element.style.opacity = 1;
- block.element.style.display = `block`;
- if (script.speed === `scan`) {
- doTransitionStep(block, target, 1.0);
- setFinalState(block,target);
- step.next();
- } else {
- const animSteps = Math.round(step.duration * 25);
- let animStep = 0;
- const continueFlag = step.continue;
- const interval = setInterval(() => {
- if (animStep < animSteps) {
- const ratio = 0.5 - Math.cos(Math.PI * animStep / animSteps) / 2;
- try {
- doTransitionStep(block, target, ratio);
- } catch (err) {
- clearInterval(interval);
- }
- animStep++;
- } else {
- clearInterval(interval);
- setFinalState(block,target);
- if (!continueFlag) {
- if (script.runMode === `manual`) {
- enterManualMode(step);
- } else {
- step.next();
- }
- }
- }
- }, 40);
- if (continueFlag) {
- step.next();
- }
- }
- };
+ // Handle a transition
+ const transition = step => {
+ let block = null;
+ let target = null;
+ script.blocks.every(item => {
+ if (item.defaults.name === step.block) {
+ block = item;
+ }
+ if (item.defaults.name === step.target) {
+ target = item;
+ }
+ return true;
+ });
+ if (typeof block.element === `undefined`) {
+ throw Error(`Block '${block.defaults.name}' has not been set up`);
+ }
+ block.element.style.opacity = 1;
+ block.element.style.display = `block`;
+ if (script.speed === `scan`) {
+ doTransitionStep(block, target, 1.0);
+ setFinalState(block,target);
+ step.next();
+ } else {
+ const animSteps = Math.round(step.duration * 25);
+ let animStep = 0;
+ const continueFlag = step.continue;
+ const interval = setInterval(() => {
+ if (animStep < animSteps) {
+ const ratio = 0.5 - Math.cos(Math.PI * animStep / animSteps) / 2;
+ try {
+ doTransitionStep(block, target, ratio);
+ } catch (err) {
+ clearIntervalTimer(interval);
+ }
+ animStep++;
+ } else {
+ clearIntervalTimer(interval);
+ setFinalState(block,target);
+ if (!continueFlag) {
+ if (script.runMode === `manual`) {
+ enterManualMode(step);
+ } else {
+ step.next();
+ }
+ }
+ }
+ }, 40);
+ addIntervalTimer(interval);
+ if (continueFlag) {
+ step.next();
+ }
+ }
+ };
- // Remove all the blocks from the player
- const removeBlocks = () => {
- if (Array.isArray(script.blocks)) {
- for (const block of script.blocks) {
- if (block.element) {
- removeElement(block.element);
- delete(block.element);
- }
- }
- }
- };
+ // Remove all the blocks from the player
+ const removeBlocks = () => {
+ if (Array.isArray(script.blocks)) {
+ for (const block of script.blocks) {
+ if (block.element) {
+ removeElement(block.element);
+ delete(block.element);
+ }
+ }
+ }
+ };
- // Remove an element
- const removeElement = element => {
- const parent = element.parentElement;
- if (parent) {
- parent.removeChild(element);
- }
- element.remove();
- };
+ // Remove an element
+ const removeElement = element => {
+ const parent = element.parentElement;
+ if (parent) {
+ parent.removeChild(element);
+ }
+ };
- // Load a plugin action
- const load = step => {
- if (script.speed === `scan`) {
- step.next();
- } else {
- const element = document.createElement(`script`);
- element.src = step.url;
- element.onload = () => {
- console.log(`Plugin ${element.src} loaded`);
- step.next();
- };
- element.onerror = () => {
- throw Error(`Can't load plugin ${step.url}`);
- };
- document.head.appendChild(element);
- }
- };
+ // Load a plugin action
+ const load = step => {
+ if (script.speed === `scan`) {
+ step.next();
+ } else {
+ const element = document.createElement(`script`);
+ element.src = step.url;
+ element.onload = () => {
+ console.log(`Plugin ${element.src} loaded`);
+ step.next();
+ };
+ element.onerror = () => {
+ throw Error(`Can't load plugin ${step.url}`);
+ };
+ document.head.appendChild(element);
+ }
+ };
- // Initialize the presentation
- const init = step => {
- if (step.title) {
- document.title = step.title;
- }
- if (step.css) {
- setHeadStyle(step.css.split(`%0a`).join(`\n`));
- }
- const aspect = step[`aspect ratio`];
- if (aspect) {
- const colon = aspect.indexOf(`:`);
- if (colon > 0) {
- const aspectW = aspect.substr(0, colon);
- const aspectH = aspect.substr(colon + 1);
- const height = Math.round(parseFloat(player.offsetWidth) * aspectH / aspectW);
- player.style.height = `${Math.round(height)}px`;
- }
- player.style.position = `relative`;
- player.style.overflow = `hidden`;
- player.style.cursor = `none`;
- player.style.border = step.border;
- if (step.background) {
- player.style.background = step.background.split(`"`).join(`"`);
- }
- player.style[`background-size`] = `cover`;
- }
- step.next();
- };
+ // Initialize the presentation
+ const init = step => {
+ if (step.title) {
+ document.title = step.title;
+ }
+ if (step.css) {
+ setHeadStyle(step.css.split(`%0a`).join(`\n`));
+ }
+ const aspect = step[`aspect ratio`];
+ if (aspect) {
+ const colon = aspect.indexOf(`:`);
+ if (colon > 0) {
+ const aspectW = aspect.substr(0, colon);
+ const aspectH = aspect.substr(colon + 1);
+ const height = Math.round(parseFloat(player.offsetWidth) * aspectH / aspectW);
+ player.style.height = `${Math.round(height)}px`;
+ }
+ player.style.position = `relative`;
+ player.style.overflow = `hidden`;
+ player.style.cursor = `none`;
+ player.style.border = step.border;
+ if (step.background) {
+ player.style.background = step.background.split(`"`).join(`"`);
+ }
+ player.style[`background-size`] = `cover`;
+ }
+ step.next();
+ };
- // Scan the script
- const scan = () => {
- script.speed = `scan`;
- removeBlocks();
- setupBlocks();
- player.innerHTML = ``;
- doStep(script.steps[0]);
- };
+ // Scan the script
+ const scan = () => {
+ script.speed = `scan`;
+ removeBlocks();
+ setupBlocks();
+ player.innerHTML = ``;
+ doStep(script.steps[0]);
+ };
- // Go to a specified label
- const goto = step => {
- const target = script.labels[step.target];
- if (typeof target !== `undefined`) {
- script.scanTarget = target;
- scan();
- } else {
- throw Error(`Unknown label '${step.target}`);
- }
- };
+ // Go to a specified label
+ const goto = step => {
+ const target = script.labels[step.target];
+ if (typeof target !== `undefined`) {
+ script.scanTarget = target;
+ scan();
+ } else {
+ throw Error(`Unknown label '${step.target}`);
+ }
+ };
- // Restore the cursor
- const restoreCursor = () => {
- player.style.cursor = `pointer`;
- script = homeScript;
- if (afterRun) {
- afterRun();
- }
- };
+ // Restore the cursor
+ const restoreCursor = () => {
+ player.style.cursor = `pointer`;
+ script = homeScript;
+ if (afterRun) {
+ afterRun();
+ }
+ };
- // Set up Showdown
- const setupShowdown = () => {
- if (typeof showdown === `undefined`) {
- require(`js`, `https://cdn.rawgit.com/showdownjs/showdown/1.9.1/dist/showdown.min.js`,
- () => {
- showdown.extension(`IWSY`, {
- type: `lang`,
- filter: function (text, converter) {
- return text.replace(/~([^~]+)~/g, function (match, group) {
- return decodeShowdown(group);
- });
- }
- });
- });
- }
- else {
- }
- };
+ // Set up Showdown
+ const setupShowdown = () => {
+ if (typeof showdown === `undefined`) {
+ require(`js`, `https://cdn.rawgit.com/showdownjs/showdown/1.9.1/dist/showdown.min.js`,
+ () => {
+ showdown.extension(`IWSY`, {
+ type: `lang`,
+ filter: function (text) {
+ return text.replace(/~([^~]+)~/g, function (match, group) {
+ return decodeShowdown(group);
+ });
+ }
+ });
+ });
+ }
+ };
- // Decode special Showdown tags
- const decodeShowdown = group => {
- if (group.slice(0, 5) === `code:`) {
- return `${group.slice(5)}`;
- }
- if (group.slice(0, 5) === `html:`) {
- return group.slice(5);
- }
- if (group.slice(0, 4) === `img:`) {
- const data = group.slice(4);
- const colon = data.indexOf(`:`);
- if (colon > 0) {
- const src = data.slice(0, colon);
- const classes = data.slice(colon + 1).split(` `);
- const styles = [];
- for (const item of classes) {
- if (item.endsWith(`%`)) {
- styles.push(`width:${item}`);
- } else if (item.startsWith(`{`) && item.endsWith(`}`)) {
- styles.push(item.slice(1, -1));
- } else {
- switch (item) {
- case `left`:
- styles.push(`float:left;margin-right:1em`);
- break;
- case `center`:
- styles.push(`margin:0 auto`);
- break;
- case `right`:
- styles.push(`float:right;margin-left:1em`);
- break;
- case `clear`:
- styles.push(`clear:both`);
- break;
- case `border`:
- styles.push(`padding:2px;border:1px solid black`);
- break;
- }
- }
- }
- return ``;
- }
- }
- return group;
- };
+ // Decode special Showdown tags
+ const decodeShowdown = group => {
+ if (group.slice(0, 5) === `code:`) {
+ return `${group.slice(5)}`;
+ }
+ if (group.slice(0, 5) === `html:`) {
+ return group.slice(5);
+ }
+ if (group.slice(0, 4) === `img:`) {
+ const data = group.slice(4);
+ const colon = data.indexOf(`:`);
+ if (colon > 0) {
+ const src = data.slice(0, colon);
+ const classes = data.slice(colon + 1).split(` `);
+ const styles = [];
+ for (const item of classes) {
+ setImageStyles(item, styles);
+ }
+ return `
`;
+ }
+ }
+ if (group.slice(0, 4) === `vfx:`) {
+ const styles = [];
+ let slide = ``;
+ const items = group.slice(4).split(` `);
+ for (const item of items) {
+ if (!setImageStyles(item, styles)) {
+ slide = item;
+ }
+ }
+ return `