npm package: @patrickkettner/ts-transformer-inline-file
Description: A TypeScript custom transformer for inlining files
Author: Jakub Jirutka
Latest version: 0.1.2

= TypeScript transformer for inlining files
:npm-name: ts-transformer-inline-file
:gh-name: jirutka/{npm-name}
:gh-branch: master
:vs-marketplace-uri: https://marketplace.visualstudio.com/items?itemName=

ifdef::env-github[]
image:https://travis-ci.com/{gh-name}.svg?branch={gh-branch}[Build Status, link="https://travis-ci.com/{gh-name}"]
image:https://img.shields.io/npm/v/{npm-name}.svg[npm Version, link="https://www.npmjs.org/package/{npm-name}"]
endif::env-github[]

This is a TypeScript AST transformer footnote:[If you’ve never heard about TypeScript transformers, I can recommend https://blog.logrocket.com/using-typescript-transforms-to-enrich-runtime-code-3fd2863221ed/[this blog post] to dive into the topic.] that allows you to include content of a file into the transpiled code, i.e. _inline it_ in build-time.

You can think about it as a C preprocessor’s directive `#include` but more powerful… way more powerful.
If the referenced file is a JSON file, it doesn’t include it as a string but converts the JSON to an object literal.
Thus it can be further optimized by a minifier.
Moreover, if you use an object destructing assignment, this transformer will optimize it itself -- include only the assigned properties!


== Usage

Add {npm-name} package to your project as a **dev**elopment dependency and <<How to Configure the Transformer, configure the transformer>>.


=== Inline Any Textual File

[source, js, subs="+attributes"]
----
import { $INLINE_FILE } from '{npm-name}'

const words = $INLINE_FILE('../data/words.txt').trim().split(' ')
----

This will be transformed into:

[source, js]
const words = "lorem ipsum dolor\n".trim().split(' ');

…where `"lorem ipsum dolor\n"` is full content of the file `../data/words.txt`.


=== Inline JSON Data

[source, js, subs="+attributes"]
----
import { $INLINE_JSON } from '{npm-name}'

const pkg = $INLINE_JSON('../package.json')
----

This will be transformed into:

[source, js]
const pkg = { "name": "my-package", "version": "0.1.0", "license": "MIT", ... }

However, if you need only few properties from the referenced JSON file, use object destructuring assignment:

[source, js]
const { name, version } = $INLINE_JSON('../package.json')

…and the transformer will include only the assigned properties:

[source, js]
const { name, version } = { "name": "my-package", "version": "0.1.0" }

NOTE: This works only for the top level; filtering of nested properties is currently not supported.


== How to Configure the Transformer

Unfortunately, TypeScript itself does not currently provide any easy way to use custom transformers (see https://github.com/Microsoft/TypeScript/issues/14419[Microsoft/TypeScript#14419]).
Fortunately, there are few solutions.


=== TTypescript

If you don’t use any bundler such as Rollup or webpack, https://github.com/cevek/ttypescript[TTypescript] is the way to go.
It provides wrappers `ttsc` and `ttserver` for the `tsc` and `tsserver` commands that add support for custom transformers.
All you have to do is to use these wrappers instead of the original commands and define the transformer in your `tsconfig.json`:

.tsconfig.json:
[source, jsonc, subs="+attributes"]
----
{
  "compilerOptions": {
    // ...
    "plugins": [
      { "transform": "{npm-name}/transformer" }
    ]
  },
  // ...
}
----


=== Rollup (with rollup-plugin-typescript2)

.rollup.config.js:
[source, js, subs="+attributes"]
----
import typescript from 'rollup-plugin-typescript2'
import inlineFileTransformer from '{npm-name}/transformer'

export default {
  // ...
  plugins: [
    typescript({
      transformers: [
        (service) => ({
          before: [ inlineFileTransformer(service.getProgram()) ],
          after: [],
        }),
      ],
    }),
  ],
}
----


=== Webpack (with ts-loader or awesome-typescript-loader)

.webpack.config.js:
[source, js, subs="+attributes"]
----
const inlineFileTransformer = require('{npm-name}/transformer').default

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader', // or 'awesome-typescript-loader',
        options: {
          getCustomTransformers: (program) => ({
            before: [
              inlineFileTransformer(program),
            ],
          }),
        },
      },
    ],
  },
}
----


ifndef::npm-readme[]

== Development

=== System Requirements

* https://nodejs.org[NodeJS] 10.13+
* https://pandoc.org[Pandoc] and https://asciidoctor.org[Asciidoctor] (used only for converting README.adoc to Markdown for npmjs)


=== Used Tools

* https://www.typescriptlang.org[TypeScript] the language
* https://yarnpkg.com[yarn] for dependencies management and building
* https://eslint.org[ESLint] for linting JS/TypeScript code
* https://github.com/substack/tape[tape] for testing


=== How to Start

. Clone this repository:
[source, subs="+attributes"]
git clone https://github.com/{gh-name}.git
cd {npm-name}

. Install Yarn (if you don’t have it already):
[source]
npm install -g yarn

. Install all JS dependencies:
[source]
yarn install

. Build the project:
[source]
yarn build

. Run tests:
[source]
yarn test

. Run linter:
[source]
yarn lint


=== Visual Studio Code

If you use Visual Studio Code, you may find the following extensions useful:

* link:{vs-marketplace-uri}EditorConfig.EditorConfig[EditorConfig for VS Code]
* link:{vs-marketplace-uri}dbaeumer.vscode-eslint[ESLint]
* link:{vs-marketplace-uri}gamunu.vscode-yarn[yarn]

endif::[]


== License

This project is licensed under http://opensource.org/licenses/MIT/[MIT License].
For the full text of the license, see the link:LICENSE[LICENSE] file.