Finds where are arbitrary templating marker heads and tails located

§ Quick Take

import { strict as assert } from "assert";
import { strFindHeadsTails } from "string-find-heads-tails";

// processing an arbitrary, custom templating markup:
    "some text %%_var1-%% more text %%_var2_%%",
    ["%%_", "%%-"], // two flavours of heads
    ["-%%", "_%%"] // two flavours of tails
      headsStartAt: 10,
      headsEndAt: 13,
      tailsStartAt: 17,
      tailsEndAt: 20,
      headsStartAt: 31,
      headsEndAt: 34,
      tailsStartAt: 38,
      tailsEndAt: 41,

§ Purpose

There are many templating languages out there, each using different special "markers" — Nunjucks use {{ and }}, Salesforce use {! and }, Mailchimp use *| and |* — there are many templating languages.

We call those "markers" heads and tails (invented term) because we need to distinguish between the two.

This program finds out, where are the templating marker heads and tails located in a given string.

It will be used in JSON pre-processing and it will let you use any existing or invented templating language.

§ Context

It's a (scanerless) parser for arbitrary templating language markers.

There are few rules:

  • Each finding must be in sequence: heads - tails - heads - tails.
  • When one heads is found, no new heads findings will be accepted into the results until there's a new tails finding. Same goes the opposite way, for tails.
  • Both heads and tails can be supplied either as a single string or array of strings. Findings are prioritised by their order in the array.



In other words, it's a function which takes four input arguments, last-one optional (marked with square brackets).

You can switch to grapheme count-based index system — use nativeToUnicode() method of string-convert-indexes. It can process the whole output of this library.

§ API - Input

Input argumentTypeObligatory?Description
strStringyesThe string in which you want to perform a search
headsString or Array of stringsyesOne or more string, the first half of the set. For example, ['%%-', '%%_'].
tailsString or Array of stringsyesOne or more string, the second half of the set. For example, ['-%%', '_%%'].
optsPlain objectnoAn Optional Options Object. See its API below.

PS. Input arguments are not mutated.

§ Optional Options Object

options object's keyType of its valueDefaultDescription
fromIndexNatural number or zero as number or string0If you want to start the search later, only from a certain index, set it here. Same as 2nd argument position in String.includes.
throwWhenSomethingWrongIsDetectedBooleantrueBy default, if anything wrong is detected, error will be thrown. For example, tails precede heads. Or two conescutive heads or tails are detected. If you want to turn this functionality off, set to false. Turning this off automatically sets the allowWholeValueToBeOnlyHeadsOrTails (see below) to true, that is, error won't be thrown when whole input is equal to one of heads or tails. This setting does not concern wrong input types. To allow input in wrong types, set relaxedAPI, see below.
allowWholeValueToBeOnlyHeadsOrTailsBooleantrueIf whole input str is equal to one of heads or tails AND opts.throwWhenSomethingWrongIsDetected is true, THEN error won't be thrown and that input will not be processed. But if you set this to false AND error throwing is on (opts.throwWhenSomethingWrongIsDetected is true), error will be thrown. This feature is activated only when opts.throwWhenSomethingWrongIsDetected is true.
sourceStringstring-find-heads-tailsPackages that consume this package as a dependency might rely on some of our error throwing functionality. Since thrown message mentions the name of the throwee, you can override it, setting to parent package's name.
matchHeadsAndTailsStrictlyInPairsByTheirOrderBooleanfalseIf it's set to true, the index numbers of heads and tails in their input arrays must match. Different pairs can have different indexes, as long as they match between the pair. For example, %%_test-%% or %%-test_%%.
relaxedAPIBooleanfalseIf it's set to true, wrong inputs will instantly yield []. If it's default setting, false, it would throw an error. This only concerns the checks before any real work is done on the input, where error-throwing is controlled by throwWhenSomethingWrongIsDetected (see above).

Here is the Optional Options Object in one place with all default settings:

fromIndex: 0,
throwWhenSomethingWrongIsDetected: true,
allowWholeValueToBeOnlyHeadsOrTails: true,
source: 'string-find-heads-tails',
matchHeadsAndTailsStrictlyInPairsByTheirOrder: false,
relaxedAPI: false

§ API - Output

Returns an array of zero or more plain objects, each having format:

headsStartAt: 1,
headsEndAt: 2,
tailsStartAt: 4,
tailsEndAt: 5,

The whole idea is that you should be able to get the heads if you put str.slice(headsStartAt, headsEndAt).

If you want to use grapheme-count-based indexing, first convert the output of this library using string-convert-indexes, then use Unicode-character-count-based string slice libraries, for example: string-slice opens in a new tab.

§ Changelog

See it in the monorepo opens in a new tab, on GitHub.

§ Contributing

To report bugs or request features or assistance, raise an issue on GitHub opens in a new tab.

Any code contributions welcome! All Pull Requests will be dealt promptly.

§ Licence

MIT opens in a new tab

Copyright © 2010–2021 Roy Revelt and other contributors

Related packages:

📦 json-variables 10.0.14
Resolves custom-marked, cross-referenced paths in parsed JSON
📦 detergent 7.0.14
Extracts, cleans and encodes text
📦 string-extract-class-names 6.0.14
Extracts CSS class/id names from a string
📦 string-match-left-right 7.0.8
Match substrings on the left or right of a given index, ignoring whitespace
📦 string-apostrophes 1.4.14
Comprehensive, HTML-entities-aware tool to typographically-correct the apostrophes and single/double quotes
📦 string-trim-spaces-only 3.0.14
Like String.trim() but you can choose granularly what to trim
📦 string-left-right 4.0.14
Looks up the first non-whitespace character to the left/right of a given index