Skip to content

Latest commit

 

History

History
182 lines (125 loc) · 6.25 KB

Typescript.md

File metadata and controls

182 lines (125 loc) · 6.25 KB

TypeScript

As of Smartdown v1.0.20, the Smartdown engine is being reconstructed using Typescript. As of v1.0.21, Smartdown supports the dynamic compilation of Typescript in the browser via typescript playables.

References:

A Typescript Playable

For our first example, we'll create a little typescript playable that just listens for changes to the Name variable and adjusts its div content accordingly. We'll use the /debug qualifier on the playable to allow us to view the augmented code that will transpile typescript into javascript.

The source for this playable is encoded in Smartdown like this:

```javascript /typescript/playable/autoplay/debug
  // SOURCE goes here
```

with // SOURCE goes here being replaced by:

const myDiv = this.div;
myDiv.style.background = 'lavender !important';
myDiv.style.color = 'magenta !important';
myDiv.style.padding = '10px 2px';
myDiv.style.margin = '10px 2px';

this.dependOn = ['Name'];
this.depend = function(): void {
  const msg: string = ['Nice', 'to', 'meet', 'you'].join(' ');

  myDiv.innerHTML = `<p>${msg}, <b>${env.Name}</b>!</p>`;
};

What is your name?

const myDiv = this.div;
myDiv.style.background = 'lavender !important';
myDiv.style.color = 'magenta !important';
myDiv.style.padding = '10px 2px';
myDiv.style.margin = '10px 2px';

this.dependOn.Name = (): void => {
  const msg: string = ['Nice', 'to', 'meet', 'you'].join(' ');

  myDiv.innerHTML = `<p>${msg}, <b>${env.Name}</b>!</p>`;
};

Detecting source errors with the playable's console

The augmented code that Smartdown generates around Typescript to transpile it to Javascript has been recently (v1.0.24) improved so that syntax errors detected during transpilation are reported via the Smartdown per-playable console, which is a new feature (see Javascript).

Let's give this feature a try by creating a TypeScript playable that is syntactically incorrect because it lacks a closing single quote on a string declaration. This playable is NOT autoplay, so you will need to click the Play button to see stuff happen:

const msg: string = 'I better not forget the closing quote...;
this.div.innerHTML = `<h1>${msg}</h1`;

Here's an example which is syntactically correct, but should fail Typescript's typechecking. Because Smartdown's usage of the Typescript transpiler does not currently use the typechecker, this playable will be transpiled successfully into Javascript.

const n: number = 'This is definitely NOT a number';
this.div.innerHTML = `<h1>n: ${n}</h1`;

Invoking the TypeScript Transpiler Explicitly

Before Smartdown had a proper typescript playable language type, I prototyped the capability by using an ordinary Javascript playable and then using smartdown.import to dynamically load the TypeScript compiler via the jsDelivr CDN, followed by transpiling some example source and then generating a Function and invoking it with the current playable's context. For the most part, the following playable is patterned after the augmented code generated by Smartdown when processing a Typescript playable.


String to uppercase Uppercased String

//smartdown.import=https://cdn.jsdelivr.net/npm/typescript/lib/typescript.min.js

const source =
`
this.dependOn = ['String'];
this.depend = function() {
  const upper: string = env.String.toUpperCase();
  smartdown.setVariable('StringUpper', upper);
}
`;


// https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#transpiling-a-single-file
  // compilerOptions?: CompilerOptions;
  // fileName?: string;
  // reportDiagnostics?: boolean;
  // moduleName?: string;
  // renamedDependencies?: Map<string>;

let result = ts.transpileModule(source, {
  compilerOptions: {
    module: ts.ModuleKind.CommonJS,
    target: 'es6',
    allowJs: true,
    checkJs: true,
  },
  reportDiagnostics: true,
});

if (result.diagnostics.length > 0) {
  console.log('result.diagnostics');
  console.log(result.diagnostics);
}

smartdown.runFunction(
  result.outputText,
  this,
  [...arguments],
  playable.language,
  this.div);
Using await without a wrapper.

As of SD v1.0.25, Javascript playable sources are wrapped with an async function wrapper so that await can be used within the source of the playable. This is exercised in a Javascript example, but let's make sure it works with TypeScript.

console.log('Hello from the typescript playable');
const response: any = await fetch('https://unpkg.com/smartdown/package.json');
const myJson: any = await response.json();
smartdown.setVariable('Package', myJson);

package.json

ES6 Modules in Typescript

Preliminary capability that allows a transpiled Typescript playable to execute as an ES6 Module by using the /module qualifier. As with ordinary Javascript ES6 Playables, you must implement a start() function which will receive a reference to the playable via playable and to the Smartdown variables via env. The signature for start() is still in flux, and we may implement a corresponding stop() hook.

Possibly this should be moved to the ES6 card, but it is here for now.


What is your name?

import * as Lib from './gallery/ExtensionsES6Module.js';

export default function start(playable, env) {
  const log = this.log;

  log('start', this, playable, env);

  this.div.innerHTML = `<h1>Waiting for dependency</h1>`;
  this.dependOn.NameA = () => {
    smartdown.setVariable('NameB', env.NameA.toUpperCase());
    this.div.innerHTML = `<h1>Hello from an ES6 Module A. ${env.NameA}</h1>`;
  };

  const nums = [12, 23, 34, 45];
  log('sum', Lib.sum(...nums));
  log('mult', Lib.mult(...nums));
  Lib.note.note = 'ModuleA was here';
}

Back to Home