Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoke the text plugin from requirejs mapping

I'm writing a web app using TypeScript, Backbone, and Mustache. I want to use Requirejs for dependency loading.

I'm also using the Web Essentials visual studio plugin for TypeScript with the AMD compilation option turned on. For those that are not familiar with this, it will wrap your type script file in an AMD module if you import external modules. For example:

In type script I import the following modules in type definition files.

export import Backbone = module("Backbone"); 
import mainTemplate = module("MainTemplate");

The output is something like:

define(["require", "exports", "Backbone", "MainTemplate"], function(require, exports, __Backbone__, __mainTemplate__) {
//...code goes here ...
});

For the template, I've declared the following in a type definition file:

declare module "MainTemplate" { }

In order to support requirejs plugins, you need to declare your module as:

declare module "text!MainTemplate.html" { }

I'd like to keep the module name free of plugins and file extensions. This would leave me with some flexibility in the future.

I have the following mapping in require.

require.config({
    map: {
        "MyModule": {
            "MainTemplate": "text!MainTemplate.html"
        }
    }
}

This successfully invokes the text plugin however, the plugin loads the wrong url. Sifting through the source code for the text plugin, I found that the following code is the culprit.

load: function (name, req, onLoad, config) {
  ...
  url = req.toUrl(nonStripName),
  //returns "scripts/**text!**MainTemplate.html**.html**"
  ...
}

If I name the module, 'MainTemplate.html' it works fine but I'd like to keep the extension out of the module name.

I've modified the text plugin with a simple regex replacement to strip out the plugin reference and the duplicate extension.

Is there a better way to handle this?

like image 381
Khoi Pham Avatar asked Dec 16 '12 23:12

Khoi Pham


2 Answers

There is a slightly nicer way to do this (I'm using typescript 2.0) Referenced here: https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html

This code expects that your requirejs configuration and plugins are set up correctly:

/// <amd-dependency path="text!./about.html" name="template"/>
declare let template: string;

This helped me a lot to migrate lagacy code to typescript.

like image 114
mode777 Avatar answered Oct 16 '22 17:10

mode777


For Typescript 1.0 this works for me. First I created a .d.ts file which stores all module declarations for each text template.

//workaround for typescript's lack of support for requirejs text template notation
//remember that a reference to the import variable has to be found in the class, otherwise typescript ignores the import
declare module "text!views/details/details.html" {
    var text: string;
    export = text;
} 
declare module "text!views/layout/layout.html" {
    var text: string;
    export = text;
} 
declare module "text!views/home/home.html" {
    var text: string;
    export = text;
} 

then to refer to the text template I add these lines on top of the class/module.

/// <reference path="../texttemplate.d.ts"/>
import detailsTemplate = require('text!views/details/details.html');

The reference line is not actually needed, since the .d.ts file is picked up globally. But I added it as a reminder of the workaround. It also makes it easy to ctrl+click to go the d.ts. file.

like image 38
Tedy Pranolo Avatar answered Oct 16 '22 19:10

Tedy Pranolo