Skip to content
Library + UI for generating Typescript definitions / DefinitelyTyped packages from COM type libraries / LibreOffice Doxygen XML
C#
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
3rdparty
common
idlbuilder
tests
tlibuilder
wpf
.gitattributes
.gitignore
LICENSE.md
README.md
screenshot.png
ts-activex-gen.sln

README.md

ts-activex-gen

Library and WPF UI for generating Typescript definitions from COM type libraries, either from the Windows Registry, or from files on disk. Also allows generating definitions for the LibreOffice API.

Ensures type defitions are complete, by following types defined in external libraries and geneerating definitions for them as well.

Can also generate definitions for a specific type or types in a type library.

Optionally, definitions can be packaged for publication on DefinitelyTyped, as outlined here and here.

UI

Choosing a registerd COM library

Library

The first step is to generate a TSNamespaceSet, which is a data structure describing a set of TypeScript namespaces, interfaces, enums, and their members (see below on how to do this).

TSNamespaceSet nsset = ...

That instance is passed to the GetTypescript method:

var builder = new TSBuilder();
List<KeyValuePair<string, NamespaceOutput>> output = builder.GetTypescript(nsset);
foreach (var x in output) {
  var name = x.Key;
  string typescriptDefinitions = x.Value.MainFile;
  string typescriptTestsFileStub = x.Value.TestsFile;
  ...
}

Generating a TSNamespaceSet for COM type libraries

To generate a TSNamespaceSet from a COM type library, use TlbInf32Generator:

var generator = new TlbInf32Generator();

To add a library from the registry:

var args = new {
  tlbid = "{420B2830-E718-11CF-893D-00A0C9054228}",
  majorVersion = 1,
  minorVersion = 1,
  lcid = 0
};
generator.AddFromRegistry(args.tlbid, args.majorVersion, args.minorVersion, args.lcid);

All arguments except for the TLBID are optional. The highest registered version in the registry with the matching details will be used.

To add a library from a file:

generator.AddFromFile(@"c:\path\to\file.dll");

To add a library based on keywords in the name (case-insensitive)

generator.AddFromKeywords(new [] {"microsoft word", "microsoft excel"});

Multiple files / registered libraries can be added.

If a library references an external library, the external library will also be added to the namespace set. For example, since the Microsoft Word obejct library uses types from the Microsoft Office shared object library, the namespace set will contain both Microsoft Word and Microsoft Office object libraries.

To get the TSNamespaceSet:

TSNamespaceSet nsset = generator.NSSet;

Event handlers and parameterized setters

Standard Javascript doesn't support the Microsoft JScript-specific syntax used for registering event handlers on ActiveX objects (objectname::eventname) and for property setters with parameters (object.Item(1) = 1). activex-js-helpers allows the use of standard JS for these tasks. Generated definitions include overloads that leverage the library.

interface ActiveXObject {
    ...
    on(obj: Word.Application, eventName: 'DocumentBeforeClose', eventArgs: ['Doc','Cancel'], handler: (
        this: Word.Application, parameter: {Doc: Word.Document,Cancel: boolean}) => void): void;
    on(obj: Word.Application, eventName: 'DocumentBeforeSave', eventArgs: ['Doc','SaveAsUI','Cancel'], handler: (
        this: Word.Application, parameter: {Doc: Word.Document,SaveAsUI: boolean,Cancel: boolean}) => void): void;
    on(obj: Word.Application, eventName: 'DocumentChange', handler: (
        this: Word.Application, parameter: {}) => void): void;
    on(obj: Word.Application, eventName: 'DocumentOpen', eventArgs: ['Doc'], handler: (
        this: Word.Application, parameter: {Doc: Word.Document}) => void): void;
    ...
    set(obj: Word.Document, propertyName: 'ActiveWritingStyle', parameterTypes: [any], newValue: string): void;
    ...

Generating a TSNamespace for the LibreOffice API

LibreOffice supports generating documentation using Doxygen, which provides an intermediate XML format. Using the outputted XML, the following is possible:

var generator = new DoxygenIDLBuilder(@"c:\path\to\xml\files", Context.Automation);
TSNamespaceSet nsset = generator.NSSet;
var builder = new TSBuilder();
NamespaceOutput output = builder.GetTypescript(nsset);
string typescriptDefinitions = output.MainFile;

Theoretically, definitions could be useful in three contexts:

  • JScript via Automation under WSH, or other environments supporting the use of the ActiveXObject constructor function
  • Javascript macros embedded in LibreOffice documents, or in the local LibreOffice instance
  • Document / application manipulation under NodeJS (I don't know if this is even possible)

Each context has specific details of the available type mappings. For example, under Automation a method which expects the native sequence<int> can also take a SafeArray<number>; the Automation bridge is responsible for converting between the two types. However, in embedded Javascript macros, there is no concept of a SafeArray<T>, and therefore the definitions will be different.

Currently only definitions for the Automation context are implemented.

Changes to the object model under the Automation context include:

  • Parameters taking a sequence<T> can handle a SafeArray<T>
  • Pairs of get<X>/set<X> methods are exposed as simple properties
  • The ServiceManager has some additional methods -- Bridge_GetStruct, Bridge_GetValueObject, DefaultContext

All such changes are wrapped in a check for the current context:

//create the LibreOffice SequenceEquivalent
var equivalents = new List<string>() { "sequence", "Array" };
if (context == Automation) { equivalents.Add("SafeArray"); }

so it will be relatively simple to reflect changes made in other contexts.

You can’t perform that action at this time.