= 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://github.com/{gh-name}/workflows/CI/badge.svg[Build Status, link=https://github.com/{gh-name}/actions?query=workflow%3A%22CI%22] 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 <>. === 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] 14+ * 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.