From ca20b6ac0600267f305a22ea2aea588a819faeed Mon Sep 17 00:00:00 2001 From: Adrian Schubek Date: Wed, 5 Apr 2023 16:17:26 +0200 Subject: [PATCH] add safe mode --- docs/docs/advanced/_category_.json | 8 +++ docs/docs/advanced/safe.mdx | 36 +++++++++++ docs/docs/development/_category_.json | 2 +- docs/docs/getting-started/usage.mdx | 33 ++++++----- .../version-0.3.x/getting-started/usage.mdx | 1 + .../version-0.4.x/advanced/_category_.json | 8 +++ .../version-0.4.x/advanced/safe.mdx | 36 +++++++++++ .../version-0.4.x/api/_category_.json | 8 +++ .../version-0.4.x/api/commands.mdx | 45 ++++++++++++++ .../version-0.4.x/development/_category_.json | 8 +++ .../version-0.4.x/development/contribute.mdx | 9 +++ .../version-0.4.x/development/roadmap.mdx | 10 ++++ .../version-0.4.x/examples/_category_.json | 8 +++ .../version-0.4.x/examples/basic.mdx | 45 ++++++++++++++ .../getting-started/_category_.json | 8 +++ .../version-0.4.x/getting-started/blocks.mdx | 13 ++++ .../getting-started/commands.mdx | 7 +++ .../getting-started/how-it-works.mdx | 11 ++++ .../getting-started/installation.md | 52 ++++++++++++++++ .../getting-started/printing.mdx | 11 ++++ .../version-0.4.x/getting-started/usage.mdx | 50 ++++++++++++++++ .../version-0.4.x/getting-started/values.mdx | 12 ++++ .../getting-started/variables.mdx | 11 ++++ docs/versioned_docs/version-0.4.x/intro.md | 38 ++++++++++++ .../version-0.4.x-sidebars.json | 8 +++ docs/versions.json | 1 + package.json | 2 +- src/index.ts | 59 +++++++++++++------ 28 files changed, 507 insertions(+), 33 deletions(-) create mode 100644 docs/docs/advanced/_category_.json create mode 100644 docs/docs/advanced/safe.mdx create mode 100644 docs/versioned_docs/version-0.4.x/advanced/_category_.json create mode 100644 docs/versioned_docs/version-0.4.x/advanced/safe.mdx create mode 100644 docs/versioned_docs/version-0.4.x/api/_category_.json create mode 100644 docs/versioned_docs/version-0.4.x/api/commands.mdx create mode 100644 docs/versioned_docs/version-0.4.x/development/_category_.json create mode 100644 docs/versioned_docs/version-0.4.x/development/contribute.mdx create mode 100644 docs/versioned_docs/version-0.4.x/development/roadmap.mdx create mode 100644 docs/versioned_docs/version-0.4.x/examples/_category_.json create mode 100644 docs/versioned_docs/version-0.4.x/examples/basic.mdx create mode 100644 docs/versioned_docs/version-0.4.x/getting-started/_category_.json create mode 100644 docs/versioned_docs/version-0.4.x/getting-started/blocks.mdx create mode 100644 docs/versioned_docs/version-0.4.x/getting-started/commands.mdx create mode 100644 docs/versioned_docs/version-0.4.x/getting-started/how-it-works.mdx create mode 100644 docs/versioned_docs/version-0.4.x/getting-started/installation.md create mode 100644 docs/versioned_docs/version-0.4.x/getting-started/printing.mdx create mode 100644 docs/versioned_docs/version-0.4.x/getting-started/usage.mdx create mode 100644 docs/versioned_docs/version-0.4.x/getting-started/values.mdx create mode 100644 docs/versioned_docs/version-0.4.x/getting-started/variables.mdx create mode 100644 docs/versioned_docs/version-0.4.x/intro.md create mode 100644 docs/versioned_sidebars/version-0.4.x-sidebars.json diff --git a/docs/docs/advanced/_category_.json b/docs/docs/advanced/_category_.json new file mode 100644 index 0000000..00eb786 --- /dev/null +++ b/docs/docs/advanced/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "⚡ Advanced", + "position": 4, + "link": { + "type": "generated-index", + "description": "Advanced concepts" + } +} diff --git a/docs/docs/advanced/safe.mdx b/docs/docs/advanced/safe.mdx new file mode 100644 index 0000000..7105ea5 --- /dev/null +++ b/docs/docs/advanced/safe.mdx @@ -0,0 +1,36 @@ +--- +sidebar_position: 1 +--- + +# Safe Mode + +When using a wide glob pattern (such as `*/**`), utpp may match files that you don't want to be processed like compiled binaries etc. +This could result in the following errors if utpp tries to match a pattern in them: + +``` +foo.txt: Command '$[�u�`�F�C���2���%�bԪ]$' found but it is not part of any block. +foo.txt: Found 1 unmatched commands. Please check your syntax. +``` + +or + +``` +bar.txt: Command '�Z��C��9�' does not exist. +``` + +To prevent this, you can use the `--safe` flag. This will cause utpp to only process files that contains the string `///utpp` anywhere in the file. +This is a good way to ensure that utpp only processes files that you want it to if you are unable to restrict your glob pattern. +All occurances of `///utpp` will be removed from the file. + +### Ignore unkown commands + +As an alternative to safe mode, you can use the `--ignore-unknown` flag. This will cause utpp to ignore any commands that it doesn't recognize. +If a command is not recognized in a block, the entire block will be ignored (unchanged). + +:::caution +Typos in commands will be ignored with this flag and no error will be thrown. This could result in unwanted behavior. +::: + +:::info +This flag only checks for unkown **commands**, not variables. +::: diff --git a/docs/docs/development/_category_.json b/docs/docs/development/_category_.json index 6daaf66..9b1ef63 100644 --- a/docs/docs/development/_category_.json +++ b/docs/docs/development/_category_.json @@ -1,6 +1,6 @@ { "label": "🛠️ Development", - "position": 5, + "position": 9, "link": { "type": "generated-index", "description": "Contribute to the development of the project", diff --git a/docs/docs/getting-started/usage.mdx b/docs/docs/getting-started/usage.mdx index 57eb8b4..c104f19 100644 --- a/docs/docs/getting-started/usage.mdx +++ b/docs/docs/getting-started/usage.mdx @@ -10,26 +10,30 @@ Universal Text Pre-Processor ('utpp') is a tool for preprocessing any file Usage: utpp [options] [variables] Options: - --help Show help [boolean] - --version Show version number [boolean] - -o, --output write to output file [string] - -c, --check checks the file's syntax only [boolean] [default: false] - -v, --verbose show more debug logs [boolean] [default: false] - -p, --print prints the output to stdout instead of files [boolean] - -q, --quiet makes the preprocessor quiet [boolean] [default: false] - --ignore glob pattern to ignore files [string] [default: ""] - --no-eval disables eval function [boolean] - --no-files disables inclusion from files [boolean] - --no-urls disables inclusion from urls [boolean] - --no-env disables inclusion of environment variables [boolean] - --no-template disables template replacement [boolean] - --no-vars disables variables replacement [boolean] + --help Show help [boolean] + --version Show version number [boolean] + -o, --output write to output file [string] + -c, --check checks the file's syntax only [boolean] [default: false] + -v, --verbose show more debug logs [boolean] [default: false] + -p, --print prints the output to stdout instead of files [boolean] + -q, --quiet makes the preprocessor quiet [boolean] [default: false] + --ignore glob pattern to ignore files [string] [default: ""] + --no-eval disables eval function [boolean] + --no-files disables inclusion from files [boolean] + --no-urls disables inclusion from urls [boolean] + --no-env disables inclusion of environment variables [boolean] + --no-template disables template replacement [boolean] + --no-vars disables variables replacement [boolean] + --ignore-unkown ignores unknown commands to improve compat [boolean] + --safe enables safe mode: only process marked files [boolean] Examples: utpp -o out.txt input.txt runs the preprocessor on input.txt and write output to out.txt utpp input.txt foo=bar runs the preprocessor on input.txt and sets variable foo to bar + utpp "*/**" foo=bar runs the preprocessor on all files in the current & + sub directory and sets variable foo to bar utpp -c input.txt validates the syntax of input.txt file for more info and support visit https://github.com/adrianschubek/utpp @@ -38,6 +42,7 @@ for more info and support visit https://github.com/adrianschubek/utpp :::tip You can use any glob pattern as *files* argument to select multiple files. For example `utpp "*/**" foo=bar` will run the preprocessor on all files in the current directory and all subdirectories and set the variable `foo` to `bar`. +Or `utpp "foo.txt;bar.tex;baz.html"` will run the preprocessor on `foo.txt`, `bar.tex` and `baz.html`. ::: :::info diff --git a/docs/versioned_docs/version-0.3.x/getting-started/usage.mdx b/docs/versioned_docs/version-0.3.x/getting-started/usage.mdx index 941881d..9ce58a2 100644 --- a/docs/versioned_docs/version-0.3.x/getting-started/usage.mdx +++ b/docs/versioned_docs/version-0.3.x/getting-started/usage.mdx @@ -38,6 +38,7 @@ for more info and support visit https://github.com/adrianschubek/utpp :::tip You can use any glob pattern as *files* argument to select multiple files. For example `utpp "*/**" foo=bar` will run the preprocessor on all files in the current directory and all subdirectories and set the variable `foo` to `bar`. +Or `utpp "foo.txt;bar.tex;baz.html"` will run the preprocessor on `foo.txt`, `bar.tex` and `baz.html`. ::: :::info diff --git a/docs/versioned_docs/version-0.4.x/advanced/_category_.json b/docs/versioned_docs/version-0.4.x/advanced/_category_.json new file mode 100644 index 0000000..00eb786 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/advanced/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "⚡ Advanced", + "position": 4, + "link": { + "type": "generated-index", + "description": "Advanced concepts" + } +} diff --git a/docs/versioned_docs/version-0.4.x/advanced/safe.mdx b/docs/versioned_docs/version-0.4.x/advanced/safe.mdx new file mode 100644 index 0000000..7105ea5 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/advanced/safe.mdx @@ -0,0 +1,36 @@ +--- +sidebar_position: 1 +--- + +# Safe Mode + +When using a wide glob pattern (such as `*/**`), utpp may match files that you don't want to be processed like compiled binaries etc. +This could result in the following errors if utpp tries to match a pattern in them: + +``` +foo.txt: Command '$[�u�`�F�C���2���%�bԪ]$' found but it is not part of any block. +foo.txt: Found 1 unmatched commands. Please check your syntax. +``` + +or + +``` +bar.txt: Command '�Z��C��9�' does not exist. +``` + +To prevent this, you can use the `--safe` flag. This will cause utpp to only process files that contains the string `///utpp` anywhere in the file. +This is a good way to ensure that utpp only processes files that you want it to if you are unable to restrict your glob pattern. +All occurances of `///utpp` will be removed from the file. + +### Ignore unkown commands + +As an alternative to safe mode, you can use the `--ignore-unknown` flag. This will cause utpp to ignore any commands that it doesn't recognize. +If a command is not recognized in a block, the entire block will be ignored (unchanged). + +:::caution +Typos in commands will be ignored with this flag and no error will be thrown. This could result in unwanted behavior. +::: + +:::info +This flag only checks for unkown **commands**, not variables. +::: diff --git a/docs/versioned_docs/version-0.4.x/api/_category_.json b/docs/versioned_docs/version-0.4.x/api/_category_.json new file mode 100644 index 0000000..6b4fe99 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/api/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "🤖 API Reference", + "position": 4, + "link": { + "type": "generated-index", + "description": "API Reference" + } +} diff --git a/docs/versioned_docs/version-0.4.x/api/commands.mdx b/docs/versioned_docs/version-0.4.x/api/commands.mdx new file mode 100644 index 0000000..4cf4295 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/api/commands.mdx @@ -0,0 +1,45 @@ +# Commands + +## Commands without side effects + +`if ` - return true when `` is truthy, otherwise false. + +`ifdef ` - return true when a variable with name `` is defined, otherwise false. + +`ifndef ` - return true when a variable with name `` is not defined, otherwise false. + +`ifeq ` - return true when `` is equal to ``, otherwise false. + +`ifne ` - return true when `` is not equal to ``, otherwise false. + +`iflt ` - return true when `` is less than ``, otherwise false. + +`ifgt ` - return true when `` is greater than ``, otherwise false. + +`ifge ` - return true when `` is greater than or equal to ``, otherwise false. + +`ifle ` - return true when `` is less than or equal to ``, otherwise false. + +## Commands with side effects + +`ifdefs ` - return true when a variable with name `` is defined, otherwise false. If the statement is true, `` will be set to ``. + +`ifndefs ` - return true when a variable with name `` is not defined, otherwise false. If the statement is true, `` will be set to ``. + +`ifeqs ` - return true when `` is equal to ``, otherwise false. If the statement is true, `` will be set to ``. + +`ifnes ` - return true when `` is not equal to ``, otherwise false. If the statement is true, `` will be set to ``. + +`iflts ` - return true when `` is less than ``, otherwise false. If the statement is true, `` will be set to ``. + +`ifgts ` - return true when `` is greater than ``, otherwise false. If the statement is true, `` will be set to ``. + +`ifges ` - return true when `` is greater than or equal to ``, otherwise false. If the statement is true, `` will be set to ``. + +`ifles ` - return true when `` is less than or equal to ``, otherwise false. If the statement is true, `` will be set to ``. + +## Special Commands + +`else` - used in a block to define an alternative output when no statement in the block is truthy. + +`end` - used to end a block. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.4.x/development/_category_.json b/docs/versioned_docs/version-0.4.x/development/_category_.json new file mode 100644 index 0000000..9b1ef63 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/development/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "🛠️ Development", + "position": 9, + "link": { + "type": "generated-index", + "description": "Contribute to the development of the project", + } +} diff --git a/docs/versioned_docs/version-0.4.x/development/contribute.mdx b/docs/versioned_docs/version-0.4.x/development/contribute.mdx new file mode 100644 index 0000000..0e23d33 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/development/contribute.mdx @@ -0,0 +1,9 @@ +--- +sidebar_position: 2 +--- +# Development + +1. clone this repo +2. run `npm install` +3. run `npm run build:watch` +4. run `node out/index.js` \ No newline at end of file diff --git a/docs/versioned_docs/version-0.4.x/development/roadmap.mdx b/docs/versioned_docs/version-0.4.x/development/roadmap.mdx new file mode 100644 index 0000000..b2390bf --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/development/roadmap.mdx @@ -0,0 +1,10 @@ +--- +sidebar_position: 1 +--- +# Roadmap +- [x] no-template option +- [x] include data from other files +- [x] include data from urls +- [x] support mutliple files as input +- [ ] custom markers +- [ ] possibility to reference variables inside JavaScript expressions diff --git a/docs/versioned_docs/version-0.4.x/examples/_category_.json b/docs/versioned_docs/version-0.4.x/examples/_category_.json new file mode 100644 index 0000000..1b0243c --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/examples/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "✨ Examples", + "position": 3, + "link": { + "type": "generated-index", + "description": "Examples" + } +} diff --git a/docs/versioned_docs/version-0.4.x/examples/basic.mdx b/docs/versioned_docs/version-0.4.x/examples/basic.mdx new file mode 100644 index 0000000..6a4acb2 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/examples/basic.mdx @@ -0,0 +1,45 @@ +--- +sidebar_position: 1 +--- + +# Basic + +*Example: test.txt* +``` +foobar +$[if `1 + 2 == 4`]$ +a +$[ifeq foo bar]$ +b ${{foo}}$ +$[else]$ +c +$[end]$ + +${{`0.1 + 0.2`}}$ + +${{file:incl.txt}}$ + +${{url:https://httpbin.org/uuid}}$ + +${{env:HOME}}$ +``` +*and incl.txt:* `This was included from incl.txt` + +Running this example with `utpp test.txt foo=bar` will result in the following output: +``` +foobar + +b bar + + +0.30000000000000004 + +This was included from incl.txt + +{ + "uuid": "ba95cd1c-2bb9-4a54-a1a4-5379ce1f2fac" +} + + +/home/adrian +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-0.4.x/getting-started/_category_.json b/docs/versioned_docs/version-0.4.x/getting-started/_category_.json new file mode 100644 index 0000000..82ef6f8 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/getting-started/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "🚀 Getting Started", + "position": 2, + "link": { + "type": "generated-index", + "description": "Getting started" + } +} diff --git a/docs/versioned_docs/version-0.4.x/getting-started/blocks.mdx b/docs/versioned_docs/version-0.4.x/getting-started/blocks.mdx new file mode 100644 index 0000000..18c47c3 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/getting-started/blocks.mdx @@ -0,0 +1,13 @@ +--- +sidebar_position: 4 +--- + +# Blocks + +A (template) block can be declared by using one or more `$[]$` statements where `` is a valid command (see API reference below) and must end in a `$[end]$` statement. + +A block's statements are evaluated from top to bottom. If the result of a command is truthy, the guarded section will be outputted and all other commands in this block ignored. + +Otherwise this statement will be skipped and the next statement is evaluated. If no statement in this block is truthy, the `else` section will be outputted and if no `else` section is present, nothing will be outputted. + +There can be any number of blocks declared in a file, but blocks **cannot** be nested. diff --git a/docs/versioned_docs/version-0.4.x/getting-started/commands.mdx b/docs/versioned_docs/version-0.4.x/getting-started/commands.mdx new file mode 100644 index 0000000..f79b3a2 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/getting-started/commands.mdx @@ -0,0 +1,7 @@ +--- +sidebar_position: 5 +--- + +# Commands +A command generally follows this syntax `$[ [arg1] [arg2] ... [argN]]$` +where `` is a [command's name](#commands-reference) `[arg]` is a [*Value*](#values). All commands return either `true` or `false`. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.4.x/getting-started/how-it-works.mdx b/docs/versioned_docs/version-0.4.x/getting-started/how-it-works.mdx new file mode 100644 index 0000000..afb8fae --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/getting-started/how-it-works.mdx @@ -0,0 +1,11 @@ +--- +sidebar_position: 2 +--- + +# How it works + +```mermaid +graph LR; + a(Read file)-->b[Apply template]-->c[Apply variables]-->e(Write file); + +``` diff --git a/docs/versioned_docs/version-0.4.x/getting-started/installation.md b/docs/versioned_docs/version-0.4.x/getting-started/installation.md new file mode 100644 index 0000000..763e6a0 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/getting-started/installation.md @@ -0,0 +1,52 @@ +--- +sidebar_position: 1 +--- + +# Installation + +### Using [npm](https://www.npmjs.com/package/utpp) (recommended) + +``` +npm install -g utpp +``` + +or if you want to test it without installing it globally: + +``` +npx utpp +``` + +### Using Precompiled binaries + +``` +sudo curl -fSsL https://github.com/adrianschubek/utpp/releases/latest/download/utpp-linux -o /usr/local/bin/utpp && sudo chmod +x /usr/local/bin/utpp +``` + +Precompiled binaries for **Linux** (x64, alpine) and **Windows** (x64) are published every [release](https://github.com/adrianschubek/utpp/releases). + +Both compressed (.tar.gz) and uncompressed binaries are available. + +_Linux-alpine_ binaries are designed to be used in docker containers. + +**MacOS** and _arm_ binaries are not published yet, but you can compile them yourself (see below). + +### Inside containers + +If you want to use utpp inside a (alpine) docker container, you can use the alpine binaries. + +```dockerfile title="Dockerfile" +# using curl: +RUN curl -fSsL https://github.com/adrianschubek/utpp/releases/latest/download/utpp-alpine -o /usr/local/bin/utpp && chmod +x /usr/local/bin/utpp +# using wget: +RUN wget -q https://github.com/adrianschubek/utpp/releases/latest/download/utpp-alpine -O /usr/local/bin/utpp && chmod +x /usr/local/bin/utpp +``` + +### Compile binaries yourself + +1. clone this repo +2. run `npm install` +3. run `npm run build:npm` +4. run `npm run pack` +5. binaries for various platforms are compiled in `/dist` + +> Move the executable to `/usr/local/bin` for easier CLI access: `sudo mv /usr/local/bin/utpp` diff --git a/docs/versioned_docs/version-0.4.x/getting-started/printing.mdx b/docs/versioned_docs/version-0.4.x/getting-started/printing.mdx new file mode 100644 index 0000000..94d847b --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/getting-started/printing.mdx @@ -0,0 +1,11 @@ +--- +sidebar_position: 8 +--- + +# Printing + +Outputting a variable can be done using `${{}}$` (curly braces) where `` is any value defined [above](#values). + +:::info +Since version 0.3.0+ the syntax for printing variables has changed from `${}$` to `${{}}$` to avoid some common conflicts. +::: diff --git a/docs/versioned_docs/version-0.4.x/getting-started/usage.mdx b/docs/versioned_docs/version-0.4.x/getting-started/usage.mdx new file mode 100644 index 0000000..c104f19 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/getting-started/usage.mdx @@ -0,0 +1,50 @@ +--- +sidebar_position: 3 +--- + +# Usage + +``` +Universal Text Pre-Processor ('utpp') is a tool for preprocessing any file + +Usage: utpp [options] [variables] + +Options: + --help Show help [boolean] + --version Show version number [boolean] + -o, --output write to output file [string] + -c, --check checks the file's syntax only [boolean] [default: false] + -v, --verbose show more debug logs [boolean] [default: false] + -p, --print prints the output to stdout instead of files [boolean] + -q, --quiet makes the preprocessor quiet [boolean] [default: false] + --ignore glob pattern to ignore files [string] [default: ""] + --no-eval disables eval function [boolean] + --no-files disables inclusion from files [boolean] + --no-urls disables inclusion from urls [boolean] + --no-env disables inclusion of environment variables [boolean] + --no-template disables template replacement [boolean] + --no-vars disables variables replacement [boolean] + --ignore-unkown ignores unknown commands to improve compat [boolean] + --safe enables safe mode: only process marked files [boolean] + +Examples: + utpp -o out.txt input.txt runs the preprocessor on input.txt and write output + to out.txt + utpp input.txt foo=bar runs the preprocessor on input.txt and sets + variable foo to bar + utpp "*/**" foo=bar runs the preprocessor on all files in the current & + sub directory and sets variable foo to bar + utpp -c input.txt validates the syntax of input.txt file + +for more info and support visit https://github.com/adrianschubek/utpp +``` + +:::tip +You can use any glob pattern as *files* argument to select multiple files. +For example `utpp "*/**" foo=bar` will run the preprocessor on all files in the current directory and all subdirectories and set the variable `foo` to `bar`. +Or `utpp "foo.txt;bar.tex;baz.html"` will run the preprocessor on `foo.txt`, `bar.tex` and `baz.html`. +::: + +:::info +Show this help page by running `utpp`. +::: \ No newline at end of file diff --git a/docs/versioned_docs/version-0.4.x/getting-started/values.mdx b/docs/versioned_docs/version-0.4.x/getting-started/values.mdx new file mode 100644 index 0000000..becdcfe --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/getting-started/values.mdx @@ -0,0 +1,12 @@ +--- +sidebar_position: 6 +--- + +# Values +- Values can reference Variables by using their name (e.g. `foo` where `foo` is variable). +- Values are treated as strings by default and cannot contain spaces (e.g. `foobar123`). +- Values surrounded by `"` are treated as strings and can contain spaces (e.g. `"foo bar"`). +- Values surrounded by `` ` `` (backticks) are evaluated using JavaScript's `eval` function. This means you can use any valid JavaScript expression inside (e.g. `` `0.1 + 0.2` ``). +- Values starting with `file:` are treated as file paths and the file's content is used as the value (e.g. `file:foo.txt` where `foo.txt` is a file relative to the preprocessed file.). +- Values starting with `url:` are treated as URLs and the URL's content is used as the value (e.g. `url:https://myapi.com/version`). +- Values starting with `env:` are treated as environment variables and the environment variable's value is used as the value (e.g. `env:HOME`). diff --git a/docs/versioned_docs/version-0.4.x/getting-started/variables.mdx b/docs/versioned_docs/version-0.4.x/getting-started/variables.mdx new file mode 100644 index 0000000..0c56bd2 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/getting-started/variables.mdx @@ -0,0 +1,11 @@ +--- +sidebar_position: 7 +--- + +# Variables + +A variable can be used inside a template block's *Value* argument by using its name. Variables are stored globally and changes to a variable can only affect statements declared **after** the current one. + +Variables can be declared on CLI execution using `key=value` pairs or just a `key`. Multiple variables can be passed as arguments by using spaces like `foo=bar foz="baz 123" foobar`. + +Statements ending in `s` (e.g. `ifeqs`) can set a variable when their statement evaluates to `true`. (see [reference](#commands-reference)) diff --git a/docs/versioned_docs/version-0.4.x/intro.md b/docs/versioned_docs/version-0.4.x/intro.md new file mode 100644 index 0000000..91f17b5 --- /dev/null +++ b/docs/versioned_docs/version-0.4.x/intro.md @@ -0,0 +1,38 @@ +--- +sidebar_position: 1 +slug: / +--- + +# 👋 Welcome + +![](/img/utpp.png) + +
+ +![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) +[![npm](https://img.shields.io/npm/v/utpp?color=blue&style=for-the-badge)](https://www.npmjs.com/package/utpp) + +
+ +## Features +- **Universal**: works with any file format +- **Branching**: use if/else logic to include/exclude/modify parts of your file +- **Variables**: use placeholders in your file and replace them with variables +- **Scripting**: execute custom JavaScript code anywhere +- **Portable**: works on any platform (Windows, Linux, MacOS, Docker containers etc.) + +## Use Cases +- Dynamically modifiy static config files based on user input +- Replace placeholder with custom eval'd JavaScript on startup +- Start a supervisor service conditionally using docker run arguments. +- Use different compile commands based on user's current architecture +- and many more... + +
+Screenshots + +![](/img/p1.png) +![](/img/p2.png) +![](/img/p3.png) + +
diff --git a/docs/versioned_sidebars/version-0.4.x-sidebars.json b/docs/versioned_sidebars/version-0.4.x-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/docs/versioned_sidebars/version-0.4.x-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/docs/versions.json b/docs/versions.json index b7a4bb4..486c4be 100644 --- a/docs/versions.json +++ b/docs/versions.json @@ -1,3 +1,4 @@ [ + "0.4.x", "0.3.x" ] diff --git a/package.json b/package.json index fca043a..8fd2094 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "utpp", - "version": "0.3.0", + "version": "0.4.0", "description": "Universal Text Pre-Processor", "main": "bin/index.js", "bin": "bin/npx.js", diff --git a/src/index.ts b/src/index.ts index cc61b6d..f6b5bda 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,6 +24,7 @@ process.emit = function (name, data: any, ...args) { .version() .example("utpp -o out.txt input.txt", "runs the preprocessor on input.txt and write output to out.txt") .example("utpp input.txt foo=bar", "runs the preprocessor on input.txt and sets variable foo to bar") + .example('utpp "*/**" foo=bar', "runs the preprocessor on all files in the current & sub directory and sets variable foo to bar") .example("utpp -c input.txt", "validates the syntax of input.txt file") .command( ["run ", "$0"], @@ -124,6 +125,14 @@ process.emit = function (name, data: any, ...args) { .option("no-vars", { describe: "disables variables replacement", type: "boolean", + }) + .option("ignore-unkown", { + describe: "ignores unknown commands to improve compat", + type: "boolean", + }) + .option("safe", { + describe: "enables safe mode: only process marked files", + type: "boolean", }); }, async (argv: any) => { @@ -138,7 +147,7 @@ process.emit = function (name, data: any, ...args) { type RetType = boolean; // for parseArg relative file includes - let currentFilename = ""; + let file: string = ""; const parseArg = async (arg: string, failOnNotFound: boolean = false): Promise => { return new Promise(async (resolve) => { @@ -165,7 +174,7 @@ process.emit = function (name, data: any, ...args) { stop(1); } - const fullPath = path.resolve(path.dirname(currentFilename) + path.sep + relativePath); + const fullPath = path.resolve(path.dirname(file) + path.sep + relativePath); if (!fs.existsSync(fullPath)) { err( chalk.red(`File '${fullPath}' does not exist. Make sure that '${relativePath}' is relative to '${path.dirname(argv.file)}' folder.`) @@ -199,7 +208,7 @@ process.emit = function (name, data: any, ...args) { console.log(chalk.red(`JavaScript evaluation \`${arg}\` is disabled, because option '--no-eval' is set`)); stop(1); } - return resolve(eval(arg.slice(1, -1))); + return resolve((0, eval)(arg.slice(1, -1))); // is string } else if (arg.startsWith('"') && arg.endsWith('"')) { return resolve(arg.slice(1, -1)); @@ -209,7 +218,13 @@ process.emit = function (name, data: any, ...args) { // raw string } else { if (failOnNotFound) { - console.log(chalk.red(`Variable '${arg}' is not defined`)); + // to remove: ignore not found if safemode and leave var unchanged + /* if (argv.ignoreUnkown) { + log(chalk.yellow(`Ignoring unknown command '${arg}'`)); + return resolve("${{" + arg + "}}$"); + } */ + + log(chalk.red(`Variable '${arg}'s is not defined`)); stop(1); } else return resolve(arg); } @@ -356,12 +371,12 @@ process.emit = function (name, data: any, ...args) { // default log const log = (message?: any, ...optionalParams: any[]) => { - if (!argv.quiet) console.log(message, ...optionalParams); + if (!argv.quiet) console.log(chalk.gray(`${file}: `) + message, ...optionalParams); }; // error log (even if quiet) const err = (message?: any, ...optionalParams: any[]) => { - console.log(message, ...optionalParams); + console.log(chalk.gray(`${file}: `) + message, ...optionalParams); }; // verbose log (uses default log) @@ -410,19 +425,25 @@ process.emit = function (name, data: any, ...args) { vlog("Files", files); for (let i = 0; i < files.length; i++) { - const file = files[i]; - currentFilename = file; - vlog(`Processing file ${i + 1}/${files.length}: ${file}`); + file = files[i]; + vlog(`Processing file ${i + 1}/${files.length}`); // raw file data let data = fs.readFileSync(file, "utf-8").toString(); + // if safe mode: check if marker exists else skip file + if (argv.safe && !data.includes("///utpp")) { + log(chalk.yellow(`Ignoring file. (safe mode)`)); + continue; + } + data = data.replaceAll("///utpp", ""); + let processedBlocks = 0; if (argv.template) { const blockMatches = data.matchAll(/(\$\[(.*?)\]\$)([\w\W]*?)(\$\[end\]\$)/g) || []; - for (const block of blockMatches) { + blocks: for (const block of blockMatches) { processedBlocks++; blockId++; vlog(">> NEXT BLOCK "); @@ -461,8 +482,8 @@ process.emit = function (name, data: any, ...args) { const command = commands.find((c) => c.name === cmdArgs[0].trim()); if (!command) { err(chalk.red(`Command '${cmdArgs[0]}' does not exist.`)); - stop(1); - continue; + if (!argv.ignoreUnkown) stop(1); + continue blocks; } // check if command arguments count is correct @@ -531,11 +552,15 @@ process.emit = function (name, data: any, ...args) { let numUnmatched = 0; for (const match of unmatchedCommands) { numUnmatched++; - err(chalk.red(`Command '${match[0]}' found but it is not part of any block.`)); + if (!argv.ignoreUnkown) err(chalk.red(`Command '${match[0]}' found but it is not part of any block.`)); } if (numUnmatched > 0) { - err(chalk.red(`Found ${numUnmatched} unmatched commands. Please check your syntax.`)); - stop(1); + if (!argv.ignoreUnkown) { + err(chalk.red(`Found ${numUnmatched} unmatched commands. Please check your syntax.`)); + stop(1); + } else { + log(chalk.yellow(`Ignoring ${numUnmatched} unmatched commands.`)); + } } } @@ -590,10 +615,10 @@ process.emit = function (name, data: any, ...args) { if (argv.check || argv.verbose) { // warn if there are no matches/blocks if (processedBlocks === 0) { - log(chalk.gray(`${file}: `) + chalk.yellow("No blocks found.")); + log(chalk.yellow("No blocks found.")); } else { // output processed blocks - log(chalk.gray(`${file}: `) + chalk.green(`Processed ${processedBlocks} blocks and ${processVars} prints. Syntax OK.`)); + log(chalk.green(`Processed ${processedBlocks} blocks and ${processVars} prints. Syntax OK.`)); } } }