{
  "name": "TextArray",
  "description": "Free online text tools that run entirely in the browser. Every tool is a pure function over text: no sign-up, no uploads, no server, and nothing typed into a tool ever leaves the device.",
  "url": "https://textarray.com/",
  "docs": "https://textarray.com/llms.txt",
  "locales": [
    "en",
    "cs",
    "de",
    "es",
    "fr",
    "hr",
    "it",
    "hu",
    "nl",
    "pl",
    "pt",
    "ro",
    "sk",
    "sl",
    "sv",
    "tr",
    "ru",
    "uk"
  ],
  "generated": "2026-09-01",
  "count": 625,
  "tools": [
    {
      "slug": "i18n-key-diff",
      "name": "i18n key diff",
      "description": "Compare two localization JSON files and list the translation keys missing from each.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/i18n-key-diff",
      "embed": "https://textarray.com/embed/i18n-key-diff",
      "mode": "transform",
      "action": "Compare keys",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "JSON B (translated file)"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "reportMode",
          "kind": "select",
          "label": "Report",
          "default": "both",
          "choices": [
            {
              "value": "missingInB",
              "label": "Missing in B"
            },
            {
              "value": "missingInA",
              "label": "Missing in A"
            },
            {
              "value": "both",
              "label": "Both"
            },
            {
              "value": "untranslated",
              "label": "Likely untranslated"
            }
          ]
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "plain",
          "choices": [
            {
              "value": "plain",
              "label": "Plain list"
            },
            {
              "value": "json",
              "label": "JSON"
            }
          ]
        }
      ],
      "keywords": [
        "i18n key diff",
        "translation key diff",
        "localization diff",
        "missing translation keys",
        "compare locale files",
        "i18n json compare",
        "find untranslated strings",
        "translation file comparison"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "kaomoji-generator",
      "name": "Kaomoji generator",
      "description": "Generate random Japanese text emoticons from a built-in library of over 120 kaomoji, sorted into twelve moods.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/kaomoji-generator",
      "embed": "https://textarray.com/embed/kaomoji-generator",
      "mode": "generate",
      "action": "Generate kaomoji",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "category",
          "kind": "select",
          "label": "Category",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All categories"
            },
            {
              "value": "happy",
              "label": "Happy"
            },
            {
              "value": "sad",
              "label": "Sad"
            },
            {
              "value": "angry",
              "label": "Angry"
            },
            {
              "value": "love",
              "label": "Love"
            },
            {
              "value": "surprise",
              "label": "Surprise"
            },
            {
              "value": "animals",
              "label": "Animals"
            },
            {
              "value": "table-flip",
              "label": "Table flip"
            },
            {
              "value": "shrug",
              "label": "Shrug"
            },
            {
              "value": "greeting",
              "label": "Greeting"
            },
            {
              "value": "sleepy",
              "label": "Sleepy"
            },
            {
              "value": "dance",
              "label": "Dancing"
            },
            {
              "value": "music",
              "label": "Music"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "Number of kaomoji",
          "default": 10,
          "min": 1,
          "max": 50,
          "step": 1
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Output format",
          "default": "lines",
          "choices": [
            {
              "value": "lines",
              "label": "One per line"
            },
            {
              "value": "comma",
              "label": "Comma-separated"
            }
          ]
        }
      ],
      "keywords": [
        "kaomoji generator",
        "kaomoji maker",
        "japanese emoticons",
        "text face emoticons",
        "ascii emoticons generator",
        "table flip text",
        "shrug emoticon text",
        "random emoticon generator",
        "generator kaomoji",
        "text smiley generator",
        "kaomoji",
        "kaomoji library",
        "ascii faces",
        "text emoticons",
        "shrug emoticon",
        "shrug face",
        "table flip",
        "tableflip",
        "lenny face",
        "unicode faces"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "toml-to-json",
      "name": "TOML to JSON converter",
      "description": "Convert a TOML configuration document to JSON, right in your browser.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/toml-to-json",
      "embed": "https://textarray.com/embed/toml-to-json",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tabs",
              "label": "Tabs"
            },
            {
              "value": "minified",
              "label": "Minified"
            }
          ]
        },
        {
          "key": "sortKeys",
          "kind": "checkbox",
          "label": "Sort keys",
          "default": false
        }
      ],
      "keywords": [
        "toml to json",
        "toml converter",
        "convert toml to json online",
        "cargo.toml to json",
        "pyproject.toml to json",
        "format config"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "pirate-speak",
      "name": "Pirate speak translator",
      "description": "Turn everyday text into pirate speech in your own language, or back again.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/pirate-speak",
      "embed": "https://textarray.com/embed/pirate-speak",
      "mode": "transform",
      "action": "Translate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "dialect",
          "kind": "select",
          "label": "Voice",
          "default": "pirate",
          "choices": [
            {
              "value": "pirate",
              "label": "Pirate"
            },
            {
              "value": "dwarf",
              "label": "Dwarf"
            },
            {
              "value": "robot",
              "label": "Robot"
            }
          ]
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "toPirate",
          "choices": [
            {
              "value": "toPirate",
              "label": "Plain → dialect"
            },
            {
              "value": "fromPirate",
              "label": "Dialect → plain"
            }
          ]
        },
        {
          "key": "exclamations",
          "kind": "select",
          "label": "Exclamations",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "rare",
              "label": "Rare"
            },
            {
              "value": "often",
              "label": "Often"
            }
          ]
        },
        {
          "key": "keepPunctuation",
          "kind": "checkbox",
          "label": "Keep punctuation",
          "default": true
        }
      ],
      "keywords": [
        "pirate speak",
        "pirate translator",
        "pirate text generator",
        "talk like a pirate",
        "arrr"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "birth-number-validator",
      "name": "Birth number validator",
      "description": "Check a Slovak or Czech birth number and see the date of birth, age and sex it encodes.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/birth-number-validator",
      "embed": "https://textarray.com/embed/birth-number-validator",
      "mode": "transform",
      "action": "Validate birth numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "report",
          "choices": [
            {
              "value": "report",
              "label": "Report lines"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        },
        {
          "key": "onlyInvalid",
          "kind": "checkbox",
          "label": "Show only invalid",
          "default": false
        },
        {
          "key": "referenceDate",
          "kind": "text",
          "label": "Reference date (YYYY-MM-DD)",
          "default": ""
        }
      ],
      "keywords": [
        "birth number validator",
        "birth number checker",
        "personal number checker",
        "decode birth number"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "voice-transcript-cleaner",
      "name": "Voice transcript cleaner",
      "description": "Clean up raw speech-to-text transcripts by removing filler words, stutters and annotations.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/voice-transcript-cleaner",
      "embed": "https://textarray.com/embed/voice-transcript-cleaner",
      "mode": "transform",
      "action": "Clean transcript",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "removeFillers",
          "kind": "checkbox",
          "label": "Remove filler words",
          "default": true
        },
        {
          "key": "fixCapitalisation",
          "kind": "checkbox",
          "label": "Fix capitalisation",
          "default": true
        },
        {
          "key": "collapseRepeats",
          "kind": "checkbox",
          "label": "Collapse repeated words",
          "default": true
        },
        {
          "key": "removeBrackets",
          "kind": "checkbox",
          "label": "Remove bracketed annotations",
          "default": true
        },
        {
          "key": "mergeLines",
          "kind": "checkbox",
          "label": "Merge lines into paragraphs",
          "default": false
        }
      ],
      "keywords": [
        "voice transcript cleaner",
        "clean transcript",
        "whisper transcript cleaner",
        "remove filler words",
        "remove um uh",
        "speech to text cleanup",
        "transcript cleanup tool",
        "stutter remover",
        "remove hesitation sounds",
        "whisper clean-up"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "baudot-code",
      "name": "Baudot code translator",
      "description": "Encode text to 5-bit Baudot / ITA2 telegraph code and decode it back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/baudot-code",
      "embed": "https://textarray.com/embed/baudot-code",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        },
        {
          "key": "variant",
          "kind": "select",
          "label": "Variant",
          "default": "ita2",
          "choices": [
            {
              "value": "ita2",
              "label": "ITA2 (international)"
            },
            {
              "value": "us-tty",
              "label": "US TTY"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "binary",
          "choices": [
            {
              "value": "binary",
              "label": "Binary (11000)"
            },
            {
              "value": "decimal",
              "label": "Decimal (0–31)"
            },
            {
              "value": "dot",
              "label": "Dot notation (●○)"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "text",
          "label": "Separator",
          "default": " "
        },
        {
          "key": "unsupported",
          "kind": "select",
          "label": "Unsupported characters",
          "default": "drop",
          "choices": [
            {
              "value": "drop",
              "label": "Drop"
            },
            {
              "value": "replace",
              "label": "Replace with ?"
            }
          ]
        }
      ],
      "keywords": [
        "baudot code",
        "ita2",
        "baudot translator",
        "baudot decoder",
        "5-bit code",
        "telegraph code",
        "teleprinter code",
        "tty code",
        "murray code",
        "baudot-code",
        "tavirokod",
        "baudot code dekoder"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "sql-to-json",
      "name": "SQL to JSON",
      "description": "Convert SQL INSERT statements into a JSON array of objects.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sql-to-json",
      "embed": "https://textarray.com/embed/sql-to-json",
      "mode": "transform",
      "action": "Convert to JSON",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "shape",
          "kind": "select",
          "label": "Output shape",
          "default": "array",
          "choices": [
            {
              "value": "array",
              "label": "Array of objects"
            },
            {
              "value": "grouped",
              "label": "Grouped by table"
            }
          ]
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print",
          "default": true
        },
        {
          "key": "typeInference",
          "kind": "checkbox",
          "label": "Infer types (numbers, booleans, null)",
          "default": true
        }
      ],
      "keywords": [
        "sql to json",
        "convert sql to json",
        "sql insert to json",
        "parse sql insert statements",
        "insert into to json",
        "mysql dump to json",
        "sql do json",
        "previest sql na json",
        "sql insert na json",
        "sql prikazy na json",
        "sql zu json",
        "sql in json umwandeln",
        "insert anweisung json",
        "sql do json konvertor"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "json-schema-validator",
      "name": "JSON Schema validator",
      "description": "Check a JSON document against a JSON Schema and get a readable, line-by-line error report.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-schema-validator",
      "embed": "https://textarray.com/embed/json-schema-validator",
      "mode": "transform",
      "action": "Validate",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "JSON Schema"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "json schema validator",
        "validate json schema",
        "draft-07 validator",
        "schema validation online",
        "json schema validator online",
        "json sema validator",
        "validator struktury pre ai json mode"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "subtitle-overlap-fixer",
      "name": "Subtitle overlap fixer",
      "description": "Find and repair overlapping, invalid or too-short timecodes in SRT and WebVTT subtitle files.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/subtitle-overlap-fixer",
      "embed": "https://textarray.com/embed/subtitle-overlap-fixer",
      "mode": "transform",
      "action": "Fix overlaps",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "fixMode",
          "kind": "select",
          "label": "Fix mode",
          "default": "trimEnd",
          "choices": [
            {
              "value": "report",
              "label": "Report only"
            },
            {
              "value": "trimEnd",
              "label": "Trim earlier cue's end"
            },
            {
              "value": "shiftStart",
              "label": "Shift later cue's start"
            }
          ]
        },
        {
          "key": "minGapMs",
          "kind": "number",
          "label": "Minimum gap (ms)",
          "default": 80,
          "min": 0,
          "max": 5000,
          "step": 10
        },
        {
          "key": "minDurationMs",
          "kind": "number",
          "label": "Minimum duration (ms)",
          "default": 700,
          "min": 0,
          "max": 10000,
          "step": 50
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Match input"
            },
            {
              "value": "srt",
              "label": "SRT"
            },
            {
              "value": "vtt",
              "label": "VTT"
            }
          ]
        }
      ],
      "keywords": [
        "subtitle overlap fixer",
        "fix overlapping subtitles",
        "srt overlap fix",
        "vtt overlap fix",
        "subtitle timing fix",
        "fix invalid subtitle timecodes",
        "subtitle gap fix",
        "srt validator"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "lrc-generator",
      "name": "LRC lyrics generator",
      "description": "Turn plain lyrics into a time-synced .lrc file, or strip an .lrc back to plain text.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/lrc-generator",
      "embed": "https://textarray.com/embed/lrc-generator",
      "mode": "transform",
      "action": "Generate .lrc",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "generate",
          "choices": [
            {
              "value": "generate",
              "label": "Lyrics → .lrc"
            },
            {
              "value": "strip",
              "label": ".lrc → Lyrics"
            }
          ]
        },
        {
          "key": "startTime",
          "kind": "text",
          "label": "Start time (mm:ss.xx)",
          "default": "00:00.00"
        },
        {
          "key": "timingMode",
          "kind": "select",
          "label": "Timing mode",
          "default": "interval",
          "choices": [
            {
              "value": "interval",
              "label": "Fixed interval per line"
            },
            {
              "value": "duration",
              "label": "Split total duration evenly"
            }
          ]
        },
        {
          "key": "intervalSeconds",
          "kind": "number",
          "label": "Interval (seconds)",
          "default": 3,
          "min": 0.1,
          "step": 0.1
        },
        {
          "key": "durationSeconds",
          "kind": "number",
          "label": "Song duration (seconds)",
          "default": 180,
          "min": 1,
          "step": 1
        },
        {
          "key": "keepBlankLines",
          "kind": "checkbox",
          "label": "Keep blank lines as timed cues",
          "default": true
        },
        {
          "key": "title",
          "kind": "text",
          "label": "Title tag (ti)",
          "default": ""
        },
        {
          "key": "artist",
          "kind": "text",
          "label": "Artist tag (ar)",
          "default": ""
        },
        {
          "key": "album",
          "kind": "text",
          "label": "Album tag (al)",
          "default": ""
        },
        {
          "key": "by",
          "kind": "text",
          "label": "Created-by tag (by)",
          "default": ""
        },
        {
          "key": "offsetMs",
          "kind": "number",
          "label": "Offset tag (ms)",
          "default": 0,
          "step": 10
        }
      ],
      "keywords": [
        "lrc generator",
        "lrc file generator",
        "synced lyrics generator",
        "lyrics timestamp generator",
        "strip lrc timestamps",
        "lrc to text"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "cliche-detector",
      "name": "Cliche detector",
      "description": "Scan your writing for clichés, filler words and empty corporate padding.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/cliche-detector",
      "embed": "https://textarray.com/embed/cliche-detector",
      "mode": "transform",
      "action": "Scan text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "cliches",
          "kind": "checkbox",
          "label": "Check clichés",
          "default": true
        },
        {
          "key": "filler",
          "kind": "checkbox",
          "label": "Check filler & hedges",
          "default": true
        },
        {
          "key": "intensifiers",
          "kind": "checkbox",
          "label": "Check weak intensifiers",
          "default": true
        },
        {
          "key": "custom",
          "kind": "text",
          "label": "Your own phrases (comma-separated)",
          "default": ""
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Output mode",
          "default": "report",
          "choices": [
            {
              "value": "report",
              "label": "Report (counts and line numbers)"
            },
            {
              "value": "annotated",
              "label": "Annotated text (hits marked)"
            },
            {
              "value": "cleaned",
              "label": "Cleaned text (flagged words removed)"
            }
          ]
        }
      ],
      "keywords": [
        "cliche detector",
        "cliché detector",
        "filler word checker",
        "weak word finder",
        "corporate jargon detector",
        "business jargon checker",
        "padding score",
        "wordiness checker",
        "hedge word finder"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "dialogue-counter",
      "name": "Dialogue balance counter",
      "description": "See how dialogue is split between characters in a screenplay or script.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/dialogue-counter",
      "embed": "https://textarray.com/embed/dialogue-counter",
      "mode": "transform",
      "action": "Count dialogue balance",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Input style",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "screenplay",
              "label": "Screenplay (NAME on its own line)"
            },
            {
              "value": "script",
              "label": "Script (NAME: text)"
            }
          ]
        },
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "words",
          "choices": [
            {
              "value": "words",
              "label": "Words"
            },
            {
              "value": "lines",
              "label": "Lines"
            },
            {
              "value": "name",
              "label": "Name"
            }
          ]
        },
        {
          "key": "mergeCase",
          "kind": "checkbox",
          "label": "Merge case variants (JOHN / John)",
          "default": false
        },
        {
          "key": "minLines",
          "kind": "number",
          "label": "Minimum lines to include a character",
          "default": 1,
          "min": 1,
          "max": 100,
          "step": 1
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Aligned text table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "dialogue counter",
        "dialogue balance",
        "screenplay dialogue stats",
        "character line count",
        "script dialogue analyzer",
        "who talks the most",
        "dialogue word count per character",
        "screenplay character stats",
        "script dialogue counter"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "action-word-density",
      "name": "Action word density",
      "description": "Measure narrative pacing by how many action verbs appear in each segment of your text.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/action-word-density",
      "embed": "https://textarray.com/embed/action-word-density",
      "mode": "transform",
      "action": "Analyze pacing",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "segmentMode",
          "kind": "select",
          "label": "Split by",
          "default": "paragraph",
          "choices": [
            {
              "value": "paragraph",
              "label": "Paragraph"
            },
            {
              "value": "words",
              "label": "Fixed word count"
            }
          ]
        },
        {
          "key": "segmentSize",
          "kind": "number",
          "label": "Words per segment",
          "default": 100,
          "min": 20,
          "max": 1000,
          "step": 10
        },
        {
          "key": "extraVerbs",
          "kind": "text",
          "label": "Extra action verbs",
          "default": ""
        },
        {
          "key": "sortByDensity",
          "kind": "checkbox",
          "label": "Sort fastest to slowest",
          "default": false
        }
      ],
      "keywords": [
        "action word density",
        "pacing analyzer",
        "action verb counter",
        "narrative pacing checker",
        "story pacing tool",
        "passive voice counter",
        "writing pace analyzer",
        "scene pacing checker"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "iban-generator",
      "name": "Test IBAN generator",
      "description": "Generate syntactically valid, fictional IBANs for testing forms, imports and validators.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/iban-generator",
      "embed": "https://textarray.com/embed/iban-generator",
      "mode": "generate",
      "action": "Generate IBANs",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "country",
          "kind": "select",
          "label": "Country",
          "default": "SK",
          "choices": [
            {
              "value": "SK",
              "label": "Slovakia (SK)"
            },
            {
              "value": "CZ",
              "label": "Czechia (CZ)"
            },
            {
              "value": "DE",
              "label": "Germany (DE)"
            },
            {
              "value": "AT",
              "label": "Austria (AT)"
            },
            {
              "value": "PL",
              "label": "Poland (PL)"
            },
            {
              "value": "HU",
              "label": "Hungary (HU)"
            },
            {
              "value": "GB",
              "label": "United Kingdom (GB)"
            },
            {
              "value": "FR",
              "label": "France (FR)"
            },
            {
              "value": "ES",
              "label": "Spain (ES)"
            },
            {
              "value": "IT",
              "label": "Italy (IT)"
            },
            {
              "value": "NL",
              "label": "Netherlands (NL)"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 10,
          "min": 1,
          "max": 1000
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "spaced",
          "choices": [
            {
              "value": "spaced",
              "label": "Spaced (groups of four)"
            },
            {
              "value": "compact",
              "label": "Compact"
            }
          ]
        },
        {
          "key": "bankCode",
          "kind": "text",
          "label": "Fixed bank code (optional)",
          "default": ""
        }
      ],
      "keywords": [
        "fake iban",
        "sample iban",
        "dummy iban generator",
        "test bank account number"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "random-name-generator",
      "name": "Random name generator",
      "description": "Generate realistic random person names for test data, in five regional styles.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/random-name-generator",
      "embed": "https://textarray.com/embed/random-name-generator",
      "mode": "generate",
      "action": "Generate names",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "region",
          "kind": "select",
          "label": "Region",
          "default": "english",
          "choices": [
            {
              "value": "english",
              "label": "English"
            },
            {
              "value": "slovak-czech",
              "label": "Slovak/Czech"
            },
            {
              "value": "german",
              "label": "German"
            },
            {
              "value": "polish",
              "label": "Polish"
            },
            {
              "value": "hungarian",
              "label": "Hungarian"
            }
          ]
        },
        {
          "key": "gender",
          "kind": "select",
          "label": "Gender",
          "default": "any",
          "choices": [
            {
              "value": "any",
              "label": "Any"
            },
            {
              "value": "male",
              "label": "Male"
            },
            {
              "value": "female",
              "label": "Female"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 10,
          "min": 1,
          "max": 1000
        },
        {
          "key": "order",
          "kind": "select",
          "label": "Order",
          "default": "first-last",
          "choices": [
            {
              "value": "first-last",
              "label": "First Last"
            },
            {
              "value": "last-first",
              "label": "Last First"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "lines",
          "choices": [
            {
              "value": "lines",
              "label": "Plain lines"
            },
            {
              "value": "csv",
              "label": "CSV (First,Last)"
            },
            {
              "value": "json",
              "label": "JSON objects"
            }
          ]
        }
      ],
      "keywords": [
        "random name generator",
        "fake name generator",
        "test data names",
        "person name generator",
        "name list generator",
        "mock names"
      ],
      "updated": "2026-07-26"
    },
    {
      "slug": "inline-math-evaluator",
      "name": "Inline math evaluator",
      "description": "Find arithmetic expressions ending in \"=\" in your text and fill in the answer.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/inline-math-evaluator",
      "embed": "https://textarray.com/embed/inline-math-evaluator",
      "mode": "transform",
      "action": "Solve expressions",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "inline math evaluator",
        "inline calculator",
        "math evaluator",
        "evaluate expressions",
        "solve equations in text",
        "text calculator",
        "arithmetic evaluator",
        "auto calculate"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "sql-insert-generator",
      "name": "SQL insert statement generator",
      "description": "Generate ready-to-run SQL INSERT statements from a column schema, without touching a real database.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sql-insert-generator",
      "embed": "https://textarray.com/embed/sql-insert-generator",
      "mode": "generate",
      "action": "Generate SQL",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "table",
          "kind": "text",
          "label": "Table name",
          "default": "users"
        },
        {
          "key": "columns",
          "kind": "text",
          "label": "Columns (name:type)",
          "default": "id:id,name:name,email:email,active:boolean,created_at:incrementing-date"
        },
        {
          "key": "rows",
          "kind": "number",
          "label": "Row count",
          "default": 10,
          "min": 1,
          "max": 1000,
          "step": 1
        }
      ],
      "keywords": [
        "sql insert generator",
        "sql insert statement generator",
        "generate sql insert statements",
        "fake sql data generator",
        "mock sql data",
        "seed data generator sql",
        "insert into generator",
        "sql test data generator",
        "sample sql rows",
        "random sql rows"
      ],
      "updated": "2026-07-24"
    },
    {
      "slug": "llm-token-cost-calculator",
      "name": "LLM token and cost calculator",
      "description": "Estimate how many tokens a pasted text costs across popular LLM APIs.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/llm-token-cost-calculator",
      "embed": "https://textarray.com/embed/llm-token-cost-calculator",
      "mode": "transform",
      "action": "Estimate cost",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "asOutput",
          "kind": "checkbox",
          "label": "Price as output tokens",
          "default": false
        },
        {
          "key": "outputMode",
          "kind": "select",
          "label": "Show",
          "default": "costs",
          "choices": [
            {
              "value": "costs",
              "label": "Cost per model"
            },
            {
              "value": "tokens",
              "label": "Token boundaries"
            }
          ]
        }
      ],
      "keywords": [
        "llm token calculator",
        "token cost calculator",
        "gpt token counter",
        "openai token cost",
        "claude token cost",
        "ai api pricing",
        "token estimator",
        "gpt/claude"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "context-window-slimmer",
      "name": "LLM context compressor",
      "description": "Shrink pasted text or code so it costs fewer tokens before you send it to an LLM.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/context-window-slimmer",
      "embed": "https://textarray.com/embed/context-window-slimmer",
      "mode": "transform",
      "action": "Slim down text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "stripComments",
          "kind": "checkbox",
          "label": "Strip code comments",
          "default": true
        },
        {
          "key": "collapseBlankLines",
          "kind": "checkbox",
          "label": "Collapse blank lines and trailing spaces",
          "default": true
        },
        {
          "key": "dedent",
          "kind": "checkbox",
          "label": "Strip redundant indentation",
          "default": true
        },
        {
          "key": "removeStopWords",
          "kind": "checkbox",
          "label": "Remove filler/stop words in prose",
          "default": false
        }
      ],
      "keywords": [
        "context window slimmer",
        "llm context compressor",
        "reduce token count",
        "compress prompt",
        "shrink context window",
        "strip code comments",
        "remove filler words",
        "token counter estimate",
        "prompt compressor"
      ],
      "updated": "2026-07-24"
    },
    {
      "slug": "url-to-html-link",
      "name": "URLs to HTML links",
      "description": "Turn every bare URL in a block of text into a clickable HTML anchor tag.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/url-to-html-link",
      "embed": "https://textarray.com/embed/url-to-html-link",
      "mode": "transform",
      "action": "Convert URLs to links",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "openInNewTab",
          "kind": "checkbox",
          "label": "Open in new tab",
          "default": true
        },
        {
          "key": "linkText",
          "kind": "select",
          "label": "Link text",
          "default": "url",
          "choices": [
            {
              "value": "url",
              "label": "The URL itself"
            },
            {
              "value": "custom",
              "label": "Custom label"
            }
          ]
        },
        {
          "key": "customLabel",
          "kind": "text",
          "label": "Custom label text",
          "default": ""
        },
        {
          "key": "matchBareDomains",
          "kind": "checkbox",
          "label": "Also wrap bare domains (example.com)",
          "default": false
        }
      ],
      "keywords": [
        "url to html link",
        "convert url to link",
        "linkify text",
        "wrap url in anchor tag",
        "make url clickable",
        "text to html link"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "ascii-banner-generator",
      "name": "ASCII banner generator",
      "description": "Turn a short word into a large multi-line ASCII-art banner.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/ascii-banner-generator",
      "embed": "https://textarray.com/embed/ascii-banner-generator",
      "mode": "transform",
      "action": "Generate banner",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "fillChar",
          "kind": "select",
          "label": "Fill glyph",
          "default": "#",
          "choices": [
            {
              "value": "#",
              "label": "#"
            },
            {
              "value": "@",
              "label": "@"
            },
            {
              "value": "*",
              "label": "*"
            },
            {
              "value": "$",
              "label": "$"
            }
          ]
        }
      ],
      "keywords": [
        "ascii art text",
        "text banner generator",
        "block letters generator",
        "big text generator",
        "ascii letters",
        "terminal banner",
        "readme banner",
        "ascii art text banner generator"
      ],
      "updated": "2026-07-24"
    },
    {
      "slug": "keyword-auto-linker",
      "name": "Keyword auto-linker",
      "description": "Turn keyword mentions in an article into HTML links, one per keyword.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/keyword-auto-linker",
      "embed": "https://textarray.com/embed/keyword-auto-linker",
      "mode": "transform",
      "action": "Link keywords",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Keyword=URL pairs, one per line"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "openNewTab",
          "kind": "checkbox",
          "label": "Open links in a new tab",
          "default": false
        },
        {
          "key": "nofollow",
          "kind": "checkbox",
          "label": "Add rel=\"nofollow\"",
          "default": false
        }
      ],
      "keywords": [
        "keyword auto linker",
        "keyword linker",
        "auto link keywords",
        "text to link",
        "internal linking tool",
        "link keywords in article",
        "seo internal links",
        "internal linking builder"
      ],
      "updated": "2026-07-24"
    },
    {
      "slug": "story-branch-checker",
      "name": "Story branch checker",
      "description": "Find broken links and orphaned nodes in a branching story or dialogue tree.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/story-branch-checker",
      "embed": "https://textarray.com/embed/story-branch-checker",
      "mode": "transform",
      "action": "Check branches",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case-sensitive node names",
          "default": false
        },
        {
          "key": "ignoreSelfLoops",
          "kind": "checkbox",
          "label": "Ignore a node's link to itself",
          "default": true
        },
        {
          "key": "treatFirstAsEntry",
          "kind": "checkbox",
          "label": "Treat first node as the entry point",
          "default": true
        }
      ],
      "keywords": [
        "story branch checker",
        "dialogue tree checker",
        "interactive fiction validator",
        "broken link checker",
        "orphan node finder",
        "branching narrative tool",
        "twine link checker",
        "ink knot checker",
        "chatbot flow validator",
        "dialogue tree linter"
      ],
      "updated": "2026-07-24"
    },
    {
      "slug": "random-email-generator",
      "name": "Random email generator",
      "description": "Generate a bulk list of fake, synthetic email addresses for testing.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/random-email-generator",
      "embed": "https://textarray.com/embed/random-email-generator",
      "mode": "generate",
      "action": "Generate emails",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 25,
          "min": 1,
          "max": 10000
        },
        {
          "key": "style",
          "kind": "select",
          "label": "Name style",
          "default": "name",
          "choices": [
            {
              "value": "name",
              "label": "Firstname.lastname"
            },
            {
              "value": "random",
              "label": "Random characters"
            }
          ]
        },
        {
          "key": "domain",
          "kind": "text",
          "label": "Domain",
          "default": "example.com"
        }
      ],
      "keywords": [
        "random email generator",
        "fake email generator",
        "test email addresses",
        "dummy email generator",
        "bulk email generator"
      ],
      "updated": "2026-07-24"
    },
    {
      "slug": "charset-detector",
      "name": "Charset detector",
      "description": "Guess the original encoding behind garbled text and recover it.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/charset-detector",
      "embed": "https://textarray.com/embed/charset-detector",
      "mode": "transform",
      "action": "Fix encoding",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "candidate",
          "kind": "select",
          "label": "Assumed corruption",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "utf8-windows-1250",
              "label": "UTF-8 read as Windows-1250"
            },
            {
              "value": "utf8-iso-8859-2",
              "label": "UTF-8 read as ISO-8859-2"
            },
            {
              "value": "utf8-windows-1252",
              "label": "UTF-8 read as Windows-1252"
            },
            {
              "value": "windows-1250-latin1",
              "label": "Windows-1250 read as Latin-1"
            },
            {
              "value": "iso-8859-2-latin1",
              "label": "ISO-8859-2 read as Latin-1"
            }
          ]
        }
      ],
      "keywords": [
        "charset detector",
        "mojibake fixer",
        "fix garbled text",
        "fix broken encoding",
        "utf-8 windows-1250",
        "utf-8 iso-8859-2",
        "detect text encoding",
        "repair mojibake",
        "garbled diacritics fix"
      ],
      "updated": "2026-07-24"
    },
    {
      "slug": "product-attribute-parser",
      "name": "Product attribute parser",
      "description": "Turn freeform product attribute text into a clean key/value table or JSON.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/product-attribute-parser",
      "embed": "https://textarray.com/embed/product-attribute-parser",
      "mode": "transform",
      "action": "Parse attributes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table (key | value)"
            },
            {
              "value": "json",
              "label": "JSON array"
            }
          ]
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicate pairs",
          "default": false
        },
        {
          "key": "sortByKey",
          "kind": "checkbox",
          "label": "Sort by key",
          "default": false
        }
      ],
      "keywords": [
        "product attribute parser",
        "attribute parser",
        "parse product attributes",
        "key value parser",
        "product spec parser",
        "catalog cleanup",
        "product feed cleanup",
        "attributes to table",
        "attributes to json"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "timezone-converter",
      "name": "Timezone converter",
      "description": "Convert a date and time from one time zone to another, with the UTC offset shown for both.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/timezone-converter",
      "embed": "https://textarray.com/embed/timezone-converter",
      "mode": "transform",
      "action": "Convert time zone",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "sourceZone",
          "kind": "text",
          "label": "From time zone",
          "default": "UTC"
        },
        {
          "key": "targetZone",
          "kind": "text",
          "label": "To time zone",
          "default": "Europe/Bratislava"
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Time format",
          "default": "readable",
          "choices": [
            {
              "value": "readable",
              "label": "Readable"
            },
            {
              "value": "iso",
              "label": "ISO 8601"
            }
          ]
        }
      ],
      "keywords": [
        "timezone converter",
        "time zone converter",
        "convert time zone",
        "utc to local time",
        "world clock",
        "iana timezone",
        "datetime converter"
      ],
      "updated": "2026-07-24"
    },
    {
      "slug": "intel-hex-parser",
      "name": "Intel HEX parser",
      "description": "Validate Intel HEX records and extract their data as a hex dump.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/intel-hex-parser",
      "embed": "https://textarray.com/embed/intel-hex-parser",
      "mode": "transform",
      "action": "Parse HEX file",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase hex",
          "default": false
        }
      ],
      "keywords": [
        "intel hex parser",
        "ihex",
        "hex file parser",
        "firmware hex file",
        "microcontroller hex file",
        "hex record checksum"
      ],
      "updated": "2026-07-24"
    },
    {
      "slug": "bcd-decoder",
      "name": "BCD decoder",
      "description": "Convert binary-coded decimal nibbles to a decimal number, or the other way round.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/bcd-decoder",
      "embed": "https://textarray.com/embed/bcd-decoder",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "decode",
              "label": "BCD to decimal"
            },
            {
              "value": "encode",
              "label": "Decimal to BCD"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "text",
          "label": "Nibble separator",
          "default": " "
        }
      ],
      "keywords": [
        "bcd decoder",
        "bcd encoder",
        "binary coded decimal",
        "binary-coded decimal converter",
        "bcd to decimal"
      ],
      "updated": "2026-07-24"
    },
    {
      "slug": "remove-lines-starting-with-number",
      "name": "Remove lines starting with a number",
      "description": "Delete every line whose first character is a digit.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-lines-starting-with-number",
      "embed": "https://textarray.com/embed/remove-lines-starting-with-number",
      "mode": "transform",
      "action": "Remove numbered lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "invert",
          "kind": "checkbox",
          "label": "Keep only lines starting with a number",
          "default": false
        }
      ],
      "keywords": [
        "remove lines starting with a number",
        "delete numbered lines",
        "strip leading digits",
        "remove numeric start lines",
        "filter lines by first character"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "ai-chat-log-parser",
      "name": "AI chat log parser",
      "description": "Cleans a pasted ChatGPT or Claude transcript into a tidy user/AI dialogue.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ai-chat-log-parser",
      "embed": "https://textarray.com/embed/ai-chat-log-parser",
      "mode": "transform",
      "action": "Parse chat log",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output",
          "default": "markdown",
          "choices": [
            {
              "value": "markdown",
              "label": "Markdown transcript"
            },
            {
              "value": "json",
              "label": "JSON as parsed"
            },
            {
              "value": "openai",
              "label": "OpenAI messages array"
            },
            {
              "value": "anthropic",
              "label": "Anthropic messages + system"
            }
          ]
        },
        {
          "key": "mergeConsecutive",
          "kind": "checkbox",
          "label": "Merge consecutive turns by the same speaker",
          "default": false
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Indent JSON",
          "default": true
        }
      ],
      "keywords": [
        "ai chat log parser",
        "chatgpt transcript cleaner",
        "claude conversation export",
        "clean chat transcript",
        "chat log to markdown",
        "ai conversation formatter",
        "strip chat ui noise",
        "chatgpt copy paste cleaner",
        "chat format converter",
        "chat transcript to json",
        "chat transcript to messages",
        "chat log converter",
        "llm messages json",
        "openai messages format",
        "anthropic messages api",
        "convert chat to json",
        "chatgpt transcript parser",
        "system user assistant json",
        "spravy pre llm",
        "claude/chatgpt log parser"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "few-shot-prompt-builder",
      "name": "Few-shot prompt builder",
      "description": "Generate a blank few-shot Markdown template with numbered input/output example blocks.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/few-shot-prompt-builder",
      "embed": "https://textarray.com/embed/few-shot-prompt-builder",
      "mode": "generate",
      "action": "Generate template",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "fields",
          "kind": "text",
          "label": "Field names",
          "default": "Input,Output"
        },
        {
          "key": "count",
          "kind": "number",
          "label": "Number of examples",
          "default": 3,
          "min": 1,
          "max": 20,
          "step": 1
        }
      ],
      "keywords": [
        "few shot prompt builder",
        "few-shot prompting",
        "prompt examples template",
        "llm prompt examples",
        "input output examples",
        "prompt engineering template"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "asin-sku-extractor",
      "name": "ASIN / SKU extractor",
      "description": "Pull Amazon ASIN and SKU-like product codes out of raw text or data exports.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/asin-sku-extractor",
      "embed": "https://textarray.com/embed/asin-sku-extractor",
      "mode": "transform",
      "action": "Extract codes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Extract",
          "default": "both",
          "choices": [
            {
              "value": "both",
              "label": "ASIN + SKU"
            },
            {
              "value": "asin",
              "label": "ASIN only"
            },
            {
              "value": "sku",
              "label": "SKU-like only"
            }
          ]
        }
      ],
      "keywords": [
        "asin extractor",
        "amazon asin finder",
        "extract asin from text",
        "extract sku codes",
        "product code extractor",
        "find asin numbers",
        "amazon product id",
        "amazon/ebay asin a sku extractor"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "env-file-validator",
      "name": ".env file validator",
      "description": "Check .env variable lists for bad keys, missing quotes and duplicates.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/env-file-validator",
      "embed": "https://textarray.com/embed/env-file-validator",
      "mode": "transform",
      "action": "Validate .env file",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "autoFix",
          "kind": "checkbox",
          "label": "Auto-fix (capitalize keys, quote values, sort)",
          "default": false
        }
      ],
      "keywords": [
        "env file validator",
        "dotenv validator",
        "validate env file",
        "env syntax checker",
        "dotenv linter",
        "env key duplicate checker",
        "environment variables validator"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "sort-lines-natural",
      "name": "Natural sort lines",
      "description": "Sort lines the way a person would, so \"item2\" comes before \"item10\".",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/sort-lines-natural",
      "embed": "https://textarray.com/embed/sort-lines-natural",
      "mode": "transform",
      "action": "Sort naturally",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "asc",
          "choices": [
            {
              "value": "asc",
              "label": "Ascending"
            },
            {
              "value": "desc",
              "label": "Descending"
            }
          ]
        }
      ],
      "keywords": [
        "natural sort",
        "natural sort lines",
        "sort lines with numbers",
        "numeric sort text",
        "alphanumeric sort"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "url-link-obfuscator",
      "name": "URL link obfuscator",
      "description": "Rewrite a URL into a percent-hex escaped form that still works when clicked.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/url-link-obfuscator",
      "embed": "https://textarray.com/embed/url-link-obfuscator",
      "mode": "transform",
      "action": "Obfuscate URL",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "scope",
          "kind": "select",
          "label": "Obfuscate",
          "default": "domain",
          "choices": [
            {
              "value": "domain",
              "label": "Domain only"
            },
            {
              "value": "full",
              "label": "Full URL"
            }
          ]
        }
      ],
      "keywords": [
        "url obfuscator",
        "link obfuscator",
        "obfuscate url",
        "hide url",
        "mask link",
        "percent encode url",
        "percent hex url",
        "disguise link",
        "zakryt url",
        "url elrejto",
        "link masker"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "icebreaker-generator",
      "name": "Icebreaker generator",
      "description": "Draw a random conversation-starter question to open a meeting, team-building session or introduction.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/icebreaker-generator",
      "embed": "https://textarray.com/embed/icebreaker-generator",
      "mode": "generate",
      "action": "Generate icebreaker",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [],
      "keywords": [
        "icebreaker generator",
        "icebreaker questions",
        "conversation starter generator",
        "team building questions",
        "meeting icebreaker",
        "getting to know you questions",
        "random conversation questions",
        "party question generator",
        "icebreakers"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "percent-calculator",
      "name": "Percent calculator",
      "description": "Calculate a whole list of percentage expressions at once, one per line.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/percent-calculator",
      "embed": "https://textarray.com/embed/percent-calculator",
      "mode": "transform",
      "action": "Calculate percentages",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "percent calculator",
        "percentage calculator",
        "batch percentage calculator",
        "percent of number",
        "what percent of",
        "percentage increase decrease",
        "list of percentages"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "enclosed-alphanumerics",
      "name": "Enclosed alphanumerics",
      "description": "Wrap letters and digits in circled or parenthesized Unicode glyphs.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/enclosed-alphanumerics",
      "embed": "https://textarray.com/embed/enclosed-alphanumerics",
      "mode": "transform",
      "action": "Enclose text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Style",
          "default": "circled",
          "choices": [
            {
              "value": "circled",
              "label": "Circled"
            },
            {
              "value": "parenthesized",
              "label": "Parenthesized"
            }
          ]
        }
      ],
      "keywords": [
        "circled letters",
        "circled numbers",
        "enclosed alphanumerics",
        "bubble text",
        "circled text generator",
        "parenthesized letters",
        "circle text",
        "unicode circled characters"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "podcast-chapter-generator",
      "name": "Podcast chapter generator",
      "description": "Turn a list of chapter titles and durations into timestamped chapter markers.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/podcast-chapter-generator",
      "embed": "https://textarray.com/embed/podcast-chapter-generator",
      "mode": "transform",
      "action": "Generate chapters",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "startAt",
          "kind": "text",
          "label": "Start time",
          "default": "0:00"
        },
        {
          "key": "defaultDurationSec",
          "kind": "number",
          "label": "Default chapter length (seconds)",
          "default": 180,
          "min": 1
        },
        {
          "key": "numbered",
          "kind": "checkbox",
          "label": "Number chapters",
          "default": false
        }
      ],
      "keywords": [
        "podcast chapters",
        "chapter timestamps",
        "youtube timestamps",
        "episode timestamps",
        "show notes generator",
        "timestamp generator",
        "audio chapters",
        "podcasting"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "tabletop-stat-roller",
      "name": "Tabletop stat roller",
      "description": "Roll a set of tabletop RPG ability scores with 4d6 drop-lowest, 3d6, or 2d6+6.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/tabletop-stat-roller",
      "embed": "https://textarray.com/embed/tabletop-stat-roller",
      "mode": "generate",
      "action": "Roll stats",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "Number of stats",
          "default": 6,
          "min": 1,
          "max": 12
        },
        {
          "key": "method",
          "kind": "select",
          "label": "Method",
          "default": "4d6-drop-lowest",
          "choices": [
            {
              "value": "4d6-drop-lowest",
              "label": "4d6, drop lowest"
            },
            {
              "value": "3d6",
              "label": "3d6 straight"
            },
            {
              "value": "2d6+6",
              "label": "2d6 + 6"
            }
          ]
        },
        {
          "key": "sortDesc",
          "kind": "checkbox",
          "label": "Sort highest to lowest",
          "default": false
        }
      ],
      "keywords": [
        "ability score roller",
        "dnd stat roller",
        "tabletop rpg dice",
        "character stats generator",
        "4d6 drop lowest",
        "rpg character generator",
        "attribute roller",
        "stat block generator"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "plot-twist-generator",
      "name": "Plot twist generator",
      "description": "Generate random plot-twist premises to jump-start a story.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/plot-twist-generator",
      "embed": "https://textarray.com/embed/plot-twist-generator",
      "mode": "generate",
      "action": "Generate twists",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "Number of twists",
          "default": 3,
          "min": 1,
          "max": 10
        }
      ],
      "keywords": [
        "story twist ideas",
        "writing prompt twist",
        "random plot twist",
        "fiction plot ideas",
        "novel twist generator",
        "screenwriting twist",
        "story idea generator"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "writing-prompt-generator",
      "name": "Writing prompt generator",
      "description": "Get random one-sentence writing prompts to spark your next story.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/writing-prompt-generator",
      "embed": "https://textarray.com/embed/writing-prompt-generator",
      "mode": "generate",
      "action": "Generate prompts",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "Number of prompts",
          "default": 3,
          "min": 1,
          "max": 10,
          "step": 1
        }
      ],
      "keywords": [
        "writing prompt generator",
        "story prompt generator",
        "creative writing prompts",
        "fiction writing ideas",
        "random story starter",
        "nanowrimo prompts",
        "writing exercise generator",
        "story idea generator"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "tts-sanitizer",
      "name": "TTS sanitizer",
      "description": "Clean raw text so it reads naturally through a text-to-speech engine.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/tts-sanitizer",
      "embed": "https://textarray.com/embed/tts-sanitizer",
      "mode": "transform",
      "action": "Clean for text-to-speech",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "stripMarkdown",
          "kind": "checkbox",
          "label": "Strip markdown syntax",
          "default": true
        },
        {
          "key": "stripEmoji",
          "kind": "checkbox",
          "label": "Strip emoji",
          "default": true
        },
        {
          "key": "stripUrls",
          "kind": "checkbox",
          "label": "Strip URLs",
          "default": true
        },
        {
          "key": "collapsePunctuation",
          "kind": "checkbox",
          "label": "Collapse repeated punctuation",
          "default": true
        }
      ],
      "keywords": [
        "tts sanitizer",
        "text to speech cleaner",
        "clean text for tts",
        "strip markdown for speech",
        "remove emoji for voice",
        "voiceover script cleaner",
        "screen reader text cleaner",
        "narration text prep"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "sort-lines-by-word-position",
      "name": "Sort lines by word position",
      "description": "Sort lines by a specific word within each line, not the whole line.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/sort-lines-by-word-position",
      "embed": "https://textarray.com/embed/sort-lines-by-word-position",
      "mode": "transform",
      "action": "Sort by word position",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "position",
          "kind": "number",
          "label": "Word position",
          "default": 2,
          "min": 1,
          "max": 20
        },
        {
          "key": "descending",
          "kind": "checkbox",
          "label": "Descending order",
          "default": false
        },
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case-sensitive",
          "default": false
        }
      ],
      "keywords": [
        "sort lines by word",
        "sort by column",
        "sort by second word",
        "sort by last word",
        "reorder lines by word",
        "sort name list by first name",
        "word position sort"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "csv-column-validator",
      "name": "CSV column validator",
      "description": "Check that every row of a CSV or TSV file has the same number of columns as the header.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/csv-column-validator",
      "embed": "https://textarray.com/embed/csv-column-validator",
      "mode": "transform",
      "action": "Validate columns",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": ",",
          "choices": [
            {
              "value": ",",
              "label": "Comma"
            },
            {
              "value": ";",
              "label": "Semicolon"
            },
            {
              "value": "\t",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "trimFields",
          "kind": "checkbox",
          "label": "Trim whitespace in fields",
          "default": true
        }
      ],
      "keywords": [
        "csv column validator",
        "check csv columns",
        "csv row length",
        "validate delimited text",
        "consistent columns csv",
        "missing csv field"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "html-to-markdown-converter",
      "name": "HTML to Markdown converter",
      "description": "Turn simple HTML markup into Markdown syntax, right in your browser.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/html-to-markdown-converter",
      "embed": "https://textarray.com/embed/html-to-markdown-converter",
      "mode": "transform",
      "action": "Convert to Markdown",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "html to markdown",
        "html to md",
        "convert html to markdown",
        "markdown converter",
        "html markdown converter",
        "strip html to markdown",
        "html to markdown syntax",
        "convert tags to markdown",
        "markdown html"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "mock-json-data-generator",
      "name": "Mock JSON data generator",
      "description": "Turn a one-line-per-field schema into an array of realistic fake JSON records.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/mock-json-data-generator",
      "embed": "https://textarray.com/embed/mock-json-data-generator",
      "mode": "transform",
      "action": "Generate mock data",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "rows",
          "kind": "number",
          "label": "Rows to generate",
          "default": 5,
          "min": 1,
          "max": 100
        }
      ],
      "keywords": [
        "mock json generator",
        "fake json data generator",
        "json test data",
        "sample json generator",
        "random json data",
        "dummy json generator",
        "generate mock data",
        "json fixtures generator",
        "mock data builder"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "fake-word-generator",
      "name": "Fake word generator",
      "description": "Generate pronounceable made-up words from random consonant-vowel syllables.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/fake-word-generator",
      "embed": "https://textarray.com/embed/fake-word-generator",
      "mode": "generate",
      "action": "Generate words",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "Number of words",
          "default": 10,
          "min": 1,
          "max": 50
        },
        {
          "key": "syllables",
          "kind": "number",
          "label": "Syllables per word",
          "default": 2,
          "min": 1,
          "max": 5
        },
        {
          "key": "capitalize",
          "kind": "checkbox",
          "label": "Capitalize each word",
          "default": false
        }
      ],
      "keywords": [
        "fake word generator",
        "nonsense word generator",
        "invented word generator",
        "pronounceable word generator",
        "made up words",
        "gibberish word generator",
        "random syllable generator",
        "fantasy name generator",
        "placeholder word generator"
      ],
      "updated": "2026-07-23"
    },
    {
      "slug": "smart-list-beautifier",
      "name": "Smart list beautifier",
      "description": "Unify mismatched bullet and number markers in a list into one consistent style.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/smart-list-beautifier",
      "embed": "https://textarray.com/embed/smart-list-beautifier",
      "mode": "transform",
      "action": "Beautify list",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "marker",
          "kind": "select",
          "label": "Marker style",
          "default": "dash",
          "choices": [
            {
              "value": "dash",
              "label": "Dash (-)"
            },
            {
              "value": "bullet",
              "label": "Bullet (•)"
            },
            {
              "value": "asterisk",
              "label": "Asterisk (*)"
            },
            {
              "value": "number",
              "label": "Number (1. 2. 3.)"
            }
          ]
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim trailing whitespace",
          "default": true
        }
      ],
      "keywords": [
        "smart list beautifier",
        "beautify list",
        "unify bullets",
        "unify list markers",
        "renumber list"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "nickname-cleaner",
      "name": "Nickname cleaner",
      "description": "Clean gamer nicknames from clan tags and decorative symbols.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/nickname-cleaner",
      "embed": "https://textarray.com/embed/nickname-cleaner",
      "mode": "transform",
      "action": "Clean nicknames",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "stripTags",
          "kind": "checkbox",
          "label": "Strip clan tags",
          "default": true
        },
        {
          "key": "symbolsOnly",
          "kind": "checkbox",
          "label": "Remove decorative symbols",
          "default": true
        },
        {
          "key": "collapseSpaces",
          "kind": "checkbox",
          "label": "Collapse spaces",
          "default": true
        }
      ],
      "keywords": [
        "nickname cleaner",
        "remove clan tags",
        "steam discord names",
        "clean gamer names",
        "strip clan tags",
        "gaming nickname cleaner"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "octal-converter",
      "name": "Octal converter",
      "description": "Convert text to octal character codes and back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/octal-converter",
      "embed": "https://textarray.com/embed/octal-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text to octal"
            },
            {
              "value": "decode",
              "label": "Octal to text"
            }
          ]
        },
        {
          "key": "unicode",
          "kind": "checkbox",
          "label": "Full Unicode code points",
          "default": false
        }
      ],
      "keywords": [
        "octal converter",
        "text to octal",
        "octal to text",
        "octal encode",
        "octal decode",
        "octal codepoints"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "caesar-brute-force",
      "name": "Caesar brute force",
      "description": "Crack a Caesar cipher by showing all 25 possible shifts at once.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/caesar-brute-force",
      "embed": "https://textarray.com/embed/caesar-brute-force",
      "mode": "transform",
      "action": "Show all shifts",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "showShift",
          "kind": "checkbox",
          "label": "Show shift number",
          "default": true
        },
        {
          "key": "padPrefix",
          "kind": "checkbox",
          "label": "Pad shift number",
          "default": true
        }
      ],
      "keywords": [
        "caesar brute force",
        "caesar cracker",
        "crack caesar cipher",
        "break caesar cipher",
        "rot brute force",
        "all rot shifts",
        "shift cipher solver"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "numeric-lines-filter",
      "name": "Numeric lines filter",
      "description": "Keep or remove lines that contain only a number.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/numeric-lines-filter",
      "embed": "https://textarray.com/embed/numeric-lines-filter",
      "mode": "transform",
      "action": "Filter numeric lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "keep",
          "choices": [
            {
              "value": "keep",
              "label": "Keep numeric lines"
            },
            {
              "value": "remove",
              "label": "Remove numeric lines"
            }
          ]
        },
        {
          "key": "allowDecimal",
          "kind": "checkbox",
          "label": "Allow decimals (3.14 / 3,14)",
          "default": true
        },
        {
          "key": "ignoreWhitespace",
          "kind": "checkbox",
          "label": "Ignore surrounding whitespace",
          "default": true
        }
      ],
      "keywords": [
        "keep numeric lines",
        "filter number lines",
        "only numbers lines",
        "numeric lines filter",
        "remove non numeric lines",
        "remove non-numeric lines",
        "keep only numeric lines",
        "filter numbers from list",
        "extract numeric lines",
        "delete non-number lines",
        "numbers only filter"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "rot-cipher",
      "name": "ROT cipher",
      "description": "Rotate letters by any amount from 1 to 25 with a slider — a variable ROT13.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/rot-cipher",
      "embed": "https://textarray.com/embed/rot-cipher",
      "mode": "transform",
      "action": "Apply ROT cipher",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "shift",
          "kind": "range",
          "label": "Shift",
          "default": 13,
          "min": 1,
          "max": 25
        },
        {
          "key": "rot47",
          "kind": "checkbox",
          "label": "ROT47 mode (rotate all printable characters)",
          "default": false
        }
      ],
      "keywords": [
        "rot-n cipher",
        "variable rot",
        "adjustable rot cipher",
        "caesar cipher generator",
        "letter shift cipher",
        "rot13 rot47 generator"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "min-words-filter",
      "name": "Minimum words filter",
      "description": "Remove lines that have fewer words than a threshold you set.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/min-words-filter",
      "embed": "https://textarray.com/embed/min-words-filter",
      "mode": "transform",
      "action": "Filter by word count",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "minWords",
          "kind": "number",
          "label": "Minimum words",
          "default": 3,
          "min": 1,
          "max": 100
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "keep-long",
          "choices": [
            {
              "value": "keep-long",
              "label": "Keep lines with enough words"
            },
            {
              "value": "keep-short",
              "label": "Keep lines below the threshold"
            }
          ]
        }
      ],
      "keywords": [
        "minimum words filter",
        "remove short lines",
        "filter lines by word count",
        "word count filter",
        "keep long lines",
        "remove lines by word count",
        "delete short lines",
        "minimum words per line",
        "strip short lines"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "reverse-line-numbers",
      "name": "Reverse line numbers",
      "description": "Prefix each line with a descending number, counting down to 1.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/reverse-line-numbers",
      "embed": "https://textarray.com/embed/reverse-line-numbers",
      "mode": "transform",
      "action": "Number lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "text",
          "label": "Separator",
          "default": ". "
        },
        {
          "key": "padZeros",
          "kind": "checkbox",
          "label": "Pad with zeros",
          "default": false
        },
        {
          "key": "skipEmpty",
          "kind": "checkbox",
          "label": "Don't number empty lines",
          "default": false
        }
      ],
      "keywords": [
        "reverse line numbers",
        "descending line numbers",
        "countdown numbering",
        "reverse numbered list",
        "number lines backwards"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "truncate-at-word",
      "name": "Truncate at word",
      "description": "Cut text at the first occurrence of a keyword and keep only the part before or after it.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/truncate-at-word",
      "embed": "https://textarray.com/embed/truncate-at-word",
      "mode": "transform",
      "action": "Truncate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keyword",
          "kind": "text",
          "label": "Keyword",
          "default": ""
        },
        {
          "key": "side",
          "kind": "select",
          "label": "Side to keep",
          "default": "before",
          "choices": [
            {
              "value": "before",
              "label": "Before"
            },
            {
              "value": "after",
              "label": "After"
            }
          ]
        },
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Case-insensitive",
          "default": false
        },
        {
          "key": "includeKeyword",
          "kind": "checkbox",
          "label": "Include keyword",
          "default": false
        }
      ],
      "keywords": [
        "truncate at word",
        "cut text at keyword",
        "split at word",
        "cut text at word",
        "truncate before keyword",
        "truncate after keyword"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "sort-lines-by-length",
      "name": "Sort lines by length",
      "description": "Order the lines of a list from shortest to longest, or the other way around.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/sort-lines-by-length",
      "embed": "https://textarray.com/embed/sort-lines-by-length",
      "mode": "transform",
      "action": "Sort by length",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "order",
          "kind": "select",
          "label": "Order",
          "default": "asc",
          "choices": [
            {
              "value": "asc",
              "label": "Shortest first"
            },
            {
              "value": "desc",
              "label": "Longest first"
            }
          ]
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace before measuring",
          "default": false
        },
        {
          "key": "stable",
          "kind": "checkbox",
          "label": "Keep original order for equal lengths",
          "default": true
        }
      ],
      "keywords": [
        "sort lines by length",
        "order lines length",
        "shortest longest lines",
        "sort by character count",
        "line length sort",
        "size ordering"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "pangram-checker",
      "name": "Pangram checker",
      "description": "Check whether your text contains every letter of the alphabet and see which are missing.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/pangram-checker",
      "embed": "https://textarray.com/embed/pangram-checker",
      "mode": "transform",
      "action": "Check pangram",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "alphabet",
          "kind": "select",
          "label": "Alphabet",
          "default": "en",
          "choices": [
            {
              "value": "en",
              "label": "English (A–Z)"
            },
            {
              "value": "de",
              "label": "German (A–Z + ä ö ü ß)"
            },
            {
              "value": "sk",
              "label": "Slovak"
            },
            {
              "value": "cs",
              "label": "Czech"
            },
            {
              "value": "pl",
              "label": "Polish"
            },
            {
              "value": "hu",
              "label": "Hungarian"
            }
          ]
        }
      ],
      "keywords": [
        "pangram checker",
        "check pangram",
        "is it a pangram",
        "perfect pangram",
        "missing letters"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "word-counter",
      "name": "Word and character counter",
      "description": "Count words, characters, sentences, paragraphs and reading time in any text.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/word-counter",
      "embed": "https://textarray.com/embed/word-counter",
      "mode": "transform",
      "action": "Count",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "word counter",
        "character counter",
        "count words",
        "letter count",
        "reading time",
        "text statistics"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "word-frequency",
      "name": "Word frequency counter",
      "description": "List every word in a text with how many times it appears, ranked by count.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/word-frequency",
      "embed": "https://textarray.com/embed/word-frequency",
      "mode": "transform",
      "action": "Count frequency",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Case-insensitive",
          "default": true
        },
        {
          "key": "ignoreStopWords",
          "kind": "checkbox",
          "label": "Skip common words",
          "default": false
        },
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "count",
          "choices": [
            {
              "value": "count",
              "label": "Count"
            },
            {
              "value": "alphabetical",
              "label": "Alphabetical"
            }
          ]
        },
        {
          "key": "minLength",
          "kind": "number",
          "label": "Minimum word length",
          "default": 1,
          "min": 1,
          "max": 20,
          "step": 1
        },
        {
          "key": "limit",
          "kind": "number",
          "label": "Limit rows (0 = all)",
          "default": 0,
          "min": 0,
          "max": 1000,
          "step": 1
        }
      ],
      "keywords": [
        "word frequency",
        "word frequency counter",
        "most common words",
        "keyword density",
        "count word occurrences",
        "word list"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "find-and-replace",
      "name": "Find and replace",
      "description": "Replace every occurrence of a word or pattern, with optional regex support.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/find-and-replace",
      "embed": "https://textarray.com/embed/find-and-replace",
      "mode": "transform",
      "action": "Replace all",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "find",
          "kind": "text",
          "label": "Find",
          "default": ""
        },
        {
          "key": "replaceWith",
          "kind": "text",
          "label": "Replace with",
          "default": ""
        },
        {
          "key": "useRegex",
          "kind": "checkbox",
          "label": "Use regular expression",
          "default": false
        },
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Match case",
          "default": true
        },
        {
          "key": "wholeWord",
          "kind": "checkbox",
          "label": "Whole words only",
          "default": false
        }
      ],
      "keywords": [
        "find and replace",
        "search and replace",
        "replace text",
        "bulk replace"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "case-converter",
      "name": "Case converter",
      "description": "Convert text between twelve formats, from UPPERCASE to camelCase and kebab-case.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/case-converter",
      "embed": "https://textarray.com/embed/case-converter",
      "mode": "transform",
      "action": "Convert case",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Format",
          "default": "upper",
          "choices": [
            {
              "value": "upper",
              "label": "UPPERCASE"
            },
            {
              "value": "lower",
              "label": "lowercase"
            },
            {
              "value": "title",
              "label": "Title Case"
            },
            {
              "value": "sentence",
              "label": "Sentence case"
            },
            {
              "value": "capitalize",
              "label": "Capitalize Each Word"
            },
            {
              "value": "camel",
              "label": "camelCase"
            },
            {
              "value": "pascal",
              "label": "PascalCase"
            },
            {
              "value": "snake",
              "label": "snake_case"
            },
            {
              "value": "constant",
              "label": "CONSTANT_CASE"
            },
            {
              "value": "kebab",
              "label": "kebab-case"
            },
            {
              "value": "dot",
              "label": "dot.case"
            },
            {
              "value": "alternating",
              "label": "aLtErNaTiNg cAsE"
            }
          ]
        }
      ],
      "keywords": [
        "case converter",
        "uppercase",
        "lowercase",
        "title case",
        "camelcase",
        "snake case",
        "kebab case",
        "pascalcase",
        "snake_case"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "text-diff",
      "name": "Text diff",
      "description": "Compare two texts line by line and see exactly what was added and removed.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/text-diff",
      "embed": "https://textarray.com/embed/text-diff",
      "mode": "transform",
      "action": "Compare texts",
      "input": {
        "kind": "text",
        "panels": 3,
        "additionalPanels": [
          "Text B",
          "Base version (optional)"
        ],
        "maxBytes": 10485760
      },
      "output": "diff",
      "options": [
        {
          "key": "ignoreCase",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": false
        },
        {
          "key": "ignoreWhitespace",
          "kind": "checkbox",
          "label": "Ignore leading and trailing spaces",
          "default": false
        }
      ],
      "keywords": [
        "text diff",
        "compare text",
        "diff checker",
        "text comparison",
        "find differences"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "utf8-byte-counter",
      "name": "UTF-8 byte counter",
      "description": "Measure the real size of text in UTF-8 bytes, UTF-16 units, code points and graphemes.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/utf8-byte-counter",
      "embed": "https://textarray.com/embed/utf8-byte-counter",
      "mode": "transform",
      "action": "Count bytes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "newline",
          "kind": "select",
          "label": "Line endings",
          "default": "asis",
          "choices": [
            {
              "value": "asis",
              "label": "Count as pasted"
            },
            {
              "value": "lf",
              "label": "As LF (Unix)"
            },
            {
              "value": "crlf",
              "label": "As CRLF (Windows)"
            }
          ]
        }
      ],
      "keywords": [
        "utf-8 byte counter",
        "byte counter",
        "string byte size",
        "text size in bytes",
        "utf-16 length",
        "code points",
        "grapheme count",
        "string length"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "palindrome-checker",
      "name": "Palindrome checker",
      "description": "Check whether text reads the same backwards and find palindromic words in it.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/palindrome-checker",
      "embed": "https://textarray.com/embed/palindrome-checker",
      "mode": "transform",
      "action": "Check palindromes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "ignoreCase",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": true
        },
        {
          "key": "ignorePunctuation",
          "kind": "checkbox",
          "label": "Ignore spaces and punctuation",
          "default": true
        },
        {
          "key": "ignoreDiacritics",
          "kind": "checkbox",
          "label": "Ignore diacritics",
          "default": true
        },
        {
          "key": "minLength",
          "kind": "number",
          "label": "Minimum word length",
          "default": 3,
          "min": 1,
          "max": 50
        }
      ],
      "keywords": [
        "palindrome checker",
        "palindrome finder",
        "find palindromes",
        "palindrome words",
        "is it a palindrome",
        "palindrom",
        "mirror text"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "reading-time",
      "name": "Reading time calculator",
      "description": "Estimate how long a text takes to read aloud or silently.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/reading-time",
      "embed": "https://textarray.com/embed/reading-time",
      "mode": "transform",
      "action": "Calculate reading time",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "speed",
          "kind": "select",
          "label": "Reading speed",
          "default": "average",
          "choices": [
            {
              "value": "slow",
              "label": "Slow (150 wpm)"
            },
            {
              "value": "average",
              "label": "Average (220 wpm)"
            },
            {
              "value": "fast",
              "label": "Fast (300 wpm)"
            }
          ]
        }
      ],
      "keywords": [
        "reading time",
        "reading time calculator",
        "read time",
        "speaking time",
        "words per minute",
        "wpm",
        "how long to read"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "readability-score",
      "name": "Readability score checker",
      "description": "Score text readability with Flesch, Fog, ARI and Coleman–Liau.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/readability-score",
      "embed": "https://textarray.com/embed/readability-score",
      "mode": "transform",
      "action": "Check readability",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "raw",
          "kind": "checkbox",
          "label": "Show raw counts",
          "default": true
        }
      ],
      "keywords": [
        "readability score",
        "readability checker",
        "readability test",
        "flesch reading ease",
        "flesch kincaid calculator",
        "flesch kincaid grade level",
        "gunning fog index",
        "automated readability index",
        "coleman liau index",
        "reading level checker",
        "flesch-kincaid gunning fog",
        "gunning-fog index"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "sentence-counter",
      "name": "Sentence counter",
      "description": "Count sentences, paragraphs and average sentence length, and flag overlong sentences.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/sentence-counter",
      "embed": "https://textarray.com/embed/sentence-counter",
      "mode": "transform",
      "action": "Count sentences",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "flagLong",
          "kind": "number",
          "label": "Flag sentences over N words",
          "default": 25,
          "min": 5,
          "max": 200,
          "step": 1
        }
      ],
      "keywords": [
        "sentence counter",
        "count sentences",
        "sentence count",
        "sentences per paragraph",
        "average sentence length",
        "run-on sentences"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "keyword-density",
      "name": "Keyword density checker",
      "description": "Check how often each keyword appears in a text and what share of it that makes.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/keyword-density",
      "embed": "https://textarray.com/embed/keyword-density",
      "mode": "transform",
      "action": "Check density",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "phraseLength",
          "kind": "select",
          "label": "Phrase length",
          "default": "1",
          "choices": [
            {
              "value": "1",
              "label": "1 word"
            },
            {
              "value": "2",
              "label": "2 words"
            },
            {
              "value": "3",
              "label": "3 words"
            },
            {
              "value": "4",
              "label": "4 words"
            },
            {
              "value": "5",
              "label": "5 words"
            },
            {
              "value": "6",
              "label": "6 words"
            },
            {
              "value": "7",
              "label": "7 words"
            }
          ]
        },
        {
          "key": "unit",
          "kind": "select",
          "label": "Units",
          "default": "words",
          "choices": [
            {
              "value": "words",
              "label": "Words"
            },
            {
              "value": "characters",
              "label": "Characters"
            }
          ]
        },
        {
          "key": "minCount",
          "kind": "number",
          "label": "Minimum count",
          "default": 2,
          "min": 1,
          "max": 1000,
          "step": 1
        },
        {
          "key": "limit",
          "kind": "number",
          "label": "Top keywords (0 = all)",
          "default": 20,
          "min": 0,
          "max": 1000,
          "step": 1
        },
        {
          "key": "ignoreCase",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": true
        }
      ],
      "keywords": [
        "keyword density",
        "keyword density checker",
        "seo keyword density",
        "keyword frequency",
        "keyword analysis",
        "ngram",
        "seo"
      ],
      "updated": "2026-08-23"
    },
    {
      "slug": "letter-frequency",
      "name": "Letter frequency counter",
      "description": "Count how often each letter appears in a text, with counts and percentages.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/letter-frequency",
      "embed": "https://textarray.com/embed/letter-frequency",
      "mode": "transform",
      "action": "Count letters",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "ignoreCase",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": true
        },
        {
          "key": "lettersOnly",
          "kind": "checkbox",
          "label": "Letters only",
          "default": true
        },
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "count",
          "choices": [
            {
              "value": "count",
              "label": "Count"
            },
            {
              "value": "alphabetical",
              "label": "Alphabetical"
            }
          ]
        }
      ],
      "keywords": [
        "letter frequency",
        "letter frequency counter",
        "character frequency",
        "count letters",
        "letter count",
        "character count table"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "anagram-checker",
      "name": "Anagram checker",
      "description": "Check whether two texts are anagrams of each other and see exactly which letters differ.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/anagram-checker",
      "embed": "https://textarray.com/embed/anagram-checker",
      "mode": "transform",
      "action": "Check anagram",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Second text"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "ignoreAccents",
          "kind": "checkbox",
          "label": "Ignore accents",
          "default": true
        }
      ],
      "keywords": [
        "anagram checker",
        "check anagram",
        "is it an anagram",
        "anagram comparison",
        "letter multiset"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "syllable-counter",
      "name": "Syllable counter",
      "description": "Count syllables in your text — total, average per word and a per-word breakdown, with long words flagged.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/syllable-counter",
      "embed": "https://textarray.com/embed/syllable-counter",
      "mode": "transform",
      "action": "Count syllables",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "breakdown",
          "kind": "checkbox",
          "label": "Show per-word breakdown",
          "default": false
        },
        {
          "key": "flagLong",
          "kind": "number",
          "label": "Flag words over N syllables",
          "default": 4,
          "min": 1,
          "max": 20,
          "step": 1
        }
      ],
      "keywords": [
        "syllable counter",
        "count syllables",
        "syllables per word",
        "how many syllables",
        "syllable count online",
        "haiku syllables"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "rhyme-scheme-analyzer",
      "name": "Rhyme scheme analyzer",
      "description": "Label each line's rhyme group (A, B, C…) and see the pattern at a glance.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/rhyme-scheme-analyzer",
      "embed": "https://textarray.com/embed/rhyme-scheme-analyzer",
      "mode": "transform",
      "action": "Analyze rhyme scheme",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "endingLength",
          "kind": "range",
          "label": "Ending length compared",
          "default": 3,
          "min": 2,
          "max": 4
        }
      ],
      "keywords": [
        "rhyme scheme analyzer",
        "rhyme scheme checker",
        "find rhyme scheme",
        "poem rhyme scheme",
        "rhyming lines finder",
        "check poem rhymes",
        "rhyme pattern finder",
        "abab rhyme scheme",
        "aabb rhyme scheme"
      ],
      "updated": "2026-07-29"
    },
    {
      "slug": "text-similarity",
      "name": "Text similarity",
      "description": "Measure how similar two texts are — similarity percentage, Levenshtein distance and word overlap.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/text-similarity",
      "embed": "https://textarray.com/embed/text-similarity",
      "mode": "transform",
      "action": "Compare texts",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Second text"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "ignoreCase",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": true
        },
        {
          "key": "ignorePunctuation",
          "kind": "checkbox",
          "label": "Ignore punctuation",
          "default": false
        }
      ],
      "keywords": [
        "text similarity",
        "similarity checker",
        "compare two texts",
        "levenshtein distance",
        "edit distance",
        "jaccard similarity",
        "how similar are two texts"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "shannon-entropy",
      "name": "Shannon entropy calculator",
      "description": "Measure how many bits of information each character or word of your text carries.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/shannon-entropy",
      "embed": "https://textarray.com/embed/shannon-entropy",
      "mode": "transform",
      "action": "Measure entropy",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "unit",
          "kind": "select",
          "label": "Measure over",
          "default": "chars",
          "choices": [
            {
              "value": "chars",
              "label": "Characters"
            },
            {
              "value": "words",
              "label": "Words"
            }
          ]
        },
        {
          "key": "ignoreCase",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": false
        },
        {
          "key": "ignoreWhitespace",
          "kind": "checkbox",
          "label": "Ignore whitespace",
          "default": false
        },
        {
          "key": "histogram",
          "kind": "checkbox",
          "label": "Byte frequency histogram",
          "default": false
        },
        {
          "key": "chiSquare",
          "kind": "checkbox",
          "label": "Chi-square uniformity test",
          "default": false
        },
        {
          "key": "windowSize",
          "kind": "number",
          "label": "Sliding window (bytes, 0 = off)",
          "default": 0,
          "min": 0,
          "max": 65536,
          "step": 64
        }
      ],
      "keywords": [
        "shannon entropy calculator",
        "text entropy",
        "entropy of a string",
        "bits per character",
        "information content calculator",
        "randomness measure text"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "subtitle-cps",
      "name": "Subtitle reading speed (CPS)",
      "description": "Measure characters per second for every subtitle cue and flag the ones nobody can read.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/subtitle-cps",
      "embed": "https://textarray.com/embed/subtitle-cps",
      "mode": "transform",
      "action": "Analyze reading speed",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "threshold",
          "kind": "number",
          "label": "Flag above (CPS)",
          "default": 20,
          "min": 1,
          "max": 50,
          "step": 1
        }
      ],
      "keywords": [
        "subtitle cps analyzer",
        "characters per second subtitles",
        "subtitle reading speed",
        "cps checker srt",
        "subtitle wpm counter",
        "too fast subtitles check"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "text-direction",
      "name": "Text direction detector (LTR/RTL)",
      "description": "Detect whether text runs left-to-right or right-to-left and get the dir attribute to use.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/text-direction",
      "embed": "https://textarray.com/embed/text-direction",
      "mode": "transform",
      "action": "Detect direction",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "text direction detector",
        "ltr or rtl checker",
        "detect rtl text",
        "right to left detection",
        "dir attribute checker",
        "bidi text analysis",
        "ltr vs rtl"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "count-occurrences",
      "name": "Count occurrences",
      "description": "Find out how many times a word or phrase appears in your text.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/count-occurrences",
      "embed": "https://textarray.com/embed/count-occurrences",
      "mode": "transform",
      "action": "Count occurrences",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "term",
          "kind": "text",
          "label": "Search term",
          "default": ""
        },
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case sensitive",
          "default": false
        },
        {
          "key": "wholeWord",
          "kind": "checkbox",
          "label": "Whole word only",
          "default": false
        }
      ],
      "keywords": [
        "count occurrences",
        "count matches",
        "find count",
        "search count",
        "how many times",
        "occurrence counter"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "longest-word-finder",
      "name": "Longest Word Finder",
      "description": "Find the longest and shortest words and calculate the average word length.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/longest-word-finder",
      "embed": "https://textarray.com/embed/longest-word-finder",
      "mode": "transform",
      "action": "Analyze words",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "longest word",
        "shortest word",
        "average word length",
        "word length",
        "longest and shortest",
        "word analysis",
        "text analysis"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "social-char-limits",
      "name": "Social media character limits",
      "description": "Check your text against the character limits of X, LinkedIn, Instagram and more, at once.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/social-char-limits",
      "embed": "https://textarray.com/embed/social-char-limits",
      "mode": "transform",
      "action": "Check limits",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "netX",
          "kind": "checkbox",
          "label": "X (Twitter)",
          "default": true
        },
        {
          "key": "netLinkedin",
          "kind": "checkbox",
          "label": "LinkedIn",
          "default": true
        },
        {
          "key": "netInstagram",
          "kind": "checkbox",
          "label": "Instagram",
          "default": true
        },
        {
          "key": "netFacebook",
          "kind": "checkbox",
          "label": "Facebook",
          "default": true
        },
        {
          "key": "netBluesky",
          "kind": "checkbox",
          "label": "Bluesky",
          "default": true
        },
        {
          "key": "netMastodon",
          "kind": "checkbox",
          "label": "Mastodon",
          "default": true
        },
        {
          "key": "netYoutube",
          "kind": "checkbox",
          "label": "YouTube description",
          "default": true
        },
        {
          "key": "netEmailSubject",
          "kind": "checkbox",
          "label": "Email subject",
          "default": true
        },
        {
          "key": "shortenLinks",
          "kind": "checkbox",
          "label": "Count links as shortened",
          "default": true
        },
        {
          "key": "emojiMode",
          "kind": "select",
          "label": "Count emoji as",
          "default": "grapheme",
          "choices": [
            {
              "value": "grapheme",
              "label": "One character"
            },
            {
              "value": "codepoint",
              "label": "Unicode code points"
            }
          ]
        },
        {
          "key": "showHeadroom",
          "kind": "checkbox",
          "label": "Show headroom to limit",
          "default": true
        },
        {
          "key": "truncateFor",
          "kind": "select",
          "label": "Truncate to limit",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Don't truncate"
            },
            {
              "value": "x",
              "label": "X (280)"
            },
            {
              "value": "linkedin",
              "label": "LinkedIn (3,000)"
            },
            {
              "value": "instagram",
              "label": "Instagram (2,200)"
            },
            {
              "value": "facebook",
              "label": "Facebook (63,206)"
            },
            {
              "value": "bluesky",
              "label": "Bluesky (300)"
            },
            {
              "value": "mastodon",
              "label": "Mastodon (500)"
            },
            {
              "value": "youtube",
              "label": "YouTube description (5,000)"
            },
            {
              "value": "emailSubject",
              "label": "Email subject (78)"
            }
          ]
        }
      ],
      "keywords": [
        "social media character limits",
        "character counter",
        "tweet length checker",
        "x character limit",
        "instagram caption limit",
        "linkedin post limit",
        "bluesky character limit",
        "mastodon character limit",
        "youtube description limit",
        "email subject length"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "sort-words",
      "name": "Sort words",
      "description": "Sort the words of your text alphabetically or by length, with optional deduplication.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/sort-words",
      "embed": "https://textarray.com/embed/sort-words",
      "mode": "transform",
      "action": "Sort words",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "order",
          "kind": "select",
          "label": "Order",
          "default": "asc",
          "choices": [
            {
              "value": "asc",
              "label": "A → Z"
            },
            {
              "value": "desc",
              "label": "Z → A"
            },
            {
              "value": "lengthAsc",
              "label": "Shortest first"
            },
            {
              "value": "lengthDesc",
              "label": "Longest first"
            }
          ]
        },
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Case-insensitive",
          "default": true
        },
        {
          "key": "ignorePunctuation",
          "kind": "checkbox",
          "label": "Ignore punctuation",
          "default": false
        },
        {
          "key": "removeDuplicates",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": false
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "newline",
              "label": "New line"
            },
            {
              "value": "comma",
              "label": "Comma"
            }
          ]
        }
      ],
      "keywords": [
        "sort words",
        "sort words alphabetically",
        "alphabetize words",
        "order words",
        "sort words by length",
        "word sorter"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "swap-words",
      "name": "Swap words",
      "description": "Swap every occurrence of one word with another, and vice versa, in a single pass.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/swap-words",
      "embed": "https://textarray.com/embed/swap-words",
      "mode": "transform",
      "action": "Swap words",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "wordA",
          "kind": "text",
          "label": "First word",
          "default": ""
        },
        {
          "key": "wordB",
          "kind": "text",
          "label": "Second word",
          "default": ""
        },
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": true
        },
        {
          "key": "wholeWords",
          "kind": "checkbox",
          "label": "Whole words only",
          "default": true
        }
      ],
      "keywords": [
        "swap words",
        "exchange words",
        "switch two words",
        "replace two words",
        "swap word a with word b"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "sort-lines",
      "name": "Sort lines",
      "description": "Sort lines alphabetically, naturally, by length or by leading number.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/sort-lines",
      "embed": "https://textarray.com/embed/sort-lines",
      "mode": "transform",
      "action": "Sort lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "order",
          "kind": "select",
          "label": "Order",
          "default": "az",
          "choices": [
            {
              "value": "az",
              "label": "A → Z"
            },
            {
              "value": "za",
              "label": "Z → A"
            },
            {
              "value": "natural",
              "label": "Natural"
            },
            {
              "value": "lengthAsc",
              "label": "Shortest first"
            },
            {
              "value": "lengthDesc",
              "label": "Longest first"
            },
            {
              "value": "numeric",
              "label": "Numeric"
            }
          ]
        },
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Case-insensitive",
          "default": true
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        },
        {
          "key": "ignoreDiacritics",
          "kind": "checkbox",
          "label": "Ignore diacritics",
          "default": false
        }
      ],
      "keywords": [
        "sort lines",
        "sort alphabetically",
        "alphabetical order",
        "natural sort",
        "sort by length",
        "sort lines by length",
        "sort list",
        "sort lines ignoring diacritics",
        "accent insensitive sort",
        "alphabetical sort"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "add-prefix-suffix",
      "name": "Add prefix and suffix",
      "description": "Add text to the beginning or end of every line at once.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/add-prefix-suffix",
      "embed": "https://textarray.com/embed/add-prefix-suffix",
      "mode": "transform",
      "action": "Add to lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "prefix",
          "kind": "text",
          "label": "Prefix",
          "default": ""
        },
        {
          "key": "suffix",
          "kind": "text",
          "label": "Suffix",
          "default": ""
        },
        {
          "key": "skipEmpty",
          "kind": "checkbox",
          "label": "Skip empty lines",
          "default": true
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim lines first",
          "default": false
        }
      ],
      "keywords": [
        "add prefix",
        "add suffix",
        "prepend to lines",
        "append to lines",
        "add text to each line",
        "wrap lines",
        "text decoration"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "line-breaks",
      "name": "Add or remove line breaks",
      "description": "Join broken lines into one block or split text into new lines.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/line-breaks",
      "embed": "https://textarray.com/embed/line-breaks",
      "mode": "transform",
      "action": "Apply",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "remove",
          "choices": [
            {
              "value": "remove",
              "label": "Remove all line breaks"
            },
            {
              "value": "paragraphs",
              "label": "Keep paragraph breaks"
            },
            {
              "value": "afterSentences",
              "label": "Break after each sentence"
            },
            {
              "value": "everyN",
              "label": "Break every N characters"
            }
          ]
        },
        {
          "key": "joiner",
          "kind": "text",
          "label": "Join with",
          "default": " "
        },
        {
          "key": "n",
          "kind": "number",
          "label": "Characters per line",
          "default": 80,
          "min": 10,
          "max": 500
        }
      ],
      "keywords": [
        "remove line breaks",
        "add line breaks",
        "join lines",
        "wrap text",
        "break after sentences",
        "newlines",
        "newline split"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "split-text",
      "name": "Split text",
      "description": "Split text by any delimiter and get one item per line.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/split-text",
      "embed": "https://textarray.com/embed/split-text",
      "mode": "transform",
      "action": "Split text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "delimiter",
          "kind": "text",
          "label": "Delimiter",
          "default": ","
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim items",
          "default": true
        },
        {
          "key": "removeEmpty",
          "kind": "checkbox",
          "label": "Remove empty items",
          "default": true
        },
        {
          "key": "regex",
          "kind": "checkbox",
          "label": "Treat delimiter as a regular expression",
          "default": false
        }
      ],
      "keywords": [
        "split text",
        "split by delimiter",
        "split by comma",
        "text to lines",
        "csv to list",
        "explode string",
        "separator splitter"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "reverse-text",
      "name": "Reverse text",
      "description": "Reverse the characters, word order or each line of your text.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/reverse-text",
      "embed": "https://textarray.com/embed/reverse-text",
      "mode": "transform",
      "action": "Reverse",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "unit",
          "kind": "select",
          "label": "Unit",
          "default": "characters",
          "choices": [
            {
              "value": "characters",
              "label": "Reverse characters"
            },
            {
              "value": "words",
              "label": "Reverse word order"
            },
            {
              "value": "lines",
              "label": "Reverse characters in each line"
            }
          ]
        }
      ],
      "keywords": [
        "reverse text",
        "mirror text",
        "reverse words",
        "reverse lines",
        "flip text",
        "text reverser",
        "backwards text"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "repeat-text",
      "name": "Repeat text",
      "description": "Repeat a piece of text as many times as you need, with the separator you choose.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/repeat-text",
      "embed": "https://textarray.com/embed/repeat-text",
      "mode": "transform",
      "action": "Repeat text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "times",
          "kind": "number",
          "label": "Times",
          "default": 5,
          "min": 1,
          "max": 100000,
          "step": 1
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "newline",
          "choices": [
            {
              "value": "newline",
              "label": "New line"
            },
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "none",
              "label": "Nothing"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customSeparator",
          "kind": "text",
          "label": "Custom separator",
          "default": ""
        }
      ],
      "keywords": [
        "repeat text",
        "text repeater",
        "duplicate text",
        "repeat string",
        "multiply text",
        "copy text n times"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "shuffle-text",
      "name": "Shuffle text",
      "description": "Put lines, words or letters into a truly random order.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/shuffle-text",
      "embed": "https://textarray.com/embed/shuffle-text",
      "mode": "transform",
      "action": "Shuffle",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "unit",
          "kind": "select",
          "label": "Unit",
          "default": "lines",
          "choices": [
            {
              "value": "lines",
              "label": "Shuffle lines"
            },
            {
              "value": "words",
              "label": "Shuffle words"
            },
            {
              "value": "letters",
              "label": "Shuffle letters"
            }
          ]
        }
      ],
      "keywords": [
        "shuffle text",
        "shuffle lines",
        "randomize lines",
        "random order",
        "shuffle words",
        "mix letters",
        "list shuffler",
        "randomizer"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "combine-lines",
      "name": "Combine texts line by line",
      "description": "Join two texts by pairing their lines: line 1 with line 1, line 2 with line 2.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/combine-lines",
      "embed": "https://textarray.com/embed/combine-lines",
      "mode": "transform",
      "action": "Combine lines",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Text B"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "none",
              "label": "Nothing"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customSeparator",
          "kind": "text",
          "label": "Custom separator",
          "default": ""
        },
        {
          "key": "lengthMode",
          "kind": "select",
          "label": "Different lengths",
          "default": "stop",
          "choices": [
            {
              "value": "stop",
              "label": "Stop at the shorter text"
            },
            {
              "value": "pad",
              "label": "Pad with empty lines"
            }
          ]
        },
        {
          "key": "prefix",
          "kind": "text",
          "label": "Prefix",
          "default": ""
        },
        {
          "key": "suffix",
          "kind": "text",
          "label": "Suffix",
          "default": ""
        }
      ],
      "keywords": [
        "combine lines",
        "zip two lists",
        "merge lines side by side",
        "join two texts line by line",
        "interleave lines",
        "combine two columns",
        "text pairing"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "truncate-text",
      "name": "Truncate text",
      "description": "Cut text down to a set number of characters or words and trim line edges.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/truncate-text",
      "embed": "https://textarray.com/embed/truncate-text",
      "mode": "transform",
      "action": "Truncate text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "unit",
          "kind": "select",
          "label": "Limit by",
          "default": "characters",
          "choices": [
            {
              "value": "characters",
              "label": "Characters"
            },
            {
              "value": "words",
              "label": "Words"
            },
            {
              "value": "keyword",
              "label": "At keyword"
            }
          ]
        },
        {
          "key": "limit",
          "kind": "number",
          "label": "Keep at most",
          "default": 160,
          "min": 1,
          "max": 1000000
        },
        {
          "key": "keyword",
          "kind": "text",
          "label": "Keyword",
          "default": ""
        },
        {
          "key": "keep",
          "kind": "select",
          "label": "What to keep",
          "default": "before",
          "choices": [
            {
              "value": "before",
              "label": "Keep text before it"
            },
            {
              "value": "after",
              "label": "Keep text after it"
            }
          ]
        },
        {
          "key": "wholeWords",
          "kind": "checkbox",
          "label": "Keep whole words",
          "default": true
        },
        {
          "key": "ellipsis",
          "kind": "checkbox",
          "label": "Add an ellipsis (…)",
          "default": false
        },
        {
          "key": "perLine",
          "kind": "checkbox",
          "label": "Truncate each line",
          "default": false
        },
        {
          "key": "trimStart",
          "kind": "number",
          "label": "Remove from line start",
          "default": 0,
          "min": 0,
          "max": 10000
        },
        {
          "key": "trimEnd",
          "kind": "number",
          "label": "Remove from line end",
          "default": 0,
          "min": 0,
          "max": 10000
        }
      ],
      "keywords": [
        "truncate text",
        "shorten text",
        "cut text",
        "character limit",
        "limit characters",
        "trim lines",
        "meta description length",
        "text truncator",
        "truncate at word",
        "cut text at keyword",
        "split at keyword",
        "cut before keyword",
        "cut after keyword"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "extract-column",
      "name": "Extract column",
      "description": "Pull the columns you need out of CSV, TSV or any delimited text.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/extract-column",
      "embed": "https://textarray.com/embed/extract-column",
      "mode": "transform",
      "action": "Extract columns",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "extract",
          "choices": [
            {
              "value": "extract",
              "label": "Keep listed columns"
            },
            {
              "value": "swap",
              "label": "Swap two columns"
            }
          ]
        },
        {
          "key": "columns",
          "kind": "text",
          "label": "Columns",
          "default": "1"
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customDelimiter",
          "kind": "text",
          "label": "Custom delimiter",
          "default": ""
        },
        {
          "key": "outputDelimiter",
          "kind": "text",
          "label": "Output delimiter",
          "default": ""
        },
        {
          "key": "quotes",
          "kind": "checkbox",
          "label": "Read quoted CSV fields",
          "default": true
        },
        {
          "key": "quoteOutput",
          "kind": "checkbox",
          "label": "Quote values with delimiter",
          "default": false
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        },
        {
          "key": "skipMissing",
          "kind": "checkbox",
          "label": "Skip rows without the column",
          "default": false
        }
      ],
      "keywords": [
        "extract column",
        "csv column extractor",
        "get nth column",
        "select column csv",
        "tsv column",
        "cut columns",
        "swap columns",
        "reorder columns",
        "rearrange csv columns",
        "change column order",
        "move column csv",
        "transpose columns",
        "flip columns",
        "reorder tsv columns"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "acronym-generator",
      "name": "Acronym generator",
      "description": "Turn each line of text into an acronym from the first letter of every word.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/acronym-generator",
      "embed": "https://textarray.com/embed/acronym-generator",
      "mode": "transform",
      "action": "Generate acronyms",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "caseMode",
          "kind": "select",
          "label": "Case",
          "default": "upper",
          "choices": [
            {
              "value": "upper",
              "label": "Uppercase"
            },
            {
              "value": "lower",
              "label": "Lowercase"
            },
            {
              "value": "keep",
              "label": "Keep original"
            }
          ]
        },
        {
          "key": "periods",
          "kind": "checkbox",
          "label": "Add periods",
          "default": false
        },
        {
          "key": "skipShort",
          "kind": "checkbox",
          "label": "Skip short words",
          "default": false
        },
        {
          "key": "separator",
          "kind": "text",
          "label": "Separator",
          "default": ""
        }
      ],
      "keywords": [
        "acronym generator",
        "acronym maker",
        "initialism",
        "abbreviation generator",
        "first letter of each word"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "extract-lines",
      "name": "Extract lines",
      "description": "Pull out a line range, the first or last N lines, or every Nth line.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/extract-lines",
      "embed": "https://textarray.com/embed/extract-lines",
      "mode": "transform",
      "action": "Extract lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "range",
          "choices": [
            {
              "value": "range",
              "label": "Line range"
            },
            {
              "value": "first",
              "label": "First N lines"
            },
            {
              "value": "last",
              "label": "Last N lines"
            },
            {
              "value": "nth",
              "label": "Every Nth line"
            }
          ]
        },
        {
          "key": "range",
          "kind": "text",
          "label": "Range",
          "default": "1-10"
        },
        {
          "key": "n",
          "kind": "number",
          "label": "N",
          "default": 10,
          "min": 1,
          "max": 100000,
          "step": 1
        },
        {
          "key": "invert",
          "kind": "checkbox",
          "label": "Invert selection",
          "default": false
        }
      ],
      "keywords": [
        "extract lines",
        "line range",
        "first n lines",
        "last n lines",
        "every nth line",
        "select lines by number",
        "get lines from text"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "extract-first-word",
      "name": "Extract first word",
      "description": "Pull out the first word from each line instantly.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/extract-first-word",
      "embed": "https://textarray.com/embed/extract-first-word",
      "mode": "transform",
      "action": "Extract",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "extract first word",
        "first word extractor",
        "extract word",
        "word extraction",
        "first word finder",
        "get first word"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "transpose-text",
      "name": "Transpose text",
      "description": "Swap rows and columns of delimited text — the first line becomes the first column and back again.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/transpose-text",
      "embed": "https://textarray.com/embed/transpose-text",
      "mode": "transform",
      "action": "Transpose",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": "tab",
          "choices": [
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "space",
              "label": "Space"
            }
          ]
        },
        {
          "key": "outDelimiter",
          "kind": "select",
          "label": "Output delimiter",
          "default": "same",
          "choices": [
            {
              "value": "same",
              "label": "Same as input"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "space",
              "label": "Space"
            }
          ]
        }
      ],
      "keywords": [
        "transpose text",
        "transpose table",
        "swap rows and columns",
        "rows to columns",
        "columns to rows",
        "transpose csv",
        "flip table"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "number-extractor",
      "name": "Number extractor",
      "description": "Pull every number out of text — integers, decimals and negatives — one per line.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/number-extractor",
      "embed": "https://textarray.com/embed/number-extractor",
      "mode": "transform",
      "action": "Extract numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "select",
          "label": "Decimal separator",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto"
            },
            {
              "value": "dot",
              "label": "Dot (3.14)"
            },
            {
              "value": "comma",
              "label": "Comma (3,14)"
            }
          ]
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": false
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort numerically",
          "default": false
        },
        {
          "key": "stats",
          "kind": "checkbox",
          "label": "Show sum and stats",
          "default": false
        }
      ],
      "keywords": [
        "number extractor",
        "extract numbers from text",
        "get numbers from text",
        "find numbers in text",
        "copy numbers from text",
        "pull numbers out of text",
        "sum numbers in text",
        "digit finder"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "hashtag-extractor",
      "name": "Hashtag extractor",
      "description": "Pull hashtags and @mentions out of any post or caption and get a clean list.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/hashtag-extractor",
      "embed": "https://textarray.com/embed/hashtag-extractor",
      "mode": "transform",
      "action": "Extract hashtags",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "extract",
          "kind": "select",
          "label": "Extract",
          "default": "hashtags",
          "choices": [
            {
              "value": "hashtags",
              "label": "Hashtags"
            },
            {
              "value": "mentions",
              "label": "Mentions"
            },
            {
              "value": "both",
              "label": "Both"
            }
          ]
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": true
        },
        {
          "key": "keepPrefix",
          "kind": "checkbox",
          "label": "Keep # / @ prefix",
          "default": true
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort alphabetically",
          "default": false
        },
        {
          "key": "count",
          "kind": "checkbox",
          "label": "Count occurrences",
          "default": false
        }
      ],
      "keywords": [
        "hashtag extractor",
        "extract hashtags",
        "extract hashtags from text",
        "extract mentions",
        "instagram hashtag list",
        "twitter hashtags from text",
        "count hashtags"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "srt-time-shifter",
      "name": "SRT subtitle time shifter",
      "description": "Shift every timestamp in an SRT or VTT subtitle file by a fixed offset.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/srt-time-shifter",
      "embed": "https://textarray.com/embed/srt-time-shifter",
      "mode": "transform",
      "action": "Shift subtitles",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "seconds",
          "kind": "number",
          "label": "Shift by (seconds)",
          "default": 0,
          "min": -86400,
          "max": 86400,
          "step": 0.1
        },
        {
          "key": "fpsFrom",
          "kind": "select",
          "label": "Source frame rate",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "No conversion"
            },
            {
              "value": "23.976",
              "label": "23.976"
            },
            {
              "value": "24",
              "label": "24"
            },
            {
              "value": "25",
              "label": "25"
            },
            {
              "value": "29.97",
              "label": "29.97"
            },
            {
              "value": "30",
              "label": "30"
            },
            {
              "value": "48",
              "label": "48"
            },
            {
              "value": "50",
              "label": "50"
            },
            {
              "value": "59.94",
              "label": "59.94"
            },
            {
              "value": "60",
              "label": "60"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "fpsTo",
          "kind": "select",
          "label": "Target frame rate",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "No conversion"
            },
            {
              "value": "23.976",
              "label": "23.976"
            },
            {
              "value": "24",
              "label": "24"
            },
            {
              "value": "25",
              "label": "25"
            },
            {
              "value": "29.97",
              "label": "29.97"
            },
            {
              "value": "30",
              "label": "30"
            },
            {
              "value": "48",
              "label": "48"
            },
            {
              "value": "50",
              "label": "50"
            },
            {
              "value": "59.94",
              "label": "59.94"
            },
            {
              "value": "60",
              "label": "60"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customFpsFrom",
          "kind": "number",
          "label": "Custom source fps",
          "default": 25,
          "min": 0,
          "max": 1000,
          "step": 0.001
        },
        {
          "key": "customFpsTo",
          "kind": "number",
          "label": "Custom target fps",
          "default": 23.976,
          "min": 0,
          "max": 1000,
          "step": 0.001
        }
      ],
      "keywords": [
        "srt time shifter",
        "shift subtitles",
        "subtitle sync fix",
        "delay subtitles",
        "srt resync",
        "subtitle timing offset",
        "vtt shift",
        "srt/vtt",
        "vtt do srt"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "typo-generator",
      "name": "Typo generator",
      "description": "Sprinkle realistic keyboard typos over clean text — adjustable rate, QWERTY or QWERTZ.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/typo-generator",
      "embed": "https://textarray.com/embed/typo-generator",
      "mode": "transform",
      "action": "Add typos",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "rate",
          "kind": "number",
          "label": "Error rate (%)",
          "default": 3,
          "min": 1,
          "max": 20,
          "step": 1
        },
        {
          "key": "layout",
          "kind": "select",
          "label": "Keyboard layout",
          "default": "qwerty",
          "choices": [
            {
              "value": "qwerty",
              "label": "QWERTY"
            },
            {
              "value": "qwertz",
              "label": "QWERTZ"
            }
          ]
        },
        {
          "key": "adjacent",
          "kind": "checkbox",
          "label": "Neighboring key hits",
          "default": true
        },
        {
          "key": "swap",
          "kind": "checkbox",
          "label": "Swapped letters",
          "default": true
        },
        {
          "key": "double",
          "kind": "checkbox",
          "label": "Doubled letters",
          "default": true
        },
        {
          "key": "drop",
          "kind": "checkbox",
          "label": "Dropped letters",
          "default": true
        }
      ],
      "keywords": [
        "add random typos to text",
        "typosquatting test data",
        "fuzzy search test strings",
        "misspelling generator",
        "keyboard typo simulator",
        "typos generator"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "reverse-words",
      "name": "Reverse words",
      "description": "Reverse the order of the words in your text without spelling them backwards.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/reverse-words",
      "embed": "https://textarray.com/embed/reverse-words",
      "mode": "transform",
      "action": "Reverse words",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "scope",
          "kind": "select",
          "label": "Scope",
          "default": "line",
          "choices": [
            {
              "value": "line",
              "label": "Per line"
            },
            {
              "value": "document",
              "label": "Whole text"
            }
          ]
        }
      ],
      "keywords": [
        "reverse words",
        "reverse word order",
        "flip words",
        "backwards word order",
        "reorder words"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "phone-number-extractor",
      "name": "Phone number extractor",
      "description": "Pull every phone number out of a block of text and get a clean list.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/phone-number-extractor",
      "embed": "https://textarray.com/embed/phone-number-extractor",
      "mode": "transform",
      "action": "Extract numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "unique",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": false
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort ascending",
          "default": false
        }
      ],
      "keywords": [
        "phone number extractor",
        "extract phone numbers",
        "find phone numbers",
        "grab phone numbers",
        "phone number scraper"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "duplicate-each-line",
      "name": "Duplicate each line",
      "description": "Repeat every line in your text a specified number of times.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/duplicate-each-line",
      "embed": "https://textarray.com/embed/duplicate-each-line",
      "mode": "transform",
      "action": "Duplicate each line",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "times",
          "kind": "number",
          "label": "Duplicate times",
          "default": 2,
          "min": 2,
          "max": 100,
          "step": 1
        }
      ],
      "keywords": [
        "duplicate each line",
        "repeat lines",
        "duplicate lines",
        "line duplication",
        "copy lines",
        "repeat text lines"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "reverse-each-word",
      "name": "Reverse each word",
      "description": "Reverse the letters inside each word while keeping the words in their original order.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/reverse-each-word",
      "embed": "https://textarray.com/embed/reverse-each-word",
      "mode": "transform",
      "action": "Reverse each word",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "reverse each word",
        "reverse word characters",
        "flip word letters",
        "reverse characters",
        "word character reversal"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "word-scrambler",
      "name": "Word scrambler",
      "description": "Randomize the interior letters of words while keeping their first and last letters fixed.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/word-scrambler",
      "embed": "https://textarray.com/embed/word-scrambler",
      "mode": "transform",
      "action": "Scramble words",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keepEnds",
          "kind": "checkbox",
          "label": "Keep first and last letter",
          "default": true
        }
      ],
      "keywords": [
        "word scrambler",
        "scramble words",
        "scrambled text",
        "word puzzle",
        "randomize letters",
        "shuffle letters",
        "scramble letters",
        "anagram game",
        "scrambler"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "sentence-splitter",
      "name": "Sentence splitter",
      "description": "Put each sentence on its own line for easier editing, analysis or processing.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/sentence-splitter",
      "embed": "https://textarray.com/embed/sentence-splitter",
      "mode": "transform",
      "action": "Split sentences",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        }
      ],
      "keywords": [
        "split sentences",
        "sentence splitter",
        "break sentences",
        "separate sentences",
        "remove sentence breaks"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-non-ascii",
      "name": "Remove non-ASCII characters",
      "description": "Strip every character outside plain ASCII, optionally transliterating accents to their closest letters first.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-non-ascii",
      "embed": "https://textarray.com/embed/remove-non-ascii",
      "mode": "transform",
      "action": "Remove non-ASCII",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "transliterate",
          "kind": "checkbox",
          "label": "Transliterate first (é→e, ß→ss)",
          "default": true
        },
        {
          "key": "keepLineBreaks",
          "kind": "checkbox",
          "label": "Keep line breaks",
          "default": true
        },
        {
          "key": "keepTabs",
          "kind": "checkbox",
          "label": "Keep tabs",
          "default": true
        },
        {
          "key": "showRemoved",
          "kind": "checkbox",
          "label": "List removed characters",
          "default": false
        }
      ],
      "keywords": [
        "remove non ascii",
        "strip non ascii characters",
        "ascii only",
        "remove unicode",
        "clean non ascii",
        "convert to ascii"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-brackets",
      "name": "Remove brackets",
      "description": "Remove bracketed content from text, or just the bracket characters, in one pass.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-brackets",
      "embed": "https://textarray.com/embed/remove-brackets",
      "mode": "transform",
      "action": "Remove brackets",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "What to remove",
          "default": "contentAndBrackets",
          "choices": [
            {
              "value": "contentAndBrackets",
              "label": "Brackets and the content inside"
            },
            {
              "value": "bracketsOnly",
              "label": "Only the bracket characters"
            }
          ]
        },
        {
          "key": "round",
          "kind": "checkbox",
          "label": "Round ( )",
          "default": true
        },
        {
          "key": "square",
          "kind": "checkbox",
          "label": "Square [ ]",
          "default": true
        },
        {
          "key": "curly",
          "kind": "checkbox",
          "label": "Curly { }",
          "default": true
        },
        {
          "key": "angle",
          "kind": "checkbox",
          "label": "Angle < >",
          "default": false
        },
        {
          "key": "tidySpaces",
          "kind": "checkbox",
          "label": "Tidy up spaces left behind",
          "default": true
        }
      ],
      "keywords": [
        "remove brackets",
        "remove parentheses",
        "delete brackets from text",
        "strip brackets",
        "remove text in brackets",
        "remove square brackets",
        "remove curly braces",
        "clean bracketed content"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-extra-spaces",
      "name": "Remove extra spaces",
      "description": "Collapse repeated spaces and tabs and trim messy whitespace from text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-extra-spaces",
      "embed": "https://textarray.com/embed/remove-extra-spaces",
      "mode": "transform",
      "action": "Clean spaces",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "collapseSpaces",
          "kind": "checkbox",
          "label": "Collapse multiple spaces",
          "default": true
        },
        {
          "key": "trimLines",
          "kind": "checkbox",
          "label": "Trim line ends",
          "default": true
        },
        {
          "key": "normalizeNbsp",
          "kind": "checkbox",
          "label": "Normalize special spaces",
          "default": true
        },
        {
          "key": "collapseBlankLines",
          "kind": "checkbox",
          "label": "Collapse blank lines",
          "default": false
        }
      ],
      "keywords": [
        "remove extra spaces",
        "collapse spaces",
        "whitespace cleaner",
        "trim spaces",
        "non-breaking space",
        "double spaces",
        "space condenser"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "remove-duplicate-lines",
      "name": "Remove duplicate lines",
      "description": "Delete repeated lines from a list and keep only the unique ones.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-duplicate-lines",
      "embed": "https://textarray.com/embed/remove-duplicate-lines",
      "mode": "transform",
      "action": "Remove duplicates",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        },
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Case-insensitive",
          "default": false
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort output",
          "default": false
        },
        {
          "key": "keepLast",
          "kind": "checkbox",
          "label": "Keep last",
          "default": false
        }
      ],
      "keywords": [
        "remove duplicate lines",
        "dedupe",
        "deduplicate",
        "unique lines",
        "duplicates",
        "duplicity",
        "de-duplicator"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "collapse-repeated-lines",
      "name": "Collapse repeated lines",
      "description": "Merge consecutive identical lines into one, similar to the Unix uniq command.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/collapse-repeated-lines",
      "embed": "https://textarray.com/embed/collapse-repeated-lines",
      "mode": "transform",
      "action": "Collapse repeated lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": false
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace when comparing",
          "default": false
        }
      ],
      "keywords": [
        "collapse repeated lines",
        "collapse consecutive lines",
        "uniq tool",
        "remove adjacent duplicates",
        "merge identical lines",
        "deduplicate adjacent",
        "collapse duplicate rows"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-empty-lines",
      "name": "Remove empty lines",
      "description": "Delete blank lines from text and get a compact, gap-free list.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-empty-lines",
      "embed": "https://textarray.com/embed/remove-empty-lines",
      "mode": "transform",
      "action": "Remove empty lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "alsoWhitespace",
          "kind": "checkbox",
          "label": "Treat whitespace-only lines as empty",
          "default": true
        },
        {
          "key": "collapseToOne",
          "kind": "checkbox",
          "label": "Keep one blank line between blocks",
          "default": false
        }
      ],
      "keywords": [
        "remove empty lines",
        "remove blank lines",
        "delete empty rows",
        "blank line remover",
        "compact text"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "remove-accents",
      "name": "Remove accents",
      "description": "Strip diacritics from text and turn accented letters into plain ones.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-accents",
      "embed": "https://textarray.com/embed/remove-accents",
      "mode": "transform",
      "action": "Remove accents",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "expandLigatures",
          "kind": "checkbox",
          "label": "Expand ligatures",
          "default": true
        }
      ],
      "keywords": [
        "remove accents",
        "remove diacritics",
        "strip diacritics",
        "unaccent text",
        "transliterate",
        "ascii text"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "remove-lines-containing",
      "name": "Remove lines containing",
      "description": "Filter a list by deleting or keeping only the lines that match a pattern.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-lines-containing",
      "embed": "https://textarray.com/embed/remove-lines-containing",
      "mode": "transform",
      "action": "Filter lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "pattern",
          "kind": "text",
          "label": "Pattern",
          "default": ""
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "remove",
          "choices": [
            {
              "value": "remove",
              "label": "Remove matching lines"
            },
            {
              "value": "keep",
              "label": "Keep only matching lines"
            }
          ]
        },
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case-sensitive",
          "default": false
        },
        {
          "key": "useRegex",
          "kind": "checkbox",
          "label": "Use regular expression",
          "default": false
        }
      ],
      "keywords": [
        "remove lines containing",
        "line removal",
        "remove lines",
        "line remover",
        "delete lines",
        "filter lines",
        "grep online",
        "keep matching lines",
        "delete lines with word",
        "regex filter"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "remove-characters",
      "name": "Remove characters",
      "description": "Strip specific characters, whole character classes or regex matches from text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-characters",
      "embed": "https://textarray.com/embed/remove-characters",
      "mode": "transform",
      "action": "Remove characters",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "custom",
          "choices": [
            {
              "value": "custom",
              "label": "Remove listed characters"
            },
            {
              "value": "keep",
              "label": "Keep only listed characters"
            },
            {
              "value": "non-alphanumeric",
              "label": "Remove non-alphanumeric"
            },
            {
              "value": "digits",
              "label": "Remove digits"
            },
            {
              "value": "letters",
              "label": "Remove letters"
            },
            {
              "value": "symbols",
              "label": "Remove punctuation and symbols"
            },
            {
              "value": "invisible",
              "label": "Remove invisible characters"
            },
            {
              "value": "regex",
              "label": "Remove regex matches"
            }
          ]
        },
        {
          "key": "characters",
          "kind": "text",
          "label": "Characters or pattern",
          "default": ""
        },
        {
          "key": "keepSpaces",
          "kind": "checkbox",
          "label": "Keep spaces",
          "default": true
        },
        {
          "key": "keepLineBreaks",
          "kind": "checkbox",
          "label": "Keep line breaks",
          "default": true
        },
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Match case",
          "default": true
        }
      ],
      "keywords": [
        "remove characters",
        "remove specific characters",
        "strip characters",
        "delete characters",
        "remove special characters",
        "remove non alphanumeric",
        "keep only characters",
        "char filter"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "remove-duplicate-words",
      "name": "Remove duplicate words",
      "description": "Delete repeated words from text and keep only the first time each one appears.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-duplicate-words",
      "embed": "https://textarray.com/embed/remove-duplicate-words",
      "mode": "transform",
      "action": "Remove duplicates",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Match case",
          "default": false
        },
        {
          "key": "ignorePunctuation",
          "kind": "checkbox",
          "label": "Ignore punctuation",
          "default": true
        },
        {
          "key": "consecutiveOnly",
          "kind": "checkbox",
          "label": "Only consecutive repeats",
          "default": false
        }
      ],
      "keywords": [
        "remove duplicate words",
        "duplicate words",
        "repeated words",
        "unique words",
        "dedupe words"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "remove-emoji",
      "name": "Remove emoji",
      "description": "Strip every emoji and pictograph out of your text, or list the ones it contains.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-emoji",
      "embed": "https://textarray.com/embed/remove-emoji",
      "mode": "transform",
      "action": "Remove emoji",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "remove",
          "choices": [
            {
              "value": "remove",
              "label": "Remove emoji"
            },
            {
              "value": "extract",
              "label": "Extract emoji only"
            }
          ]
        },
        {
          "key": "replaceWith",
          "kind": "select",
          "label": "Replace with",
          "default": "nothing",
          "choices": [
            {
              "value": "nothing",
              "label": "Nothing"
            },
            {
              "value": "space",
              "label": "A space"
            },
            {
              "value": "custom",
              "label": "Custom text"
            }
          ]
        },
        {
          "key": "custom",
          "kind": "text",
          "label": "Replacement text",
          "default": ""
        },
        {
          "key": "collapseSpaces",
          "kind": "checkbox",
          "label": "Collapse leftover spaces",
          "default": true
        },
        {
          "key": "keepTextSymbols",
          "kind": "checkbox",
          "label": "Keep text symbols like © and ™",
          "default": false
        }
      ],
      "keywords": [
        "remove emoji",
        "emoji remover",
        "strip emoji",
        "delete emoji",
        "extract emoji",
        "emoji cleaner",
        "text without emoji"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "remove-html-tags",
      "name": "Remove HTML tags",
      "description": "Strip every HTML and XML tag and keep the readable text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-html-tags",
      "embed": "https://textarray.com/embed/remove-html-tags",
      "mode": "transform",
      "action": "Remove tags",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "decodeEntities",
          "kind": "checkbox",
          "label": "Decode HTML entities",
          "default": true
        },
        {
          "key": "keepLineBreaks",
          "kind": "checkbox",
          "label": "Keep line breaks from <br> and <p>",
          "default": true
        },
        {
          "key": "removeScriptStyle",
          "kind": "checkbox",
          "label": "Remove script and style contents",
          "default": true
        },
        {
          "key": "keepTags",
          "kind": "text",
          "label": "Keep these tags",
          "default": ""
        },
        {
          "key": "stripAttributes",
          "kind": "checkbox",
          "label": "Strip attributes from kept tags",
          "default": false
        }
      ],
      "keywords": [
        "remove html tags",
        "strip html",
        "html to text",
        "strip tags online",
        "clean html markup",
        "html tag allowlist",
        "strip html tags except",
        "keep some html tags",
        "html sanitizer",
        "remove unwanted tags",
        "selective html cleaner",
        "whitelist html tags",
        "clean rich text html",
        "html filter"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "remove-punctuation",
      "name": "Remove punctuation",
      "description": "Strip punctuation marks from text and keep the words intact.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-punctuation",
      "embed": "https://textarray.com/embed/remove-punctuation",
      "mode": "transform",
      "action": "Remove punctuation",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keep",
          "kind": "text",
          "label": "Keep these characters",
          "default": ""
        },
        {
          "key": "replaceWithSpace",
          "kind": "checkbox",
          "label": "Replace with a space",
          "default": false
        },
        {
          "key": "removeDigits",
          "kind": "checkbox",
          "label": "Remove digits too",
          "default": false
        }
      ],
      "keywords": [
        "remove punctuation",
        "strip punctuation",
        "delete commas",
        "remove periods",
        "remove question marks",
        "punctuation stripper"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "remove-words",
      "name": "Remove words",
      "description": "Strip every occurrence of a word or phrase out of your text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-words",
      "embed": "https://textarray.com/embed/remove-words",
      "mode": "transform",
      "action": "Remove words",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "words",
          "kind": "text",
          "label": "Words to remove",
          "default": ""
        },
        {
          "key": "preset",
          "kind": "select",
          "label": "Stop words",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "en",
              "label": "English"
            },
            {
              "value": "sk",
              "label": "Slovak"
            },
            {
              "value": "cs",
              "label": "Czech"
            },
            {
              "value": "de",
              "label": "German"
            },
            {
              "value": "pl",
              "label": "Polish"
            },
            {
              "value": "hu",
              "label": "Hungarian"
            }
          ]
        },
        {
          "key": "wholeWords",
          "kind": "checkbox",
          "label": "Whole words only",
          "default": true
        },
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Match case",
          "default": false
        },
        {
          "key": "collapseSpaces",
          "kind": "checkbox",
          "label": "Tidy spacing",
          "default": true
        }
      ],
      "keywords": [
        "remove words",
        "remove word from text",
        "delete words",
        "remove phrase",
        "strip words",
        "remove stop words"
      ],
      "updated": "2026-08-23"
    },
    {
      "slug": "phone-number-formatter",
      "name": "Phone number formatter",
      "description": "Clean a list of phone numbers into a uniform international E.164 format.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/phone-number-formatter",
      "embed": "https://textarray.com/embed/phone-number-formatter",
      "mode": "transform",
      "action": "Format numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "prefix",
          "kind": "text",
          "label": "Country prefix",
          "default": ""
        },
        {
          "key": "assumePlus",
          "kind": "checkbox",
          "label": "Treat bare digits as international",
          "default": false
        },
        {
          "key": "invalid",
          "kind": "select",
          "label": "Invalid lines",
          "default": "remove",
          "choices": [
            {
              "value": "remove",
              "label": "Remove"
            },
            {
              "value": "keep",
              "label": "Keep and mark"
            }
          ]
        },
        {
          "key": "unique",
          "kind": "checkbox",
          "label": "Remove duplicate numbers",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "e164",
          "choices": [
            {
              "value": "e164",
              "label": "E.164 with +"
            },
            {
              "value": "digits",
              "label": "Digits only"
            }
          ]
        }
      ],
      "keywords": [
        "phone number formatter",
        "format phone numbers",
        "e164 converter",
        "bulk phone number cleaner",
        "international phone format",
        "sms list cleaner",
        "crm import"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "html-comment-remover",
      "name": "Remove HTML comments",
      "description": "Strip developer comments from HTML or XML markup before you publish it.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/html-comment-remover",
      "embed": "https://textarray.com/embed/html-comment-remover",
      "mode": "transform",
      "action": "Remove comments",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keepConditional",
          "kind": "checkbox",
          "label": "Keep IE conditional comments",
          "default": false
        },
        {
          "key": "collapseBlank",
          "kind": "checkbox",
          "label": "Remove emptied lines",
          "default": false
        }
      ],
      "keywords": [
        "remove html comments",
        "strip html comments",
        "html comment remover",
        "delete xml comments",
        "clean html comments",
        "conditional comments"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "disemvowel",
      "name": "Remove vowels",
      "description": "Strip the vowels from any text, or invert it and keep only the vowels.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/disemvowel",
      "embed": "https://textarray.com/embed/disemvowel",
      "mode": "transform",
      "action": "Remove vowels",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "remove",
          "choices": [
            {
              "value": "remove",
              "label": "Remove vowels"
            },
            {
              "value": "keep",
              "label": "Keep only vowels"
            }
          ]
        },
        {
          "key": "keepFirst",
          "kind": "checkbox",
          "label": "Keep the first letter of each word",
          "default": false
        },
        {
          "key": "treatY",
          "kind": "checkbox",
          "label": "Treat y as a vowel",
          "default": false
        },
        {
          "key": "accented",
          "kind": "checkbox",
          "label": "Include accented vowels (á, é, ö…)",
          "default": true
        }
      ],
      "keywords": [
        "remove vowels",
        "disemvowel",
        "vowel remover",
        "strip vowels",
        "delete vowels"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "line-length-filter",
      "name": "Filter lines by length",
      "description": "Keep or remove lines based on their character count or word count.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/line-length-filter",
      "embed": "https://textarray.com/embed/line-length-filter",
      "mode": "transform",
      "action": "Filter by length",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "measure",
          "kind": "select",
          "label": "Measure by",
          "default": "chars",
          "choices": [
            {
              "value": "chars",
              "label": "Characters"
            },
            {
              "value": "words",
              "label": "Words"
            }
          ]
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "keep",
          "choices": [
            {
              "value": "keep",
              "label": "Keep matching lines"
            },
            {
              "value": "remove",
              "label": "Remove matching lines"
            }
          ]
        },
        {
          "key": "min",
          "kind": "number",
          "label": "Minimum length (0 = none)",
          "default": 0,
          "min": 0,
          "max": 100000,
          "step": 1
        },
        {
          "key": "max",
          "kind": "number",
          "label": "Maximum length (0 = no limit)",
          "default": 0,
          "min": 0,
          "max": 100000,
          "step": 1
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim before measuring",
          "default": true
        }
      ],
      "keywords": [
        "filter lines by length",
        "remove long lines",
        "remove short lines",
        "keep lines by word count",
        "line length filter",
        "size keeper"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "strip-markdown",
      "name": "Strip Markdown",
      "description": "Remove Markdown formatting and keep the plain text — headings, emphasis, links, lists and tables.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/strip-markdown",
      "embed": "https://textarray.com/embed/strip-markdown",
      "mode": "transform",
      "action": "Strip Markdown",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keepUrls",
          "kind": "checkbox",
          "label": "Keep link URLs",
          "default": false
        }
      ],
      "keywords": [
        "strip markdown",
        "remove markdown",
        "markdown to plain text",
        "markdown to text",
        "markdown stripper",
        "plain text converter"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "duplicate-line-finder",
      "name": "Duplicate line finder",
      "description": "Find repeated lines and see how many times each one occurs.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/duplicate-line-finder",
      "embed": "https://textarray.com/embed/duplicate-line-finder",
      "mode": "transform",
      "action": "Find duplicates",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "show",
          "kind": "select",
          "label": "Show",
          "default": "duplicates",
          "choices": [
            {
              "value": "duplicates",
              "label": "Only duplicates"
            },
            {
              "value": "all",
              "label": "All lines with counts"
            }
          ]
        },
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Case-insensitive",
          "default": false
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        },
        {
          "key": "ignoreEmpty",
          "kind": "checkbox",
          "label": "Ignore empty lines",
          "default": true
        }
      ],
      "keywords": [
        "find duplicate lines",
        "duplicate line finder",
        "count duplicate lines",
        "line occurrence counter",
        "repeated lines"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "srt-to-text",
      "name": "SRT to plain text",
      "description": "Turn SRT and VTT subtitles into a clean transcript without numbers or timestamps.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/srt-to-text",
      "embed": "https://textarray.com/embed/srt-to-text",
      "mode": "transform",
      "action": "Convert to text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "layout",
          "kind": "select",
          "label": "Layout",
          "default": "lines",
          "choices": [
            {
              "value": "lines",
              "label": "Keep line breaks"
            },
            {
              "value": "cues",
              "label": "One line per cue"
            },
            {
              "value": "paragraph",
              "label": "Merge into one paragraph"
            }
          ]
        },
        {
          "key": "removeSpeakers",
          "kind": "checkbox",
          "label": "Remove speaker labels",
          "default": false
        },
        {
          "key": "removeSdh",
          "kind": "checkbox",
          "label": "Remove sound descriptions",
          "default": false
        }
      ],
      "keywords": [
        "srt to text",
        "srt to plain text",
        "subtitles to text",
        "subtitle converter",
        "remove timestamps from srt",
        "transcript from subtitles"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "invisible-character-detector",
      "name": "Invisible character detector",
      "description": "Find hidden Unicode characters in text and highlight, remove or replace them.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/invisible-character-detector",
      "embed": "https://textarray.com/embed/invisible-character-detector",
      "mode": "transform",
      "action": "Find invisible characters",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "action",
          "kind": "select",
          "label": "Action",
          "default": "highlight",
          "choices": [
            {
              "value": "highlight",
              "label": "Highlight"
            },
            {
              "value": "remove",
              "label": "Remove"
            },
            {
              "value": "replace",
              "label": "Replace with space"
            }
          ]
        },
        {
          "key": "keepNbsp",
          "kind": "checkbox",
          "label": "Keep non-breaking spaces",
          "default": false
        }
      ],
      "keywords": [
        "invisible character",
        "invisible characters",
        "invisible character detector",
        "zero width space",
        "hidden characters",
        "detect invisible characters",
        "remove invisible characters",
        "non breaking space",
        "zero-width characters"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "remove-numbers",
      "name": "Remove numbers",
      "description": "Strip digits or whole numbers from text and clean up the spaces they leave behind.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-numbers",
      "embed": "https://textarray.com/embed/remove-numbers",
      "mode": "transform",
      "action": "Remove numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "scope",
          "kind": "select",
          "label": "Remove",
          "default": "digits",
          "choices": [
            {
              "value": "digits",
              "label": "All digits"
            },
            {
              "value": "numbers",
              "label": "Whole numbers only"
            }
          ]
        },
        {
          "key": "collapse",
          "kind": "checkbox",
          "label": "Also remove leftover double spaces",
          "default": true
        },
        {
          "key": "dropEmpty",
          "kind": "checkbox",
          "label": "Remove lines that become empty",
          "default": false
        }
      ],
      "keywords": [
        "remove numbers from text",
        "delete numbers",
        "strip digits",
        "remove digits from text",
        "number remover",
        "take numbers out of text",
        "digit stripping"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-urls",
      "name": "Remove URLs",
      "description": "Strip links — and optionally email addresses — out of text and keep the prose clean.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-urls",
      "embed": "https://textarray.com/embed/remove-urls",
      "mode": "transform",
      "action": "Remove URLs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "bareDomains",
          "kind": "checkbox",
          "label": "Also match bare domains (example.com)",
          "default": false
        },
        {
          "key": "emails",
          "kind": "checkbox",
          "label": "Also remove email addresses",
          "default": false
        },
        {
          "key": "replace",
          "kind": "select",
          "label": "Replace with",
          "default": "nothing",
          "choices": [
            {
              "value": "nothing",
              "label": "Nothing"
            },
            {
              "value": "placeholder",
              "label": "[link] placeholder"
            }
          ]
        },
        {
          "key": "collapse",
          "kind": "checkbox",
          "label": "Clean leftover double spaces",
          "default": true
        }
      ],
      "keywords": [
        "remove urls from text",
        "delete links",
        "strip urls",
        "link remover",
        "remove links from text",
        "remove email addresses from text",
        "clean links out of text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "email-quote-stripper",
      "name": "Email quote stripper",
      "description": "Clean quoted text, \"…wrote:\" headers and signatures out of a pasted e-mail reply.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/email-quote-stripper",
      "embed": "https://textarray.com/embed/email-quote-stripper",
      "mode": "transform",
      "action": "Clean reply",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "quotes",
          "kind": "select",
          "label": "Quoted lines (>)",
          "default": "unquote",
          "choices": [
            {
              "value": "unquote",
              "label": "Strip the > markers"
            },
            {
              "value": "remove",
              "label": "Remove the lines"
            },
            {
              "value": "keep",
              "label": "Keep as they are"
            }
          ]
        },
        {
          "key": "removeAttribution",
          "kind": "checkbox",
          "label": "Remove \"…wrote:\" headers",
          "default": true
        },
        {
          "key": "removeSignature",
          "kind": "checkbox",
          "label": "Remove signature (after \"-- \")",
          "default": true
        },
        {
          "key": "collapseBlank",
          "kind": "checkbox",
          "label": "Collapse blank lines",
          "default": true
        }
      ],
      "keywords": [
        "email quote stripper",
        "remove quoted text from email",
        "remove reply quotes",
        "clean email reply",
        "strip email signature",
        "remove > from lines"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "data-redactor",
      "name": "Data redactor",
      "description": "Mask e-mails, phone numbers, IBANs, birth numbers, IPs and card numbers in one pass.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/data-redactor",
      "embed": "https://textarray.com/embed/data-redactor",
      "mode": "transform",
      "action": "Redact data",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "emails",
          "kind": "checkbox",
          "label": "E-mail addresses",
          "default": true
        },
        {
          "key": "phones",
          "kind": "checkbox",
          "label": "Phone numbers",
          "default": true
        },
        {
          "key": "ibans",
          "kind": "checkbox",
          "label": "IBANs",
          "default": true
        },
        {
          "key": "birthNumbers",
          "kind": "checkbox",
          "label": "Birth numbers (SK/CZ)",
          "default": true
        },
        {
          "key": "ips",
          "kind": "checkbox",
          "label": "IPv4 addresses",
          "default": true
        },
        {
          "key": "cards",
          "kind": "checkbox",
          "label": "Card numbers",
          "default": true
        },
        {
          "key": "mask",
          "kind": "text",
          "label": "Replacement",
          "default": "[REDACTED]"
        },
        {
          "key": "preserveLength",
          "kind": "checkbox",
          "label": "Mask with asterisks, keeping the length",
          "default": false
        }
      ],
      "keywords": [
        "data redactor",
        "anonymize text online",
        "redact personal data",
        "mask email phone iban",
        "remove pii from text",
        "gdpr text anonymization",
        "data masker",
        "mask sensitive data",
        "redact text",
        "hide email address",
        "hide phone number",
        "anonymize text",
        "scrub log",
        "sanitize text",
        "ai prompt sanitizer optimizer",
        "anonymizer"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "dedupe-by-column",
      "name": "Remove duplicate rows by column",
      "description": "Drop CSV/TSV rows whose value in one chosen column already appeared.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/dedupe-by-column",
      "embed": "https://textarray.com/embed/dedupe-by-column",
      "mode": "transform",
      "action": "Remove duplicates",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "column",
          "kind": "number",
          "label": "Column (1-based)",
          "default": 1,
          "min": 1,
          "max": 100,
          "step": 1
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect automatically"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe (|)"
            }
          ]
        },
        {
          "key": "keep",
          "kind": "select",
          "label": "Keep",
          "default": "first",
          "choices": [
            {
              "value": "first",
              "label": "First occurrence"
            },
            {
              "value": "last",
              "label": "Last occurrence"
            }
          ]
        },
        {
          "key": "hasHeader",
          "kind": "checkbox",
          "label": "First row is a header",
          "default": false
        },
        {
          "key": "ignoreCase",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": false
        }
      ],
      "keywords": [
        "dedupe by column",
        "remove duplicate rows by column",
        "csv deduplicate column",
        "unique rows by key",
        "remove rows with duplicate value",
        "tsv dedupe",
        "csv/tsv"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "bom-manager",
      "name": "BOM manager (add / remove)",
      "description": "Add or strip the invisible UTF-8 byte order mark at the start of your text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/bom-manager",
      "embed": "https://textarray.com/embed/bom-manager",
      "mode": "transform",
      "action": "Remove BOM",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "action",
          "kind": "select",
          "label": "Action",
          "default": "remove",
          "choices": [
            {
              "value": "remove",
              "label": "Remove BOM"
            },
            {
              "value": "add",
              "label": "Add BOM"
            },
            {
              "value": "detect",
              "label": "Detect only"
            }
          ]
        }
      ],
      "keywords": [
        "remove byte order mark",
        "add utf-8 bom",
        "strip bom from file",
        "byte order mark remover",
        "ufeff remover"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "sdh-stripper",
      "name": "SDH subtitle stripper",
      "description": "Remove sound descriptions, speaker labels and music cues from SDH subtitles.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/sdh-stripper",
      "embed": "https://textarray.com/embed/sdh-stripper",
      "mode": "transform",
      "action": "Strip SDH",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "brackets",
          "kind": "checkbox",
          "label": "Remove [ ] and ( ) descriptions",
          "default": true
        },
        {
          "key": "speakers",
          "kind": "checkbox",
          "label": "Remove UPPERCASE speaker labels",
          "default": true
        },
        {
          "key": "allCaps",
          "kind": "checkbox",
          "label": "Remove all-caps sound lines",
          "default": true
        },
        {
          "key": "music",
          "kind": "checkbox",
          "label": "Remove ♪ music lines",
          "default": true
        },
        {
          "key": "dropEmpty",
          "kind": "checkbox",
          "label": "Drop emptied lines",
          "default": true
        }
      ],
      "keywords": [
        "sdh stripper",
        "remove sound descriptions subtitles",
        "sdh to plain subtitles",
        "remove closed caption cues",
        "strip hearing impaired subtitles",
        "remove bracket subtitle text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "ai-phrase-remover",
      "name": "AI phrase remover",
      "description": "Strip the filler phrases, meta-remarks and clichés that give AI-written text away.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/ai-phrase-remover",
      "embed": "https://textarray.com/embed/ai-phrase-remover",
      "mode": "transform",
      "action": "Remove AI phrases",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "filler",
          "kind": "checkbox",
          "label": "Filler openers",
          "default": true
        },
        {
          "key": "meta",
          "kind": "checkbox",
          "label": "Chatbot meta remarks",
          "default": true
        },
        {
          "key": "cliche",
          "kind": "checkbox",
          "label": "Overused clichés",
          "default": true
        }
      ],
      "keywords": [
        "ai phrase remover",
        "remove ai cliches",
        "clean ai generated text",
        "remove chatgpt filler",
        "ai buzzword remover",
        "delve remover"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-line-numbers",
      "name": "Remove line numbers",
      "description": "Strip the leading number or list marker from every line of your text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-line-numbers",
      "embed": "https://textarray.com/embed/remove-line-numbers",
      "mode": "transform",
      "action": "Strip line numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keepIndent",
          "kind": "checkbox",
          "label": "Keep indentation",
          "default": false
        },
        {
          "key": "bracketsToo",
          "kind": "checkbox",
          "label": "Also strip [1] and (1)",
          "default": true
        }
      ],
      "keywords": [
        "remove line numbers",
        "strip line numbers",
        "delete numbering",
        "remove list numbering",
        "unnumber list",
        "clean numbered list"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "trim-lines",
      "name": "Trim lines",
      "description": "Remove leading and trailing whitespace from each line of your text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/trim-lines",
      "embed": "https://textarray.com/embed/trim-lines",
      "mode": "transform",
      "action": "Trim whitespace",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "side",
          "kind": "select",
          "label": "Trim",
          "default": "both",
          "choices": [
            {
              "value": "both",
              "label": "Both sides"
            },
            {
              "value": "leading",
              "label": "Leading only"
            },
            {
              "value": "trailing",
              "label": "Trailing only"
            }
          ]
        }
      ],
      "keywords": [
        "trim lines",
        "trim whitespace",
        "remove leading spaces",
        "remove trailing spaces",
        "trim text",
        "clean whitespace",
        "trim strip"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-quotes",
      "name": "Remove quotes",
      "description": "Strip all quotation marks from your text in one click.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-quotes",
      "embed": "https://textarray.com/embed/remove-quotes",
      "mode": "transform",
      "action": "Remove quotes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "which",
          "kind": "select",
          "label": "Remove",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All quotation marks"
            },
            {
              "value": "double",
              "label": "Double quotes only"
            },
            {
              "value": "single",
              "label": "Single quotes only"
            }
          ]
        }
      ],
      "keywords": [
        "remove quotes",
        "strip quotes",
        "delete quotation marks",
        "remove quotation marks",
        "remove smart quotes"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-duplicate-characters",
      "name": "Remove duplicate characters",
      "description": "Collapse consecutive duplicate characters to a single occurrence.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-duplicate-characters",
      "embed": "https://textarray.com/embed/remove-duplicate-characters",
      "mode": "transform",
      "action": "Remove duplicate characters",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case sensitive",
          "default": true
        }
      ],
      "keywords": [
        "remove duplicate characters",
        "collapse duplicate characters",
        "remove consecutive duplicates",
        "deduplicate characters",
        "remove repeated characters"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-whitespace",
      "name": "Remove whitespace",
      "description": "Strip all spaces and tabs from your text, optionally keeping line breaks.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-whitespace",
      "embed": "https://textarray.com/embed/remove-whitespace",
      "mode": "transform",
      "action": "Remove whitespace",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keepLineBreaks",
          "kind": "checkbox",
          "label": "Keep line breaks",
          "default": false
        }
      ],
      "keywords": [
        "remove whitespace",
        "remove spaces",
        "remove line breaks",
        "strip whitespace",
        "whitespace remover"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "profanity-filter",
      "name": "Profanity filter",
      "description": "Censor swear words and vulgar language in pasted text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/profanity-filter",
      "embed": "https://textarray.com/embed/profanity-filter",
      "mode": "transform",
      "action": "Censor profanity",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "maskStyle",
          "kind": "select",
          "label": "Mask style",
          "default": "edges",
          "choices": [
            {
              "value": "edges",
              "label": "Keep first and last letter (h****a)"
            },
            {
              "value": "full",
              "label": "Full stars (*****)"
            },
            {
              "value": "word",
              "label": "Replace with [censored]"
            }
          ]
        },
        {
          "key": "wholeWordsOnly",
          "kind": "checkbox",
          "label": "Whole words only",
          "default": true
        },
        {
          "key": "extraWords",
          "kind": "text",
          "label": "Extra words to censor (comma-separated)",
          "default": ""
        }
      ],
      "keywords": [
        "profanity filter",
        "swear word filter",
        "censor bad words",
        "curse word censor",
        "clean bad language",
        "mask swear words"
      ],
      "updated": "2026-07-28"
    },
    {
      "slug": "non-ascii-line-filter",
      "name": "Non-ASCII line filter",
      "description": "Keep or remove every line that contains a character outside the standard ASCII range.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/non-ascii-line-filter",
      "embed": "https://textarray.com/embed/non-ascii-line-filter",
      "mode": "transform",
      "action": "Filter lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "remove",
          "choices": [
            {
              "value": "remove",
              "label": "Remove non-ASCII lines"
            },
            {
              "value": "keep",
              "label": "Keep only non-ASCII lines"
            }
          ]
        }
      ],
      "keywords": [
        "non-ascii line filter",
        "remove non-ascii lines",
        "filter non-ascii characters",
        "ascii only lines",
        "remove lines with special characters",
        "clean log files",
        "non-english characters filter",
        "strip unicode lines"
      ],
      "updated": "2026-07-29"
    },
    {
      "slug": "homoglyph-detector",
      "name": "Homoglyph detector",
      "description": "Find look-alike letters from other alphabets hiding in your text and fix or list them.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/homoglyph-detector",
      "embed": "https://textarray.com/embed/homoglyph-detector",
      "mode": "transform",
      "action": "Detect homoglyphs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "view",
          "kind": "select",
          "label": "View",
          "default": "findings",
          "choices": [
            {
              "value": "findings",
              "label": "List findings"
            },
            {
              "value": "corrected",
              "label": "Corrected text"
            }
          ]
        },
        {
          "key": "mixedLinesOnly",
          "kind": "checkbox",
          "label": "Only mixed-script lines",
          "default": false
        },
        {
          "key": "ignoreMonoscript",
          "kind": "checkbox",
          "label": "Ignore single-script text",
          "default": false
        }
      ],
      "keywords": [
        "homoglyph detector",
        "homograph attack checker",
        "lookalike characters",
        "cyrillic lookalike letters",
        "unicode confusables finder",
        "mixed script detector",
        "idn spoofing check",
        "fake character finder",
        "unicode"
      ],
      "updated": "2026-08-05"
    },
    {
      "slug": "csv-injection-sanitizer",
      "name": "CSV injection sanitizer",
      "description": "Neutralize CSV cells that a spreadsheet would run as a formula when the file is opened.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/csv-injection-sanitizer",
      "embed": "https://textarray.com/embed/csv-injection-sanitizer",
      "mode": "transform",
      "action": "Sanitize cells",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "method",
          "kind": "select",
          "label": "Sanitize method",
          "default": "apostrophe",
          "choices": [
            {
              "value": "apostrophe",
              "label": "Prepend apostrophe"
            },
            {
              "value": "space",
              "label": "Prepend space"
            },
            {
              "value": "quote",
              "label": "Wrap in quotes"
            }
          ]
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Field delimiter",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma (,)"
            },
            {
              "value": "semicolon",
              "label": "Semicolon (;)"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe (|)"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "delimiterCustom",
          "kind": "text",
          "label": "Custom delimiter",
          "default": ""
        },
        {
          "key": "sanitizeControlChars",
          "kind": "checkbox",
          "label": "Also sanitize leading tab and line-break characters",
          "default": true
        },
        {
          "key": "listSanitized",
          "kind": "checkbox",
          "label": "List sanitized cells with coordinates",
          "default": false
        }
      ],
      "keywords": [
        "csv injection sanitizer",
        "formula injection",
        "csv formula injection",
        "excel formula injection",
        "defuse csv formulas",
        "sanitize csv cells",
        "spreadsheet injection",
        "owasp csv injection",
        "csv",
        "excel"
      ],
      "updated": "2026-08-05"
    },
    {
      "slug": "indent-text",
      "name": "Indent text",
      "description": "Add or remove indentation at the start of every line, with spaces or tabs.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/indent-text",
      "embed": "https://textarray.com/embed/indent-text",
      "mode": "transform",
      "action": "Indent text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Action",
          "default": "add",
          "choices": [
            {
              "value": "add",
              "label": "Add indentation"
            },
            {
              "value": "remove",
              "label": "Remove indentation"
            },
            {
              "value": "normalize",
              "label": "Remove common indentation"
            }
          ]
        },
        {
          "key": "unit",
          "kind": "select",
          "label": "Indent with",
          "default": "spaces",
          "choices": [
            {
              "value": "spaces",
              "label": "Spaces"
            },
            {
              "value": "tabs",
              "label": "Tabs"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "Amount per line",
          "default": 4,
          "min": 1,
          "max": 16
        },
        {
          "key": "skipEmpty",
          "kind": "checkbox",
          "label": "Leave empty lines untouched",
          "default": true
        }
      ],
      "keywords": [
        "indent text",
        "add indentation",
        "remove indentation",
        "dedent text",
        "indent lines",
        "unindent",
        "indent with spaces",
        "indent with tabs"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "insert-blank-lines",
      "name": "Insert blank lines",
      "description": "Add blank lines between your text for better readability and formatting.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/insert-blank-lines",
      "embed": "https://textarray.com/embed/insert-blank-lines",
      "mode": "transform",
      "action": "Insert blank lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "every",
          "kind": "number",
          "label": "Insert after every N lines",
          "default": 1,
          "min": 1
        },
        {
          "key": "count",
          "kind": "number",
          "label": "Number of blank lines to insert",
          "default": 1,
          "min": 1
        },
        {
          "key": "text",
          "kind": "text",
          "label": "Line to insert",
          "default": ""
        },
        {
          "key": "startOffset",
          "kind": "number",
          "label": "Skip this many lines first",
          "default": 0,
          "min": 0
        },
        {
          "key": "insertAfterLast",
          "kind": "checkbox",
          "label": "Insert after the last line too",
          "default": false
        }
      ],
      "keywords": [
        "insert blank lines",
        "add blank lines",
        "blank line inserter",
        "space lines",
        "add spacing",
        "insert text every n lines",
        "add text every nth line",
        "insert snippet every n lines",
        "periodic line insert",
        "ad injection lines",
        "insert separator lines",
        "insert marker every n lines"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "add-line-numbers",
      "name": "Add line numbers",
      "description": "Put a sequential number in front of every line of your text.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/add-line-numbers",
      "embed": "https://textarray.com/embed/add-line-numbers",
      "mode": "transform",
      "action": "Add numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "start",
          "kind": "number",
          "label": "Start at",
          "default": 1,
          "min": 0
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "asc",
          "choices": [
            {
              "value": "asc",
              "label": "Counting up"
            },
            {
              "value": "desc",
              "label": "Counting down"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "text",
          "label": "Separator",
          "default": ". "
        },
        {
          "key": "pad",
          "kind": "select",
          "label": "Padding",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "No padding"
            },
            {
              "value": "space",
              "label": "Align with spaces"
            },
            {
              "value": "zero",
              "label": "Pad with zeros"
            }
          ]
        },
        {
          "key": "format",
          "kind": "text",
          "label": "Number format",
          "default": ""
        },
        {
          "key": "skipEmpty",
          "kind": "checkbox",
          "label": "Don't number empty lines",
          "default": false
        }
      ],
      "keywords": [
        "add line numbers",
        "number lines",
        "line numbering",
        "numbered list",
        "prefix numbers",
        "countdown line numbers",
        "reverse numbering",
        "number lines backwards",
        "custom line number format"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "json-formatter",
      "name": "JSON formatter & validator",
      "description": "Format, minify and validate JSON, with the exact line and column of any error.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/json-formatter",
      "embed": "https://textarray.com/embed/json-formatter",
      "mode": "transform",
      "action": "Format JSON",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tab",
              "label": "Tabs"
            },
            {
              "value": "minify",
              "label": "Minify"
            }
          ]
        },
        {
          "key": "sortKeys",
          "kind": "checkbox",
          "label": "Sort object keys alphabetically",
          "default": false
        }
      ],
      "keywords": [
        "json validator",
        "json beautifier",
        "pretty print json",
        "minify json",
        "json parser"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "tabs-to-spaces",
      "name": "Tabs to spaces",
      "description": "Convert tabs to spaces or pack spaces back into tabs, at any tab width.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/tabs-to-spaces",
      "embed": "https://textarray.com/embed/tabs-to-spaces",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "tabs-to-spaces",
          "choices": [
            {
              "value": "tabs-to-spaces",
              "label": "Tabs to spaces"
            },
            {
              "value": "spaces-to-tabs",
              "label": "Spaces to tabs"
            }
          ]
        },
        {
          "key": "width",
          "kind": "select",
          "label": "Spaces per tab",
          "default": "4",
          "choices": [
            {
              "value": "2",
              "label": "2"
            },
            {
              "value": "4",
              "label": "4"
            },
            {
              "value": "8",
              "label": "8"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customWidth",
          "kind": "number",
          "label": "Custom width",
          "default": 4,
          "min": 1,
          "max": 16
        },
        {
          "key": "leadingOnly",
          "kind": "checkbox",
          "label": "Indentation only",
          "default": false
        }
      ],
      "keywords": [
        "tabs to spaces",
        "spaces to tabs",
        "convert tabs",
        "tab to space",
        "detab",
        "entab",
        "tab width",
        "indentation",
        "tab to spaces"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "word-wrap",
      "name": "Word wrap",
      "description": "Wrap text so no line exceeds a set number of characters.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/word-wrap",
      "embed": "https://textarray.com/embed/word-wrap",
      "mode": "transform",
      "action": "Wrap text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "width",
          "kind": "number",
          "label": "Line width",
          "default": 80,
          "min": 1,
          "max": 10000
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Line breaks",
          "default": "preserve",
          "choices": [
            {
              "value": "preserve",
              "label": "Keep existing breaks"
            },
            {
              "value": "reflow",
              "label": "Reflow paragraphs"
            }
          ]
        },
        {
          "key": "align",
          "kind": "select",
          "label": "Alignment",
          "default": "left",
          "choices": [
            {
              "value": "left",
              "label": "Left"
            },
            {
              "value": "center",
              "label": "Center"
            },
            {
              "value": "justify",
              "label": "Justify"
            }
          ]
        },
        {
          "key": "breakLongWords",
          "kind": "checkbox",
          "label": "Break long words",
          "default": false
        }
      ],
      "keywords": [
        "wrap text",
        "line wrap",
        "wrap lines at 80 characters",
        "reflow text",
        "justify text",
        "center text lines",
        "break long lines",
        "line wrapper"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "pad-text",
      "name": "Pad text",
      "description": "Pad each line to a set length with a chosen character, from the left, right or both sides.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/pad-text",
      "embed": "https://textarray.com/embed/pad-text",
      "mode": "transform",
      "action": "Pad text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "length",
          "kind": "number",
          "label": "Target length",
          "default": 10,
          "min": 1,
          "max": 100000
        },
        {
          "key": "side",
          "kind": "select",
          "label": "Pad side",
          "default": "left",
          "choices": [
            {
              "value": "left",
              "label": "Left"
            },
            {
              "value": "right",
              "label": "Right"
            },
            {
              "value": "both",
              "label": "Both (center)"
            }
          ]
        },
        {
          "key": "padChar",
          "kind": "text",
          "label": "Pad character",
          "default": ""
        },
        {
          "key": "truncate",
          "kind": "checkbox",
          "label": "Truncate longer lines",
          "default": false
        }
      ],
      "keywords": [
        "pad text",
        "pad lines",
        "left pad",
        "right pad",
        "zero padding",
        "pad numbers with zeros",
        "center lines",
        "fixed width lines"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "thousands-separator",
      "name": "Thousands separator",
      "description": "Add, change or remove thousands separators in every number in your text.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/thousands-separator",
      "embed": "https://textarray.com/embed/thousands-separator",
      "mode": "transform",
      "action": "Format numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "add",
          "choices": [
            {
              "value": "add",
              "label": "Add separators"
            },
            {
              "value": "remove",
              "label": "Remove separators"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Thousands separator",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma — 1,234,567"
            },
            {
              "value": "period",
              "label": "Period — 1.234.567"
            },
            {
              "value": "space",
              "label": "Space — 1 234 567"
            },
            {
              "value": "thin",
              "label": "Thin space — 1 234 567"
            }
          ]
        },
        {
          "key": "decimal",
          "kind": "select",
          "label": "Decimal separator",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect automatically"
            },
            {
              "value": "period",
              "label": "Period — 3.14"
            },
            {
              "value": "comma",
              "label": "Comma — 3,14"
            }
          ]
        }
      ],
      "keywords": [
        "thousands separator",
        "add commas to numbers",
        "number formatter",
        "format numbers",
        "digit grouping",
        "remove thousands separator"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "smart-quotes",
      "name": "Smart quotes converter",
      "description": "Convert straight quotes to typographic curly quotes and back, in four regional styles.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/smart-quotes",
      "embed": "https://textarray.com/embed/smart-quotes",
      "mode": "transform",
      "action": "Convert quotes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "curly",
          "choices": [
            {
              "value": "curly",
              "label": "Straight → curly"
            },
            {
              "value": "straight",
              "label": "Curly → straight"
            }
          ]
        },
        {
          "key": "style",
          "kind": "select",
          "label": "Quote style",
          "default": "english",
          "choices": [
            {
              "value": "english",
              "label": "English “ ”"
            },
            {
              "value": "german",
              "label": "German/Slovak „ “"
            },
            {
              "value": "french",
              "label": "French « »"
            },
            {
              "value": "polish",
              "label": "Polish/Hungarian „ ”"
            }
          ]
        },
        {
          "key": "apostrophes",
          "kind": "checkbox",
          "label": "Apostrophes and single quotes",
          "default": true
        },
        {
          "key": "dashes",
          "kind": "checkbox",
          "label": "Dashes (-- → –, --- → —)",
          "default": false
        },
        {
          "key": "ellipsis",
          "kind": "checkbox",
          "label": "Ellipsis (... → …)",
          "default": false
        },
        {
          "key": "nbsp",
          "kind": "checkbox",
          "label": "Non-breaking spaces (12 kg, 5 %)",
          "default": false
        },
        {
          "key": "multiplication",
          "kind": "checkbox",
          "label": "Multiplication sign (3 x 4 → 3 × 4)",
          "default": false
        }
      ],
      "keywords": [
        "straight quotes",
        "typographic quotes",
        "quotation marks converter",
        "smartypants",
        "guillemets",
        "quote converter",
        "apostrophe converter",
        "convert quotes",
        "fancy quotes",
        "ascii quotes",
        "curly to straight"
      ],
      "updated": "2026-08-22"
    },
    {
      "slug": "sort-paragraphs",
      "name": "Sort paragraphs",
      "description": "Sort whole paragraphs alphabetically, by length or in reverse order.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/sort-paragraphs",
      "embed": "https://textarray.com/embed/sort-paragraphs",
      "mode": "transform",
      "action": "Sort paragraphs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "order",
          "kind": "select",
          "label": "Order",
          "default": "az",
          "choices": [
            {
              "value": "az",
              "label": "A → Z"
            },
            {
              "value": "za",
              "label": "Z → A"
            },
            {
              "value": "lengthAsc",
              "label": "Shortest first"
            },
            {
              "value": "lengthDesc",
              "label": "Longest first"
            },
            {
              "value": "reverse",
              "label": "Reverse order"
            }
          ]
        },
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Case-insensitive",
          "default": false
        },
        {
          "key": "ignoreDiacritics",
          "kind": "checkbox",
          "label": "Ignore diacritics",
          "default": false
        }
      ],
      "keywords": [
        "sort paragraphs",
        "sort paragraphs alphabetically",
        "alphabetize paragraphs",
        "paragraph sorter",
        "order paragraphs",
        "reverse paragraphs",
        "sort text blocks"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "merge-paragraphs",
      "name": "Merge paragraphs",
      "description": "Unwrap paragraphs by joining their lines into single lines, without double spaces.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/merge-paragraphs",
      "embed": "https://textarray.com/embed/merge-paragraphs",
      "mode": "transform",
      "action": "Merge paragraphs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "joiner",
          "kind": "select",
          "label": "Join with",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customJoiner",
          "kind": "text",
          "label": "Custom separator",
          "default": ""
        },
        {
          "key": "singleLine",
          "kind": "checkbox",
          "label": "Collapse into a single line",
          "default": false
        },
        {
          "key": "keepBlank",
          "kind": "checkbox",
          "label": "Keep blank line between paragraphs",
          "default": true
        },
        {
          "key": "dehyphenate",
          "kind": "checkbox",
          "label": "Rejoin hyphenated words",
          "default": false
        }
      ],
      "keywords": [
        "merge paragraphs",
        "unwrap text",
        "unwrap lines",
        "join paragraphs",
        "remove line breaks",
        "combine paragraphs",
        "text to single line",
        "pdf line breaks"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "markdown-table-generator",
      "name": "Markdown table generator",
      "description": "Turn CSV or tab-separated data into a clean, aligned Markdown table.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/markdown-table-generator",
      "embed": "https://textarray.com/embed/markdown-table-generator",
      "mode": "transform",
      "action": "Generate table",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "headerRow",
          "kind": "checkbox",
          "label": "First row is a header",
          "default": true
        },
        {
          "key": "align",
          "kind": "select",
          "label": "Column alignment",
          "default": "left",
          "choices": [
            {
              "value": "left",
              "label": "Left"
            },
            {
              "value": "center",
              "label": "Center"
            },
            {
              "value": "right",
              "label": "Right"
            }
          ]
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pad cells to equal width",
          "default": true
        }
      ],
      "keywords": [
        "markdown table generator",
        "csv to markdown",
        "csv to markdown table",
        "markdown table",
        "md table generator",
        "tsv to markdown",
        "github table"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "xml-formatter",
      "name": "XML formatter",
      "description": "Pretty-print or minify XML with tag-nesting checks that name the offending tag.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/xml-formatter",
      "embed": "https://textarray.com/embed/xml-formatter",
      "mode": "transform",
      "action": "Format XML",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "format",
          "choices": [
            {
              "value": "format",
              "label": "Format"
            },
            {
              "value": "minify",
              "label": "Minify"
            }
          ]
        },
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tab",
              "label": "Tabs"
            }
          ]
        },
        {
          "key": "collapseShort",
          "kind": "checkbox",
          "label": "Collapse short elements",
          "default": true
        }
      ],
      "keywords": [
        "xml pretty print",
        "xml beautifier",
        "minify xml",
        "xml indent",
        "xml prettier"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "line-ending-converter",
      "name": "Line ending converter",
      "description": "Detect CRLF, LF and CR line endings with counts and convert a whole text to one consistent style.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/line-ending-converter",
      "embed": "https://textarray.com/embed/line-ending-converter",
      "mode": "transform",
      "action": "Convert line endings",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "target",
          "kind": "select",
          "label": "Convert to",
          "default": "lf",
          "choices": [
            {
              "value": "lf",
              "label": "LF (Unix, macOS)"
            },
            {
              "value": "crlf",
              "label": "CRLF (Windows)"
            },
            {
              "value": "cr",
              "label": "CR (classic Mac)"
            }
          ]
        },
        {
          "key": "ensureTrailing",
          "kind": "checkbox",
          "label": "Ensure single trailing newline",
          "default": false
        },
        {
          "key": "stripTrailing",
          "kind": "checkbox",
          "label": "Strip trailing whitespace on each line",
          "default": false
        }
      ],
      "keywords": [
        "line ending converter",
        "convert line endings",
        "crlf to lf",
        "lf to crlf",
        "dos to unix",
        "unix to dos",
        "dos2unix",
        "newline converter",
        "carriage return"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "justify-text",
      "name": "Justify text",
      "description": "Re-flow plain text into block-justified lines of an exact character width.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/justify-text",
      "embed": "https://textarray.com/embed/justify-text",
      "mode": "transform",
      "action": "Justify text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "width",
          "kind": "number",
          "label": "Line width (characters)",
          "default": 60,
          "min": 10,
          "max": 300,
          "step": 1
        }
      ],
      "keywords": [
        "justify text",
        "block justify text online",
        "justify monospace text",
        "text alignment justify",
        "full justify plain text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "spoiler-tag-wrapper",
      "name": "Spoiler tag wrapper",
      "description": "Wrap text in Discord, Reddit, BBCode or HTML spoiler markup in one paste.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/spoiler-tag-wrapper",
      "embed": "https://textarray.com/embed/spoiler-tag-wrapper",
      "mode": "transform",
      "action": "Wrap spoilers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Platform",
          "default": "discord",
          "choices": [
            {
              "value": "discord",
              "label": "Discord (||…||)"
            },
            {
              "value": "reddit",
              "label": "Reddit (>!…!<)"
            },
            {
              "value": "bbcode",
              "label": "Forum BBCode ([spoiler])"
            },
            {
              "value": "details",
              "label": "HTML (<details>)"
            }
          ]
        },
        {
          "key": "scope",
          "kind": "select",
          "label": "Wrap",
          "default": "lines",
          "choices": [
            {
              "value": "lines",
              "label": "Each line"
            },
            {
              "value": "paragraphs",
              "label": "Each paragraph"
            },
            {
              "value": "whole",
              "label": "Whole text"
            }
          ]
        }
      ],
      "keywords": [
        "spoiler tag wrapper",
        "discord spoiler tags",
        "reddit spoiler format",
        "hide spoilers in text",
        "spoiler markup generator",
        "bbcode spoiler"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "paragraph-separator",
      "name": "Paragraph divider inserter",
      "description": "Put a divider line — ***, ---, or your own — between every paragraph of a text.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/paragraph-separator",
      "embed": "https://textarray.com/embed/paragraph-separator",
      "mode": "transform",
      "action": "Insert dividers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "text",
          "label": "Divider",
          "default": "***"
        },
        {
          "key": "padded",
          "kind": "checkbox",
          "label": "Blank line around the divider",
          "default": true
        }
      ],
      "keywords": [
        "insert separator between paragraphs",
        "paragraph divider",
        "add horizontal rule between paragraphs",
        "scene break inserter",
        "section divider text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "whitespace-visualizer",
      "name": "Whitespace visualizer",
      "description": "Reveal hidden spaces, tabs, and line breaks so you can spot formatting issues instantly.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/whitespace-visualizer",
      "embed": "https://textarray.com/embed/whitespace-visualizer",
      "mode": "transform",
      "action": "Visualize whitespace",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "showSpaces",
          "kind": "checkbox",
          "label": "Show spaces",
          "default": true
        },
        {
          "key": "showTabs",
          "kind": "checkbox",
          "label": "Show tabs",
          "default": true
        },
        {
          "key": "showNewlines",
          "kind": "checkbox",
          "label": "Show line breaks",
          "default": false
        }
      ],
      "keywords": [
        "whitespace visualizer",
        "show whitespace",
        "reveal spaces",
        "reveal tabs",
        "reveal newlines",
        "visible spaces",
        "hidden spaces",
        "space marks",
        "tab marks"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "wrap-in-quotes",
      "name": "Wrap in quotes",
      "description": "Surround each line with your choice of quote style to format lists, arrays or code snippets.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/wrap-in-quotes",
      "embed": "https://textarray.com/embed/wrap-in-quotes",
      "mode": "transform",
      "action": "Wrap in quotes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Quote style",
          "default": "double",
          "choices": [
            {
              "value": "double",
              "label": "Double quotes"
            },
            {
              "value": "single",
              "label": "Single quotes"
            },
            {
              "value": "curly",
              "label": "Curly quotes"
            },
            {
              "value": "guillemets",
              "label": "Guillemets"
            },
            {
              "value": "backtick",
              "label": "Backticks"
            }
          ]
        },
        {
          "key": "trailingComma",
          "kind": "checkbox",
          "label": "Add trailing comma",
          "default": false
        }
      ],
      "keywords": [
        "wrap in quotes",
        "add quotes",
        "quote each line",
        "surround text with quotes",
        "wrap each line quotes",
        "text formatting quotes"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "mirror-text",
      "name": "Mirror text",
      "description": "Flip text left to right, swapping each letter for its mirrored Unicode lookalike.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/mirror-text",
      "embed": "https://textarray.com/embed/mirror-text",
      "mode": "transform",
      "action": "Mirror text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "perLine",
          "kind": "checkbox",
          "label": "Mirror each line separately",
          "default": true
        },
        {
          "key": "substitute",
          "kind": "checkbox",
          "label": "Swap letters for mirrored shapes",
          "default": true
        }
      ],
      "keywords": [
        "mirror text",
        "mirror text generator",
        "reversed text",
        "backwards text",
        "flip text horizontally",
        "mirror writing",
        "horizontal mirror",
        "rovesciare left to right"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "fancy-text",
      "name": "Fancy text generator",
      "description": "Turn plain text into 16 Unicode styles you can paste into any bio or post.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/fancy-text",
      "embed": "https://textarray.com/embed/fancy-text",
      "mode": "transform",
      "action": "Style text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Style",
          "default": "bold",
          "choices": [
            {
              "value": "bold",
              "label": "Bold — 𝗯𝗼𝗹𝗱"
            },
            {
              "value": "italic",
              "label": "Italic — 𝘪𝘵𝘢𝘭𝘪𝘤"
            },
            {
              "value": "boldItalic",
              "label": "Bold italic"
            },
            {
              "value": "serifBold",
              "label": "Serif bold — 𝐛𝐨𝐥𝐝"
            },
            {
              "value": "serifItalic",
              "label": "Serif italic — 𝑖𝑡𝑎𝑙𝑖𝑐"
            },
            {
              "value": "script",
              "label": "Script — 𝓈𝒸𝓇𝒾𝓅𝓉"
            },
            {
              "value": "boldScript",
              "label": "Bold script — 𝓼𝓬𝓻𝓲𝓹𝓽"
            },
            {
              "value": "fraktur",
              "label": "Fraktur — 𝔣𝔯𝔞𝔨𝔱𝔲𝔯"
            },
            {
              "value": "doubleStruck",
              "label": "Double-struck — 𝕕𝕠𝕦𝕓𝕝𝕖"
            },
            {
              "value": "monospace",
              "label": "Monospace — 𝚖𝚘𝚗𝚘"
            },
            {
              "value": "fullwidth",
              "label": "Ｆｕｌｌｗｉｄｔｈ"
            },
            {
              "value": "circled",
              "label": "Ⓒⓘⓡⓒⓛⓔⓓ"
            },
            {
              "value": "squared",
              "label": "🅂🅀🅄🄰🅁🄴🄳"
            },
            {
              "value": "smallCaps",
              "label": "Sᴍᴀʟʟ ᴄᴀᴘs"
            },
            {
              "value": "upsideDown",
              "label": "uʍop ǝpᴉsdn"
            },
            {
              "value": "strikethrough",
              "label": "S̶t̶r̶i̶k̶e̶"
            }
          ]
        }
      ],
      "keywords": [
        "fancy text",
        "fancy font generator",
        "stylish text",
        "bold text generator",
        "cursive text",
        "unicode text generator"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "normalize-unicode",
      "name": "Normalize Unicode text",
      "description": "Turn fancy Unicode text back into plain, ordinary characters.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/normalize-unicode",
      "embed": "https://textarray.com/embed/normalize-unicode",
      "mode": "transform",
      "action": "Normalize text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "removeCombining",
          "kind": "checkbox",
          "label": "Remove combining marks",
          "default": true
        },
        {
          "key": "smallCaps",
          "kind": "checkbox",
          "label": "Convert small caps",
          "default": true
        },
        {
          "key": "regionalIndicators",
          "kind": "checkbox",
          "label": "Convert flag letters",
          "default": false
        },
        {
          "key": "upsideDown",
          "kind": "checkbox",
          "label": "Flip upside-down text back",
          "default": false
        },
        {
          "key": "languageLigatures",
          "kind": "checkbox",
          "label": "Expand æ, œ and ß",
          "default": false
        }
      ],
      "keywords": [
        "normalize unicode",
        "unicode normalizer",
        "nfkc",
        "fancy text to normal",
        "remove fancy font",
        "unstyle text",
        "remove zalgo",
        "plain text converter",
        "nfc/nfd"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "text-decorations",
      "name": "Text decorations",
      "description": "Wrap your text in decorative symbol frames like ꧁text꧂ or ★彡text彡★.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/text-decorations",
      "embed": "https://textarray.com/embed/text-decorations",
      "mode": "transform",
      "action": "Decorate text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Decoration",
          "default": "royal",
          "choices": [
            {
              "value": "royal",
              "label": "Royal — ꧁text꧂"
            },
            {
              "value": "royalOrnate",
              "label": "Ornate royal — ꧁༺text༻꧂"
            },
            {
              "value": "lotus",
              "label": "Lotus — ༺text༻"
            },
            {
              "value": "leaves",
              "label": "Leaves — ⊰text⊱"
            },
            {
              "value": "starWings",
              "label": "Star wings — ★彡text彡★"
            },
            {
              "value": "sparkles",
              "label": "Sparkles — ✧･ﾟ: *text* :･ﾟ✧"
            },
            {
              "value": "wave",
              "label": "Wave — •´¯`•.text.•´¯`•"
            },
            {
              "value": "blocks",
              "label": "Blocks — ▄▀▄▀▄▀text▀▄▀▄▀▄"
            },
            {
              "value": "doubleRule",
              "label": "Double rule — ═══ text ═══"
            },
            {
              "value": "thickBrackets",
              "label": "Thick brackets — 【text】"
            },
            {
              "value": "cornerQuotes",
              "label": "Corner quotes — 「text」"
            },
            {
              "value": "angleQuotes",
              "label": "Angle quotes — «text»"
            },
            {
              "value": "flowers",
              "label": "Flowers — ✿ text ✿"
            },
            {
              "value": "hearts",
              "label": "Hearts — .•♡•.text.•♡•."
            },
            {
              "value": "crown",
              "label": "Crown — ♛ text ♛"
            },
            {
              "value": "music",
              "label": "Music notes — ♪♫ text ♫♪"
            },
            {
              "value": "arrows",
              "label": "Arrows — ➸ text ➸"
            },
            {
              "value": "stars",
              "label": "Stars — ⋆｡°✩ text ✩°｡⋆"
            },
            {
              "value": "gamingTag",
              "label": "Gaming tag — -=[ text ]=-"
            },
            {
              "value": "dots",
              "label": "Dots — .:: text ::."
            },
            {
              "value": "tildes",
              "label": "Tildes — ~*~ text ~*~"
            },
            {
              "value": "bubbles",
              "label": "Bubbles — °º¤ø,¸¸ text ¸¸,ø¤º°"
            },
            {
              "value": "shine",
              "label": "Shine — ✦ text ✦"
            },
            {
              "value": "diamonds",
              "label": "Diamonds — ◆◇◆ text ◆◇◆"
            },
            {
              "value": "custom",
              "label": "Custom — your own prefix and suffix"
            }
          ]
        },
        {
          "key": "customPrefix",
          "kind": "text",
          "label": "Custom prefix",
          "default": ""
        },
        {
          "key": "customSuffix",
          "kind": "text",
          "label": "Custom suffix",
          "default": ""
        },
        {
          "key": "perLine",
          "kind": "checkbox",
          "label": "Apply to each line",
          "default": true
        }
      ],
      "keywords": [
        "text decorations",
        "text borders",
        "decorative text frames",
        "nickname decoration",
        "symbol frames",
        "fancy borders",
        "clan tag generator"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "upside-down-text",
      "name": "Upside down text",
      "description": "Turn any text 180 degrees using Unicode characters that look reversed.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/upside-down-text",
      "embed": "https://textarray.com/embed/upside-down-text",
      "mode": "transform",
      "action": "Flip text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Style",
          "default": "upside-down",
          "choices": [
            {
              "value": "upside-down",
              "label": "Upside down"
            },
            {
              "value": "mirror",
              "label": "Mirror"
            }
          ]
        },
        {
          "key": "reverseOrder",
          "kind": "checkbox",
          "label": "Reverse character order",
          "default": true
        },
        {
          "key": "reverseLines",
          "kind": "checkbox",
          "label": "Reverse line order",
          "default": false
        },
        {
          "key": "stripAccents",
          "kind": "checkbox",
          "label": "Strip accents (á → ɐ)",
          "default": true
        }
      ],
      "keywords": [
        "upside down text",
        "flip text",
        "upside down text generator",
        "turn text upside down",
        "mirror text",
        "flipped characters"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "zalgo-text",
      "name": "Zalgo glitch text",
      "description": "Stack Unicode combining marks on your text to make it look corrupted.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/zalgo-text",
      "embed": "https://textarray.com/embed/zalgo-text",
      "mode": "transform",
      "action": "Generate again",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "intensity",
          "kind": "range",
          "label": "Intensity — mild to insane",
          "default": 2,
          "min": 1,
          "max": 5
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "both",
          "choices": [
            {
              "value": "both",
              "label": "Both"
            },
            {
              "value": "up",
              "label": "Up"
            },
            {
              "value": "down",
              "label": "Down"
            }
          ]
        }
      ],
      "keywords": [
        "zalgo text",
        "zalgo text generator",
        "glitch text generator",
        "cursed text",
        "corrupted text",
        "creepy text",
        "zalgo text online",
        "combining marks",
        "sovrapporre combining mark",
        "stack accent character",
        "stack combining"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "leet-speak",
      "name": "Leet speak translator",
      "description": "Turn text into 1337 speak and decode it back, with three intensity levels.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/leet-speak",
      "embed": "https://textarray.com/embed/leet-speak",
      "mode": "transform",
      "action": "Translate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text → leet"
            },
            {
              "value": "decode",
              "label": "Leet → text"
            }
          ]
        },
        {
          "key": "level",
          "kind": "select",
          "label": "Intensity",
          "default": "medium",
          "choices": [
            {
              "value": "low",
              "label": "Low (a → 4, e → 3)"
            },
            {
              "value": "medium",
              "label": "Medium (+ l, o, s, t)"
            },
            {
              "value": "extreme",
              "label": "Extreme (symbols, |_| and |3)"
            }
          ]
        }
      ],
      "keywords": [
        "1337",
        "leetspeak generator",
        "hacker text",
        "1337 t3xt",
        "leet speak konvertor"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "invisible-text",
      "name": "Invisible text generator",
      "description": "Generate invisible Unicode characters for blank messages, names and posts.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/invisible-text",
      "embed": "https://textarray.com/embed/invisible-text",
      "mode": "generate",
      "action": "Generate invisible text",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "character",
          "kind": "select",
          "label": "Character",
          "default": "hangul",
          "choices": [
            {
              "value": "hangul",
              "label": "Hangul filler (U+3164)"
            },
            {
              "value": "zwsp",
              "label": "Zero-width space (U+200B)"
            },
            {
              "value": "braille",
              "label": "Braille blank (U+2800)"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "Number of characters",
          "default": 5,
          "min": 1,
          "max": 100000
        }
      ],
      "keywords": [
        "invisible text",
        "invisible character",
        "blank space generator",
        "empty text",
        "zero width space",
        "hangul filler",
        "braille blank",
        "invisible letters"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "ascii-box",
      "name": "ASCII box generator",
      "description": "Draw a clean border — single, double, rounded or classic ASCII — around any text.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/ascii-box",
      "embed": "https://textarray.com/embed/ascii-box",
      "mode": "transform",
      "action": "Draw the box",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Border style",
          "default": "single",
          "choices": [
            {
              "value": "single",
              "label": "Single line ┌─┐"
            },
            {
              "value": "double",
              "label": "Double line ╔═╗"
            },
            {
              "value": "rounded",
              "label": "Rounded ╭─╮"
            },
            {
              "value": "bold",
              "label": "Bold ┏━┓"
            },
            {
              "value": "ascii",
              "label": "Plain ASCII +-+"
            },
            {
              "value": "stars",
              "label": "Stars ***"
            },
            {
              "value": "hash",
              "label": "Hashes ###"
            }
          ]
        },
        {
          "key": "align",
          "kind": "select",
          "label": "Text alignment",
          "default": "center",
          "choices": [
            {
              "value": "center",
              "label": "Center"
            },
            {
              "value": "left",
              "label": "Left"
            },
            {
              "value": "right",
              "label": "Right"
            }
          ]
        },
        {
          "key": "padding",
          "kind": "number",
          "label": "Padding",
          "default": 1,
          "min": 0,
          "max": 20,
          "step": 1
        }
      ],
      "keywords": [
        "ascii box generator",
        "text in a box",
        "ascii frame around text",
        "box drawing characters",
        "comment box generator",
        "ascii banner box",
        "ascii box um text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "text-wave",
      "name": "Text wave generator",
      "description": "Shape text into a casing wave (aBc) or a staircase of indented lines.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/text-wave",
      "embed": "https://textarray.com/embed/text-wave",
      "mode": "transform",
      "action": "Shape the text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Shape",
          "default": "wave",
          "choices": [
            {
              "value": "wave",
              "label": "Casing wave (aBc)"
            },
            {
              "value": "staircase",
              "label": "Staircase indent"
            }
          ]
        },
        {
          "key": "period",
          "kind": "number",
          "label": "Wave length (letters)",
          "default": 3,
          "min": 1,
          "max": 20,
          "step": 1
        },
        {
          "key": "step",
          "kind": "number",
          "label": "Step width (spaces)",
          "default": 2,
          "min": 1,
          "max": 10,
          "step": 1
        },
        {
          "key": "perWord",
          "kind": "checkbox",
          "label": "One word per step",
          "default": true
        },
        {
          "key": "zigzag",
          "kind": "checkbox",
          "label": "Climb back down (zigzag)",
          "default": false
        }
      ],
      "keywords": [
        "text wave generator",
        "wave case text",
        "staircase text generator",
        "stair step text",
        "wavy capitalization",
        "aesthetic text shape"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "pig-latin",
      "name": "Pig Latin translator",
      "description": "Turn English words into Pig Latin, the classic playground word game.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/pig-latin",
      "embed": "https://textarray.com/embed/pig-latin",
      "mode": "transform",
      "action": "Translate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "vowelSuffix",
          "kind": "select",
          "label": "Vowel-word suffix",
          "default": "way",
          "choices": [
            {
              "value": "way",
              "label": "way"
            },
            {
              "value": "yay",
              "label": "yay"
            }
          ]
        }
      ],
      "keywords": [
        "pig latin translator",
        "pig latin generator",
        "pig latin converter",
        "igpay atinlay"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "fullwidth-text",
      "name": "Full-width text generator",
      "description": "Turn ordinary text into wide full-width \"vaporwave\" characters.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/fullwidth-text",
      "embed": "https://textarray.com/embed/fullwidth-text",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "wideSpace",
          "kind": "checkbox",
          "label": "Wide spaces",
          "default": true
        }
      ],
      "keywords": [
        "fullwidth text",
        "full width text",
        "aesthetic text",
        "wide text",
        "unicode fullwidth"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "superscript-generator",
      "name": "Superscript generator",
      "description": "Turn text into raised superscript characters for exponents, footnotes and bios.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/superscript-generator",
      "embed": "https://textarray.com/embed/superscript-generator",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keepUnmapped",
          "kind": "checkbox",
          "label": "Keep unsupported characters",
          "default": true
        }
      ],
      "keywords": [
        "superscript generator",
        "superscript text",
        "small letters above",
        "exponent text",
        "raised characters"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "bubble-text",
      "name": "Bubble text",
      "description": "Convert your text to circled letters and numbers.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/bubble-text",
      "embed": "https://textarray.com/embed/bubble-text",
      "mode": "transform",
      "action": "Bubble text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "bubble text",
        "circled letters",
        "circled numbers",
        "circled text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "small-caps",
      "name": "Small caps converter",
      "description": "Transform text to use Unicode small capitals for a stylish typographic effect.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/small-caps",
      "embed": "https://textarray.com/embed/small-caps",
      "mode": "transform",
      "action": "Convert to small caps",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "small capitals",
        "capitalize text",
        "text styling",
        "unicode small caps"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "subscript-generator",
      "name": "Subscript generator",
      "description": "Convert text to small subscript characters for chemical formulas, math and citations.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/subscript-generator",
      "embed": "https://textarray.com/embed/subscript-generator",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "subscript text",
        "subscript generator",
        "small letters below",
        "index text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "strikethrough-text",
      "name": "Strikethrough text",
      "description": "Apply a crossed-out effect to your text using combining Unicode characters.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/strikethrough-text",
      "embed": "https://textarray.com/embed/strikethrough-text",
      "mode": "transform",
      "action": "Strike through",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Style",
          "default": "strike",
          "choices": [
            {
              "value": "strike",
              "label": "Long stroke"
            },
            {
              "value": "slash",
              "label": "Short slash"
            },
            {
              "value": "tilde",
              "label": "Wavy tilde"
            }
          ]
        }
      ],
      "keywords": [
        "strikethrough text",
        "strike through",
        "line through",
        "crossed out",
        "strike out"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "underline-text",
      "name": "Underline text",
      "description": "Apply combining underline marks to emphasize individual characters in your text.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/underline-text",
      "embed": "https://textarray.com/embed/underline-text",
      "mode": "transform",
      "action": "Underline text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Underline style",
          "default": "single",
          "choices": [
            {
              "value": "single",
              "label": "Single"
            },
            {
              "value": "double",
              "label": "Double"
            }
          ]
        }
      ],
      "keywords": [
        "underline characters",
        "text decoration",
        "combine underline",
        "styled text",
        "underlined text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "ascii85",
      "name": "Ascii85 encode and decode",
      "description": "Encode text to Ascii85 (base85) and decode it back, with optional Adobe delimiters.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/ascii85",
      "embed": "https://textarray.com/embed/ascii85",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        },
        {
          "key": "adobeDelimiters",
          "kind": "checkbox",
          "label": "Adobe delimiters (<~ ~>)",
          "default": false
        },
        {
          "key": "zAbbrev",
          "kind": "checkbox",
          "label": "Abbreviate zero groups as z",
          "default": true
        }
      ],
      "keywords": [
        "ascii85 encode",
        "ascii85 decode",
        "ascii85 converter",
        "ascii85 delimiters",
        "base85 encoding"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "base64",
      "name": "Base64 encode and decode",
      "description": "Convert text to Base64 and back, with full UTF-8 and URL-safe support.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/base64",
      "embed": "https://textarray.com/embed/base64",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        },
        {
          "key": "urlSafe",
          "kind": "checkbox",
          "label": "URL-safe alphabet",
          "default": false
        },
        {
          "key": "lineWrap",
          "kind": "checkbox",
          "label": "Wrap at 76 characters",
          "default": false
        }
      ],
      "keywords": [
        "base64 decode",
        "encoder",
        "decoder",
        "url-safe base64",
        "text in base64"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "url-encode",
      "name": "URL encode and decode",
      "description": "Percent-encode text for URLs and decode escaped addresses back to plain text.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/url-encode",
      "embed": "https://textarray.com/embed/url-encode",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        },
        {
          "key": "scope",
          "kind": "select",
          "label": "Scope",
          "default": "component",
          "choices": [
            {
              "value": "component",
              "label": "Component"
            },
            {
              "value": "full",
              "label": "Full URL"
            },
            {
              "value": "path",
              "label": "Path (RFC 3986)"
            }
          ]
        },
        {
          "key": "spacesAsPlus",
          "kind": "checkbox",
          "label": "Treat + as space (not in path scope)",
          "default": false
        },
        {
          "key": "repeat",
          "kind": "checkbox",
          "label": "Decode repeatedly",
          "default": false
        }
      ],
      "keywords": [
        "url decode",
        "uri encode",
        "rfc 3986 encoder",
        "path safe url encode",
        "encode url path segment",
        "query string",
        "multi url decode",
        "double encoded url",
        "decode url twice",
        "recursive url decode",
        "recursive url decoder",
        "double url decode",
        "triple url decode",
        "decode url multiple times",
        "nested url decode",
        "percent decode loop"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "html-entities",
      "name": "HTML entities encode and decode",
      "description": "Escape HTML special characters or turn entities back into readable text.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/html-entities",
      "embed": "https://textarray.com/embed/html-entities",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        },
        {
          "key": "scope",
          "kind": "select",
          "label": "Scope",
          "default": "reserved",
          "choices": [
            {
              "value": "reserved",
              "label": "Reserved only"
            },
            {
              "value": "nonAscii",
              "label": "Reserved + non-ASCII"
            }
          ]
        }
      ],
      "keywords": [
        "html encode",
        "html decode",
        "unescape html",
        "ampersand",
        "html entity decoder",
        "html entity encoder",
        "html entity encoder/decoder",
        "html entities"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "encrypt-text",
      "name": "Encrypt text with a password",
      "description": "Encrypt text with a password using AES — only someone who knows it can read it back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/encrypt-text",
      "embed": "https://textarray.com/embed/encrypt-text",
      "mode": "transform",
      "action": "Encrypt text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encrypt",
          "choices": [
            {
              "value": "encrypt",
              "label": "Encrypt"
            },
            {
              "value": "decrypt",
              "label": "Decrypt"
            }
          ]
        },
        {
          "key": "password",
          "kind": "text",
          "label": "Password",
          "default": "",
          "secret": true
        }
      ],
      "keywords": [
        "encrypt text",
        "decrypt text",
        "encrypt with password",
        "password encryption",
        "aes gcm",
        "browser encryption"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "hex-converter",
      "name": "Hex to text and back",
      "description": "Convert text to hexadecimal and hex back to text, byte for byte in UTF-8.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/hex-converter",
      "embed": "https://textarray.com/embed/hex-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text to hex"
            },
            {
              "value": "decode",
              "label": "Hex to text"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space — 48 65 78"
            },
            {
              "value": "none",
              "label": "None — 486578"
            },
            {
              "value": "0x",
              "label": "0x prefix — 0x48 0x65"
            },
            {
              "value": "backslash",
              "label": "\\x prefix — \\x48\\x65"
            }
          ]
        },
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase hex digits",
          "default": false
        }
      ],
      "keywords": [
        "hex to text",
        "text to hex",
        "hexadecimal converter",
        "hex encode",
        "hex decode",
        "hex dump",
        "ascii to hex",
        "utf-8 bytes",
        "hex in text",
        "text in hex",
        "hex text"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "rot13",
      "name": "ROT13 / Caesar cipher",
      "description": "Shift letters through the alphabet by any amount, ROT13 by default.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/rot13",
      "embed": "https://textarray.com/embed/rot13",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encrypt"
            },
            {
              "value": "decode",
              "label": "Decrypt"
            }
          ]
        },
        {
          "key": "shift",
          "kind": "range",
          "label": "Shift",
          "default": 13,
          "min": 1,
          "max": 25
        },
        {
          "key": "shiftDigits",
          "kind": "checkbox",
          "label": "Shift digits too (ROT5)",
          "default": false
        },
        {
          "key": "bruteForce",
          "kind": "checkbox",
          "label": "Show all 25 shifts",
          "default": false
        }
      ],
      "keywords": [
        "rot 13",
        "rot5",
        "rot18",
        "shift letters",
        "rot13 decoder",
        "brute force caesar"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "timestamp-converter",
      "name": "Unix timestamp converter",
      "description": "Convert Unix timestamps to readable dates and dates back to timestamps.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/timestamp-converter",
      "embed": "https://textarray.com/embed/timestamp-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect per line"
            },
            {
              "value": "to-date",
              "label": "Timestamp to date"
            },
            {
              "value": "to-timestamp",
              "label": "Date to timestamp"
            }
          ]
        },
        {
          "key": "unit",
          "kind": "select",
          "label": "Unit",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect"
            },
            {
              "value": "s",
              "label": "Seconds"
            },
            {
              "value": "ms",
              "label": "Milliseconds"
            },
            {
              "value": "excel1900",
              "label": "Excel serial (1900 system)"
            },
            {
              "value": "excel1904",
              "label": "Excel serial (1904 / Mac system)"
            }
          ]
        },
        {
          "key": "zone",
          "kind": "select",
          "label": "Time zone",
          "default": "local",
          "choices": [
            {
              "value": "local",
              "label": "Local"
            },
            {
              "value": "utc",
              "label": "UTC"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customZone",
          "kind": "text",
          "label": "IANA zone",
          "default": ""
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Date format",
          "default": "readable",
          "choices": [
            {
              "value": "readable",
              "label": "Readable"
            },
            {
              "value": "iso",
              "label": "ISO 8601"
            }
          ]
        },
        {
          "key": "relative",
          "kind": "checkbox",
          "label": "Add relative time",
          "default": true
        }
      ],
      "keywords": [
        "excel serial date converter",
        "excel date to unix timestamp",
        "serial number to date",
        "1904 date system",
        "epoch to date",
        "date to timestamp",
        "milliseconds to date",
        "convert unix time",
        "timestamp parser",
        "unix epoch",
        "epoch converter"
      ],
      "updated": "2026-08-22"
    },
    {
      "slug": "cron-parser",
      "name": "Cron expression parser",
      "description": "Explain a cron expression in plain language and preview its next run times.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/cron-parser",
      "embed": "https://textarray.com/embed/cron-parser",
      "mode": "transform",
      "action": "Explain",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "runs",
          "kind": "number",
          "label": "Next runs",
          "default": 5,
          "min": 1,
          "max": 20,
          "step": 1
        }
      ],
      "keywords": [
        "crontab",
        "cron explained",
        "cron next run",
        "crontab generator",
        "cron job",
        "kubernetes cronjob",
        "github actions schedule",
        "cron expression explainer",
        "cron expression generator explainer"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "binary-converter",
      "name": "Binary to text and back",
      "description": "Convert text to binary code and binary back to text, bit by bit.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/binary-converter",
      "embed": "https://textarray.com/embed/binary-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "encode",
              "label": "Text to code"
            },
            {
              "value": "decode",
              "label": "Code to text"
            }
          ]
        },
        {
          "key": "base",
          "kind": "select",
          "label": "Base",
          "default": "binary",
          "choices": [
            {
              "value": "binary",
              "label": "Binary — 01001000"
            },
            {
              "value": "octal",
              "label": "Octal — 110"
            }
          ]
        },
        {
          "key": "encoding",
          "kind": "select",
          "label": "Encoding",
          "default": "utf8",
          "choices": [
            {
              "value": "utf8",
              "label": "UTF-8 — every character"
            },
            {
              "value": "ascii",
              "label": "ASCII — codes 0-127 only"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space — 01001000 01101001"
            },
            {
              "value": "none",
              "label": "None — 0100100001101001"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "separatorCustom",
          "kind": "text",
          "label": "Custom separator",
          "default": ""
        }
      ],
      "keywords": [
        "binary to text",
        "text to binary",
        "binary translator",
        "binary code converter",
        "binary decoder",
        "ascii to binary",
        "octal to text",
        "text to octal"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "morse-code",
      "name": "Morse code translator",
      "description": "Translate text to Morse code and Morse code back to text.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/morse-code",
      "embed": "https://textarray.com/embed/morse-code",
      "mode": "transform",
      "action": "Translate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text → Morse code"
            },
            {
              "value": "decode",
              "label": "Morse code → text"
            }
          ]
        },
        {
          "key": "wordSeparator",
          "kind": "select",
          "label": "Word separator",
          "default": "slash",
          "choices": [
            {
              "value": "slash",
              "label": "Slash ( / )"
            },
            {
              "value": "spaces",
              "label": "Three spaces"
            }
          ]
        },
        {
          "key": "wpm",
          "kind": "range",
          "label": "Playback speed (WPM)",
          "default": 15,
          "min": 5,
          "max": 40
        }
      ],
      "keywords": [
        "morse code",
        "morse code translator",
        "morse decoder",
        "text to morse",
        "morse to text",
        "dots and dashes"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "atbash-cipher",
      "name": "Atbash cipher",
      "description": "Mirror the alphabet so A becomes Z and Z becomes A — encoding and decoding in one step.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/atbash-cipher",
      "embed": "https://textarray.com/embed/atbash-cipher",
      "mode": "transform",
      "action": "Apply cipher",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "atbash cipher",
        "atbash decoder",
        "reverse alphabet cipher",
        "hebrew cipher"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "base32",
      "name": "Base32 encode and decode",
      "description": "Convert text to RFC 4648 Base32 and back, with base32hex and padding options.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/base32",
      "embed": "https://textarray.com/embed/base32",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        },
        {
          "key": "variant",
          "kind": "select",
          "label": "Alphabet",
          "default": "standard",
          "choices": [
            {
              "value": "standard",
              "label": "Standard (RFC 4648)"
            },
            {
              "value": "hex",
              "label": "Base32hex"
            }
          ]
        },
        {
          "key": "padding",
          "kind": "checkbox",
          "label": "Pad with =",
          "default": true
        }
      ],
      "keywords": [
        "base32 decode",
        "2fa key",
        "base32 encode",
        "base32hex"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "char-code-converter",
      "name": "Character code converter",
      "description": "Turn text into Unicode code points and character codes back into text.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/char-code-converter",
      "embed": "https://textarray.com/embed/char-code-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text to codes"
            },
            {
              "value": "decode",
              "label": "Codes to text"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Format",
          "default": "unicode",
          "choices": [
            {
              "value": "unicode",
              "label": "U+0041"
            },
            {
              "value": "decimal",
              "label": "Decimal (65)"
            },
            {
              "value": "hex",
              "label": "Hex (0x41)"
            },
            {
              "value": "escape",
              "label": "Escape (\\u0041)"
            },
            {
              "value": "entity",
              "label": "HTML entity (&#65;)"
            },
            {
              "value": "array",
              "label": "Array ([65, 66])"
            }
          ]
        },
        {
          "key": "perLine",
          "kind": "checkbox",
          "label": "One code per line",
          "default": false
        }
      ],
      "keywords": [
        "character code converter",
        "ascii codes",
        "code point",
        "u+ notation",
        "html entity code",
        "ascii array converter",
        "decimal array",
        "text to array of char codes",
        "char code array"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "nato-alphabet",
      "name": "NATO phonetic alphabet",
      "description": "Spell text in the NATO alphabet — Alfa, Bravo, Charlie — and read it back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/nato-alphabet",
      "embed": "https://textarray.com/embed/nato-alphabet",
      "mode": "transform",
      "action": "Translate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text → NATO"
            },
            {
              "value": "decode",
              "label": "NATO → text"
            }
          ]
        },
        {
          "key": "wordSeparator",
          "kind": "select",
          "label": "Word separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "dash",
              "label": "Dash"
            },
            {
              "value": "newline",
              "label": "New line per word"
            }
          ]
        },
        {
          "key": "keepPunctuation",
          "kind": "checkbox",
          "label": "Keep punctuation",
          "default": false
        }
      ],
      "keywords": [
        "nato phonetic alphabet",
        "phonetic alphabet",
        "spelling alphabet",
        "nato spelling",
        "icao alphabet"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "punycode-converter",
      "name": "Punycode converter",
      "description": "Convert internationalized domain names to punycode (xn--) and back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/punycode-converter",
      "embed": "https://textarray.com/embed/punycode-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto"
            },
            {
              "value": "encode",
              "label": "To punycode"
            },
            {
              "value": "decode",
              "label": "To Unicode"
            }
          ]
        },
        {
          "key": "emails",
          "kind": "checkbox",
          "label": "Email addresses (convert the domain only)",
          "default": false
        }
      ],
      "keywords": [
        "punycode converter",
        "idn",
        "internationalized domain name",
        "xn--",
        "punycode decode",
        "punnycode",
        "punycode email",
        "idn email address",
        "email domain punycode"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "json-escape",
      "name": "JSON string escape and unescape",
      "description": "Escape raw text into a JSON string or parse JSON escapes back to readable text.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/json-escape",
      "embed": "https://textarray.com/embed/json-escape",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "escape",
          "choices": [
            {
              "value": "escape",
              "label": "Escape"
            },
            {
              "value": "unescape",
              "label": "Unescape"
            }
          ]
        },
        {
          "key": "wrapInQuotes",
          "kind": "checkbox",
          "label": "Wrap in quotes",
          "default": true
        },
        {
          "key": "escapeNonAscii",
          "kind": "checkbox",
          "label": "Escape non-ASCII",
          "default": false
        }
      ],
      "keywords": [
        "escape json string",
        "json string escape",
        "escape string",
        "backslash",
        "json string escaper",
        "json string encoding"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "vigenere-cipher",
      "name": "Vigenère cipher",
      "description": "Encrypt and decrypt text with the classic Vigenère keyword cipher.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/vigenere-cipher",
      "embed": "https://textarray.com/embed/vigenere-cipher",
      "mode": "transform",
      "action": "Apply cipher",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encrypt",
          "choices": [
            {
              "value": "encrypt",
              "label": "Encrypt"
            },
            {
              "value": "decrypt",
              "label": "Decrypt"
            }
          ]
        },
        {
          "key": "key",
          "kind": "text",
          "label": "Key",
          "default": "KEY"
        },
        {
          "key": "preserveCase",
          "kind": "checkbox",
          "label": "Preserve case",
          "default": true
        },
        {
          "key": "keepNonLetters",
          "kind": "checkbox",
          "label": "Keep non-letters",
          "default": true
        }
      ],
      "keywords": [
        "vigenere decoder",
        "vigenere decrypt",
        "vigenere key",
        "vigenere encrypt",
        "polyalphabetic cipher",
        "keyword cipher"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "xor-cipher",
      "name": "XOR cipher",
      "description": "XOR every byte of your text with a repeating key — encrypt and decrypt in one tool.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/xor-cipher",
      "embed": "https://textarray.com/embed/xor-cipher",
      "mode": "transform",
      "action": "Apply XOR",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "key",
          "kind": "text",
          "label": "Key",
          "default": "",
          "secret": true
        },
        {
          "key": "keyFormat",
          "kind": "select",
          "label": "Key format",
          "default": "utf8",
          "choices": [
            {
              "value": "utf8",
              "label": "Text (UTF-8)"
            },
            {
              "value": "hex",
              "label": "Hex"
            },
            {
              "value": "base64",
              "label": "Base64"
            }
          ]
        },
        {
          "key": "inputFormat",
          "kind": "select",
          "label": "Input format",
          "default": "utf8",
          "choices": [
            {
              "value": "utf8",
              "label": "Text (UTF-8)"
            },
            {
              "value": "hex",
              "label": "Hex"
            },
            {
              "value": "base64",
              "label": "Base64"
            }
          ]
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "hex",
          "choices": [
            {
              "value": "hex",
              "label": "Hex"
            },
            {
              "value": "base64",
              "label": "Base64"
            },
            {
              "value": "utf8",
              "label": "Text (UTF-8)"
            }
          ]
        }
      ],
      "keywords": [
        "xor encryption online",
        "xor text with key",
        "repeating key xor",
        "xor decrypt hex",
        "xor obfuscation"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "polybius-square",
      "name": "Polybius square",
      "description": "Turn letters into 5×5 grid coordinates (A → 11) and back, with an optional keyword.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/polybius-square",
      "embed": "https://textarray.com/embed/polybius-square",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text → numbers"
            },
            {
              "value": "decode",
              "label": "Numbers → text"
            }
          ]
        },
        {
          "key": "key",
          "kind": "text",
          "label": "Keyword (optional)",
          "default": ""
        }
      ],
      "keywords": [
        "polybius cipher",
        "polybius square decoder",
        "number pairs cipher",
        "grid cipher 5x5"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "rail-fence-cipher",
      "name": "Rail fence cipher",
      "description": "Encrypt and decrypt the classic zigzag transposition with a configurable rail count.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/rail-fence-cipher",
      "embed": "https://textarray.com/embed/rail-fence-cipher",
      "mode": "transform",
      "action": "Run the fence",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encrypt",
          "choices": [
            {
              "value": "encrypt",
              "label": "Encrypt"
            },
            {
              "value": "decrypt",
              "label": "Decrypt"
            }
          ]
        },
        {
          "key": "rails",
          "kind": "number",
          "label": "Rails",
          "default": 3,
          "min": 2,
          "max": 20,
          "step": 1
        },
        {
          "key": "offset",
          "kind": "number",
          "label": "Offset",
          "default": 0,
          "min": 0,
          "max": 40,
          "step": 1
        },
        {
          "key": "keepSpaces",
          "kind": "checkbox",
          "label": "Keep spaces and punctuation",
          "default": false
        }
      ],
      "keywords": [
        "rail fence cipher",
        "rail fence decoder",
        "rail fence encrypt decrypt",
        "zigzag cipher",
        "fence cipher decoder",
        "rail fence encoder"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "bacon-cipher",
      "name": "Bacon cipher",
      "description": "Encode text as five-symbol A/B groups with Bacon’s biliteral cipher, and back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/bacon-cipher",
      "embed": "https://textarray.com/embed/bacon-cipher",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text → A/B"
            },
            {
              "value": "decode",
              "label": "A/B → text"
            }
          ]
        },
        {
          "key": "alphabet",
          "kind": "select",
          "label": "Alphabet",
          "default": "classic",
          "choices": [
            {
              "value": "classic",
              "label": "Classic 24 (I=J, U=V)"
            },
            {
              "value": "modern",
              "label": "Modern 26"
            }
          ]
        }
      ],
      "keywords": [
        "baconian cipher",
        "bacon cipher decoder",
        "five bit letter cipher",
        "aaaaa baaba cipher",
        "biliteral a/b groups",
        "biliteral encode",
        "biliteral symbols grupe ab"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "quoted-printable",
      "name": "Quoted-printable decoder",
      "description": "Decode =C3=A9 escapes and soft line breaks from e-mail source — or encode your own.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/quoted-printable",
      "embed": "https://textarray.com/embed/quoted-printable",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "decode",
          "choices": [
            {
              "value": "decode",
              "label": "Decode"
            },
            {
              "value": "encode",
              "label": "Encode"
            }
          ]
        },
        {
          "key": "underscoreSpace",
          "kind": "checkbox",
          "label": "Decode _ as space (RFC 2047 Q)",
          "default": false
        },
        {
          "key": "lineWrap",
          "kind": "checkbox",
          "label": "Wrap encoded lines at 76 chars",
          "default": true
        }
      ],
      "keywords": [
        "quoted printable decoder",
        "quoted printable encoder",
        "decode quoted printable email",
        "qp encoding",
        "mime quoted printable",
        "soft line break decoder",
        "e-mail decoding"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "base58",
      "name": "Base58 encode and decode",
      "description": "Encode text to Base58 with the Bitcoin alphabet and decode it back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/base58",
      "embed": "https://textarray.com/embed/base58",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        }
      ],
      "keywords": [
        "base58 decode",
        "base58 converter",
        "base58 alphabet",
        "bitcoin alphabet",
        "base58 encode",
        "base58check"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "braille-translator",
      "name": "Braille translator",
      "description": "Translate text to Unicode braille letter by letter and back again.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/braille-translator",
      "embed": "https://textarray.com/embed/braille-translator",
      "mode": "transform",
      "action": "Translate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text to braille"
            },
            {
              "value": "decode",
              "label": "Braille to text"
            }
          ]
        },
        {
          "key": "capitalMarks",
          "kind": "checkbox",
          "label": "Capital marks",
          "default": true
        },
        {
          "key": "numberMarks",
          "kind": "checkbox",
          "label": "Number marks",
          "default": true
        }
      ],
      "keywords": [
        "text to braille",
        "braille to text",
        "braille alphabet",
        "unicode braille"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "caesar-cipher",
      "name": "Caesar cipher",
      "description": "Encode or decode text with a classic Caesar letter-shift cipher.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/caesar-cipher",
      "embed": "https://textarray.com/embed/caesar-cipher",
      "mode": "transform",
      "action": "Apply cipher",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "shift",
          "kind": "number",
          "label": "Shift",
          "default": 3,
          "min": 1,
          "max": 25
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        }
      ],
      "keywords": [
        "caesar encoder",
        "caesar decoder",
        "rot13",
        "rotation cipher",
        "shift cipher",
        "letter shift"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "rot47",
      "name": "ROT47 cipher",
      "description": "Encode or decode text with the ROT47 cipher, right in your browser.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/rot47",
      "embed": "https://textarray.com/embed/rot47",
      "mode": "transform",
      "action": "Apply ROT47",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "rot 47",
        "rotate ascii",
        "ascii cipher",
        "rot47 encode",
        "rot47 decode",
        "ascii rotation"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "unicode-inspector",
      "name": "Unicode character inspector",
      "description": "Break text into individual characters and see the code point, name, block, category and byte size of each.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/unicode-inspector",
      "embed": "https://textarray.com/embed/unicode-inspector",
      "mode": "transform",
      "action": "Inspect characters",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mergeSame",
          "kind": "checkbox",
          "label": "Merge identical characters",
          "default": false
        },
        {
          "key": "nonAsciiOnly",
          "kind": "checkbox",
          "label": "Non-ASCII characters only",
          "default": false
        },
        {
          "key": "decomposeEmoji",
          "kind": "checkbox",
          "label": "Decompose composed emoji",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "unicode inspector",
        "character inspector",
        "unicode code point",
        "character info",
        "unicode name lookup",
        "unicode block",
        "general category",
        "utf-8 byte count",
        "emoji code point",
        "character analyzer"
      ],
      "updated": "2026-08-01"
    },
    {
      "slug": "emoji-shortcode-converter",
      "name": "Emoji shortcode converter",
      "description": "Convert between emoji shortcodes like :smile: and the emoji character itself.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/emoji-shortcode-converter",
      "embed": "https://textarray.com/embed/emoji-shortcode-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "toEmoji",
          "choices": [
            {
              "value": "toEmoji",
              "label": "Shortcode → emoji"
            },
            {
              "value": "toShortcode",
              "label": "Emoji → shortcode"
            }
          ]
        },
        {
          "key": "nameSet",
          "kind": "select",
          "label": "Naming set",
          "default": "github",
          "choices": [
            {
              "value": "github",
              "label": "GitHub"
            },
            {
              "value": "slack",
              "label": "Slack"
            },
            {
              "value": "discord",
              "label": "Discord"
            }
          ]
        },
        {
          "key": "matchAnywhere",
          "kind": "checkbox",
          "label": "Convert inside sentences too",
          "default": true
        },
        {
          "key": "highlightUnknown",
          "kind": "checkbox",
          "label": "Highlight unrecognized codes",
          "default": false
        }
      ],
      "keywords": [
        "emoji shortcode converter",
        "shortcode to emoji",
        "emoji to shortcode",
        "github emoji codes",
        "slack emoji codes",
        "discord emoji codes",
        ":smile: converter",
        "emoji alias",
        "gemoji"
      ],
      "updated": "2026-08-01"
    },
    {
      "slug": "ieee-754-converter",
      "name": "IEEE 754 converter",
      "description": "Convert a decimal number to its IEEE 754 bit pattern, or bits back to a number.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/ieee-754-converter",
      "embed": "https://textarray.com/embed/ieee-754-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "toBits",
          "choices": [
            {
              "value": "toBits",
              "label": "Number → bits"
            },
            {
              "value": "toNumber",
              "label": "Bits → number"
            }
          ]
        },
        {
          "key": "precision",
          "kind": "select",
          "label": "Precision",
          "default": "single",
          "choices": [
            {
              "value": "single",
              "label": "32-bit (single)"
            },
            {
              "value": "double",
              "label": "64-bit (double)"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Bit notation",
          "default": "hex",
          "choices": [
            {
              "value": "hex",
              "label": "Hexadecimal"
            },
            {
              "value": "binary",
              "label": "Binary"
            }
          ]
        },
        {
          "key": "byteOrder",
          "kind": "select",
          "label": "Byte order",
          "default": "big",
          "choices": [
            {
              "value": "big",
              "label": "Big-endian"
            },
            {
              "value": "little",
              "label": "Little-endian"
            }
          ]
        },
        {
          "key": "showBreakdown",
          "kind": "checkbox",
          "label": "Show sign / exponent / mantissa",
          "default": false
        },
        {
          "key": "showRoundingError",
          "kind": "checkbox",
          "label": "Show actual stored value and rounding error",
          "default": false
        }
      ],
      "keywords": [
        "ieee 754",
        "float to binary",
        "binary to float",
        "float to hex",
        "hex to float",
        "float32",
        "float64",
        "single precision",
        "double precision",
        "floating point converter",
        "sign exponent mantissa"
      ],
      "updated": "2026-08-01"
    },
    {
      "slug": "twos-complement-converter",
      "name": "Two's complement converter",
      "description": "Convert an integer to its two's complement bit pattern at a chosen width, or decode bits back to a number.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/twos-complement-converter",
      "embed": "https://textarray.com/embed/twos-complement-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Number → bits"
            },
            {
              "value": "decode",
              "label": "Bits → number"
            }
          ]
        },
        {
          "key": "width",
          "kind": "select",
          "label": "Bit width",
          "default": "32",
          "choices": [
            {
              "value": "8",
              "label": "8-bit"
            },
            {
              "value": "16",
              "label": "16-bit"
            },
            {
              "value": "32",
              "label": "32-bit"
            },
            {
              "value": "64",
              "label": "64-bit"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Bit format",
          "default": "binary",
          "choices": [
            {
              "value": "binary",
              "label": "Binary"
            },
            {
              "value": "hex",
              "label": "Hexadecimal"
            }
          ]
        },
        {
          "key": "signed",
          "kind": "checkbox",
          "label": "Signed (two's complement)",
          "default": true
        },
        {
          "key": "warnOverflow",
          "kind": "checkbox",
          "label": "Flag out-of-range values",
          "default": true
        }
      ],
      "keywords": [
        "two's complement converter",
        "twos complement converter",
        "twos complement calculator",
        "twos complement to decimal",
        "decimal to twos complement",
        "signed binary converter",
        "binary overflow calculator",
        "signed integer to binary",
        "binary",
        "hex"
      ],
      "updated": "2026-08-01"
    },
    {
      "slug": "cyrillic-transliterator",
      "name": "Cyrillic transliterator",
      "description": "Convert Cyrillic or Greek text to Latin script using ISO 9, scientific, BGN/PCGN or Slovak transliteration rules.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/cyrillic-transliterator",
      "embed": "https://textarray.com/embed/cyrillic-transliterator",
      "mode": "transform",
      "action": "Transliterate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "sourceScript",
          "kind": "select",
          "label": "Source script",
          "default": "ru",
          "choices": [
            {
              "value": "ru",
              "label": "Russian"
            },
            {
              "value": "uk",
              "label": "Ukrainian"
            },
            {
              "value": "sr",
              "label": "Serbian"
            },
            {
              "value": "bg",
              "label": "Bulgarian"
            },
            {
              "value": "el",
              "label": "Greek"
            }
          ]
        },
        {
          "key": "norm",
          "kind": "select",
          "label": "Transliteration standard",
          "default": "scientific",
          "choices": [
            {
              "value": "iso9",
              "label": "ISO 9"
            },
            {
              "value": "scientific",
              "label": "Scientific"
            },
            {
              "value": "bgnPcgn",
              "label": "BGN/PCGN"
            },
            {
              "value": "slovak",
              "label": "Slovak usage"
            }
          ]
        },
        {
          "key": "keepDiacritics",
          "kind": "checkbox",
          "label": "Keep diacritics",
          "default": true
        },
        {
          "key": "strictScript",
          "kind": "checkbox",
          "label": "Only selected script's letters",
          "default": false
        }
      ],
      "keywords": [
        "cyrillic transliterator",
        "cyrillic to latin",
        "russian to latin",
        "transliterate cyrillic",
        "romanization",
        "cyrillic romanization",
        "iso 9",
        "bgn/pcgn",
        "greek to latin",
        "ukrainian transliteration",
        "serbian transliteration",
        "bulgarian transliteration"
      ],
      "updated": "2026-08-05"
    },
    {
      "slug": "code-string-escaper",
      "name": "Code string escaper",
      "description": "Turn pasted text into a string literal for C, Python, SQL, shell and 16 other languages — and back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/code-string-escaper",
      "embed": "https://textarray.com/embed/code-string-escaper",
      "mode": "transform",
      "action": "Escape string",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "language",
          "kind": "select",
          "label": "Language",
          "default": "javascript",
          "choices": [
            {
              "value": "c",
              "label": "C"
            },
            {
              "value": "cpp",
              "label": "C++"
            },
            {
              "value": "csharp",
              "label": "C#"
            },
            {
              "value": "java",
              "label": "Java"
            },
            {
              "value": "javascript",
              "label": "JavaScript"
            },
            {
              "value": "typescript",
              "label": "TypeScript"
            },
            {
              "value": "python",
              "label": "Python"
            },
            {
              "value": "go",
              "label": "Go"
            },
            {
              "value": "rust",
              "label": "Rust"
            },
            {
              "value": "php",
              "label": "PHP"
            },
            {
              "value": "ruby",
              "label": "Ruby"
            },
            {
              "value": "swift",
              "label": "Swift"
            },
            {
              "value": "kotlin",
              "label": "Kotlin"
            },
            {
              "value": "sql",
              "label": "SQL"
            },
            {
              "value": "shell",
              "label": "Shell (bash)"
            },
            {
              "value": "powershell",
              "label": "PowerShell"
            },
            {
              "value": "yaml",
              "label": "YAML"
            },
            {
              "value": "json",
              "label": "JSON"
            },
            {
              "value": "xml",
              "label": "XML"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "escape",
          "choices": [
            {
              "value": "escape",
              "label": "Escape"
            },
            {
              "value": "unescape",
              "label": "Unescape"
            }
          ]
        },
        {
          "key": "quoteStyle",
          "kind": "select",
          "label": "Quote style",
          "default": "double",
          "choices": [
            {
              "value": "single",
              "label": "Single (' ')"
            },
            {
              "value": "double",
              "label": "Double (\" \")"
            },
            {
              "value": "backtick",
              "label": "Backtick (` `)"
            }
          ]
        },
        {
          "key": "wrapInQuotes",
          "kind": "checkbox",
          "label": "Wrap result in quotes",
          "default": true
        },
        {
          "key": "multilineLiteral",
          "kind": "checkbox",
          "label": "Use multi-line literal instead of \\n",
          "default": false
        },
        {
          "key": "escapeNonAscii",
          "kind": "checkbox",
          "label": "Escape non-ASCII as \\u sequences",
          "default": false
        },
        {
          "key": "preserveTabs",
          "kind": "checkbox",
          "label": "Keep literal tabs",
          "default": false
        }
      ],
      "keywords": [
        "escape string",
        "unescape string",
        "string literal escaper",
        "code string escaper",
        "string escape sequences",
        "quote escaping",
        "javascript string escape",
        "python string escape",
        "java string escape",
        "sql string escape",
        "json",
        "yaml",
        "xml",
        "csv",
        "shell",
        "powershell"
      ],
      "updated": "2026-08-06"
    },
    {
      "slug": "random-emoji-generator",
      "name": "Random emoji generator",
      "description": "Generate random emoji from curated categories, with control over count and repeats.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/random-emoji-generator",
      "embed": "https://textarray.com/embed/random-emoji-generator",
      "mode": "generate",
      "action": "Generate emoji",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "category",
          "kind": "select",
          "label": "Category",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All"
            },
            {
              "value": "smileys",
              "label": "Smileys"
            },
            {
              "value": "animals",
              "label": "Animals & nature"
            },
            {
              "value": "food",
              "label": "Food & drink"
            },
            {
              "value": "objects",
              "label": "Activities & objects"
            },
            {
              "value": "travel",
              "label": "Travel & places"
            },
            {
              "value": "symbols",
              "label": "Symbols & hearts"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 10,
          "min": 1,
          "max": 1000
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "newline",
              "label": "New line"
            },
            {
              "value": "none",
              "label": "None"
            }
          ]
        },
        {
          "key": "unique",
          "kind": "checkbox",
          "label": "No repeats",
          "default": false
        }
      ],
      "keywords": [
        "random emoji generator",
        "generate emoji",
        "pick random emoji",
        "generate random emojis",
        "emoji randomizer",
        "emoji picker"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "passphrase-generator",
      "name": "Passphrase generator",
      "description": "Create memorable diceware-style passphrases from random words, right in your browser.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/passphrase-generator",
      "embed": "https://textarray.com/embed/passphrase-generator",
      "mode": "generate",
      "action": "Generate passphrases",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "words",
          "kind": "range",
          "label": "Words",
          "default": 4,
          "min": 3,
          "max": 10
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "hyphen",
          "choices": [
            {
              "value": "hyphen",
              "label": "Hyphen -"
            },
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "dot",
              "label": "Dot ."
            },
            {
              "value": "underscore",
              "label": "Underscore _"
            }
          ]
        },
        {
          "key": "capitalize",
          "kind": "checkbox",
          "label": "Capitalize each word",
          "default": false
        },
        {
          "key": "addNumber",
          "kind": "checkbox",
          "label": "Append a random digit",
          "default": true
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 5,
          "min": 1,
          "max": 100
        }
      ],
      "keywords": [
        "memorable password",
        "word password",
        "random passphrase",
        "xkcd password"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "password-generator",
      "name": "Password generator",
      "description": "Create a strong random password in your browser, with no server involved.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/password-generator",
      "embed": "https://textarray.com/embed/password-generator",
      "mode": "generate",
      "action": "Generate password",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "length",
          "kind": "range",
          "label": "Length",
          "default": 20,
          "min": 6,
          "max": 64
        },
        {
          "key": "upper",
          "kind": "checkbox",
          "label": "Uppercase A–Z",
          "default": true
        },
        {
          "key": "lower",
          "kind": "checkbox",
          "label": "Lowercase a–z",
          "default": true
        },
        {
          "key": "digits",
          "kind": "checkbox",
          "label": "Digits 0–9",
          "default": true
        },
        {
          "key": "symbols",
          "kind": "checkbox",
          "label": "Symbols !@#$%",
          "default": true
        },
        {
          "key": "excludeAmbiguous",
          "kind": "checkbox",
          "label": "Exclude ambiguous characters",
          "default": false
        }
      ],
      "keywords": [
        "strong password",
        "passphrase",
        "secure password",
        "password generator online",
        "create strong password",
        "random password"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "random-string",
      "name": "Random string generator",
      "description": "Generate random strings of any length from a character set you choose.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/random-string",
      "embed": "https://textarray.com/embed/random-string",
      "mode": "generate",
      "action": "Generate strings",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "length",
          "kind": "number",
          "label": "Length",
          "default": 32,
          "min": 1,
          "max": 4096
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 1,
          "min": 1,
          "max": 1000
        },
        {
          "key": "charset",
          "kind": "select",
          "label": "Character set",
          "default": "alphanumeric",
          "choices": [
            {
              "value": "alphanumeric",
              "label": "A–Z a–z 0–9"
            },
            {
              "value": "letters",
              "label": "A–Z a–z"
            },
            {
              "value": "lowercase",
              "label": "a–z"
            },
            {
              "value": "uppercase",
              "label": "A–Z"
            },
            {
              "value": "digits",
              "label": "0–9"
            },
            {
              "value": "hex",
              "label": "0–9 a–f"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customChars",
          "kind": "text",
          "label": "Custom characters",
          "default": ""
        }
      ],
      "keywords": [
        "random text",
        "api key",
        "token generator",
        "nonce"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "random-number",
      "name": "Random number generator",
      "description": "Draw random whole numbers from any range, with or without repeats.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/random-number",
      "embed": "https://textarray.com/embed/random-number",
      "mode": "generate",
      "action": "Generate numbers",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "min",
          "kind": "number",
          "label": "Minimum",
          "default": 1
        },
        {
          "key": "max",
          "kind": "number",
          "label": "Maximum",
          "default": 100
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 1,
          "min": 1,
          "max": 10000
        },
        {
          "key": "unique",
          "kind": "checkbox",
          "label": "No repeats",
          "default": false
        },
        {
          "key": "sort",
          "kind": "select",
          "label": "Sort",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Draw order"
            },
            {
              "value": "asc",
              "label": "Ascending"
            },
            {
              "value": "desc",
              "label": "Descending"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "newline",
          "choices": [
            {
              "value": "newline",
              "label": "One per line"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "space",
              "label": "Space"
            }
          ]
        }
      ],
      "keywords": [
        "random number generator",
        "number picker",
        "dice roll",
        "lottery numbers",
        "random integer",
        "unique random numbers",
        "random numbers no repeats",
        "random numbers no duplicates",
        "non repeating random numbers",
        "lottery number generator",
        "raffle numbers",
        "shuffle range of numbers"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "uuid-generator",
      "name": "UUID generator",
      "description": "Generate version 4 UUIDs, one per line, straight in your browser.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/uuid-generator",
      "embed": "https://textarray.com/embed/uuid-generator",
      "mode": "generate",
      "action": "Generate UUIDs",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 5,
          "min": 1,
          "max": 1000
        },
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase",
          "default": false
        },
        {
          "key": "noDashes",
          "kind": "checkbox",
          "label": "Remove dashes",
          "default": false
        }
      ],
      "keywords": [
        "guid generator",
        "unique id",
        "random uuid",
        "generator uuid/guid"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "lorem-ipsum",
      "name": "Lorem ipsum generator",
      "description": "Generate placeholder paragraphs, sentences or words for layouts and mockups.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/lorem-ipsum",
      "embed": "https://textarray.com/embed/lorem-ipsum",
      "mode": "generate",
      "action": "Generate text",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "amount",
          "kind": "number",
          "label": "How many",
          "default": 3,
          "min": 1,
          "max": 100
        },
        {
          "key": "unit",
          "kind": "select",
          "label": "Unit",
          "default": "paragraphs",
          "choices": [
            {
              "value": "paragraphs",
              "label": "Paragraphs"
            },
            {
              "value": "sentences",
              "label": "Sentences"
            },
            {
              "value": "words",
              "label": "Words"
            }
          ]
        },
        {
          "key": "startWithLorem",
          "kind": "checkbox",
          "label": "Start with \"Lorem ipsum\"",
          "default": true
        }
      ],
      "keywords": [
        "filler text",
        "sample paragraphs",
        "generate lorem ipsum",
        "placeholder text",
        "dummy text"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "random-words",
      "name": "Random word generator",
      "description": "Generate random English words by length, part of speech and starting letters.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/random-words",
      "embed": "https://textarray.com/embed/random-words",
      "mode": "generate",
      "action": "Generate words",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "dictionary",
          "choices": [
            {
              "value": "dictionary",
              "label": "Dictionary words"
            },
            {
              "value": "invented",
              "label": "Invented words"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 10,
          "min": 1,
          "max": 1000
        },
        {
          "key": "partOfSpeech",
          "kind": "select",
          "label": "Part of speech",
          "default": "any",
          "choices": [
            {
              "value": "any",
              "label": "Any"
            },
            {
              "value": "nouns",
              "label": "Nouns"
            },
            {
              "value": "adjectives",
              "label": "Adjectives"
            },
            {
              "value": "verbs",
              "label": "Verbs"
            }
          ]
        },
        {
          "key": "minLength",
          "kind": "number",
          "label": "Min length",
          "default": 3,
          "min": 1,
          "max": 12
        },
        {
          "key": "maxLength",
          "kind": "number",
          "label": "Max length",
          "default": 10,
          "min": 1,
          "max": 12
        },
        {
          "key": "startsWith",
          "kind": "text",
          "label": "Starts with",
          "default": ""
        }
      ],
      "keywords": [
        "random word generator",
        "random noun",
        "random adjective",
        "random verb",
        "made up words",
        "invented words",
        "project name generator"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "dice-roller",
      "name": "Dice roller & coin flip",
      "description": "Roll d4 to d100 dice or flip a coin with cryptographically fair results.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/dice-roller",
      "embed": "https://textarray.com/embed/dice-roller",
      "mode": "generate",
      "action": "Roll",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "die",
          "kind": "select",
          "label": "Die",
          "default": "d6",
          "choices": [
            {
              "value": "coin",
              "label": "Coin"
            },
            {
              "value": "d4",
              "label": "d4"
            },
            {
              "value": "d6",
              "label": "d6"
            },
            {
              "value": "d8",
              "label": "d8"
            },
            {
              "value": "d10",
              "label": "d10"
            },
            {
              "value": "d12",
              "label": "d12"
            },
            {
              "value": "d20",
              "label": "d20"
            },
            {
              "value": "d100",
              "label": "d100"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "Rolls",
          "default": 5,
          "min": 1,
          "max": 10000
        },
        {
          "key": "stats",
          "kind": "checkbox",
          "label": "Show sum and stats",
          "default": true
        }
      ],
      "keywords": [
        "roll dice online",
        "roll a die",
        "flip a coin",
        "d20 roll",
        "dnd dice roller",
        "heads or tails"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "mac-address-generator",
      "name": "MAC address generator",
      "description": "Generate random, well-formed MAC addresses in colon, hyphen or Cisco notation.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/mac-address-generator",
      "embed": "https://textarray.com/embed/mac-address-generator",
      "mode": "generate",
      "action": "Generate addresses",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 5,
          "min": 1,
          "max": 10000
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Format",
          "default": "colon",
          "choices": [
            {
              "value": "colon",
              "label": "aa:bb:cc:dd:ee:ff"
            },
            {
              "value": "hyphen",
              "label": "aa-bb-cc-dd-ee-ff"
            },
            {
              "value": "dot",
              "label": "aabb.ccdd.eeff (Cisco)"
            },
            {
              "value": "none",
              "label": "aabbccddeeff"
            }
          ]
        },
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase",
          "default": false
        },
        {
          "key": "localAdmin",
          "kind": "checkbox",
          "label": "Locally administered",
          "default": true
        },
        {
          "key": "unicast",
          "kind": "checkbox",
          "label": "Unicast",
          "default": true
        }
      ],
      "keywords": [
        "random mac address",
        "generate mac address",
        "fake mac address",
        "mac address list",
        "cisco mac format"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "google-calendar-link",
      "name": "Google Calendar link generator",
      "description": "Build an add-to-calendar link that opens a prefilled event in Google Calendar.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/google-calendar-link",
      "embed": "https://textarray.com/embed/google-calendar-link",
      "mode": "generate",
      "action": "Generate link",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "title",
          "kind": "text",
          "label": "Title",
          "default": "Team sync"
        },
        {
          "key": "start",
          "kind": "text",
          "label": "Start",
          "default": ""
        },
        {
          "key": "end",
          "kind": "text",
          "label": "End",
          "default": ""
        },
        {
          "key": "duration",
          "kind": "number",
          "label": "Duration (min), when no end",
          "default": 60,
          "min": 1,
          "max": 10080,
          "step": 5
        },
        {
          "key": "allDay",
          "kind": "checkbox",
          "label": "All-day",
          "default": false
        },
        {
          "key": "location",
          "kind": "text",
          "label": "Location",
          "default": ""
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "timezone",
          "kind": "text",
          "label": "Time zone",
          "default": ""
        }
      ],
      "keywords": [
        "google calendar link generator",
        "add to calendar link",
        "google calendar event link",
        "calendar link generator",
        "gcal link",
        "add event link",
        "render action template",
        "web link creator"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "random-date-generator",
      "name": "Random date generator",
      "description": "Generate random dates from any range, in the format you need.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/random-date-generator",
      "embed": "https://textarray.com/embed/random-date-generator",
      "mode": "generate",
      "action": "Generate dates",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "from",
          "kind": "text",
          "label": "From",
          "default": "2000-01-01"
        },
        {
          "key": "to",
          "kind": "text",
          "label": "To",
          "default": "2030-12-31"
        },
        {
          "key": "count",
          "kind": "number",
          "label": "Count",
          "default": 5,
          "min": 1,
          "max": 1000
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Format",
          "default": "iso",
          "choices": [
            {
              "value": "iso",
              "label": "YYYY-MM-DD"
            },
            {
              "value": "eu",
              "label": "DD.MM.YYYY"
            },
            {
              "value": "us",
              "label": "MM/DD/YYYY"
            },
            {
              "value": "long",
              "label": "Locale long"
            },
            {
              "value": "iso-time",
              "label": "ISO with time"
            }
          ]
        },
        {
          "key": "time",
          "kind": "checkbox",
          "label": "Include time",
          "default": false
        },
        {
          "key": "unique",
          "kind": "checkbox",
          "label": "Unique dates",
          "default": false
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort ascending",
          "default": false
        }
      ],
      "keywords": [
        "random date generator",
        "random day",
        "date picker random",
        "random birthday generator",
        "test dates"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "random-ip-generator",
      "name": "Random IP address generator",
      "description": "Generate random IPv4 and IPv6 addresses for testing, with public, private and CIDR options.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/random-ip-generator",
      "embed": "https://textarray.com/embed/random-ip-generator",
      "mode": "generate",
      "action": "Generate addresses",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "version",
          "kind": "select",
          "label": "Version",
          "default": "v4",
          "choices": [
            {
              "value": "v4",
              "label": "IPv4"
            },
            {
              "value": "v6",
              "label": "IPv6"
            },
            {
              "value": "both",
              "label": "Both"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 10,
          "min": 1,
          "max": 1000
        },
        {
          "key": "range",
          "kind": "select",
          "label": "IPv4 range",
          "default": "any",
          "choices": [
            {
              "value": "any",
              "label": "Any"
            },
            {
              "value": "public",
              "label": "Public only"
            },
            {
              "value": "private",
              "label": "Private only"
            }
          ]
        },
        {
          "key": "unique",
          "kind": "checkbox",
          "label": "Unique",
          "default": true
        },
        {
          "key": "cidr",
          "kind": "checkbox",
          "label": "CIDR suffix",
          "default": false
        }
      ],
      "keywords": [
        "random ip generator",
        "random ip address",
        "generate ip addresses",
        "fake ip address",
        "ipv4 generator",
        "ipv6 generator",
        "random ipv6",
        "ip address list"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "random-color-generator",
      "name": "Random color generator",
      "description": "Generate random colors as HEX, RGB or HSL, with light, dark, pastel and vivid palettes.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/random-color-generator",
      "embed": "https://textarray.com/embed/random-color-generator",
      "mode": "generate",
      "action": "Generate colors",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "Count",
          "default": 5,
          "min": 1,
          "max": 100
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Format",
          "default": "hex",
          "choices": [
            {
              "value": "hex",
              "label": "HEX"
            },
            {
              "value": "rgb",
              "label": "RGB"
            },
            {
              "value": "hsl",
              "label": "HSL"
            },
            {
              "value": "all",
              "label": "All three"
            }
          ]
        },
        {
          "key": "palette",
          "kind": "select",
          "label": "Palette",
          "default": "any",
          "choices": [
            {
              "value": "any",
              "label": "Any"
            },
            {
              "value": "light",
              "label": "Light"
            },
            {
              "value": "dark",
              "label": "Dark"
            },
            {
              "value": "pastel",
              "label": "Pastel"
            },
            {
              "value": "vivid",
              "label": "Vivid"
            }
          ]
        },
        {
          "key": "alpha",
          "kind": "checkbox",
          "label": "Include alpha",
          "default": false
        }
      ],
      "keywords": [
        "random color generator",
        "random colour generator",
        "random hex color",
        "random color palette",
        "pastel colors",
        "random hex color generator"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "ulid-generator",
      "name": "ULID generator",
      "description": "Generate sortable ULID identifiers, one per line, straight in your browser.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/ulid-generator",
      "embed": "https://textarray.com/embed/ulid-generator",
      "mode": "generate",
      "action": "Generate ULIDs",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "Count",
          "default": 5,
          "min": 1,
          "max": 1000
        },
        {
          "key": "case",
          "kind": "select",
          "label": "Case",
          "default": "upper",
          "choices": [
            {
              "value": "upper",
              "label": "Uppercase"
            },
            {
              "value": "lower",
              "label": "Lowercase"
            }
          ]
        },
        {
          "key": "showTimestamp",
          "kind": "checkbox",
          "label": "Show timestamp",
          "default": false
        }
      ],
      "keywords": [
        "sortable identifier",
        "unique id generator",
        "ulid vs uuid",
        "lexicographically sortable"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "password-strength-checker",
      "name": "Password strength checker",
      "description": "Estimate password entropy, crack time and concrete weaknesses — locally, in your browser.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/password-strength-checker",
      "embed": "https://textarray.com/embed/password-strength-checker",
      "mode": "transform",
      "action": "Check strength",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "showDetails",
          "kind": "checkbox",
          "label": "Show details",
          "default": true
        }
      ],
      "keywords": [
        "how strong is my password",
        "password entropy",
        "password checker",
        "crack time"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "nanoid-generator",
      "name": "Nano ID generator",
      "description": "Generate short, URL-safe Nano IDs with cryptographically secure randomness.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/nanoid-generator",
      "embed": "https://textarray.com/embed/nanoid-generator",
      "mode": "generate",
      "action": "Generate Nano IDs",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "length",
          "kind": "number",
          "label": "Length",
          "default": 21,
          "min": 2,
          "max": 128
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 5,
          "min": 1,
          "max": 1000
        },
        {
          "key": "alphabet",
          "kind": "select",
          "label": "Alphabet",
          "default": "standard",
          "choices": [
            {
              "value": "standard",
              "label": "Standard (A–Z a–z 0–9 _ -)"
            },
            {
              "value": "no-lookalikes",
              "label": "No lookalikes"
            },
            {
              "value": "lowercase-digits",
              "label": "Lowercase + digits"
            },
            {
              "value": "hex",
              "label": "Hex lowercase"
            }
          ]
        }
      ],
      "keywords": [
        "nanoid online",
        "short unique id",
        "url safe id",
        "url friendly id",
        "compact id generator",
        "nanoid vs uuid",
        "id generator online"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "random-username-generator",
      "name": "Random username generator",
      "description": "Generate friendly adjective + noun usernames like CleverFox07 in four styles.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/random-username-generator",
      "embed": "https://textarray.com/embed/random-username-generator",
      "mode": "generate",
      "action": "Generate usernames",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 10,
          "min": 1,
          "max": 200
        },
        {
          "key": "style",
          "kind": "select",
          "label": "Style",
          "default": "capitalized",
          "choices": [
            {
              "value": "lowercase",
              "label": "Lowercase (cleverfox)"
            },
            {
              "value": "capitalized",
              "label": "Capitalized (CleverFox)"
            },
            {
              "value": "snake",
              "label": "snake_case (clever_fox)"
            },
            {
              "value": "kebab",
              "label": "kebab-case (clever-fox)"
            }
          ]
        },
        {
          "key": "appendNumber",
          "kind": "checkbox",
          "label": "Append a number",
          "default": true
        },
        {
          "key": "maxLength",
          "kind": "number",
          "label": "Max length",
          "default": 20,
          "min": 6,
          "max": 40
        }
      ],
      "keywords": [
        "cool usernames",
        "generate username",
        "online username generator",
        "create username",
        "adjective noun generator"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "diceware",
      "name": "Diceware passphrase generator",
      "description": "Generate strong, memorable passphrases from random words with a shown entropy figure.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/diceware",
      "embed": "https://textarray.com/embed/diceware",
      "mode": "generate",
      "action": "Generate passphrase",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "words",
          "kind": "number",
          "label": "Words",
          "default": 6,
          "min": 2,
          "max": 20,
          "step": 1
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 5,
          "min": 1,
          "max": 50,
          "step": 1
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "hyphen",
          "choices": [
            {
              "value": "hyphen",
              "label": "Hyphen -"
            },
            {
              "value": "dot",
              "label": "Dot ."
            },
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "underscore",
              "label": "Underscore _"
            },
            {
              "value": "none",
              "label": "Nothing"
            }
          ]
        },
        {
          "key": "wordCase",
          "kind": "select",
          "label": "Case",
          "default": "lower",
          "choices": [
            {
              "value": "lower",
              "label": "lowercase"
            },
            {
              "value": "title",
              "label": "Title Case"
            },
            {
              "value": "upper",
              "label": "UPPERCASE"
            }
          ]
        },
        {
          "key": "addNumber",
          "kind": "checkbox",
          "label": "Append a random digit",
          "default": false
        }
      ],
      "keywords": [
        "random word password",
        "strong passphrase online",
        "xkcd password",
        "starke passphrase online"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "coin-flip",
      "name": "Coin flip",
      "description": "Flip a virtual coin for heads or tails with cryptographically fair results.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/coin-flip",
      "embed": "https://textarray.com/embed/coin-flip",
      "mode": "generate",
      "action": "Flip",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "Flips",
          "default": 1,
          "min": 1,
          "max": 1000
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Format",
          "default": "words",
          "choices": [
            {
              "value": "words",
              "label": "Heads / Tails"
            },
            {
              "value": "ht",
              "label": "H / T"
            },
            {
              "value": "binary",
              "label": "1 / 0"
            }
          ]
        }
      ],
      "keywords": [
        "flip a coin",
        "coin toss",
        "heads or tails",
        "random coin"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "pin-generator",
      "name": "PIN generator",
      "description": "Generate random numeric PIN codes instantly.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/pin-generator",
      "embed": "https://textarray.com/embed/pin-generator",
      "mode": "generate",
      "action": "Generate PINs",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "length",
          "kind": "number",
          "label": "PIN length",
          "default": 4,
          "min": 3,
          "max": 12
        },
        {
          "key": "count",
          "kind": "number",
          "label": "Number of PINs",
          "default": 1,
          "min": 1,
          "max": 100
        }
      ],
      "keywords": [
        "numeric code",
        "generate pin",
        "random pin generator",
        "pin code maker"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "repeat-character",
      "name": "Repeat character",
      "description": "Generate a line or block by repeating a character or string pattern.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/repeat-character",
      "embed": "https://textarray.com/embed/repeat-character",
      "mode": "generate",
      "action": "Generate",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "char",
          "kind": "text",
          "label": "Character",
          "default": "─"
        },
        {
          "key": "count",
          "kind": "number",
          "label": "Repetitions per line",
          "default": 40,
          "min": 1,
          "max": 10000
        },
        {
          "key": "lines",
          "kind": "number",
          "label": "Number of lines",
          "default": 1,
          "min": 1,
          "max": 1000
        }
      ],
      "keywords": [
        "character repetition",
        "ascii divider",
        "ascii ruler",
        "ascii art",
        "repeat line",
        "repeat pattern",
        "repeat dash",
        "repeat equals",
        "opakuj text",
        "ascii delnic",
        "ascii vonalak"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "birth-number-generator",
      "name": "Birth number generator",
      "description": "Generate fictional but mathematically valid Slovak/Czech birth numbers for testing.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/birth-number-generator",
      "embed": "https://textarray.com/embed/birth-number-generator",
      "mode": "generate",
      "action": "Generate birth numbers",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "fromYear",
          "kind": "number",
          "label": "From year",
          "default": 1980,
          "min": 1900,
          "max": 2053
        },
        {
          "key": "toYear",
          "kind": "number",
          "label": "To year",
          "default": 2010,
          "min": 1900,
          "max": 2053
        },
        {
          "key": "sex",
          "kind": "select",
          "label": "Sex",
          "default": "both",
          "choices": [
            {
              "value": "male",
              "label": "Male"
            },
            {
              "value": "female",
              "label": "Female"
            },
            {
              "value": "both",
              "label": "Both"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "Count",
          "default": 20,
          "min": 1,
          "max": 1000
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Format",
          "default": "slash",
          "choices": [
            {
              "value": "slash",
              "label": "With slash (900101/1234)"
            },
            {
              "value": "plain",
              "label": "Without slash (9001011234)"
            }
          ]
        }
      ],
      "keywords": [
        "generate birth number",
        "fake birth number",
        "test birth number",
        "birth number validator",
        "birth number checker",
        "fake birth numbers online"
      ],
      "updated": "2026-07-28"
    },
    {
      "slug": "persona-prompt-generator",
      "name": "AI persona prompt generator",
      "description": "Assemble a reusable system prompt that defines an AI persona from a few short fields.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/persona-prompt-generator",
      "embed": "https://textarray.com/embed/persona-prompt-generator",
      "mode": "generate",
      "action": "Generate persona prompt",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "role",
          "kind": "select",
          "label": "Role",
          "default": "support-agent",
          "choices": [
            {
              "value": "senior-developer",
              "label": "Senior developer"
            },
            {
              "value": "copywriter",
              "label": "Copywriter"
            },
            {
              "value": "teacher",
              "label": "Teacher"
            },
            {
              "value": "analyst",
              "label": "Analyst"
            },
            {
              "value": "support-agent",
              "label": "Support agent"
            },
            {
              "value": "editor",
              "label": "Editor"
            },
            {
              "value": "tutor",
              "label": "Tutor"
            },
            {
              "value": "researcher",
              "label": "Researcher"
            },
            {
              "value": "marketer",
              "label": "Marketer"
            },
            {
              "value": "product-manager",
              "label": "Product manager"
            },
            {
              "value": "ux-writer",
              "label": "UX writer"
            },
            {
              "value": "translator",
              "label": "Translator"
            },
            {
              "value": "interviewer",
              "label": "Interviewer"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customRole",
          "kind": "text",
          "label": "Custom role (used when role is \"Custom\")",
          "default": ""
        },
        {
          "key": "personaName",
          "kind": "text",
          "label": "Persona name",
          "default": ""
        },
        {
          "key": "tone",
          "kind": "select",
          "label": "Tone",
          "default": "friendly",
          "choices": [
            {
              "value": "formal",
              "label": "Formal"
            },
            {
              "value": "friendly",
              "label": "Friendly"
            },
            {
              "value": "blunt",
              "label": "Blunt"
            },
            {
              "value": "playful",
              "label": "Playful"
            },
            {
              "value": "empathetic",
              "label": "Empathetic"
            },
            {
              "value": "authoritative",
              "label": "Authoritative"
            },
            {
              "value": "academic",
              "label": "Academic"
            }
          ]
        },
        {
          "key": "expertise",
          "kind": "select",
          "label": "Audience expertise",
          "default": "intermediate",
          "choices": [
            {
              "value": "beginner",
              "label": "Beginner"
            },
            {
              "value": "intermediate",
              "label": "Intermediate"
            },
            {
              "value": "expert",
              "label": "Expert"
            },
            {
              "value": "mixed",
              "label": "Mixed"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "prose",
          "choices": [
            {
              "value": "prose",
              "label": "Prose"
            },
            {
              "value": "bullets",
              "label": "Bullet points"
            },
            {
              "value": "markdown",
              "label": "Markdown"
            },
            {
              "value": "json",
              "label": "JSON"
            },
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "steps",
              "label": "Numbered steps"
            }
          ]
        },
        {
          "key": "length",
          "kind": "select",
          "label": "Response length",
          "default": "normal",
          "choices": [
            {
              "value": "brief",
              "label": "Brief"
            },
            {
              "value": "normal",
              "label": "Normal"
            },
            {
              "value": "detailed",
              "label": "Detailed"
            }
          ]
        },
        {
          "key": "language",
          "kind": "text",
          "label": "Reply language",
          "default": "English"
        },
        {
          "key": "promptFormat",
          "kind": "select",
          "label": "Prompt structure",
          "default": "markdown",
          "choices": [
            {
              "value": "markdown",
              "label": "Markdown headings"
            },
            {
              "value": "xml",
              "label": "XML tags"
            },
            {
              "value": "plain",
              "label": "Plain titles"
            }
          ]
        },
        {
          "key": "includeBoundaries",
          "kind": "checkbox",
          "label": "Include refusal / boundaries clause",
          "default": true
        },
        {
          "key": "admitUncertainty",
          "kind": "checkbox",
          "label": "Say when unsure instead of guessing",
          "default": true
        },
        {
          "key": "askClarifying",
          "kind": "checkbox",
          "label": "Ask a clarifying question when ambiguous",
          "default": false
        },
        {
          "key": "stepByStep",
          "kind": "checkbox",
          "label": "Think step by step before answering",
          "default": false
        },
        {
          "key": "noEmoji",
          "kind": "checkbox",
          "label": "Forbid emoji",
          "default": false
        },
        {
          "key": "includeFewShot",
          "kind": "checkbox",
          "label": "Include few-shot example placeholder",
          "default": false
        },
        {
          "key": "includeVariables",
          "kind": "checkbox",
          "label": "Add an {{input}} placeholder section",
          "default": false
        }
      ],
      "keywords": [
        "ai persona prompt generator",
        "ai character prompt",
        "chatbot persona builder",
        "llm system prompt template",
        "ai role prompt",
        "persona role creator"
      ],
      "updated": "2026-07-28"
    },
    {
      "slug": "editorconfig-generator",
      "name": "EditorConfig generator",
      "description": "Generate a .editorconfig file that keeps indentation and line endings consistent across editors.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/editorconfig-generator",
      "embed": "https://textarray.com/embed/editorconfig-generator",
      "mode": "generate",
      "action": "Generate .editorconfig",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "indentStyle",
          "kind": "select",
          "label": "Indent style",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Spaces"
            },
            {
              "value": "tab",
              "label": "Tabs"
            }
          ]
        },
        {
          "key": "indentSize",
          "kind": "number",
          "label": "Indent width",
          "default": 2,
          "min": 1,
          "max": 16,
          "step": 1
        },
        {
          "key": "charset",
          "kind": "select",
          "label": "Encoding",
          "default": "utf-8",
          "choices": [
            {
              "value": "utf-8",
              "label": "UTF-8"
            },
            {
              "value": "utf-8-bom",
              "label": "UTF-8 with BOM"
            },
            {
              "value": "utf-16be",
              "label": "UTF-16 (big endian)"
            },
            {
              "value": "utf-16le",
              "label": "UTF-16 (little endian)"
            },
            {
              "value": "latin1",
              "label": "Latin-1"
            }
          ]
        },
        {
          "key": "endOfLine",
          "kind": "select",
          "label": "Line ending",
          "default": "lf",
          "choices": [
            {
              "value": "lf",
              "label": "LF (Unix / macOS)"
            },
            {
              "value": "crlf",
              "label": "CRLF (Windows)"
            }
          ]
        },
        {
          "key": "insertFinalNewline",
          "kind": "checkbox",
          "label": "Insert final newline",
          "default": true
        },
        {
          "key": "trimTrailingWhitespace",
          "kind": "checkbox",
          "label": "Trim trailing whitespace",
          "default": true
        },
        {
          "key": "maxLineLength",
          "kind": "number",
          "label": "Max line length (0 = off)",
          "default": 0,
          "min": 0,
          "max": 1000,
          "step": 10
        },
        {
          "key": "includeMakefile",
          "kind": "checkbox",
          "label": "Add Makefile section (forces tabs)",
          "default": false
        },
        {
          "key": "includeMarkdown",
          "kind": "checkbox",
          "label": "Add Markdown section (keeps trailing spaces)",
          "default": false
        }
      ],
      "keywords": [
        "create editorconfig",
        ".editorconfig file",
        "editorconfig template",
        "code style config",
        "indent style tabs or spaces",
        "end of line lf crlf",
        "trim trailing whitespace",
        "insert final newline",
        "editorconfig"
      ],
      "updated": "2026-08-01"
    },
    {
      "slug": "list-to-csv",
      "name": "List to CSV converter",
      "description": "Turn lines into a comma-separated list, or split a separated list back into lines.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/list-to-csv",
      "embed": "https://textarray.com/embed/list-to-csv",
      "mode": "transform",
      "action": "Convert list",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "linesToCsv",
          "choices": [
            {
              "value": "linesToCsv",
              "label": "Lines → separated list"
            },
            {
              "value": "csvToLines",
              "label": "Separated list → lines"
            }
          ]
        },
        {
          "key": "delimiter",
          "kind": "text",
          "label": "Delimiter",
          "default": ", "
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        },
        {
          "key": "removeEmpty",
          "kind": "checkbox",
          "label": "Remove empty items",
          "default": true
        },
        {
          "key": "quote",
          "kind": "checkbox",
          "label": "Quote items with delimiter",
          "default": false
        }
      ],
      "keywords": [
        "list to csv",
        "lines to comma separated",
        "comma separated list",
        "csv to lines",
        "convert list",
        "delimiter"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "compare-lists",
      "name": "Compare lists",
      "description": "Find items that two lists share, and items unique to each of them.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/compare-lists",
      "embed": "https://textarray.com/embed/compare-lists",
      "mode": "transform",
      "action": "Compare lists",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "List B"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "operation",
          "kind": "select",
          "label": "Operation",
          "default": "intersection",
          "choices": [
            {
              "value": "intersection",
              "label": "In both — A ∩ B"
            },
            {
              "value": "union",
              "label": "All unique — A ∪ B"
            },
            {
              "value": "onlyA",
              "label": "Only in A — A − B"
            },
            {
              "value": "onlyB",
              "label": "Only in B — B − A"
            },
            {
              "value": "symmetric",
              "label": "In one but not both"
            }
          ]
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        },
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Case-insensitive",
          "default": false
        }
      ],
      "keywords": [
        "compare lists",
        "list intersection",
        "list difference",
        "common items",
        "union",
        "set operations",
        "gemeinsame eintraege",
        "list subtractor",
        "subtract lists",
        "remove lines from list",
        "blacklist filter",
        "remove blacklisted lines",
        "exclude list b from list a"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "random-picker",
      "name": "Random picker",
      "description": "Draw one or more random entries from a list.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/random-picker",
      "embed": "https://textarray.com/embed/random-picker",
      "mode": "transform",
      "action": "Pick winners",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "How many to pick",
          "default": 1,
          "min": 1,
          "max": 1000
        },
        {
          "key": "allowRepeats",
          "kind": "checkbox",
          "label": "Allow repeats",
          "default": false
        },
        {
          "key": "numbered",
          "kind": "checkbox",
          "label": "Number the winners",
          "default": false
        }
      ],
      "keywords": [
        "random name picker",
        "giveaway winner",
        "draw from list",
        "raffle",
        "pick random",
        "lucky draw"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "reverse-list",
      "name": "Reverse list order",
      "description": "Flip the order of lines so the last one comes first.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/reverse-list",
      "embed": "https://textarray.com/embed/reverse-list",
      "mode": "transform",
      "action": "Reverse list",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "skipTrailingEmpty",
          "kind": "checkbox",
          "label": "Ignore trailing empty line",
          "default": true
        }
      ],
      "keywords": [
        "flip line order",
        "invert list",
        "last line first",
        "reverse list order",
        "list order reversal"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "combinations",
      "name": "Combination generator",
      "description": "Generate every combination of k items from a list, with or without repetition.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/combinations",
      "embed": "https://textarray.com/embed/combinations",
      "mode": "transform",
      "action": "Generate combinations",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "size",
          "kind": "number",
          "label": "Combination size (k)",
          "default": 2,
          "min": 1,
          "max": 20,
          "step": 1
        },
        {
          "key": "withRepetition",
          "kind": "checkbox",
          "label": "Allow repetition",
          "default": false
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicate items",
          "default": true
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "none",
              "label": "Nothing"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customSeparator",
          "kind": "text",
          "label": "Custom separator",
          "default": ""
        }
      ],
      "keywords": [
        "combinations",
        "generate combinations",
        "combinations calculator",
        "n choose k",
        "subsets",
        "combinations with repetition",
        "combination generator",
        "combination list",
        "combination math"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "permutation-generator",
      "name": "Permutation generator",
      "description": "List every ordering of your items — full permutations, k-permutations or letter anagrams.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/permutation-generator",
      "embed": "https://textarray.com/embed/permutation-generator",
      "mode": "transform",
      "action": "Generate permutations",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Permute",
          "default": "lines",
          "choices": [
            {
              "value": "lines",
              "label": "List items (lines)"
            },
            {
              "value": "letters",
              "label": "Letters of a word"
            }
          ]
        },
        {
          "key": "size",
          "kind": "number",
          "label": "Size k (0 = all items)",
          "default": 0,
          "min": 0,
          "max": 20,
          "step": 1
        },
        {
          "key": "withRepetition",
          "kind": "checkbox",
          "label": "With repetition",
          "default": false
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicate items",
          "default": true
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "none",
              "label": "Nothing"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customSeparator",
          "kind": "text",
          "label": "Custom separator",
          "default": ""
        }
      ],
      "keywords": [
        "generate permutations",
        "all orderings of a list",
        "k permutations",
        "anagram permutations of word",
        "letter arrangements",
        "permutacio general",
        "permutation generator",
        "permutation items"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "matrix-combinator",
      "name": "Cartesian product of lists",
      "description": "Cross every item of one list with every item of the others — all combinations, one per line.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/matrix-combinator",
      "embed": "https://textarray.com/embed/matrix-combinator",
      "mode": "transform",
      "action": "Combine lists",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "select",
          "label": "Join with",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "none",
              "label": "Nothing"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "hyphen",
              "label": "Hyphen -"
            },
            {
              "value": "slash",
              "label": "Slash /"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates within each list",
          "default": true
        }
      ],
      "keywords": [
        "cartesian product lists",
        "matrix combinator",
        "combine multiple lists",
        "cross join lists"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "line-combinations",
      "name": "Line combinations",
      "description": "Combine every line of one list with every line of another.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/line-combinations",
      "embed": "https://textarray.com/embed/line-combinations",
      "mode": "transform",
      "action": "Combine lines",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "List B"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "hyphen",
              "label": "Hyphen"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "none",
              "label": "Nothing"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customSeparator",
          "kind": "text",
          "label": "Custom separator",
          "default": ""
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicate lines",
          "default": false
        },
        {
          "key": "limit",
          "kind": "number",
          "label": "Output limit",
          "default": 10000,
          "min": 1,
          "max": 200000,
          "step": 100
        }
      ],
      "keywords": [
        "cartesian product",
        "combine two lists",
        "every line with every line",
        "list combinations",
        "cross lines"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "merge-lists",
      "name": "Merge lists",
      "description": "Combine two lists into one, with optional deduplication and sorting.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/merge-lists",
      "embed": "https://textarray.com/embed/merge-lists",
      "mode": "transform",
      "action": "Merge lists",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "List B"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Merge mode",
          "default": "append",
          "choices": [
            {
              "value": "append",
              "label": "Append B after A"
            },
            {
              "value": "interleave",
              "label": "Alternate items — A, B, A, B"
            }
          ]
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": true
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort the result",
          "default": false
        },
        {
          "key": "dropEmpty",
          "kind": "checkbox",
          "label": "Drop empty lines",
          "default": true
        }
      ],
      "keywords": [
        "join two lists",
        "interleave lists",
        "merge and dedupe",
        "merge lists"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "list-splitter",
      "name": "List splitter",
      "description": "Split a long list of lines into smaller lists by chunk size or count.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/list-splitter",
      "embed": "https://textarray.com/embed/list-splitter",
      "mode": "transform",
      "action": "Split list",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Split into",
          "default": "size",
          "choices": [
            {
              "value": "size",
              "label": "Chunks of N items"
            },
            {
              "value": "count",
              "label": "N lists"
            }
          ]
        },
        {
          "key": "n",
          "kind": "number",
          "label": "N",
          "default": 10,
          "min": 1,
          "step": 1
        },
        {
          "key": "distribution",
          "kind": "select",
          "label": "Distribution",
          "default": "sequential",
          "choices": [
            {
              "value": "sequential",
              "label": "In order"
            },
            {
              "value": "roundRobin",
              "label": "Round-robin"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Between lists",
          "default": "blank",
          "choices": [
            {
              "value": "blank",
              "label": "Blank line"
            },
            {
              "value": "header",
              "label": "Numbered header"
            }
          ]
        },
        {
          "key": "header",
          "kind": "text",
          "label": "Header text, {n} is the number",
          "default": "— Part {n} —"
        }
      ],
      "keywords": [
        "list splitter",
        "split list into chunks",
        "split list into parts",
        "divide list"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "random-team-generator",
      "name": "Random team generator",
      "description": "Split a list of names into fair random teams.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/random-team-generator",
      "embed": "https://textarray.com/embed/random-team-generator",
      "mode": "transform",
      "action": "Generate teams",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "splitBy",
          "kind": "select",
          "label": "Split by",
          "default": "teams",
          "choices": [
            {
              "value": "teams",
              "label": "Number of teams"
            },
            {
              "value": "size",
              "label": "Team size"
            }
          ]
        },
        {
          "key": "value",
          "kind": "number",
          "label": "Value",
          "default": 2,
          "min": 1,
          "max": 1000
        },
        {
          "key": "skipEmpty",
          "kind": "checkbox",
          "label": "Skip empty lines",
          "default": true
        },
        {
          "key": "numbered",
          "kind": "checkbox",
          "label": "Numbered members",
          "default": false
        }
      ],
      "keywords": [
        "random team generator",
        "random group maker",
        "team randomizer",
        "split into teams"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "matchmaker",
      "name": "Random matchmaker",
      "description": "Shuffle a list and split it into random pairs or groups, leftover handled.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/matchmaker",
      "embed": "https://textarray.com/embed/matchmaker",
      "mode": "transform",
      "action": "Make pairs",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Excluded pairs, one per line"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "size",
          "kind": "number",
          "label": "Members per group",
          "default": 2,
          "min": 2,
          "max": 20,
          "step": 1
        },
        {
          "key": "join",
          "kind": "select",
          "label": "Join with",
          "default": "vs",
          "choices": [
            {
              "value": "vs",
              "label": "vs"
            },
            {
              "value": "arrow",
              "label": "Arrow →"
            },
            {
              "value": "plus",
              "label": "Plus +"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "numbered",
          "kind": "checkbox",
          "label": "Number the lines",
          "default": true
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": true
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Draw",
          "default": "groups",
          "choices": [
            {
              "value": "groups",
              "label": "Split into groups"
            },
            {
              "value": "chain",
              "label": "Gift chain (Secret Santa)"
            }
          ]
        }
      ],
      "keywords": [
        "random pairs generator",
        "pair people randomly",
        "secret santa pairing",
        "random partner picker"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "email-validator",
      "name": "Email list validator",
      "description": "Check a list of email addresses for syntax errors and common typos.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/email-validator",
      "embed": "https://textarray.com/embed/email-validator",
      "mode": "transform",
      "action": "Validate emails",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "output",
          "kind": "select",
          "label": "Output",
          "default": "valid",
          "choices": [
            {
              "value": "valid",
              "label": "Valid only"
            },
            {
              "value": "invalid",
              "label": "Invalid only"
            },
            {
              "value": "annotated",
              "label": "All annotated"
            }
          ]
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": true
        },
        {
          "key": "lowercase",
          "kind": "checkbox",
          "label": "Convert to lowercase",
          "default": true
        }
      ],
      "keywords": [
        "validate email list",
        "check email address",
        "clean email list",
        "verify email syntax"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "duration-calculator",
      "name": "Duration calculator",
      "description": "Add up a list of durations and see the total in hours, minutes and seconds.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/duration-calculator",
      "embed": "https://textarray.com/embed/duration-calculator",
      "mode": "transform",
      "action": "Add durations",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "roundSeconds",
          "kind": "checkbox",
          "label": "Round to whole minutes",
          "default": false
        }
      ],
      "keywords": [
        "add times together",
        "sum durations",
        "time adder",
        "total hours and minutes",
        "duration calculator"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "words-to-numbers",
      "name": "Words to numbers",
      "description": "Turn spelled-out English numbers in a text into digits, keeping everything else intact.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/words-to-numbers",
      "embed": "https://textarray.com/embed/words-to-numbers",
      "mode": "transform",
      "action": "Convert to numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "ordinals",
          "kind": "checkbox",
          "label": "Convert ordinals (first → 1st)",
          "default": true
        },
        {
          "key": "thousands",
          "kind": "select",
          "label": "Thousands separator",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "comma",
              "label": "Comma (1,234)"
            },
            {
              "value": "space",
              "label": "Space (1 234)"
            }
          ]
        }
      ],
      "keywords": [
        "text to numbers",
        "spelled out numbers to digits",
        "convert words to digits",
        "twenty one to 21",
        "number word conversion"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "fraction-converter",
      "name": "Fraction converter",
      "description": "Convert between fractions, decimals and percentages, one value per line, with exact simplification.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/fraction-converter",
      "embed": "https://textarray.com/embed/fraction-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mixedNumbers",
          "kind": "checkbox",
          "label": "Show mixed numbers (7/4 → 1 3/4)",
          "default": true
        },
        {
          "key": "decimals",
          "kind": "select",
          "label": "Decimal places",
          "default": "4",
          "choices": [
            {
              "value": "2",
              "label": "2"
            },
            {
              "value": "4",
              "label": "4"
            },
            {
              "value": "6",
              "label": "6"
            },
            {
              "value": "10",
              "label": "10"
            }
          ]
        }
      ],
      "keywords": [
        "fraction to decimal",
        "decimal to fraction",
        "fraction to percent",
        "simplify fraction",
        "percentage converter"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "number-to-words",
      "name": "Number to words",
      "description": "Write numbers out in words in six languages, with an option for euro amounts.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/number-to-words",
      "embed": "https://textarray.com/embed/number-to-words",
      "mode": "transform",
      "action": "Spell out",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "currency",
          "kind": "checkbox",
          "label": "Spell as EUR amount with cents",
          "default": false
        },
        {
          "key": "capitalize",
          "kind": "checkbox",
          "label": "Capitalize first letter",
          "default": false
        }
      ],
      "keywords": [
        "spell out numbers",
        "number spelling",
        "amount in words",
        "euro amount in words"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "number-sequence",
      "name": "Number sequence generator",
      "description": "Generate a list of numbers from a start to an end value with any step.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/number-sequence",
      "embed": "https://textarray.com/embed/number-sequence",
      "mode": "generate",
      "action": "Generate sequence",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "start",
          "kind": "number",
          "label": "Start",
          "default": 1
        },
        {
          "key": "end",
          "kind": "number",
          "label": "End",
          "default": 100
        },
        {
          "key": "step",
          "kind": "number",
          "label": "Step or ratio",
          "default": 1
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Sequence",
          "default": "arithmetic",
          "choices": [
            {
              "value": "arithmetic",
              "label": "Arithmetic (adds)"
            },
            {
              "value": "geometric",
              "label": "Geometric (multiplies)"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "newline",
          "choices": [
            {
              "value": "newline",
              "label": "New line"
            },
            {
              "value": "comma",
              "label": "Comma"
            }
          ]
        },
        {
          "key": "prefix",
          "kind": "text",
          "label": "Prefix",
          "default": ""
        },
        {
          "key": "suffix",
          "kind": "text",
          "label": "Suffix",
          "default": ""
        },
        {
          "key": "pad",
          "kind": "number",
          "label": "Zero-pad to digits",
          "default": 0,
          "min": 0,
          "max": 12
        },
        {
          "key": "repeat",
          "kind": "number",
          "label": "Repeat each number",
          "default": 1,
          "min": 1,
          "max": 1000
        }
      ],
      "keywords": [
        "number range generator",
        "generate numbers",
        "number list generator",
        "arithmetic sequence"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "roman-numerals",
      "name": "Roman numeral converter",
      "description": "Convert numbers to Roman numerals and Roman numerals back to numbers, one per line.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/roman-numerals",
      "embed": "https://textarray.com/embed/roman-numerals",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect automatically"
            },
            {
              "value": "to-roman",
              "label": "Number → Roman"
            },
            {
              "value": "to-arabic",
              "label": "Roman → number"
            }
          ]
        },
        {
          "key": "lowercase",
          "kind": "checkbox",
          "label": "Lowercase Roman numerals",
          "default": false
        }
      ],
      "keywords": [
        "arabic to roman",
        "roman to arabic",
        "number to roman numerals",
        "convert roman numerals"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "number-stats",
      "name": "Sum and number statistics",
      "description": "Add up a list of numbers and get the mean, median, min, max and standard deviation.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/number-stats",
      "embed": "https://textarray.com/embed/number-stats",
      "mode": "transform",
      "action": "Calculate stats",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect automatically"
            },
            {
              "value": "newline",
              "label": "One per line"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "space",
              "label": "Space"
            }
          ]
        },
        {
          "key": "decimal",
          "kind": "select",
          "label": "Decimal separator",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect automatically"
            },
            {
              "value": "dot",
              "label": "Point — 3.14"
            },
            {
              "value": "comma",
              "label": "Comma — 3,14"
            }
          ]
        },
        {
          "key": "extract",
          "kind": "checkbox",
          "label": "Extract numbers from text",
          "default": false
        },
        {
          "key": "skipNonNumeric",
          "kind": "checkbox",
          "label": "Skip non-numeric values",
          "default": true
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 4,
          "min": 0,
          "max": 10,
          "step": 1
        },
        {
          "key": "deviation",
          "kind": "select",
          "label": "Standard deviation",
          "default": "population",
          "choices": [
            {
              "value": "population",
              "label": "Population (÷ n)"
            },
            {
              "value": "sample",
              "label": "Sample (÷ n−1)"
            }
          ]
        }
      ],
      "keywords": [
        "number stats",
        "sum numbers",
        "sum of numbers",
        "average calculator",
        "mean median"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "credit-card-validator",
      "name": "Credit card number checker",
      "description": "Check card numbers against the Luhn checksum and detect the scheme — a developer tool for test numbers, not a card verifier.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/credit-card-validator",
      "embed": "https://textarray.com/embed/credit-card-validator",
      "mode": "transform",
      "action": "Check numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "show",
          "kind": "select",
          "label": "Show",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All lines with result"
            },
            {
              "value": "valid",
              "label": "Only valid numbers"
            },
            {
              "value": "invalid",
              "label": "Only failing lines"
            }
          ]
        },
        {
          "key": "detectScheme",
          "kind": "checkbox",
          "label": "Detect card scheme",
          "default": true
        }
      ],
      "keywords": [
        "credit card validator",
        "card number checker",
        "test credit card numbers",
        "card scheme detector",
        "luhn checksum",
        "luhn check"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "byte-unit-converter",
      "name": "Byte unit converter",
      "description": "Convert data sizes between B, KB, MB, GB and TB in decimal or binary units.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/byte-unit-converter",
      "embed": "https://textarray.com/embed/byte-unit-converter",
      "mode": "transform",
      "action": "Convert units",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "standard",
          "kind": "select",
          "label": "Unit standard",
          "default": "binary",
          "choices": [
            {
              "value": "binary",
              "label": "Binary — 1 KB = 1024 B"
            },
            {
              "value": "decimal",
              "label": "Decimal — 1 kB = 1000 B"
            }
          ]
        },
        {
          "key": "target",
          "kind": "select",
          "label": "Convert to",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All units"
            },
            {
              "value": "b",
              "label": "Bytes (B)"
            },
            {
              "value": "k",
              "label": "Kilobytes (kB / KiB)"
            },
            {
              "value": "m",
              "label": "Megabytes (MB / MiB)"
            },
            {
              "value": "g",
              "label": "Gigabytes (GB / GiB)"
            },
            {
              "value": "t",
              "label": "Terabytes (TB / TiB)"
            }
          ]
        },
        {
          "key": "precision",
          "kind": "number",
          "label": "Decimal places",
          "default": 2,
          "min": 0,
          "max": 12,
          "step": 1
        }
      ],
      "keywords": [
        "byte converter",
        "byte unit converter",
        "kb to mb",
        "mb to gb",
        "file size converter"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "percentage-calculator",
      "name": "Percentage calculator",
      "description": "Work out X % of Y, percentage share, percentage change and discounted prices, with the formula shown.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/percentage-calculator",
      "embed": "https://textarray.com/embed/percentage-calculator",
      "mode": "generate",
      "action": "Calculate",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Calculation",
          "default": "percent-of",
          "choices": [
            {
              "value": "percent-of",
              "label": "X % of Y"
            },
            {
              "value": "what-percent",
              "label": "X is what % of Y"
            },
            {
              "value": "change",
              "label": "Change from X to Y"
            },
            {
              "value": "discount",
              "label": "Y after X % discount"
            }
          ]
        },
        {
          "key": "x",
          "kind": "number",
          "label": "X",
          "default": 20,
          "step": 0.01
        },
        {
          "key": "y",
          "kind": "number",
          "label": "Y",
          "default": 150,
          "step": 0.01
        }
      ],
      "keywords": [
        "percent calculator",
        "percent of a number",
        "percentage change",
        "percentage increase decrease"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "temperature-converter",
      "name": "Temperature converter",
      "description": "Convert temperatures between Celsius, Fahrenheit and Kelvin, one value per line.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/temperature-converter",
      "embed": "https://textarray.com/embed/temperature-converter",
      "mode": "transform",
      "action": "Convert temperatures",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "from",
          "kind": "select",
          "label": "From",
          "default": "c",
          "choices": [
            {
              "value": "c",
              "label": "Celsius (°C)"
            },
            {
              "value": "f",
              "label": "Fahrenheit (°F)"
            },
            {
              "value": "k",
              "label": "Kelvin (K)"
            }
          ]
        },
        {
          "key": "to",
          "kind": "select",
          "label": "To",
          "default": "f",
          "choices": [
            {
              "value": "f",
              "label": "Fahrenheit (°F)"
            },
            {
              "value": "c",
              "label": "Celsius (°C)"
            },
            {
              "value": "k",
              "label": "Kelvin (K)"
            },
            {
              "value": "all",
              "label": "All units"
            }
          ]
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimals",
          "default": 2,
          "min": 0,
          "max": 6,
          "step": 1
        }
      ],
      "keywords": [
        "celsius to fahrenheit",
        "fahrenheit to celsius",
        "kelvin converter",
        "temperature conversion"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "base-converter",
      "name": "Number base converter",
      "description": "Convert numbers between any bases from binary to base 36, one per line.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/base-converter",
      "embed": "https://textarray.com/embed/base-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "fromBase",
          "kind": "number",
          "label": "From base",
          "default": 10,
          "min": 2,
          "max": 36,
          "step": 1
        },
        {
          "key": "toBase",
          "kind": "number",
          "label": "To base",
          "default": 16,
          "min": 2,
          "max": 36,
          "step": 1
        },
        {
          "key": "allBases",
          "kind": "checkbox",
          "label": "Show all common bases",
          "default": false
        },
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase digits",
          "default": false
        },
        {
          "key": "prefix",
          "kind": "select",
          "label": "Prefix",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "code",
              "label": "0x style — 0b/0o/0x"
            }
          ]
        },
        {
          "key": "padTo",
          "kind": "number",
          "label": "Pad to width (0 = off)",
          "default": 0,
          "min": 0,
          "max": 512,
          "step": 1
        }
      ],
      "keywords": [
        "number base converter",
        "radix converter",
        "decimal to hex",
        "hex to decimal",
        "binary to decimal",
        "decimal to binary"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "iban-validator",
      "name": "IBAN validator",
      "description": "Check IBANs against the official country lengths and the mod-97 checksum — catches typos before a payment, entirely in your browser.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/iban-validator",
      "embed": "https://textarray.com/embed/iban-validator",
      "mode": "transform",
      "action": "Check IBANs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "show",
          "kind": "select",
          "label": "Output",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All lines annotated"
            },
            {
              "value": "valid",
              "label": "Valid only"
            },
            {
              "value": "invalid",
              "label": "Invalid only"
            }
          ]
        },
        {
          "key": "group",
          "kind": "checkbox",
          "label": "Format in groups of 4",
          "default": true
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": false
        }
      ],
      "keywords": [
        "check iban",
        "validate iban online",
        "validator iban",
        "iban validation",
        "bank account validator"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "gcd-lcm-calculator",
      "name": "GCD and LCM calculator",
      "description": "Find the greatest common divisor and least common multiple of two or more integers.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/gcd-lcm-calculator",
      "embed": "https://textarray.com/embed/gcd-lcm-calculator",
      "mode": "transform",
      "action": "Calculate GCD and LCM",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "factorizations",
          "kind": "checkbox",
          "label": "Show prime factorizations",
          "default": true
        },
        {
          "key": "divisors",
          "kind": "checkbox",
          "label": "Show divisors of the GCD",
          "default": false
        }
      ],
      "keywords": [
        "least common multiple",
        "gcd calculator",
        "lcm calculator",
        "prime factorization",
        "nsd nsn",
        "najvacsi spolocny delitel",
        "nwd nww"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "date-difference",
      "name": "Date difference calculator",
      "description": "Count the days, weeks, months and years between two dates, with weekdays and weekends.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/date-difference",
      "embed": "https://textarray.com/embed/date-difference",
      "mode": "generate",
      "action": "Calculate difference",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "from",
          "kind": "text",
          "label": "From date (YYYY-MM-DD)",
          "default": "2026-01-01"
        },
        {
          "key": "to",
          "kind": "text",
          "label": "To date (YYYY-MM-DD)",
          "default": "2026-12-31"
        },
        {
          "key": "includeEnd",
          "kind": "checkbox",
          "label": "Include the end date",
          "default": false
        }
      ],
      "keywords": [
        "date duration",
        "how many days until",
        "weeks between dates",
        "date difference calculator"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "prime-checker",
      "name": "Prime number checker",
      "description": "Check whether numbers are prime, see their prime factorization and the next prime.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/prime-checker",
      "embed": "https://textarray.com/embed/prime-checker",
      "mode": "transform",
      "action": "Check primes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "factorization",
          "kind": "checkbox",
          "label": "Factorization",
          "default": true
        },
        {
          "key": "showNext",
          "kind": "checkbox",
          "label": "Show next prime",
          "default": false
        }
      ],
      "keywords": [
        "is it prime",
        "prime number test",
        "factorize number",
        "next prime"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "sort-numbers",
      "name": "Sort numbers",
      "description": "Sort a list of numbers by numeric value, so 2 comes before 10, not after it.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/sort-numbers",
      "embed": "https://textarray.com/embed/sort-numbers",
      "mode": "transform",
      "action": "Sort numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "order",
          "kind": "select",
          "label": "Order",
          "default": "asc",
          "choices": [
            {
              "value": "asc",
              "label": "Ascending"
            },
            {
              "value": "desc",
              "label": "Descending"
            }
          ]
        },
        {
          "key": "unique",
          "kind": "checkbox",
          "label": "Remove duplicate values",
          "default": false
        }
      ],
      "keywords": [
        "sort numbers",
        "number sorter",
        "sort numbers numerically",
        "ascending descending numbers",
        "order numbers",
        "sort list of numbers"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "bitwise-calculator",
      "name": "Bitwise calculator",
      "description": "Run AND, OR, XOR, NOT and bit shifts on two numbers and see the result bit by bit.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/bitwise-calculator",
      "embed": "https://textarray.com/embed/bitwise-calculator",
      "mode": "transform",
      "action": "Calculate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "op",
          "kind": "select",
          "label": "Operation",
          "default": "and",
          "choices": [
            {
              "value": "and",
              "label": "AND (&)"
            },
            {
              "value": "or",
              "label": "OR (|)"
            },
            {
              "value": "xor",
              "label": "XOR (^)"
            },
            {
              "value": "not",
              "label": "NOT (~)"
            },
            {
              "value": "shl",
              "label": "Shift left (<<)"
            },
            {
              "value": "shr",
              "label": "Shift right (>>)"
            }
          ]
        },
        {
          "key": "inputBase",
          "kind": "select",
          "label": "Input base",
          "default": "10",
          "choices": [
            {
              "value": "2",
              "label": "Binary (base 2)"
            },
            {
              "value": "8",
              "label": "Octal (base 8)"
            },
            {
              "value": "10",
              "label": "Decimal (base 10)"
            },
            {
              "value": "16",
              "label": "Hexadecimal (base 16)"
            }
          ]
        },
        {
          "key": "outputBase",
          "kind": "select",
          "label": "Output base",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "Binary (base 2)"
            },
            {
              "value": "8",
              "label": "Octal (base 8)"
            },
            {
              "value": "10",
              "label": "Decimal (base 10)"
            },
            {
              "value": "16",
              "label": "Hexadecimal (base 16)"
            }
          ]
        },
        {
          "key": "width",
          "kind": "select",
          "label": "Bit width",
          "default": "8",
          "choices": [
            {
              "value": "8",
              "label": "8-bit"
            },
            {
              "value": "16",
              "label": "16-bit"
            },
            {
              "value": "32",
              "label": "32-bit"
            },
            {
              "value": "64",
              "label": "64-bit"
            }
          ]
        },
        {
          "key": "signed",
          "kind": "checkbox",
          "label": "Signed (two's complement)",
          "default": true
        },
        {
          "key": "arithmeticShift",
          "kind": "checkbox",
          "label": "Arithmetic right shift",
          "default": false
        },
        {
          "key": "showAlignment",
          "kind": "checkbox",
          "label": "Show operands aligned bit by bit",
          "default": true
        }
      ],
      "keywords": [
        "bitwise calculator",
        "bitwise operations calculator",
        "AND OR XOR calculator",
        "bit shift calculator",
        "binary AND OR XOR NOT",
        "shift left shift right calculator",
        "two's complement calculator",
        "bit width calculator",
        "binary",
        "hex",
        "octal"
      ],
      "updated": "2026-08-05"
    },
    {
      "slug": "excel-column-converter",
      "name": "Excel column converter",
      "description": "Convert a spreadsheet column number to its letter, or a column letter back to its number.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/excel-column-converter",
      "embed": "https://textarray.com/embed/excel-column-converter",
      "mode": "transform",
      "action": "Convert columns",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "toLetter",
          "choices": [
            {
              "value": "toLetter",
              "label": "Number → letter"
            },
            {
              "value": "toNumber",
              "label": "Letter → number"
            }
          ]
        },
        {
          "key": "row",
          "kind": "number",
          "label": "Row number for full cell address (0 = off)",
          "default": 0,
          "min": 0,
          "step": 1
        },
        {
          "key": "notation",
          "kind": "select",
          "label": "Address notation",
          "default": "a1",
          "choices": [
            {
              "value": "a1",
              "label": "A1"
            },
            {
              "value": "r1c1",
              "label": "R1C1"
            }
          ]
        }
      ],
      "keywords": [
        "excel column converter",
        "column letter to number",
        "number to column letter",
        "spreadsheet column converter",
        "excel column number",
        "column index converter",
        "a1 notation",
        "r1c1 notation",
        "google sheets column converter"
      ],
      "updated": "2026-08-05"
    },
    {
      "slug": "business-days-calculator",
      "name": "Business days calculator",
      "description": "Count business days between two dates, or add business days to a date, skipping weekends and holidays.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/business-days-calculator",
      "embed": "https://textarray.com/embed/business-days-calculator",
      "mode": "transform",
      "action": "Calculate business days",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "difference",
          "choices": [
            {
              "value": "difference",
              "label": "Difference between dates"
            },
            {
              "value": "add",
              "label": "Add business days to a date"
            }
          ]
        },
        {
          "key": "weekend",
          "kind": "select",
          "label": "Weekend days",
          "default": "satSun",
          "choices": [
            {
              "value": "satSun",
              "label": "Saturday + Sunday"
            },
            {
              "value": "friSat",
              "label": "Friday + Saturday"
            },
            {
              "value": "sunOnly",
              "label": "Sunday only"
            },
            {
              "value": "none",
              "label": "No weekend"
            }
          ]
        },
        {
          "key": "days",
          "kind": "number",
          "label": "Business days to add",
          "default": 10,
          "min": -3650,
          "max": 3650,
          "step": 1
        },
        {
          "key": "includeStart",
          "kind": "checkbox",
          "label": "Count the start date",
          "default": true
        },
        {
          "key": "includeEnd",
          "kind": "checkbox",
          "label": "Count the end date",
          "default": true
        },
        {
          "key": "showCalendarDays",
          "kind": "checkbox",
          "label": "Show calendar days too",
          "default": true
        }
      ],
      "keywords": [
        "business days calculator",
        "working days calculator",
        "count business days",
        "add business days",
        "workdays between two dates",
        "networkdays",
        "exclude weekends and holidays",
        "business days between dates"
      ],
      "updated": "2026-08-05"
    },
    {
      "slug": "week-number-calculator",
      "name": "Week number calculator",
      "description": "Get the ISO 8601 week number for any date, or the dates spanning a given week.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/week-number-calculator",
      "embed": "https://textarray.com/embed/week-number-calculator",
      "mode": "transform",
      "action": "Calculate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "dateToWeek",
          "choices": [
            {
              "value": "dateToWeek",
              "label": "Date → week number"
            },
            {
              "value": "weekToDate",
              "label": "Week number → date"
            }
          ]
        },
        {
          "key": "standard",
          "kind": "select",
          "label": "Numbering standard",
          "default": "iso",
          "choices": [
            {
              "value": "iso",
              "label": "ISO 8601 (Monday-start)"
            },
            {
              "value": "sunday",
              "label": "Sunday-start week"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output date format",
          "default": "iso",
          "choices": [
            {
              "value": "iso",
              "label": "ISO (2026-08-05)"
            },
            {
              "value": "eu",
              "label": "EU (05.08.2026)"
            },
            {
              "value": "long",
              "label": "Long (August 5, 2026)"
            }
          ]
        }
      ],
      "keywords": [
        "week number calculator",
        "iso week number",
        "what week is it",
        "week of the year",
        "week to date",
        "day of year calculator",
        "iso 8601 week",
        "week number lookup"
      ],
      "updated": "2026-08-05"
    },
    {
      "slug": "css-formatter",
      "name": "CSS formatter",
      "description": "Beautify minified or messy CSS into clean, indented, readable rules.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-formatter",
      "embed": "https://textarray.com/embed/css-formatter",
      "mode": "transform",
      "action": "Format CSS",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "selectorPerLine",
          "kind": "checkbox",
          "label": "One selector per line",
          "default": false
        },
        {
          "key": "blankBetweenRules",
          "kind": "checkbox",
          "label": "Blank line between rules",
          "default": true
        }
      ],
      "keywords": [
        "css formatter",
        "format css",
        "css beautifier",
        "beautify css",
        "css pretty print",
        "unminify css",
        "css indent",
        "expand css"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "css-gradient-generator",
      "name": "CSS gradient generator",
      "description": "Generate CSS linear and radial gradient declarations with custom colors and angles.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-gradient-generator",
      "embed": "https://textarray.com/embed/css-gradient-generator",
      "mode": "generate",
      "action": "Generate",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "type",
          "kind": "select",
          "label": "Gradient type",
          "default": "linear",
          "choices": [
            {
              "value": "linear",
              "label": "Linear"
            },
            {
              "value": "radial",
              "label": "Radial"
            }
          ]
        },
        {
          "key": "angle",
          "kind": "number",
          "label": "Angle (degrees)",
          "default": 90,
          "min": 0,
          "max": 360
        },
        {
          "key": "color1",
          "kind": "text",
          "label": "Color 1",
          "default": "#7A1F2B"
        },
        {
          "key": "color2",
          "kind": "text",
          "label": "Color 2",
          "default": "#C4576A"
        }
      ],
      "keywords": [
        "gradient generator",
        "css color",
        "gradient builder",
        "css background"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "sort-json",
      "name": "Sort JSON",
      "description": "Sort the keys of a JSON object alphabetically, recursively and consistently.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sort-json",
      "embed": "https://textarray.com/embed/sort-json",
      "mode": "transform",
      "action": "Sort JSON",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "order",
          "kind": "select",
          "label": "Order",
          "default": "asc",
          "choices": [
            {
              "value": "asc",
              "label": "A to Z"
            },
            {
              "value": "desc",
              "label": "Z to A"
            }
          ]
        },
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "minified",
              "label": "Minified"
            }
          ]
        },
        {
          "key": "sortArrays",
          "kind": "checkbox",
          "label": "Sort primitive arrays",
          "default": false
        }
      ],
      "keywords": [
        "sort json",
        "json sort keys",
        "sort json keys",
        "alphabetize json",
        "order json keys",
        "json key sorter",
        "json sorter"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "uuid-decoder",
      "name": "UUID decoder",
      "description": "Decode a UUID to reveal its version, variant and embedded timestamp.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/uuid-decoder",
      "embed": "https://textarray.com/embed/uuid-decoder",
      "mode": "transform",
      "action": "Decode UUID",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "showBits",
          "kind": "checkbox",
          "label": "Show raw fields",
          "default": false
        }
      ],
      "keywords": [
        "uuid decoder",
        "uuid version",
        "uuid variant",
        "uuid timestamp",
        "decode uuid",
        "inspect guid",
        "uuid v1 v4 v7"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "meta-tag-generator",
      "name": "Meta tag generator",
      "description": "Generate the HTML title, description, canonical, Open Graph and Twitter card tags for a page.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/meta-tag-generator",
      "embed": "https://textarray.com/embed/meta-tag-generator",
      "mode": "generate",
      "action": "Generate meta tags",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "title",
          "kind": "text",
          "label": "Title",
          "default": ""
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "url",
          "kind": "text",
          "label": "Canonical URL",
          "default": ""
        },
        {
          "key": "image",
          "kind": "text",
          "label": "Image URL",
          "default": ""
        },
        {
          "key": "siteName",
          "kind": "text",
          "label": "Site name",
          "default": ""
        },
        {
          "key": "ogType",
          "kind": "select",
          "label": "Open Graph type",
          "default": "website",
          "choices": [
            {
              "value": "website",
              "label": "Website"
            },
            {
              "value": "article",
              "label": "Article"
            },
            {
              "value": "product",
              "label": "Product"
            },
            {
              "value": "profile",
              "label": "Profile"
            }
          ]
        },
        {
          "key": "twitterCard",
          "kind": "select",
          "label": "Twitter card",
          "default": "summary_large_image",
          "choices": [
            {
              "value": "summary_large_image",
              "label": "Summary with large image"
            },
            {
              "value": "summary",
              "label": "Summary"
            }
          ]
        },
        {
          "key": "includeOg",
          "kind": "checkbox",
          "label": "Include Open Graph tags",
          "default": true
        },
        {
          "key": "includeTwitter",
          "kind": "checkbox",
          "label": "Include Twitter card tags",
          "default": true
        }
      ],
      "keywords": [
        "meta tag generator",
        "meta tags",
        "open graph generator",
        "og tags",
        "twitter card generator",
        "seo meta tags",
        "html head tags",
        "canonical tag",
        "open graph tags"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "svg-url-encoder",
      "name": "SVG URL encoder",
      "description": "Convert SVG markup into a CSS-ready data URI and decode data URIs back to SVG.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/svg-url-encoder",
      "embed": "https://textarray.com/embed/svg-url-encoder",
      "mode": "transform",
      "action": "Convert SVG",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode SVG"
            },
            {
              "value": "decode",
              "label": "Decode data URI"
            }
          ]
        },
        {
          "key": "output",
          "kind": "select",
          "label": "Output format",
          "default": "css",
          "choices": [
            {
              "value": "css",
              "label": "CSS rule"
            },
            {
              "value": "uri",
              "label": "Data URI"
            },
            {
              "value": "img",
              "label": "HTML <img> tag"
            },
            {
              "value": "link",
              "label": "HTML <link> tag"
            }
          ]
        },
        {
          "key": "mime",
          "kind": "select",
          "label": "MIME type",
          "default": "image/svg+xml",
          "choices": [
            {
              "value": "image/svg+xml",
              "label": "image/svg+xml"
            },
            {
              "value": "text/plain",
              "label": "text/plain"
            },
            {
              "value": "text/html",
              "label": "text/html"
            },
            {
              "value": "text/css",
              "label": "text/css"
            },
            {
              "value": "text/javascript",
              "label": "text/javascript"
            },
            {
              "value": "application/json",
              "label": "application/json"
            },
            {
              "value": "application/xml",
              "label": "application/xml"
            },
            {
              "value": "text/csv",
              "label": "text/csv"
            },
            {
              "value": "text/markdown",
              "label": "text/markdown"
            }
          ]
        },
        {
          "key": "encoding",
          "kind": "select",
          "label": "Encoding",
          "default": "percent",
          "choices": [
            {
              "value": "percent",
              "label": "Percent-encoded"
            },
            {
              "value": "base64",
              "label": "Base64"
            }
          ]
        },
        {
          "key": "charset",
          "kind": "select",
          "label": "Charset",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Not declared"
            },
            {
              "value": "utf-8",
              "label": "UTF-8"
            },
            {
              "value": "us-ascii",
              "label": "US-ASCII"
            },
            {
              "value": "iso-8859-1",
              "label": "ISO-8859-1"
            }
          ]
        }
      ],
      "keywords": [
        "svg url encoder",
        "svg to data uri",
        "svg data url",
        "encode svg css",
        "svg background image",
        "svg to base64",
        "svg url encode",
        "svg in css"
      ],
      "updated": "2026-08-24"
    },
    {
      "slug": "email-extractor",
      "name": "Email extractor",
      "description": "Pull every email address out of a block of text and get a clean list.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/email-extractor",
      "embed": "https://textarray.com/embed/email-extractor",
      "mode": "transform",
      "action": "Extract emails",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": true
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort alphabetically",
          "default": false
        },
        {
          "key": "lowercase",
          "kind": "checkbox",
          "label": "Convert to lowercase",
          "default": true
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "newline",
          "choices": [
            {
              "value": "newline",
              "label": "One per line"
            },
            {
              "value": "comma",
              "label": "Comma-separated"
            }
          ]
        }
      ],
      "keywords": [
        "email extractor",
        "extract emails",
        "find email addresses",
        "email scraper",
        "email list",
        "regex extractor"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "slug-generator",
      "name": "Slug generator",
      "description": "Turn titles into clean URL slugs without diacritics or punctuation.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/slug-generator",
      "embed": "https://textarray.com/embed/slug-generator",
      "mode": "transform",
      "action": "Generate slugs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "-",
          "choices": [
            {
              "value": "-",
              "label": "Hyphen -"
            },
            {
              "value": "_",
              "label": "Underscore _"
            }
          ]
        },
        {
          "key": "lowercase",
          "kind": "checkbox",
          "label": "Convert to lowercase",
          "default": true
        },
        {
          "key": "maxLength",
          "kind": "number",
          "label": "Max length (0 = unlimited)",
          "default": 0,
          "min": 0,
          "max": 500
        }
      ],
      "keywords": [
        "permalink",
        "seo url",
        "slugify",
        "url slug generator",
        "slug from title"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "qr-code-generator",
      "name": "QR code generator",
      "description": "Turn a URL or any text into a QR code you can download as SVG.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/qr-code-generator",
      "embed": "https://textarray.com/embed/qr-code-generator",
      "mode": "transform",
      "action": "Generate QR code",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "qr",
      "options": [
        {
          "key": "ecLevel",
          "kind": "select",
          "label": "Error correction",
          "default": "M",
          "choices": [
            {
              "value": "L",
              "label": "L — 7% recovery"
            },
            {
              "value": "M",
              "label": "M — 15%"
            },
            {
              "value": "Q",
              "label": "Q — 25%"
            },
            {
              "value": "H",
              "label": "H — 30%"
            }
          ]
        },
        {
          "key": "margin",
          "kind": "number",
          "label": "Margin",
          "default": 2,
          "min": 0,
          "max": 8
        },
        {
          "key": "foreground",
          "kind": "text",
          "label": "Module colour",
          "default": "#000000"
        },
        {
          "key": "background",
          "kind": "text",
          "label": "Background colour",
          "default": "#ffffff"
        }
      ],
      "keywords": [
        "qr code generator",
        "generate qr",
        "url to qr",
        "wifi qr code"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "hash-generator",
      "name": "Hash generator",
      "description": "Generate MD5, SHA-1, SHA-256, SHA-384 or SHA-512 digests from any text.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/hash-generator",
      "embed": "https://textarray.com/embed/hash-generator",
      "mode": "transform",
      "action": "Generate hash",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "algorithm",
          "kind": "select",
          "label": "Algorithm",
          "default": "SHA-256",
          "choices": [
            {
              "value": "MD5",
              "label": "MD5"
            },
            {
              "value": "SHA-1",
              "label": "SHA-1"
            },
            {
              "value": "SHA-256",
              "label": "SHA-256"
            },
            {
              "value": "SHA-384",
              "label": "SHA-384"
            },
            {
              "value": "SHA-512",
              "label": "SHA-512"
            }
          ]
        },
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase hex",
          "default": false
        },
        {
          "key": "perLine",
          "kind": "checkbox",
          "label": "Hash each line",
          "default": false
        }
      ],
      "keywords": [
        "md5",
        "sha1",
        "sha256",
        "sha512",
        "checksum",
        "message digest"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "color-converter",
      "name": "Color converter",
      "description": "Convert colors between HEX, RGB and HSL, with alpha and a tint palette.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/color-converter",
      "embed": "https://textarray.com/embed/color-converter",
      "mode": "transform",
      "action": "Convert color",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All formats"
            },
            {
              "value": "hex",
              "label": "HEX"
            },
            {
              "value": "rgb",
              "label": "RGB"
            },
            {
              "value": "hsl",
              "label": "HSL"
            },
            {
              "value": "cmyk",
              "label": "CMYK"
            },
            {
              "value": "hsv",
              "label": "HSV"
            },
            {
              "value": "hwb",
              "label": "HWB"
            },
            {
              "value": "lab",
              "label": "LAB"
            },
            {
              "value": "lch",
              "label": "LCH"
            },
            {
              "value": "oklab",
              "label": "OKLAB"
            },
            {
              "value": "oklch",
              "label": "OKLCH"
            }
          ]
        },
        {
          "key": "syntax",
          "kind": "select",
          "label": "CSS syntax",
          "default": "legacy",
          "choices": [
            {
              "value": "legacy",
              "label": "Commas — rgb(255, 0, 0)"
            },
            {
              "value": "modern",
              "label": "Spaces — rgb(255 0 0)"
            }
          ]
        },
        {
          "key": "alpha",
          "kind": "checkbox",
          "label": "Keep alpha channel",
          "default": true
        },
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase hex",
          "default": false
        },
        {
          "key": "palette",
          "kind": "checkbox",
          "label": "Add tint palette",
          "default": false
        },
        {
          "key": "paletteSteps",
          "kind": "range",
          "label": "Palette steps",
          "default": 4,
          "min": 1,
          "max": 8
        },
        {
          "key": "paletteOutput",
          "kind": "select",
          "label": "Palette output",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table of steps"
            },
            {
              "value": "css",
              "label": "CSS variables (50–950)"
            },
            {
              "value": "tailwind",
              "label": "Tailwind config (50–950)"
            }
          ]
        },
        {
          "key": "scaleName",
          "kind": "text",
          "label": "Scale name",
          "default": "brand"
        }
      ],
      "keywords": [
        "tailwind color scale generator",
        "css variables color palette",
        "shade scale 50 950",
        "design tokens from hex",
        "color converter",
        "colour converter",
        "hex to rgb",
        "rgb to hex",
        "hex to hsl",
        "rgb to hsl",
        "css color",
        "8 digit hex",
        "rgba",
        "hsla"
      ],
      "updated": "2026-08-25"
    },
    {
      "slug": "csv-delimiter",
      "name": "Change CSV delimiter",
      "description": "Swap the column separator in CSV data between comma, semicolon, tab and pipe.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/csv-delimiter",
      "embed": "https://textarray.com/embed/csv-delimiter",
      "mode": "transform",
      "action": "Change delimiter",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "from",
          "kind": "select",
          "label": "Input delimiter",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "fromCustom",
          "kind": "text",
          "label": "Custom input delimiter",
          "default": ""
        },
        {
          "key": "to",
          "kind": "select",
          "label": "Output delimiter",
          "default": "semicolon",
          "choices": [
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "toCustom",
          "kind": "text",
          "label": "Custom output delimiter",
          "default": ""
        },
        {
          "key": "quotes",
          "kind": "checkbox",
          "label": "Handle quoted CSV fields",
          "default": true
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": false
        }
      ],
      "keywords": [
        "csv delimiter",
        "change csv delimiter",
        "csv separator converter",
        "comma to semicolon",
        "semicolon to comma",
        "csv to tsv",
        "tab delimited",
        "csv bodkociarka excel",
        "csv strednik excel",
        "csv srednik excel"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "csv-to-json",
      "name": "CSV ⇄ JSON converter",
      "description": "Convert CSV data to JSON and back, or turn it into a Markdown or HTML table.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/csv-to-json",
      "embed": "https://textarray.com/embed/csv-to-json",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "csvToJson",
          "choices": [
            {
              "value": "csvToJson",
              "label": "CSV → JSON"
            },
            {
              "value": "jsonToCsv",
              "label": "JSON → CSV"
            },
            {
              "value": "csvToMarkdown",
              "label": "CSV → Markdown"
            },
            {
              "value": "csvToHtml",
              "label": "CSV → HTML"
            }
          ]
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect automatically"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        },
        {
          "key": "header",
          "kind": "checkbox",
          "label": "First row is headers",
          "default": true
        },
        {
          "key": "prettify",
          "kind": "checkbox",
          "label": "Prettify JSON",
          "default": true
        },
        {
          "key": "quoteAll",
          "kind": "checkbox",
          "label": "Quote all fields",
          "default": false
        }
      ],
      "keywords": [
        "csv to json",
        "json to csv",
        "csv json converter",
        "csv to markdown table",
        "csv to html table",
        "convert csv to json online"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "yaml-to-json",
      "name": "YAML ⇄ JSON converter",
      "description": "Convert YAML to JSON and back — Kubernetes manifests, CI configs, OpenAPI specs.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/yaml-to-json",
      "embed": "https://textarray.com/embed/yaml-to-json",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "yaml-to-json",
          "choices": [
            {
              "value": "yaml-to-json",
              "label": "YAML → JSON"
            },
            {
              "value": "json-to-yaml",
              "label": "JSON → YAML"
            }
          ]
        },
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "minified",
              "label": "Minified (JSON only)"
            }
          ]
        }
      ],
      "keywords": [
        "yaml to json",
        "json to yaml",
        "yaml json converter",
        "convert yaml to json online",
        "kubernetes yaml to json",
        "docker compose to json"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "ics-generator",
      "name": "ICS generator",
      "description": "Build a calendar event and get the .ics text to import anywhere.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ics-generator",
      "embed": "https://textarray.com/embed/ics-generator",
      "mode": "generate",
      "action": "Generate .ics",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "title",
          "kind": "text",
          "label": "Title",
          "default": "Team sync"
        },
        {
          "key": "start",
          "kind": "text",
          "label": "Start",
          "default": ""
        },
        {
          "key": "end",
          "kind": "text",
          "label": "End",
          "default": ""
        },
        {
          "key": "allDay",
          "kind": "checkbox",
          "label": "All-day",
          "default": false
        },
        {
          "key": "location",
          "kind": "text",
          "label": "Location",
          "default": ""
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "recurrence",
          "kind": "select",
          "label": "Repeat",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "No repeat"
            },
            {
              "value": "daily",
              "label": "Daily"
            },
            {
              "value": "weekly",
              "label": "Weekly"
            },
            {
              "value": "monthly",
              "label": "Monthly"
            },
            {
              "value": "yearly",
              "label": "Yearly"
            }
          ]
        },
        {
          "key": "reminder",
          "kind": "select",
          "label": "Reminder",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "No reminder"
            },
            {
              "value": "0",
              "label": "At start"
            },
            {
              "value": "5",
              "label": "5 min before"
            },
            {
              "value": "15",
              "label": "15 min before"
            },
            {
              "value": "30",
              "label": "30 min before"
            },
            {
              "value": "60",
              "label": "1 h before"
            },
            {
              "value": "1440",
              "label": "1 day before"
            }
          ]
        }
      ],
      "keywords": [
        "ics file generator",
        "create ics file",
        "calendar event generator",
        "ical generator",
        "add to calendar",
        "vevent",
        "vcalendar",
        "rrule",
        "generator ics"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "regex-tester",
      "name": "Regex tester",
      "description": "Test a regular expression against your text and see every match and capture group.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/regex-tester",
      "embed": "https://textarray.com/embed/regex-tester",
      "mode": "transform",
      "action": "Test pattern",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "pattern",
          "kind": "text",
          "label": "Pattern",
          "default": ""
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "matches",
          "choices": [
            {
              "value": "matches",
              "label": "List matches"
            },
            {
              "value": "replace",
              "label": "Replace matches"
            }
          ]
        },
        {
          "key": "replacement",
          "kind": "text",
          "label": "Replace with",
          "default": ""
        },
        {
          "key": "global",
          "kind": "checkbox",
          "label": "Global — g",
          "default": true
        },
        {
          "key": "ignoreCase",
          "kind": "checkbox",
          "label": "Ignore case — i",
          "default": false
        },
        {
          "key": "multiline",
          "kind": "checkbox",
          "label": "Multiline — m",
          "default": false
        },
        {
          "key": "dotAll",
          "kind": "checkbox",
          "label": "Dot matches line breaks — s",
          "default": false
        },
        {
          "key": "unicode",
          "kind": "checkbox",
          "label": "Unicode — u",
          "default": false
        }
      ],
      "keywords": [
        "regular expression tester",
        "regex online",
        "regexp",
        "capture groups",
        "visual matches evaluator",
        "pattern matching"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "url-extractor",
      "name": "URL extractor",
      "description": "Pull every link out of text or HTML and get a clean list of URLs.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/url-extractor",
      "embed": "https://textarray.com/embed/url-extractor",
      "mode": "transform",
      "action": "Extract URLs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": true
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort alphabetically",
          "default": false
        },
        {
          "key": "domainsOnly",
          "kind": "checkbox",
          "label": "Extract domains only",
          "default": false
        },
        {
          "key": "protocol",
          "kind": "select",
          "label": "Protocol",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All protocols"
            },
            {
              "value": "https",
              "label": "https only"
            },
            {
              "value": "http",
              "label": "http only"
            }
          ]
        },
        {
          "key": "domain",
          "kind": "text",
          "label": "Domain filter",
          "default": ""
        }
      ],
      "keywords": [
        "url extractor",
        "extract urls",
        "extract links from html",
        "link extractor",
        "find urls in text",
        "list domains from page",
        "url finder"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "markdown-to-html",
      "name": "Markdown to HTML and back",
      "description": "Convert Markdown to clean HTML source and turn HTML back into Markdown.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/markdown-to-html",
      "embed": "https://textarray.com/embed/markdown-to-html",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "html",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Direction",
          "default": "md2html",
          "choices": [
            {
              "value": "md2html",
              "label": "Markdown to HTML"
            },
            {
              "value": "html2md",
              "label": "HTML to Markdown"
            }
          ]
        },
        {
          "key": "lineBreaks",
          "kind": "checkbox",
          "label": "Treat single line breaks as <br>",
          "default": false
        }
      ],
      "keywords": [
        "markdown to html",
        "html to markdown",
        "md to html",
        "markdown compiler",
        "gfm to html",
        "html to md",
        "markdown in html"
      ],
      "updated": "2026-08-25"
    },
    {
      "slug": "csv-to-html-table",
      "name": "CSV to HTML table",
      "description": "Turn CSV data into clean HTML table markup with thead, tbody and escaped cells.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/csv-to-html-table",
      "embed": "https://textarray.com/embed/csv-to-html-table",
      "mode": "transform",
      "action": "Generate table",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect automatically"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        },
        {
          "key": "headerRow",
          "kind": "checkbox",
          "label": "First row is headers",
          "default": true
        },
        {
          "key": "style",
          "kind": "select",
          "label": "Table style",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Markup only"
            },
            {
              "value": "basic",
              "label": "Basic borders"
            }
          ]
        }
      ],
      "keywords": [
        "csv to html table",
        "csv to html",
        "convert csv to html table",
        "html table generator",
        "generate html table"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "html-table-to-markdown",
      "name": "HTML table to Markdown",
      "description": "Convert HTML tables to GitHub-flavored Markdown tables with alignment kept.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/html-table-to-markdown",
      "embed": "https://textarray.com/embed/html-table-to-markdown",
      "mode": "transform",
      "action": "Convert to Markdown",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "firstRowHeader",
          "kind": "checkbox",
          "label": "First row is headers",
          "default": true
        },
        {
          "key": "compact",
          "kind": "checkbox",
          "label": "Compact output",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "markdown",
          "choices": [
            {
              "value": "markdown",
              "label": "Markdown"
            },
            {
              "value": "csv",
              "label": "CSV"
            },
            {
              "value": "json",
              "label": "JSON"
            }
          ]
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "CSV delimiter",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        },
        {
          "key": "quoteAll",
          "kind": "checkbox",
          "label": "Quote every CSV field",
          "default": false
        }
      ],
      "keywords": [
        "html table to markdown",
        "convert html table to markdown",
        "table to markdown converter",
        "html to markdown table",
        "markdown table from html"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "url-query-parser",
      "name": "URL query parser",
      "description": "Extract query-string parameters from a URL and view them as readable JSON.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/url-query-parser",
      "embed": "https://textarray.com/embed/url-query-parser",
      "mode": "transform",
      "action": "Parse URL",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "arrays",
          "kind": "checkbox",
          "label": "Repeated keys as arrays",
          "default": true
        },
        {
          "key": "urlParts",
          "kind": "checkbox",
          "label": "Include URL parts",
          "default": false
        },
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "compact",
              "label": "Compact"
            }
          ]
        }
      ],
      "keywords": [
        "url query parser",
        "query string to json",
        "utm parser",
        "url params to json",
        "query string in json"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "query-string-builder",
      "name": "Query string builder",
      "description": "Convert key-value pairs into a URL query string with proper encoding.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/query-string-builder",
      "embed": "https://textarray.com/embed/query-string-builder",
      "mode": "transform",
      "action": "Build query string",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "leadingQuestion",
          "kind": "checkbox",
          "label": "Add leading question mark",
          "default": true
        }
      ],
      "keywords": [
        "query string",
        "query string builder",
        "url parameter",
        "url parameters",
        "query parameter builder",
        "url query string"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "css-minifier",
      "name": "CSS minifier",
      "description": "Minify CSS by stripping comments and whitespace without touching your values.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-minifier",
      "embed": "https://textarray.com/embed/css-minifier",
      "mode": "transform",
      "action": "Minify CSS",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keepImportant",
          "kind": "checkbox",
          "label": "Keep /*! comments",
          "default": true
        },
        {
          "key": "rulePerLine",
          "kind": "checkbox",
          "label": "One rule per line",
          "default": false
        }
      ],
      "keywords": [
        "css minifier",
        "minify css",
        "css minification",
        "compress css",
        "stylesheet minifier"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "sql-minifier",
      "name": "SQL minifier",
      "description": "Compress an SQL script by stripping comments and extra whitespace.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sql-minifier",
      "embed": "https://textarray.com/embed/sql-minifier",
      "mode": "transform",
      "action": "Minify SQL",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "removeComments",
          "kind": "checkbox",
          "label": "Remove comments",
          "default": true
        },
        {
          "key": "tight",
          "kind": "checkbox",
          "label": "Tight spacing",
          "default": true
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Layout",
          "default": "one-line",
          "choices": [
            {
              "value": "one-line",
              "label": "One line"
            },
            {
              "value": "per-statement",
              "label": "Line per statement"
            }
          ]
        }
      ],
      "keywords": [
        "minify sql",
        "compress sql query",
        "sql compressor",
        "sql one liner",
        "remove sql comments"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "json-to-env",
      "name": "JSON to .env converter",
      "description": "Turn a JSON object into ready-to-use .env lines with clean uppercase keys.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-env",
      "embed": "https://textarray.com/embed/json-to-env",
      "mode": "transform",
      "action": "Convert to .env",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase keys",
          "default": true
        },
        {
          "key": "nested",
          "kind": "select",
          "label": "Nested objects",
          "default": "flatten",
          "choices": [
            {
              "value": "flatten",
              "label": "Flatten into keys"
            },
            {
              "value": "json",
              "label": "Keep as JSON strings"
            }
          ]
        },
        {
          "key": "quotes",
          "kind": "select",
          "label": "Quotes",
          "default": "always",
          "choices": [
            {
              "value": "always",
              "label": "Always"
            },
            {
              "value": "when-needed",
              "label": "When needed"
            }
          ]
        }
      ],
      "keywords": [
        "json to env",
        "json to dotenv",
        "convert json to env file",
        "env variables from json",
        "dotenv generator"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "user-agent-parser",
      "name": "User-agent parser",
      "description": "Decode user-agent strings into browser, engine, OS and device type.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/user-agent-parser",
      "embed": "https://textarray.com/embed/user-agent-parser",
      "mode": "transform",
      "action": "Parse user agent",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "text",
          "choices": [
            {
              "value": "text",
              "label": "Text"
            },
            {
              "value": "json",
              "label": "JSON"
            }
          ]
        }
      ],
      "keywords": [
        "ua parser",
        "what is my browser",
        "user agent lookup",
        "detect browser os",
        "parse user agent",
        "user agent checker",
        "bot detection",
        "browser os detector"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "utm-generator",
      "name": "UTM link generator",
      "description": "Add UTM campaign parameters to many URLs at once.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/utm-generator",
      "embed": "https://textarray.com/embed/utm-generator",
      "mode": "transform",
      "action": "Generate links",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "source",
          "kind": "text",
          "label": "Sources (utm_source)",
          "default": ""
        },
        {
          "key": "medium",
          "kind": "text",
          "label": "Mediums (utm_medium)",
          "default": ""
        },
        {
          "key": "campaign",
          "kind": "text",
          "label": "Campaigns (utm_campaign)",
          "default": ""
        },
        {
          "key": "term",
          "kind": "text",
          "label": "Term (utm_term)",
          "default": ""
        },
        {
          "key": "content",
          "kind": "text",
          "label": "Content (utm_content)",
          "default": ""
        }
      ],
      "keywords": [
        "utm link generator",
        "campaign url builder",
        "google analytics utm",
        "bulk utm links",
        "utm tagging",
        "utm parameter generator",
        "generator utm"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "whatsapp-link-generator",
      "name": "WhatsApp link generator",
      "description": "Build a wa.me click-to-chat link from a phone number and an optional prefilled message.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/whatsapp-link-generator",
      "embed": "https://textarray.com/embed/whatsapp-link-generator",
      "mode": "generate",
      "action": "Generate link",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "phone",
          "kind": "text",
          "label": "Phone number",
          "default": ""
        },
        {
          "key": "message",
          "kind": "text",
          "label": "Message",
          "default": ""
        }
      ],
      "keywords": [
        "wa me link generator",
        "click to chat",
        "whatsapp link with message",
        "whatsapp message link",
        "generate whatsapp link",
        "whatsapp chat link"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "url-validator",
      "name": "URL validator",
      "description": "Check a list of links and separate syntactically valid URLs from broken ones.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/url-validator",
      "embed": "https://textarray.com/embed/url-validator",
      "mode": "transform",
      "action": "Validate URLs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "output",
          "kind": "select",
          "label": "Show",
          "default": "valid",
          "choices": [
            {
              "value": "valid",
              "label": "Valid only"
            },
            {
              "value": "invalid",
              "label": "Invalid only"
            },
            {
              "value": "both",
              "label": "Both sections"
            }
          ]
        },
        {
          "key": "requireHttp",
          "kind": "checkbox",
          "label": "Require http(s)",
          "default": true
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        }
      ],
      "keywords": [
        "url validator",
        "validate urls",
        "check links",
        "bulk url checker",
        "broken link syntax"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "html-to-bbcode",
      "name": "HTML to BBCode converter",
      "description": "Convert HTML markup to BBCode for forum posts and signatures.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/html-to-bbcode",
      "embed": "https://textarray.com/embed/html-to-bbcode",
      "mode": "transform",
      "action": "Convert to BBCode",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "unknown",
          "kind": "select",
          "label": "Unknown tags",
          "default": "strip",
          "choices": [
            {
              "value": "strip",
              "label": "Remove, keep text"
            },
            {
              "value": "keep",
              "label": "Keep as written"
            }
          ]
        }
      ],
      "keywords": [
        "html to bbcode",
        "convert html to bbcode",
        "bbcode generator",
        "html bbcode converter",
        "forum markup converter",
        "bbcode from html"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "sql-comment-remover",
      "name": "SQL comment remover",
      "description": "Strip -- line comments and /* */ block comments from SQL without touching string literals.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sql-comment-remover",
      "embed": "https://textarray.com/embed/sql-comment-remover",
      "mode": "transform",
      "action": "Remove comments",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "remove",
          "kind": "select",
          "label": "Remove",
          "default": "both",
          "choices": [
            {
              "value": "both",
              "label": "Line and block comments"
            },
            {
              "value": "line",
              "label": "Line comments only (--)"
            },
            {
              "value": "block",
              "label": "Block comments only (/* */)"
            }
          ]
        },
        {
          "key": "keepMarked",
          "kind": "checkbox",
          "label": "Keep marked comments",
          "default": false
        },
        {
          "key": "marker",
          "kind": "text",
          "label": "Marker",
          "default": "!"
        },
        {
          "key": "collapseBlank",
          "kind": "checkbox",
          "label": "Drop emptied lines",
          "default": true
        }
      ],
      "keywords": [
        "sql comment remover",
        "remove sql comments",
        "strip sql comments",
        "clean sql script",
        "sql line comments",
        "sql block comments"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "robots-txt-generator",
      "name": "Robots.txt generator",
      "description": "Build a correct robots.txt with presets, custom rules, crawl-delay and a sitemap link.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/robots-txt-generator",
      "embed": "https://textarray.com/embed/robots-txt-generator",
      "mode": "generate",
      "action": "Generate robots.txt",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "preset",
          "kind": "select",
          "label": "Preset",
          "default": "allow-all",
          "choices": [
            {
              "value": "allow-all",
              "label": "Allow everything"
            },
            {
              "value": "disallow-all",
              "label": "Disallow everything"
            },
            {
              "value": "custom",
              "label": "Custom paths"
            }
          ]
        },
        {
          "key": "userAgent",
          "kind": "text",
          "label": "User-agent",
          "default": "*"
        },
        {
          "key": "disallow",
          "kind": "text",
          "label": "Disallow paths (comma-separated)",
          "default": ""
        },
        {
          "key": "allow",
          "kind": "text",
          "label": "Allow paths (comma-separated)",
          "default": ""
        },
        {
          "key": "crawlDelay",
          "kind": "number",
          "label": "Crawl-delay (seconds, 0 = off)",
          "default": 0,
          "min": 0,
          "max": 3600,
          "step": 1
        },
        {
          "key": "sitemap",
          "kind": "text",
          "label": "Sitemap URL",
          "default": ""
        }
      ],
      "keywords": [
        "create robots.txt",
        "robots file",
        "disallow all",
        "block gptbot",
        "generator robots.txt",
        "crawl rules"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "sitemap-generator",
      "name": "Sitemap XML generator",
      "description": "Turn a plain list of URLs into a valid sitemap.xml, ready to upload.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sitemap-generator",
      "embed": "https://textarray.com/embed/sitemap-generator",
      "mode": "transform",
      "action": "Generate sitemap",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "changefreq",
          "kind": "select",
          "label": "Change frequency",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Omit"
            },
            {
              "value": "always",
              "label": "always"
            },
            {
              "value": "hourly",
              "label": "hourly"
            },
            {
              "value": "daily",
              "label": "daily"
            },
            {
              "value": "weekly",
              "label": "weekly"
            },
            {
              "value": "monthly",
              "label": "monthly"
            },
            {
              "value": "yearly",
              "label": "yearly"
            },
            {
              "value": "never",
              "label": "never"
            }
          ]
        },
        {
          "key": "priority",
          "kind": "text",
          "label": "Priority",
          "default": ""
        },
        {
          "key": "lastmod",
          "kind": "text",
          "label": "Last modified",
          "default": ""
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicate URLs",
          "default": true
        }
      ],
      "keywords": [
        "sitemap xml from url list",
        "create sitemap online",
        "urlset generator",
        "xml sitemap builder",
        "generator sitemap"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "csp-generator",
      "name": "CSP header generator",
      "description": "Build a Content-Security-Policy header from per-directive fields, ready to deploy.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/csp-generator",
      "embed": "https://textarray.com/embed/csp-generator",
      "mode": "generate",
      "action": "Build policy",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "defaultSrc",
          "kind": "text",
          "label": "default-src",
          "default": "'self'"
        },
        {
          "key": "scriptSrc",
          "kind": "text",
          "label": "script-src",
          "default": ""
        },
        {
          "key": "styleSrc",
          "kind": "text",
          "label": "style-src",
          "default": ""
        },
        {
          "key": "imgSrc",
          "kind": "text",
          "label": "img-src",
          "default": ""
        },
        {
          "key": "connectSrc",
          "kind": "text",
          "label": "connect-src",
          "default": ""
        },
        {
          "key": "fontSrc",
          "kind": "text",
          "label": "font-src",
          "default": ""
        },
        {
          "key": "frameAncestors",
          "kind": "text",
          "label": "frame-ancestors",
          "default": ""
        },
        {
          "key": "upgradeInsecure",
          "kind": "checkbox",
          "label": "upgrade-insecure-requests",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output as",
          "default": "header",
          "choices": [
            {
              "value": "header",
              "label": "HTTP header"
            },
            {
              "value": "meta",
              "label": "HTML meta tag"
            },
            {
              "value": "nginx",
              "label": "nginx"
            },
            {
              "value": "apache",
              "label": "Apache"
            }
          ]
        }
      ],
      "keywords": [
        "csp generator",
        "content security policy generator",
        "csp header builder",
        "generate csp header",
        "csp meta tag",
        "nginx csp header",
        "generator csp",
        "csp meta tag generator"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "humans-txt-generator",
      "name": "Humans.txt generator",
      "description": "Build a humans.txt credits file — TEAM, THANKS and SITE sections — from a simple list.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/humans-txt-generator",
      "embed": "https://textarray.com/embed/humans-txt-generator",
      "mode": "transform",
      "action": "Generate humans.txt",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "thanks",
          "kind": "text",
          "label": "Thanks (comma-separated)",
          "default": ""
        },
        {
          "key": "technology",
          "kind": "text",
          "label": "Technology (comma-separated)",
          "default": ""
        },
        {
          "key": "language",
          "kind": "text",
          "label": "Language",
          "default": ""
        },
        {
          "key": "doctype",
          "kind": "text",
          "label": "Doctype",
          "default": "HTML5"
        },
        {
          "key": "lastUpdate",
          "kind": "text",
          "label": "Last update",
          "default": ""
        }
      ],
      "keywords": [
        "humans txt file",
        "create humans.txt",
        "website credits file",
        "team credits txt",
        "humanstxt org format",
        "generator humans.txt",
        "team credits generator"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "jwt-decoder",
      "name": "JWT decoder",
      "description": "Decode a JSON Web Token and read its header and payload — without verifying the signature.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/jwt-decoder",
      "embed": "https://textarray.com/embed/jwt-decoder",
      "mode": "transform",
      "action": "Decode token",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "showDates",
          "kind": "checkbox",
          "label": "Show exp/iat/nbf as dates",
          "default": true
        }
      ],
      "keywords": [
        "decode jwt",
        "jwt token decoder",
        "jwt debugger",
        "jwt payload",
        "jwt claims",
        "jwt expiry checker",
        "is my jwt expired",
        "jwt exp nbf",
        "jwt algorithm"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "json-flattener",
      "name": "JSON flattener",
      "description": "Flatten nested JSON into single-level dot-notation keys, or rebuild the nesting.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-flattener",
      "embed": "https://textarray.com/embed/json-flattener",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "flatten",
          "choices": [
            {
              "value": "flatten",
              "label": "Flatten"
            },
            {
              "value": "unflatten",
              "label": "Unflatten"
            }
          ]
        },
        {
          "key": "delimiter",
          "kind": "text",
          "label": "Delimiter",
          "default": "."
        },
        {
          "key": "arrays",
          "kind": "select",
          "label": "Array indices",
          "default": "bracket",
          "choices": [
            {
              "value": "bracket",
              "label": "Brackets [0]"
            },
            {
              "value": "delimiter",
              "label": "Delimiter (.0)"
            }
          ]
        }
      ],
      "keywords": [
        "json flattener",
        "flat json",
        "nested json to flat",
        "dot notation json",
        "unflatten json",
        "json to spreadsheet"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "json-diff",
      "name": "JSON diff",
      "description": "Compare two JSON documents structurally and see every added, removed and changed value by its path.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-diff",
      "embed": "https://textarray.com/embed/json-diff",
      "mode": "transform",
      "action": "Compare JSON",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Changed JSON"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "showUnchanged",
          "kind": "checkbox",
          "label": "Show unchanged values",
          "default": false
        },
        {
          "key": "ignoreArrayOrder",
          "kind": "checkbox",
          "label": "Ignore array order",
          "default": false
        },
        {
          "key": "output",
          "kind": "select",
          "label": "Output format",
          "default": "text",
          "choices": [
            {
              "value": "text",
              "label": "Readable list"
            },
            {
              "value": "json-patch",
              "label": "JSON Patch (RFC 6902)"
            },
            {
              "value": "merge-patch",
              "label": "Merge Patch (RFC 7396)"
            }
          ]
        },
        {
          "key": "patchTests",
          "kind": "checkbox",
          "label": "Add test operations before each change",
          "default": false
        },
        {
          "key": "compactPatch",
          "kind": "checkbox",
          "label": "Compact patch on one line",
          "default": false
        }
      ],
      "keywords": [
        "json diff online",
        "compare json",
        "json compare",
        "compare json files",
        "json difference checker",
        "structural json diff",
        "json comparison"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "chmod-calculator",
      "name": "Chmod calculator",
      "description": "Convert Unix file permissions between octal and rwx notation with a full breakdown.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/chmod-calculator",
      "embed": "https://textarray.com/embed/chmod-calculator",
      "mode": "transform",
      "action": "Calculate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "output",
          "kind": "select",
          "label": "Output",
          "default": "breakdown",
          "choices": [
            {
              "value": "breakdown",
              "label": "Breakdown"
            },
            {
              "value": "conversion",
              "label": "Conversion only"
            }
          ]
        },
        {
          "key": "command",
          "kind": "checkbox",
          "label": "Include chmod command",
          "default": true
        }
      ],
      "keywords": [
        "chmod calculator",
        "chmod 755",
        "chmod 644",
        "file permissions",
        "unix permissions",
        "linux permissions",
        "octal permissions",
        "rwx",
        "setuid setgid sticky"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "ip-subnet-calculator",
      "name": "IP subnet calculator",
      "description": "Calculate network address, broadcast, netmask and host range from CIDR notation.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ip-subnet-calculator",
      "embed": "https://textarray.com/embed/ip-subnet-calculator",
      "mode": "transform",
      "action": "Calculate subnets",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "defaultPrefix",
          "kind": "number",
          "label": "Default prefix",
          "default": 24,
          "min": 0,
          "max": 32,
          "step": 1
        },
        {
          "key": "binary",
          "kind": "checkbox",
          "label": "Show binary",
          "default": false
        }
      ],
      "keywords": [
        "ip subnet calculator",
        "netmask",
        "netmask calculator",
        "network address",
        "broadcast address",
        "wildcard mask",
        "cidr notation"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "contrast-checker",
      "name": "Contrast checker",
      "description": "Check WCAG contrast ratios of color pairs, with AA and AAA verdicts and fix suggestions.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/contrast-checker",
      "embed": "https://textarray.com/embed/contrast-checker",
      "mode": "transform",
      "action": "Check contrast",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output",
          "default": "report",
          "choices": [
            {
              "value": "report",
              "label": "Report"
            },
            {
              "value": "compact",
              "label": "Compact"
            }
          ]
        },
        {
          "key": "suggest",
          "kind": "checkbox",
          "label": "Suggest fix",
          "default": false
        }
      ],
      "keywords": [
        "contrast ratio",
        "color contrast checker",
        "accessibility",
        "a11y",
        "aa aaa contrast"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "css-unit-converter",
      "name": "CSS unit converter",
      "description": "Convert CSS lengths between px, rem, em, pt and % against any root font size.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-unit-converter",
      "embed": "https://textarray.com/embed/css-unit-converter",
      "mode": "transform",
      "action": "Convert units",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "from",
          "kind": "select",
          "label": "From",
          "default": "px",
          "choices": [
            {
              "value": "px",
              "label": "px"
            },
            {
              "value": "rem",
              "label": "rem"
            },
            {
              "value": "em",
              "label": "em"
            },
            {
              "value": "pt",
              "label": "pt"
            },
            {
              "value": "percent",
              "label": "%"
            }
          ]
        },
        {
          "key": "to",
          "kind": "select",
          "label": "To",
          "default": "rem",
          "choices": [
            {
              "value": "rem",
              "label": "rem"
            },
            {
              "value": "px",
              "label": "px"
            },
            {
              "value": "em",
              "label": "em"
            },
            {
              "value": "pt",
              "label": "pt"
            },
            {
              "value": "percent",
              "label": "%"
            },
            {
              "value": "all",
              "label": "All units"
            }
          ]
        },
        {
          "key": "base",
          "kind": "number",
          "label": "Base size (px)",
          "default": 16,
          "min": 1,
          "max": 10000,
          "step": 1
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 4,
          "min": 0,
          "max": 6,
          "step": 1
        }
      ],
      "keywords": [
        "css unit converter",
        "px to rem",
        "rem to px",
        "em to px",
        "pt to px",
        "px to percent",
        "font size converter",
        "root font size"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "aspect-ratio-calculator",
      "name": "Aspect ratio calculator",
      "description": "Reduce any width and height to its aspect ratio, name it and solve missing sides.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/aspect-ratio-calculator",
      "embed": "https://textarray.com/embed/aspect-ratio-calculator",
      "mode": "transform",
      "action": "Calculate ratios",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "ratio",
          "kind": "text",
          "label": "Ratio",
          "default": "16:9"
        },
        {
          "key": "resolutions",
          "kind": "checkbox",
          "label": "Show common resolutions",
          "default": false
        }
      ],
      "keywords": [
        "aspect ratio calculator",
        "ratio calculator",
        "16:9",
        "4:3",
        "resolution calculator",
        "screen ratio",
        "width height"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "mailto-link-generator",
      "name": "Mailto link generator",
      "description": "Build a mailto link with recipients, cc, bcc, subject and a prefilled body.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/mailto-link-generator",
      "embed": "https://textarray.com/embed/mailto-link-generator",
      "mode": "generate",
      "action": "Generate link",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "to",
          "kind": "text",
          "label": "To",
          "default": "hello@example.com"
        },
        {
          "key": "cc",
          "kind": "text",
          "label": "Cc",
          "default": ""
        },
        {
          "key": "bcc",
          "kind": "text",
          "label": "Bcc",
          "default": ""
        },
        {
          "key": "subject",
          "kind": "text",
          "label": "Subject",
          "default": ""
        },
        {
          "key": "body",
          "kind": "text",
          "label": "Body",
          "default": ""
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output",
          "default": "link",
          "choices": [
            {
              "value": "link",
              "label": "Link only"
            },
            {
              "value": "html",
              "label": "HTML anchor"
            },
            {
              "value": "markdown",
              "label": "Markdown"
            }
          ]
        }
      ],
      "keywords": [
        "email link generator",
        "e-mail link generator",
        "email href",
        "mailto with subject and body",
        "contact form"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "vcard-generator",
      "name": "vCard generator",
      "description": "Fill in contact details and get a .vcf contact card to import anywhere.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/vcard-generator",
      "embed": "https://textarray.com/embed/vcard-generator",
      "mode": "generate",
      "action": "Generate vCard",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "firstName",
          "kind": "text",
          "label": "First name",
          "default": "Jane"
        },
        {
          "key": "lastName",
          "kind": "text",
          "label": "Last name",
          "default": "Doe"
        },
        {
          "key": "org",
          "kind": "text",
          "label": "Organization",
          "default": ""
        },
        {
          "key": "jobTitle",
          "kind": "text",
          "label": "Job title",
          "default": ""
        },
        {
          "key": "phone",
          "kind": "text",
          "label": "Phone",
          "default": ""
        },
        {
          "key": "email",
          "kind": "text",
          "label": "Email",
          "default": ""
        },
        {
          "key": "website",
          "kind": "text",
          "label": "Website",
          "default": ""
        },
        {
          "key": "street",
          "kind": "text",
          "label": "Street",
          "default": ""
        },
        {
          "key": "city",
          "kind": "text",
          "label": "City",
          "default": ""
        },
        {
          "key": "zip",
          "kind": "text",
          "label": "ZIP",
          "default": ""
        },
        {
          "key": "country",
          "kind": "text",
          "label": "Country",
          "default": ""
        },
        {
          "key": "note",
          "kind": "text",
          "label": "Note",
          "default": ""
        },
        {
          "key": "version",
          "kind": "select",
          "label": "Version",
          "default": "3.0",
          "choices": [
            {
              "value": "3.0",
              "label": "vCard 3.0"
            },
            {
              "value": "4.0",
              "label": "vCard 4.0"
            }
          ]
        }
      ],
      "keywords": [
        "vcf file generator",
        "create vcard",
        "contact file",
        "digital business card"
      ],
      "updated": "2026-07-16"
    },
    {
      "slug": "markdown-toc-generator",
      "name": "Markdown TOC generator",
      "description": "Generate a linked table of contents from the headings of a Markdown document, with GitHub-style anchors.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/markdown-toc-generator",
      "embed": "https://textarray.com/embed/markdown-toc-generator",
      "mode": "transform",
      "action": "Generate TOC",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Input format",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "markdown",
              "label": "Markdown"
            },
            {
              "value": "html",
              "label": "HTML"
            }
          ]
        },
        {
          "key": "levels",
          "kind": "select",
          "label": "Levels",
          "default": "h2-h3",
          "choices": [
            {
              "value": "h2-h3",
              "label": "H2–H3"
            },
            {
              "value": "h1-h6",
              "label": "H1–H6"
            },
            {
              "value": "h2",
              "label": "H2 only"
            },
            {
              "value": "h2-h4",
              "label": "H2–H4"
            }
          ]
        },
        {
          "key": "style",
          "kind": "select",
          "label": "Style",
          "default": "bullets",
          "choices": [
            {
              "value": "bullets",
              "label": "Bullets"
            },
            {
              "value": "numbered",
              "label": "Numbered"
            }
          ]
        },
        {
          "key": "links",
          "kind": "checkbox",
          "label": "Links",
          "default": true
        },
        {
          "key": "tabs",
          "kind": "checkbox",
          "label": "Indent with tabs",
          "default": false
        },
        {
          "key": "warn",
          "kind": "checkbox",
          "label": "Flag structure problems",
          "default": true
        }
      ],
      "keywords": [
        "table of contents generator",
        "markdown table of contents",
        "readme toc",
        "generate toc from markdown",
        "markdown headings"
      ],
      "updated": "2026-08-23"
    },
    {
      "slug": "sql-formatter",
      "name": "SQL formatter",
      "description": "Format SQL queries with each clause on its own line, consistent indentation and uppercase keywords.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sql-formatter",
      "embed": "https://textarray.com/embed/sql-formatter",
      "mode": "transform",
      "action": "Format SQL",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase keywords",
          "default": true
        },
        {
          "key": "oneColumnPerLine",
          "kind": "checkbox",
          "label": "One column per line in SELECT",
          "default": true
        }
      ],
      "keywords": [
        "sql formatter",
        "format sql",
        "beautify sql",
        "sql query formatter"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "html-formatter",
      "name": "HTML formatter",
      "description": "Pretty-print HTML with proper nesting indentation, without ever touching pre, script or style content.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/html-formatter",
      "embed": "https://textarray.com/embed/html-formatter",
      "mode": "transform",
      "action": "Format HTML",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "removeBlankLines",
          "kind": "checkbox",
          "label": "Remove blank lines between elements",
          "default": true
        },
        {
          "key": "collapseWhitespace",
          "kind": "checkbox",
          "label": "Collapse whitespace in text",
          "default": true
        }
      ],
      "keywords": [
        "html formatter",
        "format html",
        "html pretty print",
        "beautify html",
        "tidy html"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "json-to-typescript",
      "name": "JSON to TypeScript",
      "description": "Generate TypeScript interfaces from a JSON document, with nested objects as named sub-interfaces.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-typescript",
      "embed": "https://textarray.com/embed/json-to-typescript",
      "mode": "transform",
      "action": "Generate TypeScript",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "rootName",
          "kind": "text",
          "label": "Root type name",
          "default": "Root"
        },
        {
          "key": "declaration",
          "kind": "select",
          "label": "Declaration",
          "default": "interface",
          "choices": [
            {
              "value": "interface",
              "label": "interface"
            },
            {
              "value": "type",
              "label": "type"
            }
          ]
        },
        {
          "key": "optionalNulls",
          "kind": "checkbox",
          "label": "Optional properties for null values",
          "default": false
        },
        {
          "key": "readonlyProps",
          "kind": "checkbox",
          "label": "Readonly properties",
          "default": false
        },
        {
          "key": "exportDecls",
          "kind": "checkbox",
          "label": "Export declarations",
          "default": true
        }
      ],
      "keywords": [
        "json to typescript",
        "json to ts",
        "typescript interface generator",
        "generate typescript from json",
        "json to interface",
        "json typescript types",
        "type generation"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "hmac-generator",
      "name": "HMAC generator",
      "description": "Compute HMAC-SHA256, SHA-1, SHA-384 or SHA-512 signatures with a secret key.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/hmac-generator",
      "embed": "https://textarray.com/embed/hmac-generator",
      "mode": "transform",
      "action": "Compute HMAC",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "key",
          "kind": "text",
          "label": "Secret key",
          "default": "",
          "secret": true
        },
        {
          "key": "algorithm",
          "kind": "select",
          "label": "Algorithm",
          "default": "SHA-256",
          "choices": [
            {
              "value": "SHA-256",
              "label": "SHA-256"
            },
            {
              "value": "SHA-1",
              "label": "SHA-1"
            },
            {
              "value": "SHA-384",
              "label": "SHA-384"
            },
            {
              "value": "SHA-512",
              "label": "SHA-512"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output",
          "default": "hex",
          "choices": [
            {
              "value": "hex",
              "label": "Hex"
            },
            {
              "value": "base64",
              "label": "Base64"
            }
          ]
        },
        {
          "key": "perLine",
          "kind": "checkbox",
          "label": "HMAC per line",
          "default": false
        }
      ],
      "keywords": [
        "hmac calculator",
        "hmac sha512",
        "api signature",
        "webhook signature",
        "keyed hash"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "domain-extractor",
      "name": "Domain extractor",
      "description": "Pull clean domain names out of any text full of links and e-mail addresses.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/domain-extractor",
      "embed": "https://textarray.com/embed/domain-extractor",
      "mode": "transform",
      "action": "Extract domains",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "source",
          "kind": "select",
          "label": "Take domains from",
          "default": "both",
          "choices": [
            {
              "value": "both",
              "label": "URLs and e-mails"
            },
            {
              "value": "urls",
              "label": "URLs only"
            },
            {
              "value": "emails",
              "label": "E-mails only"
            }
          ]
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": true
        },
        {
          "key": "stripWww",
          "kind": "checkbox",
          "label": "Strip www.",
          "default": true
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort alphabetically",
          "default": false
        },
        {
          "key": "tld",
          "kind": "text",
          "label": "Only these TLDs",
          "default": ""
        }
      ],
      "keywords": [
        "extract domains from urls",
        "extract domain from email",
        "get domain from link",
        "domain list from text",
        "hostname extractor"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "ip-extractor",
      "name": "IP address extractor",
      "description": "Pull every IPv4 and IPv6 address out of logs, configs or any text.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ip-extractor",
      "embed": "https://textarray.com/embed/ip-extractor",
      "mode": "transform",
      "action": "Extract IP addresses",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "kind",
          "kind": "select",
          "label": "Address type",
          "default": "both",
          "choices": [
            {
              "value": "both",
              "label": "IPv4 and IPv6"
            },
            {
              "value": "ipv4",
              "label": "IPv4 only"
            },
            {
              "value": "ipv6",
              "label": "IPv6 only"
            }
          ]
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": true
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort numerically",
          "default": false
        }
      ],
      "keywords": [
        "extract ip addresses from text",
        "ip address extractor",
        "ipv4 extractor",
        "ipv6 extractor",
        "extract ips from log file",
        "find ip addresses in text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "vtt-to-srt",
      "name": "VTT ⇄ SRT converter",
      "description": "Convert subtitles between WebVTT and SubRip in either direction, instantly.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/vtt-to-srt",
      "embed": "https://textarray.com/embed/vtt-to-srt",
      "mode": "transform",
      "action": "Convert subtitles",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect automatically"
            },
            {
              "value": "vtt-to-srt",
              "label": "VTT → SRT"
            },
            {
              "value": "srt-to-vtt",
              "label": "SRT → VTT"
            }
          ]
        }
      ],
      "keywords": [
        "vtt to srt",
        "srt to vtt",
        "webvtt converter",
        "convert vtt srt online",
        "subtitle format conversion"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "subtitle-line-wrapper",
      "name": "Subtitle line wrapper",
      "description": "Re-wrap subtitle dialogue to a maximum characters-per-line limit, timing preserved.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/subtitle-line-wrapper",
      "embed": "https://textarray.com/embed/subtitle-line-wrapper",
      "mode": "transform",
      "action": "Wrap lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "maxChars",
          "kind": "number",
          "label": "Max characters per line",
          "default": 42,
          "min": 10,
          "max": 100,
          "step": 1
        },
        {
          "key": "balance",
          "kind": "checkbox",
          "label": "Balance two-line cues",
          "default": true
        }
      ],
      "keywords": [
        "subtitle line wrapper",
        "max characters per line subtitle",
        "srt line length",
        "wrap subtitle lines",
        "subtitle 42 characters",
        "break long subtitle lines"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "ip-converter",
      "name": "IP address converter (hex/dec/binary)",
      "description": "Convert an IPv4 address between dotted, decimal (DWORD), hexadecimal and binary.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ip-converter",
      "embed": "https://textarray.com/embed/ip-converter",
      "mode": "transform",
      "action": "Convert IP",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "from",
          "kind": "select",
          "label": "Input format",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect automatically"
            },
            {
              "value": "dotted",
              "label": "Dotted (192.168.0.1)"
            },
            {
              "value": "decimal",
              "label": "Decimal / DWORD"
            },
            {
              "value": "hex",
              "label": "Hexadecimal"
            },
            {
              "value": "binary",
              "label": "Binary"
            }
          ]
        }
      ],
      "keywords": [
        "ip converter hex dec binary",
        "ip to decimal",
        "ip to integer dword",
        "ipv4 to hex",
        "ipv4 to binary",
        "decimal to ip address"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "xml-to-json",
      "name": "XML to JSON converter",
      "description": "Convert XML into equivalent JSON, with attributes prefixed and repeated tags as arrays.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/xml-to-json",
      "embed": "https://textarray.com/embed/xml-to-json",
      "mode": "transform",
      "action": "Convert to JSON",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indent",
          "kind": "select",
          "label": "Indentation",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "0",
              "label": "Minified"
            }
          ]
        },
        {
          "key": "attrPrefix",
          "kind": "text",
          "label": "Attribute prefix",
          "default": "@"
        }
      ],
      "keywords": [
        "xml to json",
        "xml to json converter",
        "convert xml to json online",
        "xml json parser",
        "xml2json",
        "parse xml to object",
        "xml json parser online"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "split-camel-case",
      "name": "Split camelCase",
      "description": "Separate camelCase and snake_case identifiers into individual words for readability.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/split-camel-case",
      "embed": "https://textarray.com/embed/split-camel-case",
      "mode": "transform",
      "action": "Split identifier",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "output",
          "kind": "select",
          "label": "Output case",
          "default": "lower",
          "choices": [
            {
              "value": "lower",
              "label": "lowercase"
            },
            {
              "value": "title",
              "label": "Title Case"
            },
            {
              "value": "keep",
              "label": "Keep original"
            }
          ]
        }
      ],
      "keywords": [
        "split camel case",
        "camel case splitter",
        "identifier splitter",
        "camelcase formatter",
        "snake case converter",
        "pascal case",
        "dehyphenate",
        "split identifiers"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "lines-to-html-list",
      "name": "Lines to HTML list",
      "description": "Convert line-separated text into properly formatted HTML list markup.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/lines-to-html-list",
      "embed": "https://textarray.com/embed/lines-to-html-list",
      "mode": "transform",
      "action": "Generate list",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "type",
          "kind": "select",
          "label": "List type",
          "default": "ul",
          "choices": [
            {
              "value": "ul",
              "label": "Unordered (ul)"
            },
            {
              "value": "ol",
              "label": "Ordered (ol)"
            }
          ]
        },
        {
          "key": "indent",
          "kind": "checkbox",
          "label": "Indent items",
          "default": true
        }
      ],
      "keywords": [
        "lines to html list",
        "convert lines to list",
        "ul li tags",
        "ol li tags",
        "lines to ul",
        "lines to ol"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "meta-tag-checker",
      "name": "Meta tag checker",
      "description": "Audit the SEO and social meta tags in a page's HTML — no URL fetch, paste the source instead.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/meta-tag-checker",
      "embed": "https://textarray.com/embed/meta-tag-checker",
      "mode": "transform",
      "action": "Check meta tags",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "showGooglePreview",
          "kind": "checkbox",
          "label": "Show Google search preview",
          "default": true
        },
        {
          "key": "showSocialPreview",
          "kind": "checkbox",
          "label": "Show social share preview",
          "default": true
        },
        {
          "key": "platform",
          "kind": "select",
          "label": "Preview for",
          "default": "generic",
          "choices": [
            {
              "value": "generic",
              "label": "Any network (no truncation)"
            },
            {
              "value": "facebook",
              "label": "Facebook"
            },
            {
              "value": "x",
              "label": "X"
            },
            {
              "value": "linkedin",
              "label": "LinkedIn"
            },
            {
              "value": "slack",
              "label": "Slack"
            },
            {
              "value": "discord",
              "label": "Discord"
            }
          ]
        },
        {
          "key": "warningsOnly",
          "kind": "checkbox",
          "label": "Warnings only",
          "default": false
        }
      ],
      "keywords": [
        "seo meta tag audit",
        "title tag checker",
        "meta description checker",
        "open graph checker",
        "twitter card checker",
        "canonical tag checker",
        "serp preview",
        "seo tag check"
      ],
      "updated": "2026-08-25"
    },
    {
      "slug": "json-tree-viewer",
      "name": "JSON tree view",
      "description": "Validate JSON and render its structure as an indented tree so a large payload reads at a glance.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-tree-viewer",
      "embed": "https://textarray.com/embed/json-tree-viewer",
      "mode": "transform",
      "action": "Build tree",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "maxDepth",
          "kind": "number",
          "label": "Max depth",
          "default": 6,
          "min": 1,
          "max": 20,
          "step": 1
        },
        {
          "key": "maxValueLength",
          "kind": "number",
          "label": "Max value length",
          "default": 40,
          "min": 5,
          "max": 200,
          "step": 5
        },
        {
          "key": "showTypes",
          "kind": "checkbox",
          "label": "Show types",
          "default": true
        },
        {
          "key": "sortKeys",
          "kind": "checkbox",
          "label": "Sort keys",
          "default": false
        }
      ],
      "keywords": [
        "json explorer",
        "view json",
        "json formatter",
        "parse json",
        "json viewer",
        "json validator",
        "json structure"
      ],
      "updated": "2026-07-28"
    },
    {
      "slug": "js-obfuscator",
      "name": "JavaScript obfuscator",
      "description": "Turn JavaScript source into a hex-encoded eval(unescape(...)) snippet that hides it from a casual read.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/js-obfuscator",
      "embed": "https://textarray.com/embed/js-obfuscator",
      "mode": "transform",
      "action": "Obfuscate JavaScript",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "iife",
          "kind": "checkbox",
          "label": "Wrap in self-executing function",
          "default": true
        }
      ],
      "keywords": [
        "javascript obfuscator",
        "obfuscate javascript",
        "js code obfuscator",
        "eval unescape obfuscator",
        "hex encode javascript"
      ],
      "updated": "2026-07-29"
    },
    {
      "slug": "code-to-svg",
      "name": "Code to SVG image",
      "description": "Turn a code snippet into a syntax-highlighted image with a window frame and gradient background.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/code-to-svg",
      "embed": "https://textarray.com/embed/code-to-svg",
      "mode": "transform",
      "action": "Generate image",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "language",
          "kind": "select",
          "label": "Language",
          "default": "javascript",
          "choices": [
            {
              "value": "javascript",
              "label": "JavaScript"
            },
            {
              "value": "typescript",
              "label": "TypeScript"
            },
            {
              "value": "python",
              "label": "Python"
            },
            {
              "value": "json",
              "label": "JSON"
            },
            {
              "value": "html",
              "label": "HTML"
            },
            {
              "value": "css",
              "label": "CSS"
            },
            {
              "value": "bash",
              "label": "Bash"
            },
            {
              "value": "sql",
              "label": "SQL"
            },
            {
              "value": "plaintext",
              "label": "Plain text"
            }
          ]
        },
        {
          "key": "theme",
          "kind": "select",
          "label": "Background theme",
          "default": "ocean",
          "choices": [
            {
              "value": "sunset",
              "label": "Sunset"
            },
            {
              "value": "ocean",
              "label": "Ocean"
            },
            {
              "value": "midnight",
              "label": "Midnight"
            },
            {
              "value": "forest",
              "label": "Forest"
            },
            {
              "value": "grape",
              "label": "Grape"
            },
            {
              "value": "mono",
              "label": "Mono"
            }
          ]
        },
        {
          "key": "fileName",
          "kind": "text",
          "label": "Window title",
          "default": ""
        },
        {
          "key": "fontSize",
          "kind": "range",
          "label": "Font size",
          "default": 14,
          "min": 10,
          "max": 28
        },
        {
          "key": "padding",
          "kind": "range",
          "label": "Background padding",
          "default": 48,
          "min": 0,
          "max": 160
        },
        {
          "key": "showLineNumbers",
          "kind": "checkbox",
          "label": "Show line numbers",
          "default": true
        },
        {
          "key": "showWindowChrome",
          "kind": "checkbox",
          "label": "Show window title bar",
          "default": true
        },
        {
          "key": "shadow",
          "kind": "checkbox",
          "label": "Drop shadow",
          "default": true
        }
      ],
      "keywords": [
        "code to svg",
        "code to image",
        "syntax highlighting image",
        "code snippet image",
        "carbon alternative",
        "code image generator",
        "code screenshot generator"
      ],
      "updated": "2026-07-29"
    },
    {
      "slug": "jsonl-converter",
      "name": "JSONL converter",
      "description": "Convert between a JSON array of objects and JSONL / NDJSON, one object per line.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/jsonl-converter",
      "embed": "https://textarray.com/embed/jsonl-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "array-to-jsonl",
          "choices": [
            {
              "value": "array-to-jsonl",
              "label": "JSON array → JSONL"
            },
            {
              "value": "jsonl-to-array",
              "label": "JSONL → JSON array"
            }
          ]
        },
        {
          "key": "indent",
          "kind": "select",
          "label": "Array indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "minify",
              "label": "Minified"
            }
          ]
        },
        {
          "key": "skipEmptyLines",
          "kind": "checkbox",
          "label": "Skip empty lines",
          "default": true
        },
        {
          "key": "reportLineNumbers",
          "kind": "checkbox",
          "label": "Report line number on error",
          "default": true
        },
        {
          "key": "skipInvalidLines",
          "kind": "checkbox",
          "label": "Skip invalid lines",
          "default": false
        },
        {
          "key": "preserveKeyOrder",
          "kind": "checkbox",
          "label": "Preserve key order",
          "default": true
        }
      ],
      "keywords": [
        "jsonl converter",
        "ndjson converter",
        "json to jsonl",
        "jsonl to json",
        "newline delimited json",
        "json lines",
        "json",
        "jsonl",
        "ndjson"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "yaml-formatter",
      "name": "YAML formatter",
      "description": "Validate and reformat YAML, with clear line and column errors.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/yaml-formatter",
      "embed": "https://textarray.com/embed/yaml-formatter",
      "mode": "transform",
      "action": "Format YAML",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indentWidth",
          "kind": "select",
          "label": "Indent width",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            }
          ]
        },
        {
          "key": "sortKeys",
          "kind": "checkbox",
          "label": "Sort keys alphabetically",
          "default": false
        },
        {
          "key": "collapseLists",
          "kind": "checkbox",
          "label": "Collapse short lists",
          "default": false
        },
        {
          "key": "documentStart",
          "kind": "checkbox",
          "label": "Add --- document start",
          "default": false
        },
        {
          "key": "removeComments",
          "kind": "checkbox",
          "label": "Remove comments",
          "default": false
        }
      ],
      "keywords": [
        "yaml formatter",
        "yaml linter",
        "yaml beautifier",
        "yaml syntax checker",
        "format yaml",
        "validate yaml",
        "yml formatter"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "basic-auth-generator",
      "name": "Basic auth header generator",
      "description": "Build or decode an HTTP Basic Authorization header from a username and password.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/basic-auth-generator",
      "embed": "https://textarray.com/embed/basic-auth-generator",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output",
          "default": "header",
          "choices": [
            {
              "value": "header",
              "label": "Full header line"
            },
            {
              "value": "value",
              "label": "Base64 value only"
            }
          ]
        },
        {
          "key": "showCurl",
          "kind": "checkbox",
          "label": "Show curl example",
          "default": false
        }
      ],
      "keywords": [
        "authorization header",
        "basic auth header",
        "http basic authentication",
        "base64 username password",
        "basic auth encoder",
        "basic auth decoder",
        "curl authorization header",
        "base64"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "gitignore-generator",
      "name": "Gitignore generator",
      "description": "Build a .gitignore file from ready-made templates for languages, editors and operating systems.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/gitignore-generator",
      "embed": "https://textarray.com/embed/gitignore-generator",
      "mode": "generate",
      "action": "Generate .gitignore",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "node",
          "kind": "checkbox",
          "label": "Node",
          "default": true
        },
        {
          "key": "python",
          "kind": "checkbox",
          "label": "Python",
          "default": false
        },
        {
          "key": "rust",
          "kind": "checkbox",
          "label": "Rust",
          "default": false
        },
        {
          "key": "go",
          "kind": "checkbox",
          "label": "Go",
          "default": false
        },
        {
          "key": "java",
          "kind": "checkbox",
          "label": "Java",
          "default": false
        },
        {
          "key": "php",
          "kind": "checkbox",
          "label": "PHP",
          "default": false
        },
        {
          "key": "ruby",
          "kind": "checkbox",
          "label": "Ruby",
          "default": false
        },
        {
          "key": "dotnet",
          "kind": "checkbox",
          "label": ".NET",
          "default": false
        },
        {
          "key": "swift",
          "kind": "checkbox",
          "label": "Swift",
          "default": false
        },
        {
          "key": "android",
          "kind": "checkbox",
          "label": "Android",
          "default": false
        },
        {
          "key": "cpp",
          "kind": "checkbox",
          "label": "C/C++",
          "default": false
        },
        {
          "key": "dart",
          "kind": "checkbox",
          "label": "Dart",
          "default": false
        },
        {
          "key": "unity",
          "kind": "checkbox",
          "label": "Unity",
          "default": false
        },
        {
          "key": "terraform",
          "kind": "checkbox",
          "label": "Terraform",
          "default": false
        },
        {
          "key": "jetbrains",
          "kind": "checkbox",
          "label": "JetBrains",
          "default": false
        },
        {
          "key": "vscode",
          "kind": "checkbox",
          "label": "VS Code",
          "default": false
        },
        {
          "key": "vim",
          "kind": "checkbox",
          "label": "Vim",
          "default": false
        },
        {
          "key": "macos",
          "kind": "checkbox",
          "label": "macOS",
          "default": false
        },
        {
          "key": "windows",
          "kind": "checkbox",
          "label": "Windows",
          "default": false
        },
        {
          "key": "linux",
          "kind": "checkbox",
          "label": "Linux",
          "default": false
        },
        {
          "key": "mergeDuplicates",
          "kind": "checkbox",
          "label": "Merge duplicate rules",
          "default": true
        },
        {
          "key": "sortSections",
          "kind": "checkbox",
          "label": "Sort sections alphabetically",
          "default": false
        },
        {
          "key": "sortRules",
          "kind": "checkbox",
          "label": "Sort rules within sections",
          "default": false
        },
        {
          "key": "sectionComments",
          "kind": "checkbox",
          "label": "Add section comments",
          "default": true
        },
        {
          "key": "customRules",
          "kind": "text",
          "label": "Custom rules, added at the end",
          "default": ""
        }
      ],
      "keywords": [
        "create gitignore",
        ".gitignore file",
        "gitignore templates",
        "git ignore rules",
        "ignore node_modules",
        "node",
        "python",
        "rust",
        "go",
        "java",
        "php",
        "ruby",
        "dotnet",
        "swift",
        "android",
        "unity",
        "terraform",
        "jetbrains",
        "vscode",
        "macos",
        "windows",
        "linux"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "regex-escape",
      "name": "Regex escape",
      "description": "Escape the characters with special meaning in a regular expression, so text matches literally.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/regex-escape",
      "embed": "https://textarray.com/embed/regex-escape",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "escape",
          "choices": [
            {
              "value": "escape",
              "label": "Escape"
            },
            {
              "value": "unescape",
              "label": "Unescape"
            }
          ]
        },
        {
          "key": "dialect",
          "kind": "select",
          "label": "Dialect",
          "default": "javascript",
          "choices": [
            {
              "value": "javascript",
              "label": "JavaScript"
            },
            {
              "value": "pcre",
              "label": "PCRE"
            },
            {
              "value": "posix",
              "label": "POSIX (BRE)"
            }
          ]
        },
        {
          "key": "escapeDelimiter",
          "kind": "checkbox",
          "label": "Escape delimiter (/) too",
          "default": false
        },
        {
          "key": "perLine",
          "kind": "checkbox",
          "label": "Each line as its own pattern",
          "default": false
        },
        {
          "key": "wordBoundaries",
          "kind": "checkbox",
          "label": "Wrap in word boundaries",
          "default": false
        },
        {
          "key": "joinAlternation",
          "kind": "checkbox",
          "label": "Join lines into one alternation",
          "default": false
        }
      ],
      "keywords": [
        "regex escape",
        "escape regex",
        "regexp escape",
        "escape special characters",
        "regex metacharacters",
        "quote regex",
        "regex literal string",
        "unescape regex"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "tracking-param-remover",
      "name": "Tracking parameter remover",
      "description": "Strip UTM tags and other tracking parameters from a URL and get a clean link.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/tracking-param-remover",
      "embed": "https://textarray.com/embed/tracking-param-remover",
      "mode": "transform",
      "action": "Remove tracking parameters",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "customParams",
          "kind": "text",
          "label": "Also remove (comma-separated)",
          "default": ""
        },
        {
          "key": "keepParams",
          "kind": "text",
          "label": "Always keep (comma-separated)",
          "default": ""
        },
        {
          "key": "removeHash",
          "kind": "checkbox",
          "label": "Remove #fragment",
          "default": false
        },
        {
          "key": "removeTrailingSlash",
          "kind": "checkbox",
          "label": "Remove trailing slash",
          "default": false
        },
        {
          "key": "dedupeUrls",
          "kind": "checkbox",
          "label": "Remove duplicate URLs",
          "default": false
        },
        {
          "key": "sortParams",
          "kind": "checkbox",
          "label": "Sort remaining parameters",
          "default": false
        }
      ],
      "keywords": [
        "tracking parameter remover",
        "remove utm parameters",
        "strip utm tags",
        "clean url",
        "remove fbclid",
        "remove gclid",
        "utm stripper",
        "url cleaner"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "json-path-extractor",
      "name": "JSONPath extractor",
      "description": "Pull matching values out of a JSON document with a JSONPath or JSON Pointer expression.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-path-extractor",
      "embed": "https://textarray.com/embed/json-path-extractor",
      "mode": "transform",
      "action": "Extract values",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "expression",
          "kind": "text",
          "label": "JSONPath / Pointer expression",
          "default": "$"
        },
        {
          "key": "syntax",
          "kind": "select",
          "label": "Expression syntax",
          "default": "jsonpath",
          "choices": [
            {
              "value": "jsonpath",
              "label": "JSONPath ($.users[*].email)"
            },
            {
              "value": "pointer",
              "label": "JSON Pointer (/users/0/email)"
            }
          ]
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "lines",
          "choices": [
            {
              "value": "lines",
              "label": "List of lines"
            },
            {
              "value": "json",
              "label": "JSON array"
            },
            {
              "value": "csv",
              "label": "CSV table"
            }
          ]
        },
        {
          "key": "uniqueMatches",
          "kind": "checkbox",
          "label": "Unique matches only",
          "default": false
        },
        {
          "key": "showPaths",
          "kind": "checkbox",
          "label": "Show path for each match",
          "default": false
        }
      ],
      "keywords": [
        "jsonpath extractor",
        "json path",
        "json pointer",
        "extract json values",
        "jsonpath query",
        "json query tool",
        "json",
        "jsonpath"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "http-header-parser",
      "name": "HTTP header parser",
      "description": "Parse a pasted block of raw HTTP request or response headers into readable name/value pairs.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/http-header-parser",
      "embed": "https://textarray.com/embed/http-header-parser",
      "mode": "transform",
      "action": "Parse headers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "normalizeCase",
          "kind": "checkbox",
          "label": "Normalize header name casing",
          "default": true
        },
        {
          "key": "expandCompound",
          "kind": "checkbox",
          "label": "Expand compound headers (Cache-Control, CSP…)",
          "default": false
        },
        {
          "key": "sortAlpha",
          "kind": "checkbox",
          "label": "Sort headers alphabetically",
          "default": false
        },
        {
          "key": "warnMissingSecurity",
          "kind": "checkbox",
          "label": "Warn about missing security headers",
          "default": false
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "json",
              "label": "JSON"
            },
            {
              "value": "grade",
              "label": "Security grade"
            }
          ]
        }
      ],
      "keywords": [
        "http header parser",
        "parse http headers",
        "header analyzer",
        "response headers",
        "request headers",
        "security headers checker",
        "cache-control parser",
        "content-security-policy",
        "http",
        "json"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "cookie-parser",
      "name": "Cookie parser",
      "description": "Break a Cookie or Set-Cookie header into individual cookies, values and attributes.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/cookie-parser",
      "embed": "https://textarray.com/embed/cookie-parser",
      "mode": "transform",
      "action": "Parse cookies",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Header",
          "default": "cookie",
          "choices": [
            {
              "value": "cookie",
              "label": "Cookie (request)"
            },
            {
              "value": "setCookie",
              "label": "Set-Cookie (response)"
            }
          ]
        },
        {
          "key": "urlDecode",
          "kind": "checkbox",
          "label": "URL-decode values",
          "default": true
        },
        {
          "key": "humanExpiry",
          "kind": "checkbox",
          "label": "Show expiry in readable form",
          "default": true
        },
        {
          "key": "flagInsecure",
          "kind": "checkbox",
          "label": "Flag cookies missing Secure or HttpOnly",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "json",
              "label": "JSON"
            },
            {
              "value": "audit",
              "label": "Security audit"
            }
          ]
        }
      ],
      "keywords": [
        "cookie parser",
        "parse cookie header",
        "set-cookie parser",
        "cookie attributes",
        "http cookie decoder",
        "cookie inspector",
        "samesite",
        "httponly secure flag"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "http-status-lookup",
      "name": "HTTP status code lookup",
      "description": "Find HTTP status codes in text or a log and see the name, class and meaning of each.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/http-status-lookup",
      "embed": "https://textarray.com/embed/http-status-lookup",
      "mode": "transform",
      "action": "Look up status codes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "log",
          "choices": [
            {
              "value": "single",
              "label": "Single code"
            },
            {
              "value": "log",
              "label": "Search in log"
            }
          ]
        },
        {
          "key": "sortByCount",
          "kind": "checkbox",
          "label": "Sort by occurrences",
          "default": false
        },
        {
          "key": "errorsOnly",
          "kind": "checkbox",
          "label": "Errors only (4xx/5xx)",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List"
            },
            {
              "value": "table",
              "label": "Table"
            }
          ]
        }
      ],
      "keywords": [
        "http status code lookup",
        "http status codes",
        "status code checker",
        "status code meaning",
        "http error codes list",
        "status code reference",
        "404 not found",
        "500 internal server error",
        "4xx client error",
        "5xx server error"
      ],
      "updated": "2026-08-01"
    },
    {
      "slug": "semver-sorter",
      "name": "SemVer sorter and comparator",
      "description": "Sort a list of version numbers by semantic versioning precedence.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/semver-sorter",
      "embed": "https://textarray.com/embed/semver-sorter",
      "mode": "transform",
      "action": "Sort versions",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "sort",
          "choices": [
            {
              "value": "sort",
              "label": "Sort versions"
            },
            {
              "value": "compare",
              "label": "Compare pairs"
            },
            {
              "value": "inspect",
              "label": "Inspect and validate"
            }
          ]
        },
        {
          "key": "range",
          "kind": "text",
          "label": "Range to check against",
          "default": ""
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "asc",
          "choices": [
            {
              "value": "asc",
              "label": "Ascending"
            },
            {
              "value": "desc",
              "label": "Descending"
            }
          ]
        },
        {
          "key": "ignoreVPrefix",
          "kind": "checkbox",
          "label": "Ignore \"v\" prefix",
          "default": true
        },
        {
          "key": "excludePrerelease",
          "kind": "checkbox",
          "label": "Exclude pre-release versions",
          "default": false
        },
        {
          "key": "keepHighestPerBranch",
          "kind": "select",
          "label": "Keep only the highest version per",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Keep every version"
            },
            {
              "value": "major",
              "label": "Major branch"
            },
            {
              "value": "minor",
              "label": "Minor branch"
            }
          ]
        },
        {
          "key": "markInvalid",
          "kind": "checkbox",
          "label": "Mark lines that are not valid SemVer",
          "default": true
        }
      ],
      "keywords": [
        "semver sorter",
        "semantic versioning sort",
        "version number sorter",
        "compare semver versions",
        "sort version numbers",
        "semver comparator",
        "npm version sort",
        "version precedence",
        "semver"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "mime-type-lookup",
      "name": "MIME type lookup",
      "description": "Look up the MIME type for a file extension, or the usual extensions for a MIME type.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/mime-type-lookup",
      "embed": "https://textarray.com/embed/mime-type-lookup",
      "mode": "transform",
      "action": "Look up MIME types",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "extToMime",
          "choices": [
            {
              "value": "extToMime",
              "label": "Extension → MIME type"
            },
            {
              "value": "mimeToExt",
              "label": "MIME type → extension"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "plain",
          "choices": [
            {
              "value": "plain",
              "label": "Plain list"
            },
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "nginx",
              "label": "nginx types"
            },
            {
              "value": "apache",
              "label": "Apache AddType"
            }
          ]
        },
        {
          "key": "markUnknown",
          "kind": "checkbox",
          "label": "Mark unknown entries",
          "default": true
        }
      ],
      "keywords": [
        "mime type lookup",
        "mime type",
        "file extension to mime type",
        "content-type lookup",
        "mime type of extension",
        "nginx mime types",
        "apache addtype",
        "mime",
        "content-type",
        "json",
        "base64"
      ],
      "updated": "2026-08-01"
    },
    {
      "slug": "text-to-array",
      "name": "Text to array converter",
      "description": "Turn a pasted list into an array literal in JavaScript, Python, PHP, JSON, SQL and more.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/text-to-array",
      "embed": "https://textarray.com/embed/text-to-array",
      "mode": "transform",
      "action": "Convert to array",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "inputDelimiter",
          "kind": "select",
          "label": "Split input on",
          "default": "newline",
          "choices": [
            {
              "value": "newline",
              "label": "New line"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customInputDelimiter",
          "kind": "text",
          "label": "Custom input delimiter",
          "default": ""
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "javascript",
          "choices": [
            {
              "value": "javascript",
              "label": "JavaScript array"
            },
            {
              "value": "python",
              "label": "Python list"
            },
            {
              "value": "php",
              "label": "PHP array"
            },
            {
              "value": "json",
              "label": "JSON array"
            },
            {
              "value": "sql",
              "label": "SQL IN() clause"
            },
            {
              "value": "csv",
              "label": "CSV"
            },
            {
              "value": "quoted-list",
              "label": "Quoted list"
            },
            {
              "value": "custom",
              "label": "Custom delimiter"
            }
          ]
        },
        {
          "key": "customOutputDelimiter",
          "kind": "text",
          "label": "Custom output delimiter",
          "default": " | "
        },
        {
          "key": "quoteType",
          "kind": "select",
          "label": "Quote style",
          "default": "double",
          "choices": [
            {
              "value": "double",
              "label": "Double quotes"
            },
            {
              "value": "single",
              "label": "Single quotes"
            }
          ]
        },
        {
          "key": "unquoteNumbers",
          "kind": "checkbox",
          "label": "Leave numbers unquoted",
          "default": true
        },
        {
          "key": "variableName",
          "kind": "text",
          "label": "Variable name",
          "default": "items"
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print with indentation",
          "default": true
        },
        {
          "key": "trailingComma",
          "kind": "checkbox",
          "label": "Trailing comma",
          "default": false
        },
        {
          "key": "sqlColumn",
          "kind": "text",
          "label": "SQL column name",
          "default": ""
        },
        {
          "key": "sqlNotIn",
          "kind": "checkbox",
          "label": "SQL NOT IN",
          "default": false
        },
        {
          "key": "sqlBatchSize",
          "kind": "number",
          "label": "SQL batch size",
          "default": 0,
          "min": 0,
          "max": 100000,
          "step": 100
        },
        {
          "key": "escapeSpecial",
          "kind": "checkbox",
          "label": "Escape special characters",
          "default": true
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        },
        {
          "key": "removeEmpty",
          "kind": "checkbox",
          "label": "Remove empty items",
          "default": true
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": false
        },
        {
          "key": "dedupeCaseInsensitive",
          "kind": "checkbox",
          "label": "Case-insensitive duplicates",
          "default": false
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort alphabetically",
          "default": false
        },
        {
          "key": "caseTransform",
          "kind": "select",
          "label": "Change case",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Keep original case"
            },
            {
              "value": "lower",
              "label": "lowercase"
            },
            {
              "value": "upper",
              "label": "UPPERCASE"
            }
          ]
        }
      ],
      "keywords": [
        "text to array",
        "string to array converter",
        "list to array",
        "array literal generator",
        "lines to json array",
        "convert list to code",
        "javascript array",
        "python list",
        "php array",
        "json array",
        "sql in clause"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "ruby-hash-to-json",
      "name": "Ruby hash to JSON",
      "description": "Convert a Ruby hash literal or pp/inspect output to JSON, or back.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ruby-hash-to-json",
      "embed": "https://textarray.com/embed/ruby-hash-to-json",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "ruby-to-json",
          "choices": [
            {
              "value": "ruby-to-json",
              "label": "Ruby hash → JSON"
            },
            {
              "value": "json-to-ruby",
              "label": "JSON → Ruby hash"
            }
          ]
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print",
          "default": true
        },
        {
          "key": "indentSize",
          "kind": "select",
          "label": "Indent size",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "symbolKeyStyle",
          "kind": "select",
          "label": "Symbol keys as",
          "default": "plain",
          "choices": [
            {
              "value": "plain",
              "label": "Plain strings (\"name\")"
            },
            {
              "value": "colon",
              "label": "Leading colon (\":name\")"
            }
          ]
        },
        {
          "key": "sortKeys",
          "kind": "checkbox",
          "label": "Sort keys alphabetically",
          "default": false
        },
        {
          "key": "nilHandling",
          "kind": "select",
          "label": "Ruby nil becomes",
          "default": "null",
          "choices": [
            {
              "value": "null",
              "label": "JSON null"
            },
            {
              "value": "omit",
              "label": "Omitted entirely"
            }
          ]
        },
        {
          "key": "rubyKeyStyle",
          "kind": "select",
          "label": "Ruby key style (JSON → Ruby)",
          "default": "shorthand",
          "choices": [
            {
              "value": "shorthand",
              "label": "Shorthand (key: value)"
            },
            {
              "value": "rocket",
              "label": "Hash rocket (:key => value)"
            }
          ]
        }
      ],
      "keywords": [
        "ruby hash to json",
        "ruby hash converter",
        "ruby to json",
        "json to ruby hash",
        "ruby pp output",
        "ruby inspect output",
        "hash rocket",
        "ruby symbols",
        "json"
      ],
      "updated": "2026-08-03"
    },
    {
      "slug": "array-to-text",
      "name": "Array to text",
      "description": "Parse a JavaScript, Python, PHP, JSON or SQL array literal and list its items as plain text.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/array-to-text",
      "embed": "https://textarray.com/embed/array-to-text",
      "mode": "transform",
      "action": "Convert to text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "outputDelimiter",
          "kind": "select",
          "label": "Join output with",
          "default": "newline",
          "choices": [
            {
              "value": "newline",
              "label": "New line"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customOutputDelimiter",
          "kind": "text",
          "label": "Custom output delimiter",
          "default": ""
        },
        {
          "key": "stripQuotes",
          "kind": "checkbox",
          "label": "Remove quotes",
          "default": true
        },
        {
          "key": "unescapeChars",
          "kind": "checkbox",
          "label": "Unescape characters",
          "default": true
        },
        {
          "key": "flattenNested",
          "kind": "checkbox",
          "label": "Flatten nested arrays",
          "default": false
        },
        {
          "key": "numberItems",
          "kind": "checkbox",
          "label": "Number items",
          "default": false
        },
        {
          "key": "prefix",
          "kind": "text",
          "label": "Prefix",
          "default": ""
        },
        {
          "key": "suffix",
          "kind": "text",
          "label": "Suffix",
          "default": ""
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        },
        {
          "key": "removeEmpty",
          "kind": "checkbox",
          "label": "Remove empty items",
          "default": true
        }
      ],
      "keywords": [
        "array to text",
        "array to list converter",
        "parse array literal",
        "json array to lines",
        "javascript array to text",
        "python list to text",
        "php array to text",
        "sql in clause to list",
        "flatten array",
        "json",
        "php",
        "sql"
      ],
      "updated": "2026-08-05"
    },
    {
      "slug": "js-formatter",
      "name": "JavaScript formatter",
      "description": "Reformat JavaScript or TypeScript into consistent, readable code.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/js-formatter",
      "embed": "https://textarray.com/embed/js-formatter",
      "mode": "transform",
      "action": "Format code",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tab",
              "label": "Tabs"
            }
          ]
        },
        {
          "key": "quotes",
          "kind": "select",
          "label": "Quotes",
          "default": "double",
          "choices": [
            {
              "value": "double",
              "label": "Double (\"…\")"
            },
            {
              "value": "single",
              "label": "Single ('…')"
            }
          ]
        },
        {
          "key": "semicolons",
          "kind": "checkbox",
          "label": "Semicolons",
          "default": true
        },
        {
          "key": "trailingComma",
          "kind": "checkbox",
          "label": "Trailing commas",
          "default": true
        },
        {
          "key": "maxLineWidth",
          "kind": "range",
          "label": "Max line width",
          "default": 80,
          "min": 40,
          "max": 200
        },
        {
          "key": "minify",
          "kind": "checkbox",
          "label": "Minify",
          "default": false
        }
      ],
      "keywords": [
        "js formatter",
        "format javascript",
        "format typescript",
        "beautify javascript",
        "js pretty print",
        "unminify javascript",
        "code formatter",
        "javascript",
        "typescript",
        "js",
        "ts"
      ],
      "updated": "2026-08-05"
    },
    {
      "slug": "log-entity-extractor",
      "name": "Log entity extractor",
      "description": "Pull every IP, domain, email, URL, path, timestamp, hash, UUID and MAC address out of a log in one pass.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/log-entity-extractor",
      "embed": "https://textarray.com/embed/log-entity-extractor",
      "mode": "transform",
      "action": "Extract entities",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "typeIpv4",
          "kind": "checkbox",
          "label": "IPv4 addresses",
          "default": true
        },
        {
          "key": "typeIpv6",
          "kind": "checkbox",
          "label": "IPv6 addresses",
          "default": true
        },
        {
          "key": "typeDomain",
          "kind": "checkbox",
          "label": "Domains",
          "default": true
        },
        {
          "key": "typeEmail",
          "kind": "checkbox",
          "label": "Email addresses",
          "default": true
        },
        {
          "key": "typeUrl",
          "kind": "checkbox",
          "label": "URLs",
          "default": true
        },
        {
          "key": "typePath",
          "kind": "checkbox",
          "label": "File paths",
          "default": true
        },
        {
          "key": "typeDatetime",
          "kind": "checkbox",
          "label": "Dates & timestamps",
          "default": true
        },
        {
          "key": "typeHash",
          "kind": "checkbox",
          "label": "Hashes (MD5, SHA-1, SHA-256)",
          "default": true
        },
        {
          "key": "typeUuid",
          "kind": "checkbox",
          "label": "UUIDs",
          "default": true
        },
        {
          "key": "typeMac",
          "kind": "checkbox",
          "label": "MAC addresses",
          "default": true
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": true
        },
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "occurrence",
          "choices": [
            {
              "value": "occurrence",
              "label": "Order of appearance"
            },
            {
              "value": "alphabetical",
              "label": "Alphabetical"
            }
          ]
        },
        {
          "key": "showCounts",
          "kind": "checkbox",
          "label": "Show occurrence count per value",
          "default": false
        },
        {
          "key": "defang",
          "kind": "checkbox",
          "label": "Defang output (hxxp://, 1.2.3[.]4)",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "grouped",
          "choices": [
            {
              "value": "grouped",
              "label": "Grouped by type"
            },
            {
              "value": "flat",
              "label": "Flat list"
            },
            {
              "value": "csv",
              "label": "CSV"
            },
            {
              "value": "json",
              "label": "JSON"
            }
          ]
        },
        {
          "key": "excludePrivate",
          "kind": "checkbox",
          "label": "Exclude private and loopback IP ranges",
          "default": false
        }
      ],
      "keywords": [
        "log entity extractor",
        "log parser",
        "extract ip addresses from log",
        "extract entities",
        "log analysis tool",
        "indicators of compromise",
        "ioc extractor",
        "stack trace parser",
        "email header parser",
        "packet dump parser",
        "md5",
        "sha1",
        "sha256",
        "uuid",
        "mac address",
        "csv",
        "json"
      ],
      "updated": "2026-08-06"
    },
    {
      "slug": "json-to-go-struct",
      "name": "JSON to Go struct",
      "description": "Turn a JSON sample into Go struct definitions with inferred types and tags.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-go-struct",
      "embed": "https://textarray.com/embed/json-to-go-struct",
      "mode": "transform",
      "action": "Generate Go struct",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "rootName",
          "kind": "text",
          "label": "Root struct name",
          "default": "Root"
        },
        {
          "key": "tagFormat",
          "kind": "select",
          "label": "JSON tag format",
          "default": "original",
          "choices": [
            {
              "value": "original",
              "label": "Original key"
            },
            {
              "value": "snake_case",
              "label": "snake_case"
            },
            {
              "value": "camelCase",
              "label": "camelCase"
            }
          ]
        },
        {
          "key": "omitempty",
          "kind": "checkbox",
          "label": "Add omitempty",
          "default": false
        },
        {
          "key": "pointerOptional",
          "kind": "checkbox",
          "label": "Pointers for optional fields",
          "default": false
        },
        {
          "key": "inlineNested",
          "kind": "checkbox",
          "label": "Inline nested structs",
          "default": false
        },
        {
          "key": "useRawMessage",
          "kind": "checkbox",
          "label": "Use json.RawMessage for unknown types",
          "default": false
        },
        {
          "key": "useAny",
          "kind": "checkbox",
          "label": "Use any instead of interface{}",
          "default": true
        },
        {
          "key": "mergeArrayTypes",
          "kind": "checkbox",
          "label": "Merge array element shapes",
          "default": true
        },
        {
          "key": "commentOriginalKey",
          "kind": "checkbox",
          "label": "Comment original key",
          "default": false
        }
      ],
      "keywords": [
        "json to go struct",
        "json to golang struct",
        "json to go",
        "golang json tags",
        "struct from json",
        "generate go types from json",
        "json",
        "go",
        "golang"
      ],
      "updated": "2026-08-06"
    },
    {
      "slug": "json-to-python-dataclass",
      "name": "JSON to Python dataclass",
      "description": "Turn a JSON sample into typed Python classes — dataclass, Pydantic, TypedDict or NamedTuple.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-python-dataclass",
      "embed": "https://textarray.com/embed/json-to-python-dataclass",
      "mode": "transform",
      "action": "Generate Python",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Output style",
          "default": "dataclass",
          "choices": [
            {
              "value": "dataclass",
              "label": "dataclass"
            },
            {
              "value": "pydantic",
              "label": "Pydantic BaseModel"
            },
            {
              "value": "typeddict",
              "label": "TypedDict"
            },
            {
              "value": "namedtuple",
              "label": "NamedTuple"
            }
          ]
        },
        {
          "key": "rootName",
          "kind": "text",
          "label": "Root class name",
          "default": "Root"
        },
        {
          "key": "optionalForMissing",
          "kind": "checkbox",
          "label": "Optional for null fields",
          "default": true
        },
        {
          "key": "includeDefaults",
          "kind": "checkbox",
          "label": "Add default values",
          "default": true
        },
        {
          "key": "useFieldAlias",
          "kind": "checkbox",
          "label": "Alias invalid field names",
          "default": true
        },
        {
          "key": "futureAnnotations",
          "kind": "checkbox",
          "label": "from __future__ import annotations",
          "default": false
        },
        {
          "key": "useBuiltinGenerics",
          "kind": "checkbox",
          "label": "Use list[T] instead of List[T]",
          "default": true
        },
        {
          "key": "sortByDependencies",
          "kind": "checkbox",
          "label": "Sort classes by dependencies",
          "default": true
        }
      ],
      "keywords": [
        "json to python",
        "json to dataclass",
        "python dataclass generator",
        "json to pydantic",
        "json to typeddict",
        "json to namedtuple",
        "json schema to python",
        "python type hints from json",
        "json",
        "pydantic",
        "dataclass"
      ],
      "updated": "2026-08-06"
    },
    {
      "slug": "json-to-zod-schema",
      "name": "JSON to Zod schema",
      "description": "Generate a Zod validation schema and TypeScript types from a JSON sample, with format and enum detection.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-zod-schema",
      "embed": "https://textarray.com/embed/json-to-zod-schema",
      "mode": "transform",
      "action": "Generate Zod schema",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "schemaName",
          "kind": "text",
          "label": "Schema name",
          "default": "Schema"
        },
        {
          "key": "inferType",
          "kind": "checkbox",
          "label": "Export inferred TypeScript type",
          "default": true
        },
        {
          "key": "nullHandling",
          "kind": "select",
          "label": "Null handling",
          "default": "nullable",
          "choices": [
            {
              "value": "nullable",
              "label": "Nullable"
            },
            {
              "value": "optional",
              "label": "Optional"
            }
          ]
        },
        {
          "key": "strictObjects",
          "kind": "checkbox",
          "label": "Strict objects (.strict())",
          "default": false
        },
        {
          "key": "detectFormats",
          "kind": "checkbox",
          "label": "Detect email, URL, UUID and date formats",
          "default": true
        },
        {
          "key": "detectEnums",
          "kind": "checkbox",
          "label": "Detect enums from repeated values",
          "default": true
        },
        {
          "key": "splitNestedSchemas",
          "kind": "checkbox",
          "label": "Split nested objects into named schemas",
          "default": false
        }
      ],
      "keywords": [
        "json to zod",
        "json to zod schema",
        "zod schema generator",
        "generate zod from json",
        "json validation schema",
        "zod object schema",
        "zod",
        "typescript",
        "z.infer",
        "json schema validator"
      ],
      "updated": "2026-08-06"
    },
    {
      "slug": "xpath-evaluator",
      "name": "XPath evaluator",
      "description": "Run an XPath 1.0 expression against pasted XML and see every match, its value and its path.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/xpath-evaluator",
      "embed": "https://textarray.com/embed/xpath-evaluator",
      "mode": "transform",
      "action": "Evaluate expression",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "expression",
          "kind": "text",
          "label": "XPath expression",
          "default": ""
        },
        {
          "key": "resultType",
          "kind": "select",
          "label": "Result type",
          "default": "nodes",
          "choices": [
            {
              "value": "nodes",
              "label": "Node-set (matches)"
            },
            {
              "value": "string",
              "label": "String"
            },
            {
              "value": "number",
              "label": "Number"
            },
            {
              "value": "boolean",
              "label": "Boolean"
            }
          ]
        },
        {
          "key": "matchOutput",
          "kind": "select",
          "label": "Show matches as",
          "default": "text",
          "choices": [
            {
              "value": "text",
              "label": "Text content"
            },
            {
              "value": "xml",
              "label": "Serialized XML"
            }
          ]
        },
        {
          "key": "showIndex",
          "kind": "checkbox",
          "label": "Number the matches",
          "default": false
        },
        {
          "key": "showPath",
          "kind": "checkbox",
          "label": "Show the path to each match",
          "default": false
        },
        {
          "key": "namespaceBindings",
          "kind": "text",
          "label": "Namespace bindings (prefix=URI, space separated)",
          "default": ""
        },
        {
          "key": "ignoreNamespaces",
          "kind": "checkbox",
          "label": "Ignore namespaces",
          "default": false
        }
      ],
      "keywords": [
        "xpath tester",
        "xpath query tool",
        "evaluate xpath expression",
        "xpath 1.0",
        "xpath online",
        "xml",
        "xslt",
        "xquery"
      ],
      "updated": "2026-08-06"
    },
    {
      "slug": "nginx-config-generator",
      "name": "NGINX config generator",
      "description": "Builds a complete NGINX server block from your domain, TLS, proxy, caching and security-header options.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/nginx-config-generator",
      "embed": "https://textarray.com/embed/nginx-config-generator",
      "mode": "generate",
      "action": "Generate",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "serverName",
          "kind": "text",
          "label": "Domain and aliases",
          "default": "example.com www.example.com"
        },
        {
          "key": "root",
          "kind": "text",
          "label": "Document root",
          "default": "/var/www/example.com"
        },
        {
          "key": "enableSsl",
          "kind": "checkbox",
          "label": "Listen on 443 with HTTP/2",
          "default": true
        },
        {
          "key": "redirectHttps",
          "kind": "checkbox",
          "label": "Redirect HTTP to HTTPS",
          "default": true
        },
        {
          "key": "sslCertificate",
          "kind": "text",
          "label": "Certificate path",
          "default": "/etc/ssl/certs/example.com.crt"
        },
        {
          "key": "sslCertificateKey",
          "kind": "text",
          "label": "Private key path",
          "default": "/etc/ssl/private/example.com.key"
        },
        {
          "key": "reverseProxy",
          "kind": "checkbox",
          "label": "Reverse proxy to an upstream",
          "default": false
        },
        {
          "key": "upstream",
          "kind": "text",
          "label": "Upstream address",
          "default": "127.0.0.1:3000"
        },
        {
          "key": "staticCache",
          "kind": "checkbox",
          "label": "Cache static assets",
          "default": true
        },
        {
          "key": "cacheExpires",
          "kind": "text",
          "label": "Cache expiration",
          "default": "30d"
        },
        {
          "key": "gzip",
          "kind": "checkbox",
          "label": "Gzip compression",
          "default": true
        },
        {
          "key": "brotli",
          "kind": "checkbox",
          "label": "Brotli compression",
          "default": false
        },
        {
          "key": "spaFallback",
          "kind": "checkbox",
          "label": "SPA fallback to index.html",
          "default": false
        },
        {
          "key": "securityHeaders",
          "kind": "checkbox",
          "label": "Security headers (HSTS, X-Content-Type-Options, Referrer-Policy)",
          "default": true
        },
        {
          "key": "blockHiddenFiles",
          "kind": "checkbox",
          "label": "Block access to hidden files",
          "default": true
        },
        {
          "key": "errorPage",
          "kind": "text",
          "label": "Custom 404 page",
          "default": ""
        },
        {
          "key": "maxBodySize",
          "kind": "text",
          "label": "Max request body size",
          "default": "10m"
        },
        {
          "key": "accessLog",
          "kind": "checkbox",
          "label": "Access and error logs",
          "default": true
        }
      ],
      "keywords": [
        "nginx config generator",
        "nginx server block generator",
        "generate nginx config",
        "nginx reverse proxy config",
        "nginx ssl config",
        "nginx virtual host generator",
        "nginx",
        "server block",
        "reverse proxy",
        "http2",
        "gzip",
        "brotli"
      ],
      "updated": "2026-08-06"
    },
    {
      "slug": "cron-expression-builder",
      "name": "Cron expression builder",
      "description": "Build a cron expression from simple options and see what it means and when it next runs.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/cron-expression-builder",
      "embed": "https://textarray.com/embed/cron-expression-builder",
      "mode": "generate",
      "action": "Build expression",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "preset",
          "kind": "select",
          "label": "Preset",
          "default": "daily",
          "choices": [
            {
              "value": "everyMinute",
              "label": "Every minute"
            },
            {
              "value": "everyNMinutes",
              "label": "Every N minutes"
            },
            {
              "value": "hourly",
              "label": "Hourly"
            },
            {
              "value": "daily",
              "label": "Daily at a time"
            },
            {
              "value": "weekly",
              "label": "Weekly on selected days"
            },
            {
              "value": "monthly",
              "label": "Monthly on a day"
            },
            {
              "value": "yearly",
              "label": "Yearly"
            },
            {
              "value": "custom",
              "label": "Custom fields"
            }
          ]
        },
        {
          "key": "everyNMinutes",
          "kind": "number",
          "label": "Every N minutes",
          "default": 5,
          "min": 1,
          "max": 59,
          "step": 1
        },
        {
          "key": "hour",
          "kind": "number",
          "label": "Hour",
          "default": 9,
          "min": 0,
          "max": 23,
          "step": 1
        },
        {
          "key": "minute",
          "kind": "number",
          "label": "Minute",
          "default": 0,
          "min": 0,
          "max": 59,
          "step": 1
        },
        {
          "key": "weekdays",
          "kind": "text",
          "label": "Weekdays (0=Sun … 6=Sat)",
          "default": "1"
        },
        {
          "key": "domDay",
          "kind": "number",
          "label": "Day of month",
          "default": 1,
          "min": 1,
          "max": 31,
          "step": 1
        },
        {
          "key": "month",
          "kind": "number",
          "label": "Month",
          "default": 1,
          "min": 1,
          "max": 12,
          "step": 1
        },
        {
          "key": "customMinute",
          "kind": "text",
          "label": "Minute field",
          "default": "*"
        },
        {
          "key": "customHour",
          "kind": "text",
          "label": "Hour field",
          "default": "*"
        },
        {
          "key": "customDom",
          "kind": "text",
          "label": "Day-of-month field",
          "default": "*"
        },
        {
          "key": "customMonth",
          "kind": "text",
          "label": "Month field",
          "default": "*"
        },
        {
          "key": "customDow",
          "kind": "text",
          "label": "Day-of-week field",
          "default": "*"
        },
        {
          "key": "useNames",
          "kind": "checkbox",
          "label": "Use month/weekday names",
          "default": false
        },
        {
          "key": "withSeconds",
          "kind": "checkbox",
          "label": "6-field syntax with seconds",
          "default": false
        },
        {
          "key": "seconds",
          "kind": "number",
          "label": "Seconds",
          "default": 0,
          "min": 0,
          "max": 59,
          "step": 1
        },
        {
          "key": "useMacro",
          "kind": "checkbox",
          "label": "Prefer @macro shorthand when possible",
          "default": true
        },
        {
          "key": "runs",
          "kind": "number",
          "label": "Upcoming runs to show",
          "default": 5,
          "min": 1,
          "max": 20,
          "step": 1
        },
        {
          "key": "timezone",
          "kind": "select",
          "label": "Preview timezone",
          "default": "local",
          "choices": [
            {
              "value": "local",
              "label": "Your local time"
            },
            {
              "value": "UTC",
              "label": "UTC"
            },
            {
              "value": "America/New_York",
              "label": "New York"
            },
            {
              "value": "America/Los_Angeles",
              "label": "Los Angeles"
            },
            {
              "value": "Europe/London",
              "label": "London"
            },
            {
              "value": "Europe/Berlin",
              "label": "Berlin"
            },
            {
              "value": "Europe/Prague",
              "label": "Prague"
            },
            {
              "value": "Asia/Tokyo",
              "label": "Tokyo"
            },
            {
              "value": "Australia/Sydney",
              "label": "Sydney"
            }
          ]
        }
      ],
      "keywords": [
        "cron expression builder",
        "cron job generator",
        "crontab builder",
        "cron schedule generator",
        "cron syntax helper",
        "crontab generator",
        "cron",
        "crontab",
        "@daily",
        "cron next run"
      ],
      "updated": "2026-08-06"
    },
    {
      "slug": "remove-first-line",
      "name": "Remove first line",
      "description": "Delete the first N lines from your text instantly.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-first-line",
      "embed": "https://textarray.com/embed/remove-first-line",
      "mode": "transform",
      "action": "Remove lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "Number of lines to remove",
          "default": 1,
          "min": 1,
          "step": 1
        }
      ],
      "keywords": [
        "remove first line",
        "delete first line",
        "skip first line",
        "extract remaining lines"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-last-line",
      "name": "Remove last line",
      "description": "Delete the last N lines from your text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-last-line",
      "embed": "https://textarray.com/embed/remove-last-line",
      "mode": "transform",
      "action": "Remove lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "Number of lines to remove",
          "default": 1,
          "min": 1,
          "max": 10000
        }
      ],
      "keywords": [
        "remove last line",
        "delete last line",
        "strip last line",
        "remove trailing line",
        "drop last line",
        "eliminate last line",
        "remove final line"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-leading-zeros",
      "name": "Remove leading zeros",
      "description": "Strip leading zeros from numbers in your text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-leading-zeros",
      "embed": "https://textarray.com/embed/remove-leading-zeros",
      "mode": "transform",
      "action": "Remove zeros",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keepSingleZero",
          "kind": "checkbox",
          "label": "Keep single zero",
          "default": true
        }
      ],
      "keywords": [
        "remove leading zeros",
        "strip leading zeros",
        "leading zeros remover",
        "remove zeros from numbers",
        "zero stripper"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-text-in-brackets",
      "name": "Remove text in brackets",
      "description": "Strip out text enclosed in brackets and keep only the content you need.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-text-in-brackets",
      "embed": "https://textarray.com/embed/remove-text-in-brackets",
      "mode": "transform",
      "action": "Remove brackets",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "kind",
          "kind": "select",
          "label": "Bracket type",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All brackets"
            },
            {
              "value": "round",
              "label": "Round ()"
            },
            {
              "value": "square",
              "label": "Square []"
            },
            {
              "value": "curly",
              "label": "Curly {}"
            }
          ]
        }
      ],
      "keywords": [
        "remove brackets",
        "remove parentheses",
        "remove text in brackets",
        "clean brackets",
        "bracket removal"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "remove-repeated-words",
      "name": "Remove repeated words",
      "description": "Collapse consecutive duplicate words within each line, instantly.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/remove-repeated-words",
      "embed": "https://textarray.com/embed/remove-repeated-words",
      "mode": "transform",
      "action": "Remove repeated words",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Case insensitive",
          "default": true
        }
      ],
      "keywords": [
        "remove repeated words",
        "duplicate words",
        "remove duplicate words",
        "repeated text",
        "word deduplication",
        "remove word repetition",
        "consecutive duplicate words",
        "word repetition removal",
        "remove duplicate adjacent words",
        "delete repeated word",
        "stuttering words fix"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "keep-only-letters",
      "name": "Keep only letters",
      "description": "Remove all characters except letters, optionally keeping spaces.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/keep-only-letters",
      "embed": "https://textarray.com/embed/keep-only-letters",
      "mode": "transform",
      "action": "Keep only letters",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "alphabet",
          "kind": "select",
          "label": "Alphabet",
          "default": "any",
          "choices": [
            {
              "value": "any",
              "label": "Any script"
            },
            {
              "value": "ascii",
              "label": "ASCII (a–z)"
            },
            {
              "value": "sk",
              "label": "Slovenčina"
            },
            {
              "value": "cs",
              "label": "Čeština"
            },
            {
              "value": "pl",
              "label": "Polski"
            },
            {
              "value": "hu",
              "label": "Magyar"
            },
            {
              "value": "de",
              "label": "Deutsch"
            }
          ]
        },
        {
          "key": "keepSpaces",
          "kind": "checkbox",
          "label": "Keep spaces",
          "default": true
        }
      ],
      "keywords": [
        "keep only letters",
        "letters only",
        "remove non-letters",
        "remove numbers and symbols",
        "extract letters",
        "remove digits",
        "remove cyrillic",
        "remove non-latin characters",
        "keep only ascii letters",
        "alphabet filter",
        "letter extractor"
      ],
      "updated": "2026-07-31"
    },
    {
      "slug": "keep-only-numbers",
      "name": "Keep only numbers",
      "description": "Extract all digits and remove every other character from text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/keep-only-numbers",
      "embed": "https://textarray.com/embed/keep-only-numbers",
      "mode": "transform",
      "action": "Keep only numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "keepSpaces",
          "kind": "checkbox",
          "label": "Keep spaces",
          "default": false
        }
      ],
      "keywords": [
        "keep only numbers",
        "extract numbers",
        "remove letters",
        "digit filter",
        "numeric filter",
        "number extractor"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "extract-last-word",
      "name": "Extract last word",
      "description": "Get the last word from each line of text.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/extract-last-word",
      "embed": "https://textarray.com/embed/extract-last-word",
      "mode": "transform",
      "action": "Extract last word",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "extract last word",
        "last word per line",
        "word extractor",
        "line parser",
        "text splitter",
        "extract words"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "rotate-lines",
      "name": "Rotate lines",
      "description": "Shift the order of your lines by a fixed amount, wrapping around from top to bottom.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/rotate-lines",
      "embed": "https://textarray.com/embed/rotate-lines",
      "mode": "transform",
      "action": "Rotate lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "amount",
          "kind": "number",
          "label": "Amount",
          "default": 1,
          "min": 0,
          "step": 1
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "up",
          "choices": [
            {
              "value": "up",
              "label": "Up (first lines to end)"
            },
            {
              "value": "down",
              "label": "Down (last lines to start)"
            }
          ]
        }
      ],
      "keywords": [
        "rotate",
        "rotate lines",
        "reorder lines",
        "cycle lines",
        "rotate text",
        "rearrange lines",
        "line rotator",
        "line rotation"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "interleave-lines",
      "name": "Interleave lines",
      "description": "Merge two lists or texts by alternating their lines one by one.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/interleave-lines",
      "embed": "https://textarray.com/embed/interleave-lines",
      "mode": "transform",
      "action": "Interleave",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Second list"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "interleave lines",
        "combine two texts",
        "alternate lines",
        "zip lines"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "numbered-list",
      "name": "Numbered list",
      "description": "Add automatic numbering to each line of your text.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/numbered-list",
      "embed": "https://textarray.com/embed/numbered-list",
      "mode": "transform",
      "action": "Number list",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "start",
          "kind": "number",
          "label": "Start number",
          "default": 1,
          "min": -999999,
          "max": 999999,
          "step": 1
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": ". ",
          "choices": [
            {
              "value": ". ",
              "label": "Period and space"
            },
            {
              "value": ") ",
              "label": "Parenthesis and space"
            },
            {
              "value": "- ",
              "label": "Hyphen and space"
            }
          ]
        }
      ],
      "keywords": [
        "numbered list",
        "list numbering",
        "number lines",
        "numbered lines",
        "automatic numbering",
        "list formatter",
        "enumerated list",
        "ordered list"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "bullet-list",
      "name": "Bullet list",
      "description": "Add bullet points to each line of your text.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/bullet-list",
      "embed": "https://textarray.com/embed/bullet-list",
      "mode": "transform",
      "action": "Add bullets",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "bullet",
          "kind": "select",
          "label": "Bullet style",
          "default": "- ",
          "choices": [
            {
              "value": "- ",
              "label": "Dash"
            },
            {
              "value": "* ",
              "label": "Asterisk"
            },
            {
              "value": "• ",
              "label": "Dot"
            }
          ]
        }
      ],
      "keywords": [
        "bulleted list",
        "bulleted text",
        "line to bullets",
        "text to bullets",
        "add bullets",
        "bullet points"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "capitalize-sentences",
      "name": "Capitalize sentences",
      "description": "Automatically capitalize the first letter of every sentence in your text.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/capitalize-sentences",
      "embed": "https://textarray.com/embed/capitalize-sentences",
      "mode": "transform",
      "action": "Capitalize sentences",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "capitalize sentences",
        "capitalize first letter",
        "sentence capitalization",
        "auto capitalize",
        "capitalize tool"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "swap-case",
      "name": "Case swapper",
      "description": "Instantly toggle the case of every letter in your text.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/swap-case",
      "embed": "https://textarray.com/embed/swap-case",
      "mode": "transform",
      "action": "Swap case",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "case switcher",
        "invert case",
        "change case",
        "alternate case",
        "upper lower",
        "uppercase lowercase"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "count-words-per-line",
      "name": "Count words per line",
      "description": "Add word counts to each line of your text.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/count-words-per-line",
      "embed": "https://textarray.com/embed/count-words-per-line",
      "mode": "transform",
      "action": "Count words per line",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Format",
          "default": "suffix",
          "choices": [
            {
              "value": "suffix",
              "label": "Append count"
            },
            {
              "value": "prefix",
              "label": "Prepend count"
            },
            {
              "value": "only",
              "label": "Count only"
            }
          ]
        }
      ],
      "keywords": [
        "count words per line",
        "word count per line",
        "line word count",
        "count words each line"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "duplicate-word-finder",
      "name": "Duplicate word finder",
      "description": "Find words that occur more than once in your text.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/duplicate-word-finder",
      "embed": "https://textarray.com/embed/duplicate-word-finder",
      "mode": "transform",
      "action": "Find duplicates",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "minCount",
          "kind": "number",
          "label": "Minimum occurrences",
          "default": 2,
          "min": 2
        },
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Case insensitive",
          "default": true
        }
      ],
      "keywords": [
        "duplicate word finder",
        "find duplicate words",
        "repeated words",
        "word counter",
        "find repeated words"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "cursive-text",
      "name": "Cursive text",
      "description": "Transform your text into elegant Unicode mathematical script letters.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/cursive-text",
      "embed": "https://textarray.com/embed/cursive-text",
      "mode": "transform",
      "action": "Apply cursive",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "bold",
          "kind": "checkbox",
          "label": "Bold",
          "default": false
        }
      ],
      "keywords": [
        "cursive text",
        "cursive generator",
        "mathematical script",
        "unicode cursive",
        "fancy script",
        "stylish text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "gothic-text",
      "name": "Gothic text",
      "description": "Convert your text to Gothic and Fraktur letterforms, the ornate script of historical documents.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/gothic-text",
      "embed": "https://textarray.com/embed/gothic-text",
      "mode": "transform",
      "action": "Transform",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "bold",
          "kind": "checkbox",
          "label": "Bold style",
          "default": false
        }
      ],
      "keywords": [
        "gothic text",
        "gothic font",
        "old english",
        "blackletter",
        "fraktur generator",
        "fraktur converter",
        "gothic style text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "monospace-text",
      "name": "Monospace text",
      "description": "Convert text to Unicode monospace characters that render in a fixed-width font.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/monospace-text",
      "embed": "https://textarray.com/embed/monospace-text",
      "mode": "transform",
      "action": "Transform",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "monospace",
        "monospace text",
        "unicode monospace",
        "typewriter",
        "typewriter text",
        "monospaced",
        "courier",
        "fixed width"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "double-struck-text",
      "name": "Double-struck text",
      "description": "Convert text to mathematical double-struck characters, also known as blackboard bold.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/double-struck-text",
      "embed": "https://textarray.com/embed/double-struck-text",
      "mode": "transform",
      "action": "Transform",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "double struck text",
        "double-struck",
        "mathematical alphabet",
        "fancy text generator",
        "unicode text transformation",
        "stylish text converter",
        "character mapper",
        "mathematical text",
        "text transformer",
        "blackboard bold math",
        "blackboard bold",
        "math letter"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "clap-text",
      "name": "Clap text",
      "description": "Insert an emoji between every word to add emphasis and visual flair.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/clap-text",
      "embed": "https://textarray.com/embed/clap-text",
      "mode": "transform",
      "action": "Add emoji",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "emoji",
          "kind": "select",
          "label": "Emoji",
          "default": "clap",
          "choices": [
            {
              "value": "clap",
              "label": "Clap 👏"
            },
            {
              "value": "fire",
              "label": "Fire 🔥"
            },
            {
              "value": "hundred",
              "label": "Hundred 💯"
            }
          ]
        },
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase words",
          "default": false
        }
      ],
      "keywords": [
        "emoji spacing",
        "add emoji between words",
        "word separator emoji",
        "clapping text",
        "emphatic text",
        "clap emoji"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "mocking-case",
      "name": "Mocking case",
      "description": "Alternate between uppercase and lowercase letters, the SpongeBob mocking style.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/mocking-case",
      "embed": "https://textarray.com/embed/mocking-case",
      "mode": "transform",
      "action": "Mock",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "alternating case",
        "alternating caps",
        "mockingcase",
        "alternating letters",
        "case converter",
        "mockingtext",
        "mocking spongebob",
        "mock alternation"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "squared-text",
      "name": "Squared text",
      "description": "Transform letters into styled squared Unicode characters for eye-catching text.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/squared-text",
      "embed": "https://textarray.com/embed/squared-text",
      "mode": "transform",
      "action": "Apply squared style",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "squared text",
        "negative squared",
        "unicode squared",
        "emoji letters",
        "styled text",
        "block text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "regional-indicator-text",
      "name": "Regional indicator text",
      "description": "Convert letters to regional indicator symbols, the decorative Unicode flag letters.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/regional-indicator-text",
      "embed": "https://textarray.com/embed/regional-indicator-text",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "regional indicators text",
        "unicode flag",
        "regional indicator letters",
        "flag letter generator",
        "unicode regional indicators"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "spaced-letters",
      "name": "Spaced letters",
      "description": "Insert a separator between every character to create visually spaced text.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/spaced-letters",
      "embed": "https://textarray.com/embed/spaced-letters",
      "mode": "transform",
      "action": "Space letters",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "text",
          "label": "Separator",
          "default": " "
        }
      ],
      "keywords": [
        "letter spacing",
        "character separator",
        "insert spaces",
        "space between characters",
        "spacing characters",
        "spaced letters",
        "spread text"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "sum-numbers",
      "name": "Sum numbers",
      "description": "Find all numbers in text and add them together instantly.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/sum-numbers",
      "embed": "https://textarray.com/embed/sum-numbers",
      "mode": "transform",
      "action": "Calculate sum",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "sum numbers",
        "add numbers",
        "sum calculator",
        "total numbers",
        "arithmetic sum",
        "calculate sum",
        "addition"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "factorial-calculator",
      "name": "Factorial calculator",
      "description": "Compute factorials instantly, from 0! to 500! with exact results using BigInt.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/factorial-calculator",
      "embed": "https://textarray.com/embed/factorial-calculator",
      "mode": "generate",
      "action": "Calculate",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "n",
          "kind": "number",
          "label": "Number",
          "default": 10,
          "min": 0,
          "max": 500
        }
      ],
      "keywords": [
        "compute factorial",
        "factorial online",
        "calculate factorial",
        "bigint factorial",
        "factorial calculator",
        "n factorial"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "fibonacci-generator",
      "name": "Fibonacci generator",
      "description": "Generate Fibonacci sequences of any length with your choice of starting values and formatting.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/fibonacci-generator",
      "embed": "https://textarray.com/embed/fibonacci-generator",
      "mode": "generate",
      "action": "Generate",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "count",
          "kind": "number",
          "label": "Count",
          "default": 10,
          "min": 1,
          "max": 1000
        },
        {
          "key": "start",
          "kind": "select",
          "label": "Starting values",
          "default": "0",
          "choices": [
            {
              "value": "0",
              "label": "0, 1"
            },
            {
              "value": "1",
              "label": "1, 1"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "newline",
          "choices": [
            {
              "value": "newline",
              "label": "Newline"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "space",
              "label": "Space"
            }
          ]
        }
      ],
      "keywords": [
        "fibonacci",
        "fibonacci numbers",
        "fibonacci calculator",
        "golden ratio",
        "sequence generator"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "multiplication-table",
      "name": "Multiplication table",
      "description": "Generate a multiplication table for any number, perfect for learning or reference.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/multiplication-table",
      "embed": "https://textarray.com/embed/multiplication-table",
      "mode": "generate",
      "action": "Generate table",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "n",
          "kind": "number",
          "label": "Number",
          "default": 7,
          "min": 0,
          "max": 1000
        },
        {
          "key": "upTo",
          "kind": "number",
          "label": "Up to",
          "default": 10,
          "min": 1,
          "max": 100
        }
      ],
      "keywords": [
        "multiplication chart",
        "math table",
        "generate times table",
        "times table maker",
        "times table",
        "multiplication grid"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "percentage-change",
      "name": "Percentage change",
      "description": "Instantly calculate the percentage change from one value to another.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/percentage-change",
      "embed": "https://textarray.com/embed/percentage-change",
      "mode": "generate",
      "action": "Calculate",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "from",
          "kind": "number",
          "label": "Starting value",
          "default": 100
        },
        {
          "key": "to",
          "kind": "number",
          "label": "Ending value",
          "default": 150
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 2,
          "min": 0,
          "max": 10
        }
      ],
      "keywords": [
        "percentage change",
        "percent change calculator",
        "percentage increase decrease",
        "calculate percentage change"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "number-to-ordinal",
      "name": "Number to ordinal",
      "description": "Replace integers in text with their English ordinal forms (1st, 2nd, 3rd, etc.).",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/number-to-ordinal",
      "embed": "https://textarray.com/embed/number-to-ordinal",
      "mode": "transform",
      "action": "Convert to ordinals",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [],
      "keywords": [
        "ordinal",
        "number to ordinal",
        "convert to ordinal",
        "convert numbers ordinal",
        "text ordinals",
        "ordinal text",
        "1st 2nd 3rd"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "round-numbers",
      "name": "Round numbers",
      "description": "Round every number in your text to a specified number of decimal places.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/round-numbers",
      "embed": "https://textarray.com/embed/round-numbers",
      "mode": "transform",
      "action": "Round numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 0,
          "min": 0,
          "max": 10
        }
      ],
      "keywords": [
        "round numbers",
        "decimal places",
        "round decimals",
        "number rounding"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "even-odd-splitter",
      "name": "Even / odd splitter",
      "description": "Separate even and odd numbers instantly from any text.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/even-odd-splitter",
      "embed": "https://textarray.com/embed/even-odd-splitter",
      "mode": "transform",
      "action": "Split numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "output",
          "kind": "select",
          "label": "Output",
          "default": "both",
          "choices": [
            {
              "value": "both",
              "label": "Both"
            },
            {
              "value": "even",
              "label": "Even only (0, 2, 4, ...)"
            },
            {
              "value": "odd",
              "label": "Odd only (1, 3, 5, ...)"
            }
          ]
        }
      ],
      "keywords": [
        "separate even odd",
        "filter numbers",
        "split numbers",
        "number classifier",
        "integer filter"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "a1z26-cipher",
      "name": "A1Z26 cipher",
      "description": "Convert letters to numbers and back with the simple A1Z26 substitution cipher.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/a1z26-cipher",
      "embed": "https://textarray.com/embed/a1z26-cipher",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Letters to numbers"
            },
            {
              "value": "decode",
              "label": "Numbers to letters"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "text",
          "label": "Separator between numbers",
          "default": "-"
        }
      ],
      "keywords": [
        "a1z26",
        "a1z26 encoder",
        "a1z26 decoder",
        "letter to number",
        "alphabet cipher",
        "a1z26 converter",
        "number substitution cipher"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "affine-cipher",
      "name": "Affine cipher",
      "description": "Encrypt text using the affine cipher, a linear mathematical encryption based on modular arithmetic.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/affine-cipher",
      "embed": "https://textarray.com/embed/affine-cipher",
      "mode": "transform",
      "action": "Encrypt / Decrypt",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        },
        {
          "key": "a",
          "kind": "number",
          "label": "Multiplier (a)",
          "default": 5,
          "min": 1,
          "max": 25
        },
        {
          "key": "b",
          "kind": "number",
          "label": "Offset (b)",
          "default": 8,
          "min": 0,
          "max": 25
        }
      ],
      "keywords": [
        "affine encryption",
        "affine cipher encoder",
        "affine cipher decoder",
        "affine transformation",
        "modular arithmetic cipher",
        "linear congruential cipher",
        "encryption algorithm"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "keyboard-shift-cipher",
      "name": "Keyboard shift cipher",
      "description": "Encrypt text by shifting each letter to its neighboring key on a QWERTY keyboard.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/keyboard-shift-cipher",
      "embed": "https://textarray.com/embed/keyboard-shift-cipher",
      "mode": "transform",
      "action": "Shift characters",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Shift direction",
          "default": "right",
          "choices": [
            {
              "value": "right",
              "label": "Right"
            },
            {
              "value": "left",
              "label": "Left"
            }
          ]
        }
      ],
      "keywords": [
        "keyboard shift cipher",
        "keyboard encryption",
        "keyboard shift encrypt",
        "shift keyboard decode",
        "qwerty cipher",
        "keyboard cipher"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "base45",
      "name": "Base45 encoder",
      "description": "Encode text to Base45 or decode Base45 to text per RFC 9285.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/base45",
      "embed": "https://textarray.com/embed/base45",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode to Base45"
            },
            {
              "value": "decode",
              "label": "Decode from Base45"
            }
          ]
        }
      ],
      "keywords": [
        "base45",
        "base45 decoder",
        "base45 converter",
        "base45 encoding",
        "digital green pass"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "tap-code",
      "name": "Tap code",
      "description": "Encode or decode messages using tap code, the classic communication method.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/tap-code",
      "embed": "https://textarray.com/embed/tap-code",
      "mode": "transform",
      "action": "Encode",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        },
        {
          "key": "style",
          "kind": "select",
          "label": "Style",
          "default": "dots",
          "choices": [
            {
              "value": "dots",
              "label": "Dots"
            },
            {
              "value": "numbers",
              "label": "Numbers"
            }
          ]
        }
      ],
      "keywords": [
        "tapping code",
        "polybius square",
        "prison code",
        "prisoner communication",
        "dots and dashes",
        "morse alternative",
        "radio code",
        "polybius",
        "morse"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "beaufort-cipher",
      "name": "Beaufort cipher",
      "description": "Encrypt and decrypt text with the Beaufort cipher, a self-reciprocal variant of the Vigenère cipher.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/beaufort-cipher",
      "embed": "https://textarray.com/embed/beaufort-cipher",
      "mode": "transform",
      "action": "Apply cipher",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "key",
          "kind": "text",
          "label": "Key",
          "default": "key"
        }
      ],
      "keywords": [
        "beaufort decrypt",
        "self-reciprocal cipher",
        "beaufort vigenere",
        "self-reciprocal encrypt",
        "decrypt beaufort",
        "beaufort encryption"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "json-to-xml",
      "name": "JSON to XML converter",
      "description": "Convert JSON data into XML format with indentation and custom root elements.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-xml",
      "embed": "https://textarray.com/embed/json-to-xml",
      "mode": "transform",
      "action": "Convert to XML",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "root",
          "kind": "text",
          "label": "Root element",
          "default": "root"
        }
      ],
      "keywords": [
        "json",
        "xml",
        "json to xml",
        "convert json",
        "json converter",
        "json formatter",
        "xml generator",
        "data conversion",
        "json xml transform",
        "json xml converter",
        "xml json format"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "json-to-csv",
      "name": "JSON to CSV converter",
      "description": "Transform JSON arrays into properly formatted CSV files for spreadsheet programs.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-csv",
      "embed": "https://textarray.com/embed/json-to-csv",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        }
      ],
      "keywords": [
        "json to csv",
        "json csv converter",
        "json array to csv",
        "convert json to csv",
        "csv export tool",
        "csv export online",
        "csv export json",
        "spreadsheet format"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "html-list-to-lines",
      "name": "HTML list to lines",
      "description": "Extract text from HTML list items into plain lines.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/html-list-to-lines",
      "embed": "https://textarray.com/embed/html-list-to-lines",
      "mode": "transform",
      "action": "Extract lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "numbered",
          "kind": "checkbox",
          "label": "Number the lines",
          "default": false
        }
      ],
      "keywords": [
        "html list to lines",
        "extract list items",
        "li tags extract",
        "html list extractor",
        "list text converter",
        "html parser",
        "extract from html",
        "html list converter",
        "html to text list",
        "li to text",
        "extract li items",
        "strip html list",
        "numbered list from html",
        "html to plain text",
        "convert li tags"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "markdown-link-extractor",
      "name": "Markdown link extractor",
      "description": "Extract all links from Markdown text and list them by URL, text, or both.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/markdown-link-extractor",
      "embed": "https://textarray.com/embed/markdown-link-extractor",
      "mode": "transform",
      "action": "Extract links",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "output",
          "kind": "select",
          "label": "Output format",
          "default": "urls",
          "choices": [
            {
              "value": "urls",
              "label": "URLs only"
            },
            {
              "value": "text",
              "label": "Link text only"
            },
            {
              "value": "both",
              "label": "Both text and URL"
            }
          ]
        }
      ],
      "keywords": [
        "extract links",
        "markdown extractor",
        "url extractor",
        "markdown urls",
        "links from markdown",
        "get markdown links"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "env-to-json",
      "name": "Env to JSON",
      "description": "Convert environment variable files into structured JSON objects.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/env-to-json",
      "embed": "https://textarray.com/embed/env-to-json",
      "mode": "transform",
      "action": "Convert to JSON",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indent",
          "kind": "number",
          "label": "Indent spaces",
          "default": 2,
          "min": 0,
          "max": 8,
          "step": 1
        }
      ],
      "keywords": [
        "env to json",
        "dotenv to json",
        "environment to json",
        "env parser",
        "dotenv parser",
        "key value to json",
        "env to json converter",
        "env converter",
        "parse dotenv",
        "key value parser"
      ],
      "updated": "2026-07-17"
    },
    {
      "slug": "ini-to-json",
      "name": "INI ⇄ JSON converter",
      "description": "Convert INI config files to JSON and back, right in your browser.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ini-to-json",
      "embed": "https://textarray.com/embed/ini-to-json",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "ini-to-json",
          "choices": [
            {
              "value": "ini-to-json",
              "label": "INI → JSON"
            },
            {
              "value": "json-to-ini",
              "label": "JSON → INI"
            }
          ]
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print JSON",
          "default": true
        }
      ],
      "keywords": [
        "ini to json",
        "json to ini",
        "ini parser",
        "convert ini to json online",
        "ini file to json",
        "config to json"
      ],
      "updated": "2026-07-21"
    },
    {
      "slug": "properties-to-json",
      "name": "Properties to JSON converter",
      "description": "Convert Java .properties files to JSON and back, right in your browser.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/properties-to-json",
      "embed": "https://textarray.com/embed/properties-to-json",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "properties-to-json",
          "choices": [
            {
              "value": "properties-to-json",
              "label": "Properties → JSON"
            },
            {
              "value": "json-to-properties",
              "label": "JSON → Properties"
            }
          ]
        },
        {
          "key": "nested",
          "kind": "checkbox",
          "label": "Nest dotted keys",
          "default": false
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Prettify JSON",
          "default": true
        }
      ],
      "keywords": [
        "properties to json",
        "json to properties",
        "properties file to json",
        "convert properties to json",
        "spring properties",
        "java properties parser"
      ],
      "updated": "2026-07-21"
    },
    {
      "slug": "csv-to-sql",
      "name": "CSV to SQL INSERT generator",
      "description": "Turn CSV rows into ready-to-run SQL INSERT statements for any database.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/csv-to-sql",
      "embed": "https://textarray.com/embed/csv-to-sql",
      "mode": "transform",
      "action": "Generate SQL",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "table",
          "kind": "text",
          "label": "Table name",
          "default": "my_table"
        },
        {
          "key": "header",
          "kind": "checkbox",
          "label": "First row is column names",
          "default": true
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "multiRow",
          "kind": "checkbox",
          "label": "Combine into one multi-row INSERT",
          "default": false
        }
      ],
      "keywords": [
        "csv to sql",
        "csv to insert",
        "csv to sql insert",
        "generate insert statements",
        "insert generator"
      ],
      "updated": "2026-07-21"
    },
    {
      "slug": "css-to-js-object",
      "name": "CSS to JS object converter",
      "description": "Convert CSS declarations to a React/JS inline-style object, and back again.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-to-js-object",
      "embed": "https://textarray.com/embed/css-to-js-object",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "css-to-js",
          "choices": [
            {
              "value": "css-to-js",
              "label": "CSS → JS object"
            },
            {
              "value": "js-to-css",
              "label": "JS object → CSS"
            }
          ]
        },
        {
          "key": "unitlessNumbers",
          "kind": "checkbox",
          "label": "Unitless values as numbers",
          "default": false
        },
        {
          "key": "quotes",
          "kind": "select",
          "label": "Quotes",
          "default": "single",
          "choices": [
            {
              "value": "single",
              "label": "Single"
            },
            {
              "value": "double",
              "label": "Double"
            }
          ]
        }
      ],
      "keywords": [
        "css to js object",
        "css to react",
        "css to jsx object",
        "inline styles",
        "style object",
        "css in js",
        "js object to css",
        "camelcase css"
      ],
      "updated": "2026-07-21"
    },
    {
      "slug": "html-to-jsx",
      "name": "HTML to JSX converter",
      "description": "Turn HTML markup into JSX you can paste straight into a React component.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/html-to-jsx",
      "embed": "https://textarray.com/embed/html-to-jsx",
      "mode": "transform",
      "action": "Convert to JSX",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "styleObject",
          "kind": "checkbox",
          "label": "Convert style to object",
          "default": true
        },
        {
          "key": "selfClose",
          "kind": "checkbox",
          "label": "Self-close void elements",
          "default": true
        }
      ],
      "keywords": [
        "html to jsx",
        "html to react",
        "html to jsx converter",
        "convert html to jsx online",
        "class to classname"
      ],
      "updated": "2026-07-21"
    },
    {
      "slug": "curl-to-code",
      "name": "cURL to code converter",
      "description": "Turn a curl command into runnable Python, JavaScript or Node.js code.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/curl-to-code",
      "embed": "https://textarray.com/embed/curl-to-code",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "target",
          "kind": "select",
          "label": "Language",
          "default": "python",
          "choices": [
            {
              "value": "python",
              "label": "Python (requests)"
            },
            {
              "value": "js-fetch",
              "label": "JavaScript (fetch)"
            },
            {
              "value": "node",
              "label": "Node.js (fetch)"
            },
            {
              "value": "axios",
              "label": "Axios"
            },
            {
              "value": "node-https",
              "label": "Node.js (https)"
            }
          ]
        }
      ],
      "keywords": [
        "curl to python",
        "curl to fetch",
        "curl to javascript",
        "curl to node",
        "convert curl command",
        "curl to requests",
        "curl command to code",
        "curl to axios",
        "devtools copy as curl"
      ],
      "updated": "2026-07-21"
    },
    {
      "slug": "bbcode-to-html",
      "name": "BBCode to HTML converter",
      "description": "Convert BBCode from forums into clean HTML markup.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/bbcode-to-html",
      "embed": "https://textarray.com/embed/bbcode-to-html",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "bbcode-to-html",
          "choices": [
            {
              "value": "bbcode-to-html",
              "label": "BBCode to HTML"
            },
            {
              "value": "html-to-bbcode",
              "label": "HTML to BBCode"
            }
          ]
        }
      ],
      "keywords": [
        "bbcode to html",
        "convert bbcode to html",
        "forum tags",
        "phpbb",
        "bbcode parser",
        "forum tags html"
      ],
      "updated": "2026-07-21"
    },
    {
      "slug": "htaccess-generator",
      "name": ".htaccess generator",
      "description": "Build an Apache .htaccess file with HTTPS redirects, www rules, Gzip, caching and access blocks.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/htaccess-generator",
      "embed": "https://textarray.com/embed/htaccess-generator",
      "mode": "generate",
      "action": "Generate",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "forceHttps",
          "kind": "checkbox",
          "label": "Force HTTPS redirect",
          "default": false
        },
        {
          "key": "www",
          "kind": "select",
          "label": "www canonicalization",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "No change"
            },
            {
              "value": "force-www",
              "label": "Redirect to www"
            },
            {
              "value": "non-www",
              "label": "Redirect to non-www"
            }
          ]
        },
        {
          "key": "blockDirListing",
          "kind": "checkbox",
          "label": "Disable directory listing",
          "default": false
        },
        {
          "key": "gzip",
          "kind": "checkbox",
          "label": "Enable Gzip compression",
          "default": false
        },
        {
          "key": "caching",
          "kind": "checkbox",
          "label": "Enable browser caching",
          "default": false
        },
        {
          "key": "errorPage",
          "kind": "text",
          "label": "Custom 404 page",
          "default": ""
        },
        {
          "key": "blockDotfiles",
          "kind": "checkbox",
          "label": "Block access to hidden files",
          "default": false
        }
      ],
      "keywords": [
        "htaccess generator online",
        "apache htaccess",
        "force https",
        "htaccess redirect",
        "redirect www to non-www",
        "gzip compression htaccess",
        "browser caching htaccess",
        "block directory listing",
        "errordocument 404",
        "deny access to dotfiles"
      ],
      "updated": "2026-07-21"
    },
    {
      "slug": "rpg-name-generator",
      "name": "RPG name generator",
      "description": "Generate fantasy character and place names for elves, dwarves, orcs, humans, halflings and realms.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/rpg-name-generator",
      "embed": "https://textarray.com/embed/rpg-name-generator",
      "mode": "generate",
      "action": "Generate names",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "race",
          "kind": "select",
          "label": "Race",
          "default": "elf",
          "choices": [
            {
              "value": "human",
              "label": "Human"
            },
            {
              "value": "elf",
              "label": "Elf"
            },
            {
              "value": "dwarf",
              "label": "Dwarf"
            },
            {
              "value": "orc",
              "label": "Orc"
            },
            {
              "value": "halfling",
              "label": "Halfling"
            },
            {
              "value": "place",
              "label": "Place (town / realm)"
            },
            {
              "value": "settlement",
              "label": "Settlement (invented town name)"
            }
          ]
        },
        {
          "key": "gender",
          "kind": "select",
          "label": "Gender",
          "default": "any",
          "choices": [
            {
              "value": "any",
              "label": "Any"
            },
            {
              "value": "male",
              "label": "Male"
            },
            {
              "value": "female",
              "label": "Female"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 8,
          "min": 1,
          "max": 100
        }
      ],
      "keywords": [
        "rpg name generator",
        "fantasy name generator",
        "elf name generator",
        "dwarf name generator",
        "orc name generator",
        "halfling name generator",
        "dnd names",
        "dnd name generator",
        "d&d names",
        "fantasy town names",
        "fantasy place names",
        "medieval name generator",
        "town name generator",
        "village name generator",
        "city name generator",
        "worldbuilding names",
        "rpg place names",
        "dnd town names",
        "random place name"
      ],
      "updated": "2026-07-21"
    },
    {
      "slug": "url-defanger",
      "name": "URL defanger",
      "description": "Defang and refang URLs, IPs and emails so links can't be clicked.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/url-defanger",
      "embed": "https://textarray.com/embed/url-defanger",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "defang",
          "choices": [
            {
              "value": "defang",
              "label": "Defang (make safe)"
            },
            {
              "value": "refang",
              "label": "Refang (restore)"
            }
          ]
        },
        {
          "key": "protocol",
          "kind": "checkbox",
          "label": "Break http/https",
          "default": true
        },
        {
          "key": "dots",
          "kind": "checkbox",
          "label": "Wrap dots in brackets",
          "default": true
        },
        {
          "key": "atSign",
          "kind": "checkbox",
          "label": "Neutralize @ in emails",
          "default": true
        }
      ],
      "keywords": [
        "refang url",
        "defang ip",
        "defang link",
        "hxxp",
        "neutralize url",
        "sanitize url"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "base62",
      "name": "Base62 encode and decode",
      "description": "Encode text to Base62 with digits and letters, and decode it back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/base62",
      "embed": "https://textarray.com/embed/base62",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        }
      ],
      "keywords": [
        "base62",
        "base62 decode",
        "base62 converter",
        "base62 alphabet",
        "encode text base62"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "rc4-cipher",
      "name": "RC4 cipher",
      "description": "Encrypt and decrypt text with the RC4 stream cipher and a key — hex out, text back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/rc4-cipher",
      "embed": "https://textarray.com/embed/rc4-cipher",
      "mode": "transform",
      "action": "Run",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "key",
          "kind": "text",
          "label": "Key",
          "default": "",
          "secret": true
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encrypt",
          "choices": [
            {
              "value": "encrypt",
              "label": "Encrypt (text → hex)"
            },
            {
              "value": "decrypt",
              "label": "Decrypt (hex → text)"
            }
          ]
        }
      ],
      "keywords": [
        "rc4",
        "rc4 decrypt",
        "rc4 online",
        "rc4 stream cipher",
        "rc4 hex",
        "rc4 with key",
        "arcfour"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "unicode-escape",
      "name": "Unicode escape",
      "description": "Convert characters to \\uXXXX escape sequences and decode them back to text.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/unicode-escape",
      "embed": "https://textarray.com/embed/unicode-escape",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode to \\uXXXX"
            },
            {
              "value": "decode",
              "label": "Decode from \\uXXXX"
            }
          ]
        },
        {
          "key": "onlyNonAscii",
          "kind": "checkbox",
          "label": "Only non-ASCII characters",
          "default": true
        }
      ],
      "keywords": [
        "unicode unescape",
        "u escape",
        "escape unicode characters",
        "javascript string escape",
        "json unicode escape",
        "unicode encoder",
        "\\uxxxx converter"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "prompt-templater",
      "name": "Prompt templater",
      "description": "Fill {{placeholders}} in a template with your own key = value pairs.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/prompt-templater",
      "embed": "https://textarray.com/embed/prompt-templater",
      "mode": "transform",
      "action": "Fill",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Values"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "unfilled",
          "kind": "select",
          "label": "Unfilled placeholders",
          "default": "keep",
          "choices": [
            {
              "value": "keep",
              "label": "Keep {{key}}"
            },
            {
              "value": "blank",
              "label": "Replace with nothing"
            },
            {
              "value": "mark",
              "label": "Mark as [MISSING: key]"
            }
          ]
        },
        {
          "key": "trimValues",
          "kind": "checkbox",
          "label": "Trim whitespace from values",
          "default": true
        }
      ],
      "keywords": [
        "prompt template",
        "prompt templater",
        "fill placeholders",
        "variable substitution",
        "mustache",
        "template variables",
        "fill in template",
        "mail merge",
        "placeholder text"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "faq-schema-generator",
      "name": "FAQ schema generator",
      "description": "Turn a list of questions and answers into FAQPage JSON-LD.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/faq-schema-generator",
      "embed": "https://textarray.com/embed/faq-schema-generator",
      "mode": "transform",
      "action": "Generate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Input format",
          "default": "prefixed",
          "choices": [
            {
              "value": "prefixed",
              "label": "Q: / A: prefixes"
            },
            {
              "value": "alternating",
              "label": "Alternating lines"
            },
            {
              "value": "markdown",
              "label": "Markdown headings"
            }
          ]
        },
        {
          "key": "headingLevel",
          "kind": "select",
          "label": "Question heading level",
          "default": "2",
          "choices": [
            {
              "value": "1",
              "label": "#"
            },
            {
              "value": "2",
              "label": "##"
            },
            {
              "value": "3",
              "label": "###"
            },
            {
              "value": "4",
              "label": "####"
            }
          ]
        },
        {
          "key": "outputShape",
          "kind": "select",
          "label": "Output",
          "default": "jsonld",
          "choices": [
            {
              "value": "jsonld",
              "label": "FAQPage JSON-LD"
            },
            {
              "value": "array",
              "label": "Plain JSON array"
            }
          ]
        },
        {
          "key": "stripAnswerMarkdown",
          "kind": "checkbox",
          "label": "Strip Markdown from answers",
          "default": false
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print (2-space indent)",
          "default": true
        },
        {
          "key": "wrapScript",
          "kind": "checkbox",
          "label": "Wrap in <script> tag",
          "default": true
        }
      ],
      "keywords": [
        "faqpage json-ld",
        "structured data faq",
        "faq rich results",
        "faq structured data generator",
        "schema.org faqpage",
        "generator faq schema",
        "faq json-ld generator",
        "markdown faq to json",
        "faq to json",
        "markdown to json",
        "faq json converter",
        "chatbot knowledge base",
        "faq schema json",
        "headings to json"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "hash-identifier",
      "name": "Hash identifier",
      "description": "Guess which algorithm produced a hash from its length, charset and prefix.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/hash-identifier",
      "embed": "https://textarray.com/embed/hash-identifier",
      "mode": "transform",
      "action": "Identify",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "onlyMostLikely",
          "kind": "checkbox",
          "label": "Most likely only",
          "default": false
        }
      ],
      "keywords": [
        "hash identifier",
        "identify hash",
        "what hash is this",
        "hash analyzer",
        "md5 or sha",
        "bcrypt detect"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "levenshtein-distance",
      "name": "Levenshtein distance",
      "description": "Measure the edit distance between two strings, plus a similarity percentage.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/levenshtein-distance",
      "embed": "https://textarray.com/embed/levenshtein-distance",
      "mode": "transform",
      "action": "Compare",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Compare with"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "caseInsensitive",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": false
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": false
        },
        {
          "key": "unit",
          "kind": "select",
          "label": "Compare by",
          "default": "chars",
          "choices": [
            {
              "value": "chars",
              "label": "Characters"
            },
            {
              "value": "words",
              "label": "Words"
            }
          ]
        }
      ],
      "keywords": [
        "levenshtein",
        "string distance",
        "compute levenshtein distance",
        "similarity ratio",
        "compare two strings",
        "how many edits between strings"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "date-extractor",
      "name": "Date extractor",
      "description": "Pull every date out of text and get a clean list, one per line.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/date-extractor",
      "embed": "https://textarray.com/embed/date-extractor",
      "mode": "transform",
      "action": "Extract",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "output",
          "kind": "select",
          "label": "Output format",
          "default": "asFound",
          "choices": [
            {
              "value": "asFound",
              "label": "As found"
            },
            {
              "value": "iso",
              "label": "Normalize to ISO (YYYY-MM-DD)"
            }
          ]
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicates",
          "default": false
        },
        {
          "key": "sort",
          "kind": "checkbox",
          "label": "Sort ascending",
          "default": false
        }
      ],
      "keywords": [
        "extract dates",
        "extract dates from text",
        "find dates",
        "find dates in text",
        "get dates from text",
        "pull dates out of text",
        "list dates",
        "iso date extractor"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "hex-dump",
      "name": "Hex dump",
      "description": "Turn text into a classic hexdump with offsets and an ASCII gutter, or read one back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/hex-dump",
      "embed": "https://textarray.com/embed/hex-dump",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text to hexdump"
            },
            {
              "value": "decode",
              "label": "Hexdump to text"
            }
          ]
        },
        {
          "key": "uppercase",
          "kind": "checkbox",
          "label": "Uppercase hex digits",
          "default": false
        }
      ],
      "keywords": [
        "xxd",
        "hex viewer",
        "text to hexdump",
        "hexdump to text",
        "byte viewer",
        "od hex"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "prompt-splitter",
      "name": "Prompt splitter",
      "description": "Split long text into sequential chunks that fit a character limit, breaking on sensible boundaries.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/prompt-splitter",
      "embed": "https://textarray.com/embed/prompt-splitter",
      "mode": "transform",
      "action": "Split",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "network",
          "kind": "select",
          "label": "Post limit",
          "default": "custom",
          "choices": [
            {
              "value": "custom",
              "label": "Custom"
            },
            {
              "value": "x",
              "label": "X — 280"
            },
            {
              "value": "bluesky",
              "label": "Bluesky — 300"
            },
            {
              "value": "threads",
              "label": "Threads — 500"
            },
            {
              "value": "mastodon",
              "label": "Mastodon — 500"
            },
            {
              "value": "linkedin",
              "label": "LinkedIn — 3000"
            }
          ]
        },
        {
          "key": "maxChars",
          "kind": "number",
          "label": "Max characters per part",
          "default": 2000,
          "min": 50
        },
        {
          "key": "splitOn",
          "kind": "select",
          "label": "Break on",
          "default": "paragraph",
          "choices": [
            {
              "value": "paragraph",
              "label": "Paragraphs"
            },
            {
              "value": "sentence",
              "label": "Sentences"
            },
            {
              "value": "word",
              "label": "Words"
            }
          ]
        },
        {
          "key": "labelStyle",
          "kind": "select",
          "label": "Chunk labels",
          "default": "part",
          "choices": [
            {
              "value": "part",
              "label": "[Part x/y] label line"
            },
            {
              "value": "thread",
              "label": "Thread numbering (x/y)"
            },
            {
              "value": "slash",
              "label": "Slash numbering (x/)"
            },
            {
              "value": "emoji",
              "label": "Thread emoji (🧵 x)"
            },
            {
              "value": "none",
              "label": "No labels"
            }
          ]
        },
        {
          "key": "numberPosition",
          "kind": "select",
          "label": "Number position",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Format default"
            },
            {
              "value": "start",
              "label": "Before the text"
            },
            {
              "value": "end",
              "label": "After the text"
            }
          ]
        }
      ],
      "keywords": [
        "split long text",
        "character limit split",
        "split text for chatgpt",
        "sms character split",
        "paste long prompt",
        "text splitter"
      ],
      "updated": "2026-08-24"
    },
    {
      "slug": "serp-pixel-width",
      "name": "SERP pixel width checker",
      "description": "Estimate the pixel width of a Google title or meta description and see if it fits before truncation.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/serp-pixel-width",
      "embed": "https://textarray.com/embed/serp-pixel-width",
      "mode": "transform",
      "action": "Measure",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "type",
          "kind": "select",
          "label": "Element",
          "default": "title",
          "choices": [
            {
              "value": "title",
              "label": "Title (20px, ~580px)"
            },
            {
              "value": "description",
              "label": "Description (14px, ~920px)"
            }
          ]
        }
      ],
      "keywords": [
        "title pixel width",
        "meta description length",
        "google snippet length",
        "pixel width checker",
        "title tag length",
        "seo title length",
        "pixel width calculator"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "bcrypt-generator",
      "name": "Bcrypt generator",
      "description": "Hash passwords with bcrypt or verify a password against an existing bcrypt hash.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/bcrypt-generator",
      "embed": "https://textarray.com/embed/bcrypt-generator",
      "mode": "transform",
      "action": "Hash",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "hash",
          "choices": [
            {
              "value": "hash",
              "label": "Hash a password"
            },
            {
              "value": "verify",
              "label": "Verify against a hash"
            }
          ]
        },
        {
          "key": "rounds",
          "kind": "number",
          "label": "Cost (rounds)",
          "default": 10,
          "min": 4,
          "max": 12
        },
        {
          "key": "hash",
          "kind": "text",
          "label": "Hash to verify against",
          "default": ""
        }
      ],
      "keywords": [
        "bcrypt",
        "bcrypt verify",
        "bcrypt hash generator",
        "password hashing",
        "salt rounds",
        "cost factor"
      ],
      "updated": "2026-07-22"
    },
    {
      "slug": "markdown-table-to-csv",
      "name": "Markdown table to CSV",
      "description": "Turn a Markdown pipe table into CSV or JSON.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/markdown-table-to-csv",
      "embed": "https://textarray.com/embed/markdown-table-to-csv",
      "mode": "transform",
      "action": "Convert to CSV",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "inputFormat",
          "kind": "select",
          "label": "Input format",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Detect automatically"
            },
            {
              "value": "markdown",
              "label": "Markdown table"
            },
            {
              "value": "console",
              "label": "Console table (psql, MySQL)"
            }
          ]
        },
        {
          "key": "header",
          "kind": "checkbox",
          "label": "First row is header",
          "default": true
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Output delimiter",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        },
        {
          "key": "quoteAll",
          "kind": "checkbox",
          "label": "Quote every field",
          "default": false
        },
        {
          "key": "unescapePipes",
          "kind": "checkbox",
          "label": "Unescape \\| inside cells",
          "default": true
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace",
          "default": true
        },
        {
          "key": "stripFormatting",
          "kind": "checkbox",
          "label": "Strip bold, italic and links",
          "default": false
        },
        {
          "key": "asJson",
          "kind": "checkbox",
          "label": "Output as JSON array",
          "default": false
        },
        {
          "key": "allTables",
          "kind": "checkbox",
          "label": "Convert every table in the input",
          "default": true
        },
        {
          "key": "ignoreAlignmentRow",
          "kind": "checkbox",
          "label": "Ignore the alignment row",
          "default": true
        }
      ],
      "keywords": [
        "psql table to csv",
        "mysql console table to csv",
        "ascii table to csv",
        "console table converter",
        "markdown table to csv",
        "md table to csv",
        "markdown to csv",
        "table converter",
        "pipe table",
        "csv",
        "markdown",
        "convert markdown table"
      ],
      "updated": "2026-08-22"
    },
    {
      "slug": "robots-txt-tester",
      "name": "Robots.txt tester",
      "description": "Check whether specific paths or URLs are allowed or blocked by a robots.txt file.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/robots-txt-tester",
      "embed": "https://textarray.com/embed/robots-txt-tester",
      "mode": "transform",
      "action": "Test paths",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Paths or URLs to test (one per line)"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "userAgent",
          "kind": "select",
          "label": "User-agent",
          "default": "googlebot",
          "choices": [
            {
              "value": "googlebot",
              "label": "Googlebot"
            },
            {
              "value": "googlebot-image",
              "label": "Googlebot-Image"
            },
            {
              "value": "bingbot",
              "label": "Bingbot"
            },
            {
              "value": "gptbot",
              "label": "GPTBot"
            },
            {
              "value": "claudebot",
              "label": "ClaudeBot"
            },
            {
              "value": "custom",
              "label": "Custom…"
            }
          ]
        },
        {
          "key": "customUserAgent",
          "kind": "text",
          "label": "Custom user-agent token",
          "default": ""
        },
        {
          "key": "showRule",
          "kind": "checkbox",
          "label": "Show deciding rule",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "json",
              "label": "JSON"
            }
          ]
        }
      ],
      "keywords": [
        "robots.txt tester",
        "robots.txt checker",
        "robots.txt validator",
        "disallow checker",
        "crawler access checker",
        "user-agent simulator",
        "googlebot blocked",
        "gptbot blocked",
        "sitemap",
        "json"
      ],
      "updated": "2026-08-08"
    },
    {
      "slug": "article-schema-generator",
      "name": "Article schema generator",
      "description": "Build a schema.org Article JSON-LD block from headline, author, publisher and image fields.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/article-schema-generator",
      "embed": "https://textarray.com/embed/article-schema-generator",
      "mode": "generate",
      "action": "Generate schema",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "type",
          "kind": "select",
          "label": "Article type",
          "default": "Article",
          "choices": [
            {
              "value": "Article",
              "label": "Article"
            },
            {
              "value": "NewsArticle",
              "label": "News article"
            },
            {
              "value": "BlogPosting",
              "label": "Blog posting"
            },
            {
              "value": "TechArticle",
              "label": "Tech article"
            }
          ]
        },
        {
          "key": "headline",
          "kind": "text",
          "label": "Headline",
          "default": ""
        },
        {
          "key": "alternativeHeadline",
          "kind": "text",
          "label": "Alternative headline",
          "default": ""
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "imageUrl",
          "kind": "text",
          "label": "Image URL",
          "default": ""
        },
        {
          "key": "imageWidth",
          "kind": "number",
          "label": "Image width (px)",
          "default": 0,
          "min": 0
        },
        {
          "key": "imageHeight",
          "kind": "number",
          "label": "Image height (px)",
          "default": 0,
          "min": 0
        },
        {
          "key": "authorType",
          "kind": "select",
          "label": "Author type",
          "default": "Person",
          "choices": [
            {
              "value": "Person",
              "label": "Person"
            },
            {
              "value": "Organization",
              "label": "Organization"
            }
          ]
        },
        {
          "key": "authorName",
          "kind": "text",
          "label": "Author name",
          "default": ""
        },
        {
          "key": "authorUrl",
          "kind": "text",
          "label": "Author URL",
          "default": ""
        },
        {
          "key": "publisherName",
          "kind": "text",
          "label": "Publisher name",
          "default": ""
        },
        {
          "key": "publisherLogoUrl",
          "kind": "text",
          "label": "Publisher logo URL",
          "default": ""
        },
        {
          "key": "datePublished",
          "kind": "text",
          "label": "Date published",
          "default": ""
        },
        {
          "key": "dateModified",
          "kind": "text",
          "label": "Date modified",
          "default": ""
        },
        {
          "key": "mainEntityOfPage",
          "kind": "text",
          "label": "Canonical page URL",
          "default": ""
        },
        {
          "key": "articleSection",
          "kind": "text",
          "label": "Article section",
          "default": ""
        },
        {
          "key": "keywords",
          "kind": "text",
          "label": "Keywords",
          "default": ""
        },
        {
          "key": "wordCount",
          "kind": "number",
          "label": "Word count",
          "default": 0,
          "min": 0
        },
        {
          "key": "inLanguage",
          "kind": "text",
          "label": "Language code",
          "default": ""
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print (2-space indent)",
          "default": true
        },
        {
          "key": "wrapScript",
          "kind": "checkbox",
          "label": "Wrap in <script> tag",
          "default": true
        }
      ],
      "keywords": [
        "article schema generator",
        "article structured data",
        "schema.org article json-ld",
        "newsarticle schema",
        "blogposting schema",
        "article rich results",
        "google news structured data",
        "techarticle schema",
        "article schema markup"
      ],
      "updated": "2026-08-08"
    },
    {
      "slug": "product-schema-generator",
      "name": "Product schema generator",
      "description": "Fill in product details and get a ready-to-paste Product JSON-LD block.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/product-schema-generator",
      "embed": "https://textarray.com/embed/product-schema-generator",
      "mode": "generate",
      "action": "Generate schema",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "name",
          "kind": "text",
          "label": "Product name",
          "default": "Wireless headphones"
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": "Noise-cancelling over-ear headphones with 30-hour battery life."
        },
        {
          "key": "imageUrls",
          "kind": "text",
          "label": "Image URLs",
          "default": "https://example.com/images/headphones-1.jpg"
        },
        {
          "key": "brand",
          "kind": "text",
          "label": "Brand",
          "default": "Acme Audio"
        },
        {
          "key": "sku",
          "kind": "text",
          "label": "SKU",
          "default": "WH-1000"
        },
        {
          "key": "gtin",
          "kind": "text",
          "label": "GTIN",
          "default": ""
        },
        {
          "key": "mpn",
          "kind": "text",
          "label": "MPN",
          "default": ""
        },
        {
          "key": "category",
          "kind": "text",
          "label": "Category",
          "default": "Electronics > Audio > Headphones"
        },
        {
          "key": "productUrl",
          "kind": "text",
          "label": "Product page URL",
          "default": "https://example.com/products/wireless-headphones"
        },
        {
          "key": "price",
          "kind": "text",
          "label": "Price",
          "default": "129.99"
        },
        {
          "key": "currency",
          "kind": "select",
          "label": "Currency",
          "default": "USD",
          "choices": [
            {
              "value": "USD",
              "label": "USD — US dollar"
            },
            {
              "value": "EUR",
              "label": "EUR — euro"
            },
            {
              "value": "GBP",
              "label": "GBP — British pound"
            },
            {
              "value": "CZK",
              "label": "CZK — Czech koruna"
            },
            {
              "value": "PLN",
              "label": "PLN — Polish złoty"
            },
            {
              "value": "HUF",
              "label": "HUF — Hungarian forint"
            },
            {
              "value": "CHF",
              "label": "CHF — Swiss franc"
            },
            {
              "value": "SEK",
              "label": "SEK — Swedish krona"
            },
            {
              "value": "RON",
              "label": "RON — Romanian leu"
            },
            {
              "value": "TRY",
              "label": "TRY — Turkish lira"
            },
            {
              "value": "RUB",
              "label": "RUB — Russian ruble"
            },
            {
              "value": "UAH",
              "label": "UAH — Ukrainian hryvnia"
            },
            {
              "value": "JPY",
              "label": "JPY — Japanese yen"
            },
            {
              "value": "CAD",
              "label": "CAD — Canadian dollar"
            }
          ]
        },
        {
          "key": "availability",
          "kind": "select",
          "label": "Availability",
          "default": "InStock",
          "choices": [
            {
              "value": "InStock",
              "label": "In stock"
            },
            {
              "value": "OutOfStock",
              "label": "Out of stock"
            },
            {
              "value": "PreOrder",
              "label": "Pre-order"
            },
            {
              "value": "BackOrder",
              "label": "Back order"
            },
            {
              "value": "LimitedAvailability",
              "label": "Limited availability"
            },
            {
              "value": "Discontinued",
              "label": "Discontinued"
            }
          ]
        },
        {
          "key": "priceValidUntil",
          "kind": "text",
          "label": "Price valid until",
          "default": ""
        },
        {
          "key": "itemCondition",
          "kind": "select",
          "label": "Condition",
          "default": "NewCondition",
          "choices": [
            {
              "value": "NewCondition",
              "label": "New"
            },
            {
              "value": "UsedCondition",
              "label": "Used"
            },
            {
              "value": "RefurbishedCondition",
              "label": "Refurbished"
            }
          ]
        },
        {
          "key": "ratingValue",
          "kind": "number",
          "label": "Average rating",
          "default": 4.5,
          "min": 0,
          "max": 5,
          "step": 0.1
        },
        {
          "key": "reviewCount",
          "kind": "number",
          "label": "Number of ratings",
          "default": 128,
          "min": 0
        },
        {
          "key": "bestRating",
          "kind": "number",
          "label": "Rating scale — best",
          "default": 5,
          "min": 1
        },
        {
          "key": "worstRating",
          "kind": "number",
          "label": "Rating scale — worst",
          "default": 1,
          "min": 0
        },
        {
          "key": "reviewAuthor",
          "kind": "text",
          "label": "Review author",
          "default": ""
        },
        {
          "key": "reviewRating",
          "kind": "number",
          "label": "Review rating",
          "default": 5,
          "min": 0,
          "max": 5
        },
        {
          "key": "reviewText",
          "kind": "text",
          "label": "Review text",
          "default": ""
        },
        {
          "key": "shippingCountry",
          "kind": "text",
          "label": "Ships to (country code)",
          "default": ""
        },
        {
          "key": "shippingRate",
          "kind": "text",
          "label": "Shipping rate",
          "default": ""
        },
        {
          "key": "shippingDays",
          "kind": "number",
          "label": "Delivery time (days)",
          "default": 0,
          "min": 0
        },
        {
          "key": "returnDays",
          "kind": "number",
          "label": "Return window (days)",
          "default": 30,
          "min": 0
        },
        {
          "key": "wrapScript",
          "kind": "checkbox",
          "label": "Wrap in <script> tag",
          "default": true
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print JSON",
          "default": true
        }
      ],
      "keywords": [
        "product schema generator",
        "product schema markup",
        "json-ld product",
        "google rich results product",
        "google merchant product markup",
        "product structured data",
        "json",
        "seo"
      ],
      "updated": "2026-08-08"
    },
    {
      "slug": "csv-mail-merge",
      "name": "CSV mail merge",
      "description": "Turn a template and CSV rows into one personalized message per row.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/csv-mail-merge",
      "embed": "https://textarray.com/embed/csv-mail-merge",
      "mode": "transform",
      "action": "Generate messages",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "CSV data"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "syntax",
          "kind": "select",
          "label": "Placeholder syntax",
          "default": "doubleBrace",
          "choices": [
            {
              "value": "doubleBrace",
              "label": "{{column}}"
            },
            {
              "value": "singleBrace",
              "label": "{column}"
            },
            {
              "value": "dollar",
              "label": "$column"
            }
          ]
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "CSV delimiter",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "comma",
              "label": "Comma (,)"
            },
            {
              "value": "semicolon",
              "label": "Semicolon (;)"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe (|)"
            }
          ]
        },
        {
          "key": "header",
          "kind": "checkbox",
          "label": "First row is header",
          "default": true
        },
        {
          "key": "messageSeparator",
          "kind": "text",
          "label": "Separator between messages",
          "default": "\\n\\n"
        },
        {
          "key": "emptyValue",
          "kind": "text",
          "label": "Fallback for an empty cell",
          "default": ""
        },
        {
          "key": "skipMissingRequired",
          "kind": "checkbox",
          "label": "Skip rows with a missing value",
          "default": false
        },
        {
          "key": "caseTransform",
          "kind": "select",
          "label": "Case of substituted value",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "As in the CSV"
            },
            {
              "value": "capitalize",
              "label": "Capitalize first letter"
            },
            {
              "value": "upper",
              "label": "UPPERCASE"
            },
            {
              "value": "lower",
              "label": "lowercase"
            }
          ]
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace from cell values",
          "default": true
        },
        {
          "key": "numbering",
          "kind": "checkbox",
          "label": "Number the messages",
          "default": false
        },
        {
          "key": "warnUnused",
          "kind": "checkbox",
          "label": "Warn about unused columns and unfilled placeholders",
          "default": true
        }
      ],
      "keywords": [
        "csv mail merge",
        "mail merge",
        "bulk personalized messages",
        "template from csv",
        "placeholder substitution",
        "form letter generator",
        "csv to template",
        "personalize from spreadsheet"
      ],
      "updated": "2026-08-08"
    },
    {
      "slug": "totp-generator",
      "name": "TOTP code generator",
      "description": "Generate time-based (TOTP) or counter-based (HOTP) one-time codes from a shared secret.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/totp-generator",
      "embed": "https://textarray.com/embed/totp-generator",
      "mode": "generate",
      "action": "Generate code",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "secret",
          "kind": "text",
          "label": "Shared secret",
          "default": "",
          "secret": true
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "totp",
          "choices": [
            {
              "value": "totp",
              "label": "TOTP (time-based)"
            },
            {
              "value": "hotp",
              "label": "HOTP (counter-based)"
            }
          ]
        },
        {
          "key": "algorithm",
          "kind": "select",
          "label": "Algorithm",
          "default": "SHA-1",
          "choices": [
            {
              "value": "SHA-1",
              "label": "SHA-1"
            },
            {
              "value": "SHA-256",
              "label": "SHA-256"
            },
            {
              "value": "SHA-512",
              "label": "SHA-512"
            }
          ]
        },
        {
          "key": "digits",
          "kind": "select",
          "label": "Digits",
          "default": "6",
          "choices": [
            {
              "value": "6",
              "label": "6"
            },
            {
              "value": "7",
              "label": "7"
            },
            {
              "value": "8",
              "label": "8"
            }
          ]
        },
        {
          "key": "period",
          "kind": "number",
          "label": "Period (seconds)",
          "default": 30,
          "min": 1,
          "max": 300,
          "step": 1
        },
        {
          "key": "counter",
          "kind": "number",
          "label": "HOTP counter",
          "default": 0,
          "min": 0,
          "step": 1
        },
        {
          "key": "window",
          "kind": "number",
          "label": "Verification window (steps before/after)",
          "default": 0,
          "min": 0,
          "max": 10,
          "step": 1
        }
      ],
      "keywords": [
        "totp generator",
        "hotp generator",
        "2fa code generator",
        "authenticator code",
        "one-time password",
        "rfc 6238",
        "rfc 4226",
        "otpauth uri",
        "base32 secret",
        "two-factor authentication"
      ],
      "updated": "2026-08-08"
    },
    {
      "slug": "intl-number-formatter",
      "name": "Locale number formatter",
      "description": "Format a list of numbers as currency, percentages or units, following the rules of any language locale.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/intl-number-formatter",
      "embed": "https://textarray.com/embed/intl-number-formatter",
      "mode": "transform",
      "action": "Format numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "locale",
          "kind": "select",
          "label": "Locale",
          "default": "en-US",
          "choices": [
            {
              "value": "en-US",
              "label": "English (US)"
            },
            {
              "value": "en-GB",
              "label": "English (UK)"
            },
            {
              "value": "sk-SK",
              "label": "Slovak"
            },
            {
              "value": "cs-CZ",
              "label": "Czech"
            },
            {
              "value": "de-DE",
              "label": "German"
            },
            {
              "value": "pl-PL",
              "label": "Polish"
            },
            {
              "value": "hu-HU",
              "label": "Hungarian"
            },
            {
              "value": "es-ES",
              "label": "Spanish"
            },
            {
              "value": "fr-FR",
              "label": "French"
            },
            {
              "value": "it-IT",
              "label": "Italian"
            },
            {
              "value": "nl-NL",
              "label": "Dutch"
            },
            {
              "value": "pt-PT",
              "label": "Portuguese"
            },
            {
              "value": "ro-RO",
              "label": "Romanian"
            },
            {
              "value": "hr-HR",
              "label": "Croatian"
            },
            {
              "value": "sl-SI",
              "label": "Slovenian"
            },
            {
              "value": "sv-SE",
              "label": "Swedish"
            },
            {
              "value": "tr-TR",
              "label": "Turkish"
            },
            {
              "value": "ru-RU",
              "label": "Russian"
            },
            {
              "value": "uk-UA",
              "label": "Ukrainian"
            }
          ]
        },
        {
          "key": "style",
          "kind": "select",
          "label": "Style",
          "default": "decimal",
          "choices": [
            {
              "value": "decimal",
              "label": "Plain number"
            },
            {
              "value": "currency",
              "label": "Currency"
            },
            {
              "value": "percent",
              "label": "Percent"
            },
            {
              "value": "unit",
              "label": "Unit"
            }
          ]
        },
        {
          "key": "currency",
          "kind": "select",
          "label": "Currency code",
          "default": "USD",
          "choices": [
            {
              "value": "USD",
              "label": "USD — US dollar"
            },
            {
              "value": "EUR",
              "label": "EUR — euro"
            },
            {
              "value": "GBP",
              "label": "GBP — British pound"
            },
            {
              "value": "CZK",
              "label": "CZK — Czech koruna"
            },
            {
              "value": "PLN",
              "label": "PLN — Polish złoty"
            },
            {
              "value": "HUF",
              "label": "HUF — Hungarian forint"
            },
            {
              "value": "CHF",
              "label": "CHF — Swiss franc"
            },
            {
              "value": "JPY",
              "label": "JPY — Japanese yen"
            },
            {
              "value": "SEK",
              "label": "SEK — Swedish krona"
            },
            {
              "value": "RON",
              "label": "RON — Romanian leu"
            },
            {
              "value": "UAH",
              "label": "UAH — Ukrainian hryvnia"
            }
          ]
        },
        {
          "key": "currencyDisplay",
          "kind": "select",
          "label": "Currency shown as",
          "default": "symbol",
          "choices": [
            {
              "value": "symbol",
              "label": "Symbol ($, €, £)"
            },
            {
              "value": "code",
              "label": "Code (USD, EUR)"
            },
            {
              "value": "name",
              "label": "Name (US dollars)"
            }
          ]
        },
        {
          "key": "unit",
          "kind": "select",
          "label": "Unit",
          "default": "kilometer",
          "choices": [
            {
              "value": "kilometer",
              "label": "Kilometer"
            },
            {
              "value": "meter",
              "label": "Meter"
            },
            {
              "value": "centimeter",
              "label": "Centimeter"
            },
            {
              "value": "mile",
              "label": "Mile"
            },
            {
              "value": "kilogram",
              "label": "Kilogram"
            },
            {
              "value": "gram",
              "label": "Gram"
            },
            {
              "value": "liter",
              "label": "Liter"
            },
            {
              "value": "celsius",
              "label": "Celsius"
            },
            {
              "value": "fahrenheit",
              "label": "Fahrenheit"
            },
            {
              "value": "byte",
              "label": "Byte"
            },
            {
              "value": "megabyte",
              "label": "Megabyte"
            }
          ]
        },
        {
          "key": "unitDisplay",
          "kind": "select",
          "label": "Unit length",
          "default": "short",
          "choices": [
            {
              "value": "long",
              "label": "Long (5 kilometers)"
            },
            {
              "value": "short",
              "label": "Short (5 km)"
            },
            {
              "value": "narrow",
              "label": "Narrow (5km)"
            }
          ]
        },
        {
          "key": "minimumFractionDigits",
          "kind": "number",
          "label": "Minimum decimal places",
          "default": 0,
          "min": 0,
          "max": 20,
          "step": 1
        },
        {
          "key": "maximumFractionDigits",
          "kind": "number",
          "label": "Maximum decimal places",
          "default": 3,
          "min": 0,
          "max": 20,
          "step": 1
        },
        {
          "key": "useGrouping",
          "kind": "checkbox",
          "label": "Group thousands",
          "default": true
        },
        {
          "key": "notation",
          "kind": "select",
          "label": "Notation",
          "default": "standard",
          "choices": [
            {
              "value": "standard",
              "label": "Standard (1,234,567)"
            },
            {
              "value": "compact",
              "label": "Compact (1.2M)"
            },
            {
              "value": "scientific",
              "label": "Scientific (1.235E6)"
            },
            {
              "value": "engineering",
              "label": "Engineering (1.235E6)"
            }
          ]
        },
        {
          "key": "signDisplay",
          "kind": "select",
          "label": "Sign",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Only for negative numbers"
            },
            {
              "value": "always",
              "label": "Always show +/−"
            },
            {
              "value": "exceptZero",
              "label": "Always, except zero"
            },
            {
              "value": "never",
              "label": "Never show a sign"
            }
          ]
        },
        {
          "key": "showOriginal",
          "kind": "checkbox",
          "label": "Show original value",
          "default": true
        }
      ],
      "keywords": [
        "number formatter",
        "locale number formatter",
        "intl numberformat",
        "currency formatter",
        "percent formatter",
        "unit formatter",
        "number notation converter",
        "thousands grouping",
        "decimal places formatter"
      ],
      "updated": "2026-08-08"
    },
    {
      "slug": "google-ads-length-checker",
      "name": "Google Ads length checker",
      "description": "Check headlines, descriptions and paths against Google Ads character limits before you upload them.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/google-ads-length-checker",
      "embed": "https://textarray.com/embed/google-ads-length-checker",
      "mode": "transform",
      "action": "Check lengths",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "defaultField",
          "kind": "select",
          "label": "Default field type",
          "default": "headline",
          "choices": [
            {
              "value": "headline",
              "label": "Headline (30)"
            },
            {
              "value": "description",
              "label": "Description (90)"
            },
            {
              "value": "path",
              "label": "Path (15)"
            }
          ]
        },
        {
          "key": "countDynamicInsertion",
          "kind": "checkbox",
          "label": "Count dynamic insertion syntax literally",
          "default": true
        },
        {
          "key": "warnDuplicateHeadlines",
          "kind": "checkbox",
          "label": "Warn on duplicate headlines",
          "default": true
        },
        {
          "key": "warnCapsAndExclaim",
          "kind": "checkbox",
          "label": "Warn on exclamation marks and ALL CAPS",
          "default": true
        }
      ],
      "keywords": [
        "google ads character limit checker",
        "headline length checker",
        "description character limit",
        "rsa character count",
        "google ads headline limit",
        "ad copy length checker",
        "ppc character counter",
        "responsive search ads limit"
      ],
      "updated": "2026-08-08"
    },
    {
      "slug": "hreflang-generator",
      "name": "Hreflang tag generator",
      "description": "Turn a list of language versions into a complete set of hreflang tags.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/hreflang-generator",
      "embed": "https://textarray.com/embed/hreflang-generator",
      "mode": "transform",
      "action": "Generate hreflang tags",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "html",
          "choices": [
            {
              "value": "html",
              "label": "HTML tags"
            },
            {
              "value": "http",
              "label": "HTTP headers"
            },
            {
              "value": "xml",
              "label": "XML sitemap"
            }
          ]
        },
        {
          "key": "addXDefault",
          "kind": "checkbox",
          "label": "Add x-default",
          "default": true
        },
        {
          "key": "xDefaultCode",
          "kind": "text",
          "label": "x-default language code",
          "default": ""
        }
      ],
      "keywords": [
        "hreflang tag generator",
        "rel alternate hreflang",
        "x-default tag",
        "multilingual seo tags",
        "international seo",
        "hreflang sitemap",
        "html",
        "xml",
        "http header"
      ],
      "updated": "2026-07-15"
    },
    {
      "slug": "redirect-rule-generator",
      "name": "Redirect rule generator",
      "description": "Turn a list of old-URL/new-URL pairs into ready-to-use redirect rules.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/redirect-rule-generator",
      "embed": "https://textarray.com/embed/redirect-rule-generator",
      "mode": "transform",
      "action": "Generate redirect rules",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Target format",
          "default": "apache",
          "choices": [
            {
              "value": "apache",
              "label": "Apache (.htaccess)"
            },
            {
              "value": "nginx",
              "label": "nginx"
            },
            {
              "value": "netlify",
              "label": "Netlify (_redirects)"
            },
            {
              "value": "cloudflare",
              "label": "Cloudflare Pages (_redirects)"
            },
            {
              "value": "json",
              "label": "JSON"
            }
          ]
        },
        {
          "key": "status",
          "kind": "select",
          "label": "Redirect type",
          "default": "301",
          "choices": [
            {
              "value": "301",
              "label": "301 — permanent"
            },
            {
              "value": "302",
              "label": "302 — temporary"
            },
            {
              "value": "308",
              "label": "308 — permanent, keeps method"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Input separator",
          "default": "arrow",
          "choices": [
            {
              "value": "arrow",
              "label": "Arrow (->)"
            },
            {
              "value": "comma",
              "label": "Comma (,)"
            },
            {
              "value": "pipe",
              "label": "Pipe (|)"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "space",
              "label": "Space"
            }
          ]
        },
        {
          "key": "stripDomain",
          "kind": "checkbox",
          "label": "Strip domain, use relative paths",
          "default": false
        },
        {
          "key": "detectIssues",
          "kind": "checkbox",
          "label": "Warn about redirect chains and loops",
          "default": true
        }
      ],
      "keywords": [
        "redirect rule generator",
        "301 redirect generator",
        "htaccess redirect generator",
        "nginx redirect generator",
        "netlify redirects generator",
        "cloudflare redirects generator",
        "url redirect generator",
        "redirect chain checker",
        "redirect loop detector",
        "htaccess",
        "nginx",
        "json"
      ],
      "updated": "2026-08-08"
    },
    {
      "slug": "passive-voice-detector",
      "name": "Passive voice detector",
      "description": "Find passive-voice sentences in your text and see who or what performed the action.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/passive-voice-detector",
      "embed": "https://textarray.com/embed/passive-voice-detector",
      "mode": "transform",
      "action": "Find passive voice",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "language",
          "kind": "select",
          "label": "Text language",
          "default": "en",
          "choices": [
            {
              "value": "en",
              "label": "English"
            },
            {
              "value": "sk",
              "label": "Slovak"
            },
            {
              "value": "cs",
              "label": "Czech"
            },
            {
              "value": "de",
              "label": "German"
            }
          ]
        },
        {
          "key": "threshold",
          "kind": "range",
          "label": "Warn above this passive share (%)",
          "default": 25,
          "min": 0,
          "max": 100
        },
        {
          "key": "reflexivePassive",
          "kind": "checkbox",
          "label": "Include reflexive passive (sa / se)",
          "default": false
        },
        {
          "key": "highlightIndefinite",
          "kind": "checkbox",
          "label": "Also mark indefinite subjects and verbal nouns",
          "default": false
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List of sentences"
            },
            {
              "value": "highlighted",
              "label": "Highlighted text"
            }
          ]
        }
      ],
      "keywords": [
        "passive voice detector",
        "passive voice checker",
        "find passive sentences",
        "passive to active",
        "writing style checker",
        "weak writing detector",
        "grammar checker",
        "sentence agent finder"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "vat-number-validator",
      "name": "EU VAT number validator",
      "description": "Check the format and check digit of European VAT numbers, per country.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/vat-number-validator",
      "embed": "https://textarray.com/embed/vat-number-validator",
      "mode": "transform",
      "action": "Validate VAT numbers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "country",
          "kind": "select",
          "label": "Country",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect from prefix"
            },
            {
              "value": "AT",
              "label": "Austria (AT)"
            },
            {
              "value": "BE",
              "label": "Belgium (BE)"
            },
            {
              "value": "BG",
              "label": "Bulgaria (BG)"
            },
            {
              "value": "CY",
              "label": "Cyprus (CY)"
            },
            {
              "value": "CZ",
              "label": "Czechia (CZ)"
            },
            {
              "value": "DE",
              "label": "Germany (DE)"
            },
            {
              "value": "DK",
              "label": "Denmark (DK)"
            },
            {
              "value": "EE",
              "label": "Estonia (EE)"
            },
            {
              "value": "EL",
              "label": "Greece (EL)"
            },
            {
              "value": "ES",
              "label": "Spain (ES)"
            },
            {
              "value": "FI",
              "label": "Finland (FI)"
            },
            {
              "value": "FR",
              "label": "France (FR)"
            },
            {
              "value": "HR",
              "label": "Croatia (HR)"
            },
            {
              "value": "HU",
              "label": "Hungary (HU)"
            },
            {
              "value": "IE",
              "label": "Ireland (IE)"
            },
            {
              "value": "IT",
              "label": "Italy (IT)"
            },
            {
              "value": "LT",
              "label": "Lithuania (LT)"
            },
            {
              "value": "LU",
              "label": "Luxembourg (LU)"
            },
            {
              "value": "LV",
              "label": "Latvia (LV)"
            },
            {
              "value": "MT",
              "label": "Malta (MT)"
            },
            {
              "value": "NL",
              "label": "Netherlands (NL)"
            },
            {
              "value": "PL",
              "label": "Poland (PL)"
            },
            {
              "value": "PT",
              "label": "Portugal (PT)"
            },
            {
              "value": "RO",
              "label": "Romania (RO)"
            },
            {
              "value": "SE",
              "label": "Sweden (SE)"
            },
            {
              "value": "SI",
              "label": "Slovenia (SI)"
            },
            {
              "value": "SK",
              "label": "Slovakia (SK)"
            }
          ]
        },
        {
          "key": "stripSeparators",
          "kind": "checkbox",
          "label": "Remove spaces and dashes before checking",
          "default": true
        },
        {
          "key": "addPrefix",
          "kind": "checkbox",
          "label": "Add country prefix when missing",
          "default": false
        },
        {
          "key": "show",
          "kind": "select",
          "label": "Show",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All numbers"
            },
            {
              "value": "valid",
              "label": "Valid only"
            },
            {
              "value": "invalid",
              "label": "Invalid only"
            }
          ]
        },
        {
          "key": "reason",
          "kind": "checkbox",
          "label": "Show rejection reason",
          "default": true
        }
      ],
      "keywords": [
        "vat number validator",
        "eu vat checker",
        "validate vat number",
        "vat id validator",
        "vat check digit",
        "vies alternative",
        "vat format checker"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "isbn-validator",
      "name": "ISBN validator",
      "description": "Check ISBN-10 and ISBN-13 checksums, convert between formats, and format with hyphens.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/isbn-validator",
      "embed": "https://textarray.com/embed/isbn-validator",
      "mode": "transform",
      "action": "Validate ISBNs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "hyphens",
          "kind": "checkbox",
          "label": "With hyphens",
          "default": true
        },
        {
          "key": "convert",
          "kind": "select",
          "label": "Convert",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Keep format"
            },
            {
              "value": "toIsbn13",
              "label": "Convert to ISBN-13"
            },
            {
              "value": "toIsbn10",
              "label": "Convert to ISBN-10"
            }
          ]
        },
        {
          "key": "showPrefix",
          "kind": "checkbox",
          "label": "Show publisher prefix",
          "default": false
        },
        {
          "key": "onlyValid",
          "kind": "checkbox",
          "label": "Keep only valid numbers",
          "default": false
        }
      ],
      "keywords": [
        "isbn validator",
        "isbn checker",
        "isbn checksum",
        "validate isbn",
        "isbn-10 to isbn-13",
        "isbn-13 to isbn-10",
        "check book isbn",
        "isbn format"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "ean-upc-validator",
      "name": "EAN and UPC validator",
      "description": "Check the check digit of EAN-13, EAN-8, UPC-A and UPC-E barcodes, or complete a missing one.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/ean-upc-validator",
      "embed": "https://textarray.com/embed/ean-upc-validator",
      "mode": "transform",
      "action": "Validate barcodes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "codeType",
          "kind": "select",
          "label": "Code type",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect by length"
            },
            {
              "value": "ean13",
              "label": "EAN-13"
            },
            {
              "value": "ean8",
              "label": "EAN-8"
            },
            {
              "value": "upca",
              "label": "UPC-A"
            },
            {
              "value": "upce",
              "label": "UPC-E"
            }
          ]
        },
        {
          "key": "completeCheckDigit",
          "kind": "checkbox",
          "label": "Complete missing check digit",
          "default": true
        },
        {
          "key": "convertToEan13",
          "kind": "checkbox",
          "label": "Convert UPC-A/UPC-E to EAN-13",
          "default": false
        },
        {
          "key": "showCountry",
          "kind": "checkbox",
          "label": "Show country from GS1 prefix",
          "default": false
        },
        {
          "key": "validOnly",
          "kind": "checkbox",
          "label": "Keep only valid lines",
          "default": false
        }
      ],
      "keywords": [
        "ean validator",
        "upc validator",
        "barcode checker",
        "ean-13",
        "ean-8",
        "upc-a",
        "upc-e",
        "gtin",
        "check digit calculator",
        "gs1 prefix",
        "barcode check digit"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "test-card-number-generator",
      "name": "Test card number generator",
      "description": "Generate fake payment card numbers with a valid Luhn checksum for testing forms.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/test-card-number-generator",
      "embed": "https://textarray.com/embed/test-card-number-generator",
      "mode": "generate",
      "action": "Generate test cards",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "brand",
          "kind": "select",
          "label": "Card brand",
          "default": "visa",
          "choices": [
            {
              "value": "visa",
              "label": "Visa"
            },
            {
              "value": "mastercard",
              "label": "Mastercard"
            },
            {
              "value": "amex",
              "label": "American Express"
            },
            {
              "value": "discover",
              "label": "Discover"
            },
            {
              "value": "jcb",
              "label": "JCB"
            }
          ]
        },
        {
          "key": "count",
          "kind": "number",
          "label": "How many",
          "default": 10,
          "min": 1,
          "max": 1000,
          "step": 1
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Number formatting",
          "default": "grouped",
          "choices": [
            {
              "value": "grouped",
              "label": "Grouped in fours"
            },
            {
              "value": "continuous",
              "label": "Continuous"
            }
          ]
        },
        {
          "key": "includeExpiry",
          "kind": "checkbox",
          "label": "Include expiry date",
          "default": false
        },
        {
          "key": "includeCvv",
          "kind": "checkbox",
          "label": "Include CVV",
          "default": false
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "test card number generator",
        "fake credit card generator",
        "dummy card number",
        "luhn algorithm generator",
        "test visa number",
        "sample credit card number",
        "card checkout testing",
        "mastercard",
        "amex",
        "discover",
        "jcb",
        "csv"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "sitemap-parser",
      "name": "Sitemap parser",
      "description": "Turn a sitemap.xml into a readable URL list and check it for common errors.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sitemap-parser",
      "embed": "https://textarray.com/embed/sitemap-parser",
      "mode": "transform",
      "action": "Parse sitemap",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "showLastmod",
          "kind": "checkbox",
          "label": "Show lastmod",
          "default": true
        },
        {
          "key": "showChangefreq",
          "kind": "checkbox",
          "label": "Show changefreq",
          "default": true
        },
        {
          "key": "showPriority",
          "kind": "checkbox",
          "label": "Show priority",
          "default": true
        },
        {
          "key": "showHreflangCount",
          "kind": "checkbox",
          "label": "Show hreflang alternate count",
          "default": false
        },
        {
          "key": "checks",
          "kind": "checkbox",
          "label": "Run validity checks",
          "default": true
        },
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Document order"
            },
            {
              "value": "lastmod-desc",
              "label": "Lastmod (newest first)"
            },
            {
              "value": "lastmod-asc",
              "label": "Lastmod (oldest first)"
            },
            {
              "value": "priority-desc",
              "label": "Priority (high to low)"
            },
            {
              "value": "priority-asc",
              "label": "Priority (low to high)"
            }
          ]
        },
        {
          "key": "pathFilter",
          "kind": "text",
          "label": "Filter by path",
          "default": ""
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "URL list"
            },
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            },
            {
              "value": "json",
              "label": "JSON"
            }
          ]
        }
      ],
      "keywords": [
        "sitemap parser",
        "parse sitemap.xml",
        "sitemap validator",
        "sitemap checker",
        "sitemap index",
        "urlset",
        "xml",
        "lastmod",
        "changefreq",
        "priority",
        "hreflang"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "breadcrumb-schema-generator",
      "name": "Breadcrumb schema generator",
      "description": "Turn a list of page names and URLs into a BreadcrumbList JSON-LD block.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/breadcrumb-schema-generator",
      "embed": "https://textarray.com/embed/breadcrumb-schema-generator",
      "mode": "transform",
      "action": "Generate schema",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "baseUrl",
          "kind": "text",
          "label": "Base URL",
          "default": ""
        },
        {
          "key": "omitLastUrl",
          "kind": "checkbox",
          "label": "Omit URL on the last item (Google's recommendation)",
          "default": true
        },
        {
          "key": "deriveNames",
          "kind": "checkbox",
          "label": "Derive missing names from the URL",
          "default": true
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Indent the JSON",
          "default": true
        },
        {
          "key": "wrapScript",
          "kind": "checkbox",
          "label": "Wrap in a <script> tag",
          "default": true
        }
      ],
      "keywords": [
        "breadcrumb schema generator",
        "breadcrumb structured data",
        "breadcrumblist json-ld",
        "schema.org breadcrumb",
        "breadcrumb rich snippet",
        "seo breadcrumb markup",
        "json-ld",
        "json"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "howto-schema-generator",
      "name": "HowTo schema generator",
      "description": "Turn a list of steps into a schema.org HowTo JSON-LD block for rich results.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/howto-schema-generator",
      "embed": "https://textarray.com/embed/howto-schema-generator",
      "mode": "transform",
      "action": "Generate schema",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "name",
          "kind": "text",
          "label": "Guide name",
          "default": ""
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "totalTime",
          "kind": "text",
          "label": "Total time (ISO 8601 duration)",
          "default": ""
        },
        {
          "key": "image",
          "kind": "text",
          "label": "Guide image URL",
          "default": ""
        },
        {
          "key": "tools",
          "kind": "text",
          "label": "Tools needed (comma-separated)",
          "default": ""
        },
        {
          "key": "supplies",
          "kind": "text",
          "label": "Materials needed (comma-separated)",
          "default": ""
        },
        {
          "key": "estimatedCost",
          "kind": "text",
          "label": "Estimated cost",
          "default": ""
        },
        {
          "key": "currency",
          "kind": "text",
          "label": "Currency code",
          "default": ""
        },
        {
          "key": "stepUrlPrefix",
          "kind": "text",
          "label": "Step anchor URL prefix",
          "default": ""
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print JSON",
          "default": true
        },
        {
          "key": "wrapScript",
          "kind": "checkbox",
          "label": "Wrap in <script> tag",
          "default": true
        }
      ],
      "keywords": [
        "howto schema generator",
        "howto schema",
        "schema.org howto",
        "json-ld howto",
        "howto structured data",
        "rich results howto",
        "howto rich snippet",
        "json-ld",
        "structured data"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "localbusiness-schema-generator",
      "name": "LocalBusiness schema generator",
      "description": "Build a schema.org LocalBusiness JSON-LD block from your business details.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/localbusiness-schema-generator",
      "embed": "https://textarray.com/embed/localbusiness-schema-generator",
      "mode": "transform",
      "action": "Generate schema",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "subtype",
          "kind": "select",
          "label": "Business type",
          "default": "LocalBusiness",
          "choices": [
            {
              "value": "LocalBusiness",
              "label": "Local business (generic)"
            },
            {
              "value": "Restaurant",
              "label": "Restaurant"
            },
            {
              "value": "Store",
              "label": "Store"
            },
            {
              "value": "ProfessionalService",
              "label": "Professional service"
            },
            {
              "value": "MedicalBusiness",
              "label": "Medical business"
            },
            {
              "value": "Dentist",
              "label": "Dentist"
            },
            {
              "value": "HairSalon",
              "label": "Hair salon"
            },
            {
              "value": "BeautySalon",
              "label": "Beauty salon"
            },
            {
              "value": "AutoRepair",
              "label": "Auto repair shop"
            },
            {
              "value": "LegalService",
              "label": "Legal service"
            },
            {
              "value": "RealEstateAgent",
              "label": "Real estate agent"
            },
            {
              "value": "LodgingBusiness",
              "label": "Lodging / hotel"
            }
          ]
        },
        {
          "key": "name",
          "kind": "text",
          "label": "Business name",
          "default": ""
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "url",
          "kind": "text",
          "label": "Website URL",
          "default": ""
        },
        {
          "key": "logo",
          "kind": "text",
          "label": "Logo URL",
          "default": ""
        },
        {
          "key": "streetAddress",
          "kind": "text",
          "label": "Street address",
          "default": ""
        },
        {
          "key": "addressLocality",
          "kind": "text",
          "label": "City",
          "default": ""
        },
        {
          "key": "addressRegion",
          "kind": "text",
          "label": "Region / state",
          "default": ""
        },
        {
          "key": "postalCode",
          "kind": "text",
          "label": "Postal code",
          "default": ""
        },
        {
          "key": "addressCountry",
          "kind": "text",
          "label": "Country code",
          "default": ""
        },
        {
          "key": "latitude",
          "kind": "text",
          "label": "Latitude",
          "default": ""
        },
        {
          "key": "longitude",
          "kind": "text",
          "label": "Longitude",
          "default": ""
        },
        {
          "key": "telephone",
          "kind": "text",
          "label": "Phone (international format)",
          "default": ""
        },
        {
          "key": "email",
          "kind": "text",
          "label": "Email",
          "default": ""
        },
        {
          "key": "priceRange",
          "kind": "select",
          "label": "Price range",
          "default": "",
          "choices": [
            {
              "value": "",
              "label": "Not set"
            },
            {
              "value": "$",
              "label": "$"
            },
            {
              "value": "$$",
              "label": "$$"
            },
            {
              "value": "$$$",
              "label": "$$$"
            },
            {
              "value": "$$$$",
              "label": "$$$$"
            }
          ]
        },
        {
          "key": "ratingValue",
          "kind": "number",
          "label": "Rating value",
          "default": 0,
          "min": 0,
          "max": 5,
          "step": 0.1
        },
        {
          "key": "reviewCount",
          "kind": "number",
          "label": "Review count",
          "default": 0,
          "min": 0,
          "step": 1
        },
        {
          "key": "bestRating",
          "kind": "number",
          "label": "Best possible rating",
          "default": 5,
          "min": 1,
          "max": 10,
          "step": 1
        },
        {
          "key": "worstRating",
          "kind": "number",
          "label": "Worst possible rating",
          "default": 1,
          "min": 0,
          "max": 10,
          "step": 1
        },
        {
          "key": "wrapScript",
          "kind": "checkbox",
          "label": "Wrap in <script> tag",
          "default": true
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print JSON",
          "default": true
        }
      ],
      "keywords": [
        "localbusiness schema generator",
        "schema.org localbusiness",
        "json-ld generator",
        "local business structured data",
        "google business schema markup",
        "nap schema markup",
        "opening hours schema",
        "json-ld",
        "schema.org",
        "rich results local business"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "tournament-bracket-generator",
      "name": "Tournament bracket generator",
      "description": "Turn a list of participants into a single-elimination bracket with byes handled automatically.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/tournament-bracket-generator",
      "embed": "https://textarray.com/embed/tournament-bracket-generator",
      "mode": "transform",
      "action": "Generate bracket",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "seeding",
          "kind": "select",
          "label": "Seeding",
          "default": "seeded",
          "choices": [
            {
              "value": "seeded",
              "label": "Keep list order (seeded)"
            },
            {
              "value": "random",
              "label": "Random draw"
            }
          ]
        },
        {
          "key": "size",
          "kind": "select",
          "label": "Bracket size",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto (next power of two)"
            },
            {
              "value": "4",
              "label": "4"
            },
            {
              "value": "8",
              "label": "8"
            },
            {
              "value": "16",
              "label": "16"
            },
            {
              "value": "32",
              "label": "32"
            },
            {
              "value": "64",
              "label": "64"
            },
            {
              "value": "128",
              "label": "128"
            },
            {
              "value": "256",
              "label": "256"
            }
          ]
        },
        {
          "key": "pairing",
          "kind": "select",
          "label": "Rounds shown",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "Every round"
            },
            {
              "value": "first",
              "label": "First round only"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "tree",
          "choices": [
            {
              "value": "tree",
              "label": "Indented tree"
            },
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "text",
              "label": "Text diagram"
            }
          ]
        },
        {
          "key": "byePlacement",
          "kind": "select",
          "label": "Bye placement",
          "default": "spread",
          "choices": [
            {
              "value": "spread",
              "label": "Spread evenly"
            },
            {
              "value": "top",
              "label": "Top of bracket"
            },
            {
              "value": "bottom",
              "label": "Bottom of bracket"
            }
          ]
        }
      ],
      "keywords": [
        "tournament bracket generator",
        "bracket maker",
        "single elimination bracket",
        "knockout bracket",
        "seeding",
        "bye",
        "matchup generator",
        "bracket"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "round-robin-scheduler",
      "name": "Round-robin schedule generator",
      "description": "Build a schedule where every participant plays every other exactly once, split into fair rounds.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/round-robin-scheduler",
      "embed": "https://textarray.com/embed/round-robin-scheduler",
      "mode": "transform",
      "action": "Generate schedule",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "legs",
          "kind": "select",
          "label": "Rounds",
          "default": "single",
          "choices": [
            {
              "value": "single",
              "label": "Single round-robin"
            },
            {
              "value": "double",
              "label": "Double round-robin (home & away)"
            }
          ]
        },
        {
          "key": "showByes",
          "kind": "checkbox",
          "label": "Show byes for odd participant counts",
          "default": true
        },
        {
          "key": "numbered",
          "kind": "checkbox",
          "label": "Number rounds and matches",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List"
            },
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "round robin scheduler",
        "round robin generator",
        "everyone plays everyone",
        "league schedule maker",
        "tournament schedule generator",
        "fixture generator",
        "home and away schedule",
        "league fixtures"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "align-columns",
      "name": "Align text into columns",
      "description": "Line up separator-delimited text into neat columns by padding every cell to the widest one.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/align-columns",
      "embed": "https://textarray.com/embed/align-columns",
      "mode": "transform",
      "action": "Align columns",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "text",
          "label": "Separator",
          "default": ","
        },
        {
          "key": "align",
          "kind": "select",
          "label": "Column alignment",
          "default": "left",
          "choices": [
            {
              "value": "left",
              "label": "Left"
            },
            {
              "value": "right",
              "label": "Right"
            },
            {
              "value": "decimal",
              "label": "Decimal point"
            }
          ]
        },
        {
          "key": "spacing",
          "kind": "number",
          "label": "Spaces between columns",
          "default": 2,
          "min": 0,
          "max": 10,
          "step": 1
        },
        {
          "key": "fillChar",
          "kind": "select",
          "label": "Fill character",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Spaces"
            },
            {
              "value": "dot",
              "label": "Dots"
            }
          ]
        },
        {
          "key": "border",
          "kind": "checkbox",
          "label": "Border as ASCII table",
          "default": false
        },
        {
          "key": "keepEmpty",
          "kind": "checkbox",
          "label": "Keep empty cells",
          "default": true
        }
      ],
      "keywords": [
        "align columns",
        "align text columns",
        "column alignment",
        "align csv",
        "align tsv",
        "text table",
        "ascii table",
        "tabular text",
        "csv",
        "tsv"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "fixed-width-splitter",
      "name": "Fixed-width column splitter",
      "description": "Split lines with fixed-width fields into columns using widths or cut positions.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/fixed-width-splitter",
      "embed": "https://textarray.com/embed/fixed-width-splitter",
      "mode": "transform",
      "action": "Split columns",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "specMode",
          "kind": "select",
          "label": "Split by",
          "default": "widths",
          "choices": [
            {
              "value": "widths",
              "label": "Column widths"
            },
            {
              "value": "positions",
              "label": "Cut positions"
            }
          ]
        },
        {
          "key": "spec",
          "kind": "text",
          "label": "Widths or positions",
          "default": "3,3"
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim cell whitespace",
          "default": true
        },
        {
          "key": "header",
          "kind": "checkbox",
          "label": "First line is a header",
          "default": false
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Output delimiter",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma (,)"
            },
            {
              "value": "semicolon",
              "label": "Semicolon (;)"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe (|)"
            }
          ]
        },
        {
          "key": "reverse",
          "kind": "checkbox",
          "label": "Reverse: delimited text to fixed width",
          "default": false
        },
        {
          "key": "warnUneven",
          "kind": "checkbox",
          "label": "Warn about lines with a different length",
          "default": true
        }
      ],
      "keywords": [
        "fixed width splitter",
        "fixed-width columns",
        "column splitter",
        "flat file parser",
        "positional text file",
        "fixed width to csv",
        "csv to fixed width",
        "mainframe file converter",
        "csv"
      ],
      "updated": "2026-08-11"
    },
    {
      "slug": "json-to-java-class",
      "name": "JSON to Java class",
      "description": "Turn a JSON sample into Java classes, with nested types and generic lists inferred automatically.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-java-class",
      "embed": "https://textarray.com/embed/json-to-java-class",
      "mode": "transform",
      "action": "Generate Java class",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "rootName",
          "kind": "text",
          "label": "Root class name",
          "default": "Root"
        },
        {
          "key": "annotations",
          "kind": "select",
          "label": "Annotations",
          "default": "jackson",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "jackson",
              "label": "Jackson (@JsonProperty)"
            },
            {
              "value": "gson",
              "label": "Gson (@SerializedName)"
            }
          ]
        },
        {
          "key": "generateGetters",
          "kind": "checkbox",
          "label": "Generate getters and setters",
          "default": true
        },
        {
          "key": "lombokData",
          "kind": "checkbox",
          "label": "Use Lombok @Data instead",
          "default": false
        },
        {
          "key": "useRecord",
          "kind": "checkbox",
          "label": "Use a Java record instead of a class",
          "default": false
        },
        {
          "key": "useWrapperTypes",
          "kind": "checkbox",
          "label": "Use wrapper types (Integer, Boolean) instead of primitives",
          "default": false
        },
        {
          "key": "packageName",
          "kind": "text",
          "label": "Package declaration",
          "default": ""
        },
        {
          "key": "classStyle",
          "kind": "select",
          "label": "Class layout",
          "default": "nested",
          "choices": [
            {
              "value": "nested",
              "label": "Static nested classes"
            },
            {
              "value": "separate",
              "label": "Separate top-level classes"
            }
          ]
        }
      ],
      "keywords": [
        "json to java class",
        "json to pojo",
        "pojo generator",
        "java class generator",
        "jackson annotations",
        "gson annotations",
        "lombok",
        "java record",
        "json"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "json-to-csharp-class",
      "name": "JSON to C# class",
      "description": "Turn a JSON sample into ready-to-use C# classes.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-csharp-class",
      "embed": "https://textarray.com/embed/json-to-csharp-class",
      "mode": "transform",
      "action": "Generate C# class",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "rootClassName",
          "kind": "text",
          "label": "Root class name",
          "default": "Root"
        },
        {
          "key": "attributeStyle",
          "kind": "select",
          "label": "Attributes",
          "default": "systemTextJson",
          "choices": [
            {
              "value": "systemTextJson",
              "label": "System.Text.Json"
            },
            {
              "value": "newtonsoft",
              "label": "Newtonsoft.Json"
            },
            {
              "value": "none",
              "label": "None"
            }
          ]
        },
        {
          "key": "memberKind",
          "kind": "select",
          "label": "Members",
          "default": "properties",
          "choices": [
            {
              "value": "properties",
              "label": "Properties"
            },
            {
              "value": "fields",
              "label": "Fields"
            }
          ]
        },
        {
          "key": "listSyntax",
          "kind": "select",
          "label": "Array type",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List<T>"
            },
            {
              "value": "array",
              "label": "T[]"
            }
          ]
        },
        {
          "key": "pascalCase",
          "kind": "checkbox",
          "label": "PascalCase property names",
          "default": true
        },
        {
          "key": "nullableRefs",
          "kind": "checkbox",
          "label": "Nullable reference types",
          "default": true
        },
        {
          "key": "useRecord",
          "kind": "checkbox",
          "label": "Use record instead of class",
          "default": false
        },
        {
          "key": "namespaceName",
          "kind": "text",
          "label": "Namespace",
          "default": ""
        }
      ],
      "keywords": [
        "json to c# class",
        "json to csharp",
        "c# class generator",
        "csharp model generator",
        "json to c# model",
        "json2csharp",
        "json",
        "c#",
        "csharp",
        ".net",
        "json.net",
        "system.text.json"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "json-to-protobuf",
      "name": "JSON to Protobuf schema",
      "description": "Turn a JSON sample into a Protocol Buffers .proto message definition.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-protobuf",
      "embed": "https://textarray.com/embed/json-to-protobuf",
      "mode": "transform",
      "action": "Generate schema",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "syntax",
          "kind": "select",
          "label": "Syntax",
          "default": "proto3",
          "choices": [
            {
              "value": "proto3",
              "label": "proto3"
            },
            {
              "value": "proto2",
              "label": "proto2"
            }
          ]
        },
        {
          "key": "rootName",
          "kind": "text",
          "label": "Root message name",
          "default": "Root"
        },
        {
          "key": "packageName",
          "kind": "text",
          "label": "Package",
          "default": ""
        },
        {
          "key": "startFieldNumber",
          "kind": "number",
          "label": "Start field number at",
          "default": 1,
          "min": 1,
          "max": 536870911
        },
        {
          "key": "fieldNumberStep",
          "kind": "number",
          "label": "Field number step",
          "default": 1,
          "min": 1,
          "max": 1000
        },
        {
          "key": "useMapForObjects",
          "kind": "checkbox",
          "label": "Use map<string, T> for dictionary-like objects",
          "default": true
        },
        {
          "key": "optionalFields",
          "kind": "checkbox",
          "label": "Mark sometimes-missing fields as optional (proto3)",
          "default": false
        },
        {
          "key": "nestedMessages",
          "kind": "checkbox",
          "label": "Nest messages inside their parent",
          "default": true
        },
        {
          "key": "detectTimestamps",
          "kind": "checkbox",
          "label": "Use google.protobuf.Timestamp for dates",
          "default": true
        },
        {
          "key": "commentOriginalKey",
          "kind": "checkbox",
          "label": "Comment each field with its original JSON key",
          "default": false
        }
      ],
      "keywords": [
        "json to protobuf",
        "protobuf schema generator",
        "protocol buffers",
        "proto3",
        "proto2",
        ".proto file generator",
        "json",
        "grpc"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "json-patch-applier",
      "name": "JSON Patch applier",
      "description": "Apply an RFC 6902 JSON Patch (or RFC 7396 merge patch) to a JSON document.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-patch-applier",
      "embed": "https://textarray.com/embed/json-patch-applier",
      "mode": "transform",
      "action": "Apply patch",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Patch (JSON)"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Patch format",
          "default": "patch",
          "choices": [
            {
              "value": "patch",
              "label": "JSON Patch (RFC 6902)"
            },
            {
              "value": "merge",
              "label": "JSON Merge Patch (RFC 7396)"
            }
          ]
        },
        {
          "key": "onError",
          "kind": "select",
          "label": "On error",
          "default": "stop",
          "choices": [
            {
              "value": "stop",
              "label": "Stop at first error"
            },
            {
              "value": "continue",
              "label": "Skip and continue"
            }
          ]
        },
        {
          "key": "dryRun",
          "kind": "checkbox",
          "label": "Dry run (don't write)",
          "default": false
        },
        {
          "key": "trace",
          "kind": "checkbox",
          "label": "Show step-by-step trace",
          "default": false
        },
        {
          "key": "compact",
          "kind": "checkbox",
          "label": "Compact output",
          "default": false
        }
      ],
      "keywords": [
        "json patch",
        "rfc 6902",
        "rfc 7396",
        "apply json patch",
        "merge patch",
        "json pointer",
        "patch json online",
        "json"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "web-app-manifest-generator",
      "name": "Web app manifest generator",
      "description": "Build a valid manifest.json for your progressive web app from name, icons, colors and display options.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/web-app-manifest-generator",
      "embed": "https://textarray.com/embed/web-app-manifest-generator",
      "mode": "generate",
      "action": "Generate manifest",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "name",
          "kind": "text",
          "label": "App name",
          "default": "My App"
        },
        {
          "key": "shortName",
          "kind": "text",
          "label": "Short name",
          "default": "My App"
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "startUrl",
          "kind": "text",
          "label": "Start URL",
          "default": "/"
        },
        {
          "key": "scope",
          "kind": "text",
          "label": "Scope",
          "default": "/"
        },
        {
          "key": "display",
          "kind": "select",
          "label": "Display",
          "default": "standalone",
          "choices": [
            {
              "value": "standalone",
              "label": "Standalone"
            },
            {
              "value": "fullscreen",
              "label": "Fullscreen"
            },
            {
              "value": "minimal-ui",
              "label": "Minimal UI"
            },
            {
              "value": "browser",
              "label": "Browser"
            }
          ]
        },
        {
          "key": "orientation",
          "kind": "select",
          "label": "Orientation",
          "default": "any",
          "choices": [
            {
              "value": "any",
              "label": "Any"
            },
            {
              "value": "natural",
              "label": "Natural"
            },
            {
              "value": "portrait",
              "label": "Portrait"
            },
            {
              "value": "landscape",
              "label": "Landscape"
            }
          ]
        },
        {
          "key": "themeColor",
          "kind": "text",
          "label": "Theme color",
          "default": "#0b0b0c"
        },
        {
          "key": "backgroundColor",
          "kind": "text",
          "label": "Background color",
          "default": "#ffffff"
        },
        {
          "key": "lang",
          "kind": "text",
          "label": "Language",
          "default": "en"
        },
        {
          "key": "dir",
          "kind": "select",
          "label": "Text direction",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto"
            },
            {
              "value": "ltr",
              "label": "Left to right"
            },
            {
              "value": "rtl",
              "label": "Right to left"
            }
          ]
        },
        {
          "key": "categories",
          "kind": "text",
          "label": "Categories (comma-separated)",
          "default": ""
        },
        {
          "key": "icons",
          "kind": "text",
          "label": "Icons (src|sizes|purpose, separated by ;)",
          "default": "/icons/icon-192.png|192x192|any;/icons/icon-512.png|512x512|any"
        },
        {
          "key": "shortcuts",
          "kind": "text",
          "label": "Shortcuts (name|url|description, separated by ;)",
          "default": ""
        },
        {
          "key": "relatedApplications",
          "kind": "text",
          "label": "Related applications (platform|url|id, separated by ;)",
          "default": ""
        },
        {
          "key": "preferRelated",
          "kind": "checkbox",
          "label": "Prefer related applications",
          "default": false
        }
      ],
      "keywords": [
        "web app manifest generator",
        "pwa manifest generator",
        "manifest.json generator",
        "create manifest.json",
        "progressive web app manifest",
        "app icons manifest",
        "web manifest maker",
        "manifest.json",
        "pwa"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "har-sanitizer",
      "name": "HAR file sanitizer",
      "description": "Strip auth tokens, cookies and secrets from a HAR file before sharing it in a support ticket.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/har-sanitizer",
      "embed": "https://textarray.com/embed/har-sanitizer",
      "mode": "transform",
      "action": "Sanitize HAR file",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "stripAuthHeaders",
          "kind": "checkbox",
          "label": "Remove auth headers (Authorization, Cookie, Set-Cookie, Proxy-Authorization, X-Api-Key)",
          "default": true
        },
        {
          "key": "maskParams",
          "kind": "checkbox",
          "label": "Mask sensitive query & form parameters",
          "default": true
        },
        {
          "key": "maskResponseBodies",
          "kind": "checkbox",
          "label": "Mask response bodies",
          "default": false
        },
        {
          "key": "stripPostData",
          "kind": "checkbox",
          "label": "Remove request bodies (postData)",
          "default": false
        },
        {
          "key": "replacement",
          "kind": "select",
          "label": "Replacement value",
          "default": "redacted",
          "choices": [
            {
              "value": "redacted",
              "label": "REDACTED"
            },
            {
              "value": "empty",
              "label": "Empty string"
            }
          ]
        },
        {
          "key": "keepHeaderNames",
          "kind": "checkbox",
          "label": "Keep header names, clear only the value",
          "default": true
        },
        {
          "key": "showSummary",
          "kind": "checkbox",
          "label": "List what was removed",
          "default": true
        },
        {
          "key": "indent",
          "kind": "select",
          "label": "Output format",
          "default": "pretty",
          "choices": [
            {
              "value": "pretty",
              "label": "Indented"
            },
            {
              "value": "compact",
              "label": "Compact"
            }
          ]
        }
      ],
      "keywords": [
        "har sanitizer",
        "har file",
        "sanitize har",
        "redact har",
        "remove sensitive data",
        "http archive",
        "authorization header",
        "cookie removal",
        "json",
        "devtools export"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "file-signature-identifier",
      "name": "File signature identifier",
      "description": "Identify a file's type from its raw header bytes using a magic-number database.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/file-signature-identifier",
      "embed": "https://textarray.com/embed/file-signature-identifier",
      "mode": "transform",
      "action": "Identify file type",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Input format",
          "default": "hexSpaced",
          "choices": [
            {
              "value": "hexSpaced",
              "label": "Hex with spaces"
            },
            {
              "value": "hexContinuous",
              "label": "Continuous hex"
            },
            {
              "value": "escaped",
              "label": "Escaped \\x bytes"
            },
            {
              "value": "base64",
              "label": "Base64"
            }
          ]
        },
        {
          "key": "showAllMatches",
          "kind": "checkbox",
          "label": "Show all matches",
          "default": true
        },
        {
          "key": "findNested",
          "kind": "checkbox",
          "label": "Search nested signatures",
          "default": false
        },
        {
          "key": "showAscii",
          "kind": "checkbox",
          "label": "Show first bytes as ASCII",
          "default": true
        }
      ],
      "keywords": [
        "file signature identifier",
        "magic number",
        "magic bytes",
        "file type from hex",
        "identify file type",
        "hex signature lookup",
        "file header bytes",
        "file type detector",
        "base64",
        "mime type"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "snowflake-id-decoder",
      "name": "Snowflake ID decoder",
      "description": "Break a 64-bit Snowflake ID into its timestamp, machine and sequence fields.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/snowflake-id-decoder",
      "embed": "https://textarray.com/embed/snowflake-id-decoder",
      "mode": "transform",
      "action": "Decode Snowflake IDs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Epoch / format",
          "default": "twitter",
          "choices": [
            {
              "value": "twitter",
              "label": "Twitter"
            },
            {
              "value": "discord",
              "label": "Discord"
            },
            {
              "value": "instagram",
              "label": "Instagram"
            },
            {
              "value": "mastodon",
              "label": "Mastodon"
            },
            {
              "value": "custom",
              "label": "Custom (ms epoch)"
            }
          ]
        },
        {
          "key": "customEpoch",
          "kind": "number",
          "label": "Custom epoch (Unix ms)",
          "default": 0,
          "min": 0,
          "max": 8640000000000000
        },
        {
          "key": "mode",
          "kind": "select",
          "label": "Direction",
          "default": "decode",
          "choices": [
            {
              "value": "decode",
              "label": "Decode IDs"
            },
            {
              "value": "fromDate",
              "label": "Date → boundary ID"
            }
          ]
        },
        {
          "key": "localTime",
          "kind": "checkbox",
          "label": "Show local time",
          "default": true
        },
        {
          "key": "showBits",
          "kind": "checkbox",
          "label": "Show binary breakdown",
          "default": false
        }
      ],
      "keywords": [
        "snowflake id decoder",
        "twitter snowflake",
        "discord snowflake",
        "decode snowflake id",
        "snowflake timestamp",
        "distributed id",
        "instagram id",
        "mastodon id",
        "epoch",
        "unix timestamp",
        "pagination cursor"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "ics-parser",
      "name": "ICS calendar parser",
      "description": "Turn a pasted .ics calendar file into a readable list of events.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ics-parser",
      "embed": "https://textarray.com/embed/ics-parser",
      "mode": "transform",
      "action": "Parse calendar",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            },
            {
              "value": "json",
              "label": "JSON"
            }
          ]
        },
        {
          "key": "colTitle",
          "kind": "checkbox",
          "label": "Title",
          "default": true
        },
        {
          "key": "colStart",
          "kind": "checkbox",
          "label": "Start",
          "default": true
        },
        {
          "key": "colEnd",
          "kind": "checkbox",
          "label": "End",
          "default": true
        },
        {
          "key": "colDuration",
          "kind": "checkbox",
          "label": "Duration",
          "default": true
        },
        {
          "key": "colLocation",
          "kind": "checkbox",
          "label": "Location",
          "default": true
        },
        {
          "key": "colOrganizer",
          "kind": "checkbox",
          "label": "Organizer",
          "default": false
        },
        {
          "key": "colDescription",
          "kind": "checkbox",
          "label": "Description",
          "default": false
        },
        {
          "key": "colStatus",
          "kind": "checkbox",
          "label": "Status",
          "default": false
        },
        {
          "key": "colUid",
          "kind": "checkbox",
          "label": "UID",
          "default": false
        },
        {
          "key": "timezone",
          "kind": "select",
          "label": "Time zone",
          "default": "original",
          "choices": [
            {
              "value": "original",
              "label": "Original (as written)"
            },
            {
              "value": "utc",
              "label": "UTC"
            },
            {
              "value": "America/Los_Angeles",
              "label": "Los Angeles"
            },
            {
              "value": "America/Chicago",
              "label": "Chicago"
            },
            {
              "value": "America/New_York",
              "label": "New York"
            },
            {
              "value": "Europe/London",
              "label": "London"
            },
            {
              "value": "Europe/Berlin",
              "label": "Berlin"
            },
            {
              "value": "Europe/Bratislava",
              "label": "Bratislava"
            },
            {
              "value": "Asia/Kolkata",
              "label": "Mumbai / Delhi"
            },
            {
              "value": "Asia/Tokyo",
              "label": "Tokyo"
            },
            {
              "value": "Australia/Sydney",
              "label": "Sydney"
            }
          ]
        },
        {
          "key": "expandRecurrence",
          "kind": "checkbox",
          "label": "Expand recurring events",
          "default": true
        },
        {
          "key": "occurrences",
          "kind": "number",
          "label": "Occurrences to show",
          "default": 5,
          "min": 1,
          "max": 100,
          "step": 1
        },
        {
          "key": "sortByStart",
          "kind": "checkbox",
          "label": "Sort by start time",
          "default": true
        },
        {
          "key": "filterFrom",
          "kind": "text",
          "label": "From date",
          "default": ""
        },
        {
          "key": "filterTo",
          "kind": "text",
          "label": "To date",
          "default": ""
        }
      ],
      "keywords": [
        "ics parser",
        "icalendar parser",
        "ics file reader",
        "vevent parser",
        "rrule expander",
        "calendar file viewer",
        "ics to csv",
        "ics to json",
        "vcalendar",
        "ics viewer"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "vigenere-cipher-solver",
      "name": "Vigenere cipher solver",
      "description": "Recover the key and decrypt Vigenere-enciphered text without knowing the key in advance.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/vigenere-cipher-solver",
      "embed": "https://textarray.com/embed/vigenere-cipher-solver",
      "mode": "transform",
      "action": "Solve cipher",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "language",
          "kind": "select",
          "label": "Reference language",
          "default": "en",
          "choices": [
            {
              "value": "en",
              "label": "English"
            },
            {
              "value": "sk",
              "label": "Slovak"
            },
            {
              "value": "cs",
              "label": "Czech"
            },
            {
              "value": "de",
              "label": "German"
            }
          ]
        },
        {
          "key": "keyLength",
          "kind": "number",
          "label": "Key length (0 = auto-detect)",
          "default": 0,
          "min": 0,
          "max": 40,
          "step": 1
        },
        {
          "key": "maxTestLength",
          "kind": "number",
          "label": "Longest key length to test",
          "default": 20,
          "min": 2,
          "max": 40,
          "step": 1
        },
        {
          "key": "view",
          "kind": "select",
          "label": "Show",
          "default": "plaintext",
          "choices": [
            {
              "value": "plaintext",
              "label": "Decrypted text"
            },
            {
              "value": "report",
              "label": "Full analysis report"
            }
          ]
        }
      ],
      "keywords": [
        "vigenere cipher solver",
        "vigenere decoder",
        "crack vigenere cipher",
        "vigenere cipher breaker",
        "kasiski examination",
        "index of coincidence",
        "frequency analysis",
        "decrypt vigenere cipher without key"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "bip39-mnemonic-generator",
      "name": "BIP39 mnemonic generator",
      "description": "Generate a valid BIP39 recovery phrase, or verify one you already have — entirely offline.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/bip39-mnemonic-generator",
      "embed": "https://textarray.com/embed/bip39-mnemonic-generator",
      "mode": "generate",
      "action": "Generate mnemonic",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "wordCount",
          "kind": "select",
          "label": "Word count",
          "default": "12",
          "choices": [
            {
              "value": "12",
              "label": "12 words (128 bits)"
            },
            {
              "value": "15",
              "label": "15 words (160 bits)"
            },
            {
              "value": "18",
              "label": "18 words (192 bits)"
            },
            {
              "value": "21",
              "label": "21 words (224 bits)"
            },
            {
              "value": "24",
              "label": "24 words (256 bits)"
            }
          ]
        },
        {
          "key": "language",
          "kind": "select",
          "label": "Wordlist language",
          "default": "english",
          "choices": [
            {
              "value": "english",
              "label": "English"
            },
            {
              "value": "czech",
              "label": "Czech"
            },
            {
              "value": "french",
              "label": "French"
            },
            {
              "value": "spanish",
              "label": "Spanish"
            },
            {
              "value": "italian",
              "label": "Italian"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "hyphen",
              "label": "Hyphen"
            },
            {
              "value": "newline",
              "label": "New line"
            }
          ]
        },
        {
          "key": "showIndices",
          "kind": "checkbox",
          "label": "Show wordlist index for each word",
          "default": false
        },
        {
          "key": "numberWords",
          "kind": "checkbox",
          "label": "Number the words",
          "default": false
        },
        {
          "key": "showEntropyHex",
          "kind": "checkbox",
          "label": "Show entropy as hex",
          "default": false
        }
      ],
      "keywords": [
        "bip39 mnemonic generator",
        "seed phrase generator",
        "recovery phrase generator",
        "bip39 word list",
        "mnemonic phrase validator",
        "wallet seed phrase",
        "bip39 checksum",
        "crypto seed phrase"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "bingo-card-generator",
      "name": "Bingo card generator",
      "description": "Generate randomized bingo cards from your own list of items.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/bingo-card-generator",
      "embed": "https://textarray.com/embed/bingo-card-generator",
      "mode": "generate",
      "action": "Generate bingo cards",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "size",
          "kind": "select",
          "label": "Grid size",
          "default": "3",
          "choices": [
            {
              "value": "3",
              "label": "3×3"
            },
            {
              "value": "4",
              "label": "4×4"
            },
            {
              "value": "5",
              "label": "5×5"
            }
          ]
        },
        {
          "key": "freeCenter",
          "kind": "checkbox",
          "label": "Free center space",
          "default": true
        },
        {
          "key": "cards",
          "kind": "number",
          "label": "Number of cards",
          "default": 4,
          "min": 1,
          "max": 50,
          "step": 1
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "grid",
          "choices": [
            {
              "value": "grid",
              "label": "Plain text grid"
            },
            {
              "value": "markdown",
              "label": "Markdown table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "bingo card generator",
        "bingo card maker",
        "random bingo cards",
        "printable bingo cards",
        "custom bingo cards",
        "bingo generator",
        "classroom bingo",
        "csv",
        "markdown table"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "word-search-generator",
      "name": "Word search generator",
      "description": "Turn a list of words into a word search puzzle, with an optional solution key.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/word-search-generator",
      "embed": "https://textarray.com/embed/word-search-generator",
      "mode": "generate",
      "action": "Generate puzzle",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "gridSize",
          "kind": "number",
          "label": "Grid size",
          "default": 15,
          "min": 5,
          "max": 30,
          "step": 1
        },
        {
          "key": "horizontal",
          "kind": "checkbox",
          "label": "Horizontal",
          "default": true
        },
        {
          "key": "vertical",
          "kind": "checkbox",
          "label": "Vertical",
          "default": true
        },
        {
          "key": "diagonal",
          "kind": "checkbox",
          "label": "Diagonal",
          "default": true
        },
        {
          "key": "reverse",
          "kind": "checkbox",
          "label": "Allow backwards",
          "default": true
        },
        {
          "key": "letterCase",
          "kind": "select",
          "label": "Letter case",
          "default": "upper",
          "choices": [
            {
              "value": "upper",
              "label": "UPPERCASE"
            },
            {
              "value": "lower",
              "label": "lowercase"
            }
          ]
        },
        {
          "key": "fillAlphabet",
          "kind": "select",
          "label": "Filler alphabet",
          "default": "plain",
          "choices": [
            {
              "value": "plain",
              "label": "Plain (A–Z)"
            },
            {
              "value": "diacritics",
              "label": "With accented letters"
            }
          ]
        },
        {
          "key": "showSolution",
          "kind": "checkbox",
          "label": "Show solution",
          "default": true
        }
      ],
      "keywords": [
        "word search generator",
        "word search puzzle maker",
        "word search creator",
        "wordsearch maker",
        "find a word puzzle",
        "printable word search",
        "letter grid puzzle",
        "word search with solution"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "acrostic-generator",
      "name": "Acrostic generator",
      "description": "Turn any word or name into a ready-to-fill acrostic poem skeleton, one line per letter.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/acrostic-generator",
      "embed": "https://textarray.com/embed/acrostic-generator",
      "mode": "generate",
      "action": "Generate acrostic",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "word",
          "kind": "text",
          "label": "Word or name",
          "default": ""
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Letter position",
          "default": "start",
          "choices": [
            {
              "value": "start",
              "label": "Initial letters (acrostic)"
            },
            {
              "value": "end",
              "label": "Final letters (telestich)"
            }
          ]
        },
        {
          "key": "letterCase",
          "kind": "select",
          "label": "Letter case",
          "default": "upper",
          "choices": [
            {
              "value": "upper",
              "label": "Uppercase"
            },
            {
              "value": "lower",
              "label": "Lowercase"
            },
            {
              "value": "keep",
              "label": "Keep as typed"
            }
          ]
        },
        {
          "key": "suggestions",
          "kind": "text",
          "label": "Word suggestions (optional)",
          "default": ""
        },
        {
          "key": "highlight",
          "kind": "checkbox",
          "label": "Highlight key letters",
          "default": true
        },
        {
          "key": "preserveSpaces",
          "kind": "checkbox",
          "label": "Keep spaces for multi-word input",
          "default": false
        }
      ],
      "keywords": [
        "acrostic generator",
        "acrostic poem maker",
        "acrostic poem generator",
        "name acrostic",
        "create an acrostic",
        "acrostic maker",
        "telestich generator",
        "acrostic poem template"
      ],
      "updated": "2026-08-12"
    },
    {
      "slug": "compression-size-calculator",
      "name": "Compression size calculator",
      "description": "See how much smaller your text gets with gzip, deflate or brotli compression.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/compression-size-calculator",
      "embed": "https://textarray.com/embed/compression-size-calculator",
      "mode": "transform",
      "action": "Calculate compression",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "algorithm",
          "kind": "select",
          "label": "Algorithm",
          "default": "gzip",
          "choices": [
            {
              "value": "gzip",
              "label": "gzip"
            },
            {
              "value": "deflate",
              "label": "deflate"
            },
            {
              "value": "deflate-raw",
              "label": "deflate-raw"
            },
            {
              "value": "brotli",
              "label": "brotli"
            }
          ]
        },
        {
          "key": "compareAll",
          "kind": "checkbox",
          "label": "Compare all algorithms",
          "default": false
        },
        {
          "key": "showBase64",
          "kind": "checkbox",
          "label": "Show compressed data as Base64",
          "default": false
        }
      ],
      "keywords": [
        "compression size calculator",
        "gzip size calculator",
        "compression ratio calculator",
        "text compression size",
        "compressed size estimator",
        "gzip vs brotli",
        "gzip",
        "brotli",
        "deflate",
        "base64"
      ],
      "updated": "2026-08-13"
    },
    {
      "slug": "bifid-cipher",
      "name": "Bifid cipher",
      "description": "Encrypt or decrypt text with the Bifid cipher, combining a Polybius square with transposition.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/bifid-cipher",
      "embed": "https://textarray.com/embed/bifid-cipher",
      "mode": "transform",
      "action": "Apply Bifid cipher",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "key",
          "kind": "text",
          "label": "Keyword",
          "default": ""
        },
        {
          "key": "size",
          "kind": "select",
          "label": "Square size",
          "default": "5x5",
          "choices": [
            {
              "value": "5x5",
              "label": "5×5 (merges I / J)"
            },
            {
              "value": "6x6",
              "label": "6×6 (adds digits)"
            }
          ]
        },
        {
          "key": "period",
          "kind": "number",
          "label": "Transposition period",
          "default": 5,
          "min": 1,
          "max": 50,
          "step": 1
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encrypt",
          "choices": [
            {
              "value": "encrypt",
              "label": "Encrypt"
            },
            {
              "value": "decrypt",
              "label": "Decrypt"
            }
          ]
        },
        {
          "key": "nonAlpha",
          "kind": "select",
          "label": "Characters outside the alphabet",
          "default": "remove",
          "choices": [
            {
              "value": "remove",
              "label": "Remove"
            },
            {
              "value": "keep",
              "label": "Keep in place"
            }
          ]
        },
        {
          "key": "outputCase",
          "kind": "select",
          "label": "Output case",
          "default": "upper",
          "choices": [
            {
              "value": "upper",
              "label": "UPPERCASE"
            },
            {
              "value": "lower",
              "label": "lowercase"
            }
          ]
        },
        {
          "key": "groupSize",
          "kind": "number",
          "label": "Group output every N characters",
          "default": 0,
          "min": 0,
          "max": 20,
          "step": 1
        },
        {
          "key": "showSteps",
          "kind": "checkbox",
          "label": "Show square and intermediate steps",
          "default": false
        }
      ],
      "keywords": [
        "bifid cipher",
        "felix delastelle cipher",
        "polybius square cipher",
        "fractionating cipher",
        "transposition cipher",
        "classical cipher",
        "encrypt text",
        "decrypt text",
        "cipher square"
      ],
      "updated": "2026-08-13"
    },
    {
      "slug": "strip-ansi",
      "name": "Strip ANSI escape codes",
      "description": "Remove ANSI color and cursor-control codes from terminal output, leaving clean readable text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/strip-ansi",
      "embed": "https://textarray.com/embed/strip-ansi",
      "mode": "transform",
      "action": "Strip ANSI codes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "colorsOnly",
          "kind": "checkbox",
          "label": "Remove only colors, keep other codes",
          "default": false
        },
        {
          "key": "convert",
          "kind": "select",
          "label": "Convert colors to",
          "default": "strip",
          "choices": [
            {
              "value": "strip",
              "label": "Remove"
            },
            {
              "value": "markdown",
              "label": "Markdown"
            },
            {
              "value": "html",
              "label": "HTML"
            }
          ]
        },
        {
          "key": "collapseRedraws",
          "kind": "checkbox",
          "label": "Collapse redrawn lines (progress bars)",
          "default": false
        },
        {
          "key": "stripHyperlinks",
          "kind": "checkbox",
          "label": "Convert terminal hyperlinks to plain text",
          "default": true
        }
      ],
      "keywords": [
        "strip ansi",
        "ansi escape codes",
        "remove ansi colors",
        "ansi color codes",
        "terminal output cleaner",
        "clean console log",
        "remove color codes",
        "strip terminal colors",
        "progress bar log",
        "osc hyperlink"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "json-to-rust-struct",
      "name": "JSON to Rust struct",
      "description": "Turn a JSON document into Rust structs ready for serde.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-rust-struct",
      "embed": "https://textarray.com/embed/json-to-rust-struct",
      "mode": "transform",
      "action": "Generate struct",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "rootName",
          "kind": "text",
          "label": "Root struct name",
          "default": "Root"
        },
        {
          "key": "deriveDebug",
          "kind": "checkbox",
          "label": "Derive Debug",
          "default": true
        },
        {
          "key": "deriveClone",
          "kind": "checkbox",
          "label": "Derive Clone",
          "default": true
        },
        {
          "key": "deriveSerialize",
          "kind": "checkbox",
          "label": "Derive Serialize",
          "default": true
        },
        {
          "key": "deriveDeserialize",
          "kind": "checkbox",
          "label": "Derive Deserialize",
          "default": true
        },
        {
          "key": "derivePartialEq",
          "kind": "checkbox",
          "label": "Derive PartialEq",
          "default": false
        },
        {
          "key": "renameCamelCase",
          "kind": "checkbox",
          "label": "Add #[serde(rename_all = \"camelCase\")]",
          "default": true
        },
        {
          "key": "optionalFromNull",
          "kind": "checkbox",
          "label": "Wrap null fields in Option<T>",
          "default": true
        },
        {
          "key": "intType",
          "kind": "select",
          "label": "Integer type",
          "default": "i64",
          "choices": [
            {
              "value": "i32",
              "label": "i32"
            },
            {
              "value": "i64",
              "label": "i64"
            },
            {
              "value": "u64",
              "label": "u64"
            }
          ]
        },
        {
          "key": "stringType",
          "kind": "select",
          "label": "String type",
          "default": "owned",
          "choices": [
            {
              "value": "owned",
              "label": "String (owned)"
            },
            {
              "value": "borrowed",
              "label": "&str (borrowed)"
            }
          ]
        },
        {
          "key": "nestedStyle",
          "kind": "select",
          "label": "Nested objects",
          "default": "structs",
          "choices": [
            {
              "value": "structs",
              "label": "Separate structs"
            },
            {
              "value": "modules",
              "label": "Nested modules"
            }
          ]
        },
        {
          "key": "pubFields",
          "kind": "checkbox",
          "label": "Public fields",
          "default": true
        }
      ],
      "keywords": [
        "json to rust struct",
        "rust struct generator",
        "serde",
        "serde derive",
        "rust codegen",
        "json",
        "rust",
        "deserialize json rust"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "json-to-sql-schema",
      "name": "JSON to SQL CREATE TABLE",
      "description": "Turn a JSON object or array of objects into a SQL CREATE TABLE statement.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-sql-schema",
      "embed": "https://textarray.com/embed/json-to-sql-schema",
      "mode": "transform",
      "action": "Generate CREATE TABLE",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "tableName",
          "kind": "text",
          "label": "Table name",
          "default": "my_table"
        },
        {
          "key": "dialect",
          "kind": "select",
          "label": "Dialect",
          "default": "ansi",
          "choices": [
            {
              "value": "ansi",
              "label": "ANSI SQL"
            },
            {
              "value": "mysql",
              "label": "MySQL"
            },
            {
              "value": "postgres",
              "label": "PostgreSQL"
            },
            {
              "value": "sqlite",
              "label": "SQLite"
            },
            {
              "value": "mssql",
              "label": "SQL Server"
            }
          ]
        },
        {
          "key": "nested",
          "kind": "select",
          "label": "Nested objects",
          "default": "flatten",
          "choices": [
            {
              "value": "flatten",
              "label": "Flatten with underscore"
            },
            {
              "value": "json",
              "label": "Keep as a JSON column"
            }
          ]
        },
        {
          "key": "snakeCase",
          "kind": "checkbox",
          "label": "Convert names to snake_case",
          "default": true
        },
        {
          "key": "includeInserts",
          "kind": "checkbox",
          "label": "Add INSERT statements",
          "default": false
        }
      ],
      "keywords": [
        "json to sql",
        "create table from json",
        "json to database schema",
        "infer sql schema",
        "json to mysql",
        "json to postgres",
        "sql create table generator",
        "json",
        "sql"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "css-specificity",
      "name": "CSS specificity calculator",
      "description": "Calculate the specificity of CSS selectors and see which one wins.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-specificity",
      "embed": "https://textarray.com/embed/css-specificity",
      "mode": "transform",
      "action": "Calculate specificity",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "splitCommaLists",
          "kind": "checkbox",
          "label": "Split comma-separated lists",
          "default": true
        },
        {
          "key": "sortStrongest",
          "kind": "checkbox",
          "label": "Sort by strongest first",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "tuple",
              "label": "0-1-2 notation"
            }
          ]
        },
        {
          "key": "explain",
          "kind": "checkbox",
          "label": "Show breakdown explanation",
          "default": false
        }
      ],
      "keywords": [
        "css specificity calculator",
        "css specificity",
        "selector specificity",
        "css cascade",
        "css selector priority",
        "0-1-2 notation",
        "css !important",
        "css"
      ],
      "updated": "2026-08-14"
    },
    {
      "slug": "ass-to-srt",
      "name": "ASS/SSA to SRT converter",
      "description": "Convert Advanced SubStation Alpha or SSA subtitles to plain SRT.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ass-to-srt",
      "embed": "https://textarray.com/embed/ass-to-srt",
      "mode": "transform",
      "action": "Convert to SRT",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "styleTags",
          "kind": "select",
          "label": "Style tags",
          "default": "remove",
          "choices": [
            {
              "value": "remove",
              "label": "Remove"
            },
            {
              "value": "html",
              "label": "Convert to HTML"
            }
          ]
        },
        {
          "key": "lineBreaks",
          "kind": "checkbox",
          "label": "Convert \\N and \\n to line breaks",
          "default": true
        },
        {
          "key": "styleFilter",
          "kind": "text",
          "label": "Only this style",
          "default": ""
        },
        {
          "key": "actorFilter",
          "kind": "text",
          "label": "Only this actor",
          "default": ""
        },
        {
          "key": "sortByStart",
          "kind": "checkbox",
          "label": "Sort by start time",
          "default": false
        },
        {
          "key": "skipEffects",
          "kind": "checkbox",
          "label": "Skip effect lines",
          "default": false
        }
      ],
      "keywords": [
        "ass to srt",
        "ssa to srt",
        "ass converter",
        "ssa converter",
        "advanced substation alpha",
        "subtitle converter",
        "subrip",
        "convert subtitles",
        "srt",
        "ass",
        "ssa"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "json-to-graphql-sdl",
      "name": "JSON to GraphQL SDL",
      "description": "Turn a JSON document into GraphQL types written in Schema Definition Language.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-to-graphql-sdl",
      "embed": "https://textarray.com/embed/json-to-graphql-sdl",
      "mode": "transform",
      "action": "Generate GraphQL SDL",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "rootName",
          "kind": "text",
          "label": "Root type name",
          "default": "Root"
        },
        {
          "key": "generate",
          "kind": "select",
          "label": "Generate as",
          "default": "type",
          "choices": [
            {
              "value": "type",
              "label": "type"
            },
            {
              "value": "input",
              "label": "input"
            }
          ]
        },
        {
          "key": "idFromField",
          "kind": "checkbox",
          "label": "Detect ID from \"id\" field",
          "default": true
        },
        {
          "key": "customDateScalar",
          "kind": "checkbox",
          "label": "Custom scalar for dates",
          "default": true
        },
        {
          "key": "includeQueryType",
          "kind": "checkbox",
          "label": "Include Query type",
          "default": true
        }
      ],
      "keywords": [
        "json to graphql",
        "graphql schema generator",
        "graphql sdl",
        "json to graphql schema",
        "graphql type generator",
        "schema definition language",
        "graphql",
        "json"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "openapi-endpoint-lister",
      "name": "OpenAPI endpoint lister",
      "description": "List every endpoint from an OpenAPI or Swagger document as a readable table.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/openapi-endpoint-lister",
      "embed": "https://textarray.com/embed/openapi-endpoint-lister",
      "mode": "transform",
      "action": "List endpoints",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "method",
          "kind": "select",
          "label": "HTTP method",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All methods"
            },
            {
              "value": "get",
              "label": "GET"
            },
            {
              "value": "post",
              "label": "POST"
            },
            {
              "value": "put",
              "label": "PUT"
            },
            {
              "value": "patch",
              "label": "PATCH"
            },
            {
              "value": "delete",
              "label": "DELETE"
            },
            {
              "value": "head",
              "label": "HEAD"
            },
            {
              "value": "options",
              "label": "OPTIONS"
            },
            {
              "value": "trace",
              "label": "TRACE"
            }
          ]
        },
        {
          "key": "tag",
          "kind": "text",
          "label": "Filter by tag",
          "default": ""
        },
        {
          "key": "showParams",
          "kind": "checkbox",
          "label": "Show path and query parameters",
          "default": true
        },
        {
          "key": "showRequestBody",
          "kind": "checkbox",
          "label": "Show request body type",
          "default": true
        },
        {
          "key": "showResponses",
          "kind": "checkbox",
          "label": "Show response codes",
          "default": true
        },
        {
          "key": "showAuth",
          "kind": "checkbox",
          "label": "Show whether authentication is required",
          "default": true
        },
        {
          "key": "showSummary",
          "kind": "checkbox",
          "label": "Show summary",
          "default": true
        },
        {
          "key": "skipDeprecated",
          "kind": "checkbox",
          "label": "Skip deprecated endpoints",
          "default": false
        },
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "path",
          "choices": [
            {
              "value": "path",
              "label": "Path"
            },
            {
              "value": "tag",
              "label": "Tag"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List"
            },
            {
              "value": "markdown",
              "label": "Markdown table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "openapi endpoint lister",
        "swagger endpoint list",
        "openapi to markdown table",
        "list api routes",
        "api documentation generator",
        "openapi paths",
        "swagger",
        "openapi",
        "yaml",
        "json",
        "csv",
        "rest api"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "mermaid-diagram-generator",
      "name": "Mermaid diagram generator",
      "description": "Turn an indented list into a Mermaid flowchart, hierarchy graph or mindmap definition.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/mermaid-diagram-generator",
      "embed": "https://textarray.com/embed/mermaid-diagram-generator",
      "mode": "transform",
      "action": "Generate diagram",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "diagramType",
          "kind": "select",
          "label": "Diagram type",
          "default": "flowchart",
          "choices": [
            {
              "value": "flowchart",
              "label": "Flowchart"
            },
            {
              "value": "graph",
              "label": "Hierarchy graph"
            },
            {
              "value": "mindmap",
              "label": "Mindmap"
            }
          ]
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "TD",
          "choices": [
            {
              "value": "TD",
              "label": "Top to bottom"
            },
            {
              "value": "LR",
              "label": "Left to right"
            },
            {
              "value": "BT",
              "label": "Bottom to top"
            },
            {
              "value": "RL",
              "label": "Right to left"
            }
          ]
        },
        {
          "key": "nodeShape",
          "kind": "select",
          "label": "Node shape",
          "default": "rectangle",
          "choices": [
            {
              "value": "rectangle",
              "label": "Rectangle"
            },
            {
              "value": "rounded",
              "label": "Rounded"
            },
            {
              "value": "diamond",
              "label": "Diamond"
            },
            {
              "value": "cylinder",
              "label": "Cylinder"
            }
          ]
        },
        {
          "key": "connectorStyle",
          "kind": "select",
          "label": "Connector style",
          "default": "arrow",
          "choices": [
            {
              "value": "arrow",
              "label": "Arrow"
            },
            {
              "value": "dotted",
              "label": "Dotted"
            },
            {
              "value": "thick",
              "label": "Thick"
            }
          ]
        },
        {
          "key": "autoIds",
          "kind": "checkbox",
          "label": "Auto-generate node IDs",
          "default": true
        },
        {
          "key": "numberNodes",
          "kind": "checkbox",
          "label": "Number nodes",
          "default": false
        },
        {
          "key": "maxDepth",
          "kind": "number",
          "label": "Maximum nesting depth",
          "default": 10,
          "min": 1,
          "max": 20,
          "step": 1
        }
      ],
      "keywords": [
        "mermaid diagram generator",
        "mermaid",
        "flowchart generator",
        "mindmap generator",
        "list to diagram",
        "diagram from outline",
        "mermaid syntax",
        "mermaid.js",
        "flowchart",
        "mindmap"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "markdown-reference-links",
      "name": "Markdown inline and reference links",
      "description": "Convert Markdown links and images between inline [text](url) and reference [text][1] style.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/markdown-reference-links",
      "embed": "https://textarray.com/embed/markdown-reference-links",
      "mode": "transform",
      "action": "Convert links",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "inline-to-reference",
          "choices": [
            {
              "value": "inline-to-reference",
              "label": "Inline → reference"
            },
            {
              "value": "reference-to-inline",
              "label": "Reference → inline"
            }
          ]
        },
        {
          "key": "labelStyle",
          "kind": "select",
          "label": "Label style",
          "default": "number",
          "choices": [
            {
              "value": "number",
              "label": "Number (1, 2, 3…)"
            },
            {
              "value": "text",
              "label": "Link text"
            },
            {
              "value": "custom",
              "label": "Custom prefix"
            }
          ]
        },
        {
          "key": "customPrefix",
          "kind": "text",
          "label": "Custom prefix",
          "default": "ref"
        },
        {
          "key": "definitionPlacement",
          "kind": "select",
          "label": "Place definitions",
          "default": "document",
          "choices": [
            {
              "value": "document",
              "label": "End of document"
            },
            {
              "value": "paragraph",
              "label": "End of each paragraph"
            }
          ]
        },
        {
          "key": "mergeSameUrl",
          "kind": "checkbox",
          "label": "Merge definitions with the same URL",
          "default": true
        },
        {
          "key": "keepTitles",
          "kind": "checkbox",
          "label": "Keep link titles",
          "default": true
        },
        {
          "key": "processImages",
          "kind": "checkbox",
          "label": "Also convert images",
          "default": true
        },
        {
          "key": "sortDefinitions",
          "kind": "select",
          "label": "Sort definitions",
          "default": "occurrence",
          "choices": [
            {
              "value": "occurrence",
              "label": "By order of appearance"
            },
            {
              "value": "alphabetical",
              "label": "Alphabetically"
            }
          ]
        },
        {
          "key": "skipCodeBlocks",
          "kind": "checkbox",
          "label": "Skip links inside code blocks",
          "default": true
        }
      ],
      "keywords": [
        "markdown reference links",
        "inline to reference links",
        "markdown link converter",
        "reference-style links",
        "markdown link definitions",
        "convert markdown links",
        "markdown"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "bilingual-subtitle-merger",
      "name": "Bilingual subtitle merger",
      "description": "Combine two subtitle files into one dual-language track, original above translation.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/bilingual-subtitle-merger",
      "embed": "https://textarray.com/embed/bilingual-subtitle-merger",
      "mode": "transform",
      "action": "Merge subtitles",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Second language subtitles"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "topLanguage",
          "kind": "select",
          "label": "Language on top",
          "default": "first",
          "choices": [
            {
              "value": "first",
              "label": "First document"
            },
            {
              "value": "second",
              "label": "Second document"
            }
          ]
        },
        {
          "key": "matchByOrder",
          "kind": "checkbox",
          "label": "Match by subtitle order instead of time",
          "default": false
        },
        {
          "key": "toleranceMs",
          "kind": "number",
          "label": "Time-matching tolerance (ms)",
          "default": 500,
          "min": 0,
          "max": 5000,
          "step": 100
        },
        {
          "key": "unmatched",
          "kind": "select",
          "label": "Unmatched subtitles",
          "default": "keep",
          "choices": [
            {
              "value": "keep",
              "label": "Keep separately"
            },
            {
              "value": "omit",
              "label": "Omit"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator between languages",
          "default": "\n",
          "choices": [
            {
              "value": "\n",
              "label": "New line"
            },
            {
              "value": " / ",
              "label": "Slash ( / )"
            },
            {
              "value": " - ",
              "label": "Dash ( - )"
            },
            {
              "value": " | ",
              "label": "Pipe ( | )"
            }
          ]
        },
        {
          "key": "italicizeSecond",
          "kind": "checkbox",
          "label": "Italicize second language",
          "default": false
        },
        {
          "key": "timingSource",
          "kind": "select",
          "label": "Timing source",
          "default": "first",
          "choices": [
            {
              "value": "first",
              "label": "First document"
            },
            {
              "value": "intersect",
              "label": "Overlap of both"
            }
          ]
        }
      ],
      "keywords": [
        "bilingual subtitle merger",
        "merge subtitles",
        "dual language subtitles",
        "combine srt files",
        "two language subtitles",
        "subtitle translation merge",
        "srt",
        "vtt"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "iso-8601-duration-converter",
      "name": "ISO 8601 duration converter",
      "description": "Convert ISO 8601 durations like PT1H30M to seconds or readable text, and back.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/iso-8601-duration-converter",
      "embed": "https://textarray.com/embed/iso-8601-duration-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "toValue",
          "choices": [
            {
              "value": "toValue",
              "label": "ISO duration → value"
            },
            {
              "value": "toIso",
              "label": "Value → ISO duration"
            }
          ]
        },
        {
          "key": "unit",
          "kind": "select",
          "label": "Unit",
          "default": "seconds",
          "choices": [
            {
              "value": "seconds",
              "label": "Seconds"
            },
            {
              "value": "minutes",
              "label": "Minutes"
            },
            {
              "value": "hours",
              "label": "Hours"
            },
            {
              "value": "days",
              "label": "Days"
            }
          ]
        },
        {
          "key": "readable",
          "kind": "checkbox",
          "label": "Show readable text",
          "default": true
        },
        {
          "key": "yearMonthMode",
          "kind": "select",
          "label": "Count years/months as",
          "default": "calendar",
          "choices": [
            {
              "value": "calendar",
              "label": "Calendar average (approximate)"
            },
            {
              "value": "fixed",
              "label": "365 and 30 days (approximate)"
            }
          ]
        },
        {
          "key": "rounding",
          "kind": "number",
          "label": "Decimal places",
          "default": 2,
          "min": 0,
          "max": 6,
          "step": 1
        },
        {
          "key": "compact",
          "kind": "checkbox",
          "label": "Compact (omit zero units)",
          "default": true
        },
        {
          "key": "showTotal",
          "kind": "checkbox",
          "label": "Show total of all lines",
          "default": false
        }
      ],
      "keywords": [
        "iso 8601 duration",
        "duration converter",
        "iso 8601 to seconds",
        "seconds to iso 8601",
        "duration parser",
        "iso duration format",
        "pt1h30m",
        "p1y2m"
      ],
      "updated": "2026-08-15"
    },
    {
      "slug": "unified-diff-analyzer",
      "name": "Unified diff analyzer",
      "description": "Summarize a unified diff or .patch file: files changed, lines added and removed.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/unified-diff-analyzer",
      "embed": "https://textarray.com/embed/unified-diff-analyzer",
      "mode": "transform",
      "action": "Analyze diff",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "path",
          "choices": [
            {
              "value": "path",
              "label": "File path"
            },
            {
              "value": "changes",
              "label": "Number of changes"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "markdown",
              "label": "Markdown"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        },
        {
          "key": "showHunks",
          "kind": "checkbox",
          "label": "Show individual hunks",
          "default": false
        },
        {
          "key": "detectRenames",
          "kind": "checkbox",
          "label": "Detect renames and mode changes",
          "default": true
        },
        {
          "key": "ignoreWhitespace",
          "kind": "checkbox",
          "label": "Ignore whitespace-only changes",
          "default": false
        },
        {
          "key": "showRatio",
          "kind": "checkbox",
          "label": "Show addition/removal ratio",
          "default": false
        },
        {
          "key": "extensions",
          "kind": "text",
          "label": "Filter by extension",
          "default": ""
        },
        {
          "key": "excludeGenerated",
          "kind": "text",
          "label": "Exclude generated files (path pattern)",
          "default": ""
        }
      ],
      "keywords": [
        "unified diff analyzer",
        "diff analyzer",
        "patch analyzer",
        "diff stat",
        "patch file",
        "diffstat",
        "code review",
        "pull request diff",
        "git diff",
        "diff -u",
        "diffstat summary",
        "diff summary"
      ],
      "updated": "2026-08-16"
    },
    {
      "slug": "conventional-commit-builder",
      "name": "Conventional commit builder",
      "description": "Compose a Conventional Commits message from a type, scope and description, or check existing messages for problems.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/conventional-commit-builder",
      "embed": "https://textarray.com/embed/conventional-commit-builder",
      "mode": "transform",
      "action": "Build commit message",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Mode",
          "default": "build",
          "choices": [
            {
              "value": "build",
              "label": "Build message"
            },
            {
              "value": "check",
              "label": "Check message(s)"
            }
          ]
        },
        {
          "key": "type",
          "kind": "select",
          "label": "Type",
          "default": "feat",
          "choices": [
            {
              "value": "feat",
              "label": "feat — new feature"
            },
            {
              "value": "fix",
              "label": "fix — bug fix"
            },
            {
              "value": "docs",
              "label": "docs — documentation"
            },
            {
              "value": "style",
              "label": "style — formatting only"
            },
            {
              "value": "refactor",
              "label": "refactor — no behavior change"
            },
            {
              "value": "perf",
              "label": "perf — performance"
            },
            {
              "value": "test",
              "label": "test — tests"
            },
            {
              "value": "build",
              "label": "build — build system"
            },
            {
              "value": "ci",
              "label": "ci — CI configuration"
            },
            {
              "value": "chore",
              "label": "chore — maintenance"
            },
            {
              "value": "revert",
              "label": "revert — reverts a commit"
            }
          ]
        },
        {
          "key": "scope",
          "kind": "text",
          "label": "Scope (optional)",
          "default": ""
        },
        {
          "key": "breaking",
          "kind": "checkbox",
          "label": "Breaking change",
          "default": false
        },
        {
          "key": "breakingNote",
          "kind": "text",
          "label": "Breaking change note",
          "default": ""
        },
        {
          "key": "footer",
          "kind": "text",
          "label": "Footer (ticket references)",
          "default": ""
        },
        {
          "key": "maxHeaderLength",
          "kind": "number",
          "label": "Max header length",
          "default": 72,
          "min": 20,
          "max": 200,
          "step": 1
        },
        {
          "key": "lowercaseDescription",
          "kind": "checkbox",
          "label": "Force lowercase start",
          "default": true
        },
        {
          "key": "noTrailingPeriod",
          "kind": "checkbox",
          "label": "Forbid trailing period",
          "default": true
        },
        {
          "key": "outputMode",
          "kind": "select",
          "label": "Check output",
          "default": "errors",
          "choices": [
            {
              "value": "errors",
              "label": "List errors"
            },
            {
              "value": "fixed",
              "label": "Corrected message"
            }
          ]
        }
      ],
      "keywords": [
        "conventional commits",
        "commit message builder",
        "commit message linter",
        "commit message validator",
        "git commit format",
        "semantic commit message",
        "commitlint",
        "breaking change",
        "changelog",
        "feat fix chore"
      ],
      "updated": "2026-08-16"
    },
    {
      "slug": "graphql-formatter",
      "name": "GraphQL formatter",
      "description": "Format or minify a GraphQL query, mutation, fragment or schema with consistent indentation.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/graphql-formatter",
      "embed": "https://textarray.com/embed/graphql-formatter",
      "mode": "transform",
      "action": "Format query",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent size",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "minify",
          "kind": "checkbox",
          "label": "Minify instead of format",
          "default": false
        },
        {
          "key": "sortFields",
          "kind": "checkbox",
          "label": "Sort fields alphabetically",
          "default": false
        },
        {
          "key": "keepComments",
          "kind": "checkbox",
          "label": "Keep comments",
          "default": true
        },
        {
          "key": "collapseVariables",
          "kind": "checkbox",
          "label": "Collapse query variables to one line",
          "default": true
        },
        {
          "key": "blankLineBetweenOperations",
          "kind": "checkbox",
          "label": "Blank line between operations",
          "default": true
        }
      ],
      "keywords": [
        "graphql formatter",
        "graphql minifier",
        "graphql beautifier",
        "graphql query formatter",
        "graphql schema formatter",
        "format graphql",
        "minify graphql",
        "graphql",
        "sdl",
        "query",
        "mutation",
        "fragment"
      ],
      "updated": "2026-08-16"
    },
    {
      "slug": "front-matter-editor",
      "name": "Front matter editor",
      "description": "Split, validate and reformat the YAML front matter of a Markdown document.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/front-matter-editor",
      "embed": "https://textarray.com/embed/front-matter-editor",
      "mode": "transform",
      "action": "Format front matter",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "view",
          "kind": "select",
          "label": "Show",
          "default": "both",
          "choices": [
            {
              "value": "both",
              "label": "Front matter + body"
            },
            {
              "value": "frontmatter",
              "label": "Front matter only"
            },
            {
              "value": "body",
              "label": "Body only"
            }
          ]
        },
        {
          "key": "sortMode",
          "kind": "select",
          "label": "Sort keys",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Keep order"
            },
            {
              "value": "alphabetical",
              "label": "Alphabetical"
            },
            {
              "value": "custom",
              "label": "Custom order"
            }
          ]
        },
        {
          "key": "customOrder",
          "kind": "text",
          "label": "Custom order (comma-separated keys)",
          "default": ""
        },
        {
          "key": "requiredKeys",
          "kind": "text",
          "label": "Required keys (comma-separated)",
          "default": ""
        },
        {
          "key": "removeEmptyKeys",
          "kind": "checkbox",
          "label": "Remove empty keys",
          "default": false
        },
        {
          "key": "normalizeDates",
          "kind": "checkbox",
          "label": "Normalize dates to ISO 8601",
          "default": false
        },
        {
          "key": "listStyle",
          "kind": "select",
          "label": "List style",
          "default": "block",
          "choices": [
            {
              "value": "block",
              "label": "Block"
            },
            {
              "value": "inline",
              "label": "Inline"
            }
          ]
        },
        {
          "key": "multiDoc",
          "kind": "checkbox",
          "label": "Process multiple documents",
          "default": false
        }
      ],
      "keywords": [
        "front matter editor",
        "yaml front matter",
        "markdown front matter",
        "front matter validator",
        "jekyll front matter",
        "hugo front matter",
        "yaml",
        "markdown"
      ],
      "updated": "2026-08-16"
    },
    {
      "slug": "tailwind-class-sorter",
      "name": "Tailwind class sorter",
      "description": "Sort utility classes in class/className attributes into Tailwind’s recommended order.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/tailwind-class-sorter",
      "embed": "https://textarray.com/embed/tailwind-class-sorter",
      "mode": "transform",
      "action": "Sort classes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "scope",
          "kind": "select",
          "label": "Scope",
          "default": "document",
          "choices": [
            {
              "value": "document",
              "label": "Whole document (class / className attributes)"
            },
            {
              "value": "list",
              "label": "Pasted list of classes only"
            }
          ]
        },
        {
          "key": "customPosition",
          "kind": "select",
          "label": "Custom (non-Tailwind) classes",
          "default": "start",
          "choices": [
            {
              "value": "start",
              "label": "Keep at the start"
            },
            {
              "value": "end",
              "label": "Keep at the end"
            }
          ]
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicate classes",
          "default": true
        },
        {
          "key": "warnConflicts",
          "kind": "checkbox",
          "label": "Warn about classes that cancel each other out",
          "default": true
        },
        {
          "key": "groupResponsive",
          "kind": "checkbox",
          "label": "Group responsive variants (sm, md, lg…) together",
          "default": false
        },
        {
          "key": "ignoreDynamic",
          "kind": "checkbox",
          "label": "Leave dynamic classes in template expressions untouched",
          "default": true
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output",
          "default": "code",
          "choices": [
            {
              "value": "code",
              "label": "Modified code"
            },
            {
              "value": "list",
              "label": "Sorted list, one per line"
            }
          ]
        }
      ],
      "keywords": [
        "tailwind class sorter",
        "tailwind css sort classes",
        "sort tailwind classes",
        "tailwind class order",
        "prettier plugin tailwindcss",
        "className sorter",
        "tailwind lint classes",
        "css utility class order"
      ],
      "updated": "2026-08-16"
    },
    {
      "slug": "json-schema-generator",
      "name": "JSON Schema generator",
      "description": "Generate a JSON Schema from a sample JSON document, including types, nested objects and formats.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-schema-generator",
      "embed": "https://textarray.com/embed/json-schema-generator",
      "mode": "transform",
      "action": "Generate schema",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "schemaVersion",
          "kind": "select",
          "label": "Schema version",
          "default": "2020-12",
          "choices": [
            {
              "value": "2020-12",
              "label": "2020-12"
            },
            {
              "value": "draft-07",
              "label": "Draft-07"
            }
          ]
        },
        {
          "key": "requiredMode",
          "kind": "select",
          "label": "Required fields",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "None required"
            },
            {
              "value": "all",
              "label": "All required"
            }
          ]
        },
        {
          "key": "noAdditionalProperties",
          "kind": "checkbox",
          "label": "Disallow additional properties",
          "default": false
        },
        {
          "key": "inferFormats",
          "kind": "checkbox",
          "label": "Infer formats (email, URI, UUID, date-time)",
          "default": true
        },
        {
          "key": "multipleSamples",
          "kind": "checkbox",
          "label": "Merge multiple samples (one JSON value per line)",
          "default": false
        },
        {
          "key": "inferConstraints",
          "kind": "checkbox",
          "label": "Add length and range limits from sample values",
          "default": false
        },
        {
          "key": "descriptionsFromKeys",
          "kind": "checkbox",
          "label": "Add descriptions from field names",
          "default": false
        },
        {
          "key": "extractDefs",
          "kind": "checkbox",
          "label": "Extract nested objects into definitions",
          "default": false
        }
      ],
      "keywords": [
        "json schema generator",
        "generate json schema",
        "json schema from sample",
        "json schema from json",
        "json schema draft-07",
        "json schema 2020-12",
        "schema inference",
        "infer json schema",
        "json",
        "schema"
      ],
      "updated": "2026-08-16"
    },
    {
      "slug": "regex-explainer",
      "name": "Regex explainer",
      "description": "Break a regular expression into plain-English steps, one piece at a time.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/regex-explainer",
      "embed": "https://textarray.com/embed/regex-explainer",
      "mode": "transform",
      "action": "Explain pattern",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "dialect",
          "kind": "select",
          "label": "Dialect",
          "default": "javascript",
          "choices": [
            {
              "value": "javascript",
              "label": "JavaScript"
            },
            {
              "value": "pcre",
              "label": "PCRE"
            },
            {
              "value": "python",
              "label": "Python"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Show as",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "Numbered steps"
            },
            {
              "value": "tree",
              "label": "Tree"
            }
          ]
        },
        {
          "key": "explainFlags",
          "kind": "checkbox",
          "label": "Explain flags",
          "default": true
        },
        {
          "key": "listGroups",
          "kind": "checkbox",
          "label": "List capturing and named groups",
          "default": true
        },
        {
          "key": "warnBacktracking",
          "kind": "checkbox",
          "label": "Warn about backtracking risk",
          "default": true
        },
        {
          "key": "suggestSimpler",
          "kind": "checkbox",
          "label": "Suggest simpler notation",
          "default": false
        },
        {
          "key": "generateSample",
          "kind": "checkbox",
          "label": "Generate sample match",
          "default": false
        }
      ],
      "keywords": [
        "regex explainer",
        "regex breakdown",
        "explain regular expression",
        "regex analyzer",
        "regex documentation",
        "regex cheat sheet",
        "regex",
        "regular expression",
        "pcre",
        "python regex",
        "catastrophic backtracking"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "secret-scanner",
      "name": "Secret scanner",
      "description": "Scan text, logs or configs for AWS, GitHub, Slack and Stripe keys, private keys, JWTs and other leaked secrets.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/secret-scanner",
      "embed": "https://textarray.com/embed/secret-scanner",
      "mode": "transform",
      "action": "Scan for secrets",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "aws",
          "kind": "checkbox",
          "label": "Detect AWS keys",
          "default": true
        },
        {
          "key": "google",
          "kind": "checkbox",
          "label": "Detect Google API keys",
          "default": true
        },
        {
          "key": "github",
          "kind": "checkbox",
          "label": "Detect GitHub tokens",
          "default": true
        },
        {
          "key": "slack",
          "kind": "checkbox",
          "label": "Detect Slack tokens",
          "default": true
        },
        {
          "key": "stripe",
          "kind": "checkbox",
          "label": "Detect Stripe keys",
          "default": true
        },
        {
          "key": "pem",
          "kind": "checkbox",
          "label": "Detect PEM private keys",
          "default": true
        },
        {
          "key": "jwt",
          "kind": "checkbox",
          "label": "Detect JWTs",
          "default": true
        },
        {
          "key": "dbConn",
          "kind": "checkbox",
          "label": "Detect database connection strings",
          "default": true
        },
        {
          "key": "highEntropy",
          "kind": "checkbox",
          "label": "Detect generic high-entropy strings",
          "default": true
        },
        {
          "key": "sensitivity",
          "kind": "select",
          "label": "Entropy sensitivity",
          "default": "medium",
          "choices": [
            {
              "value": "low",
              "label": "Low"
            },
            {
              "value": "medium",
              "label": "Medium"
            },
            {
              "value": "high",
              "label": "High"
            }
          ]
        },
        {
          "key": "showContext",
          "kind": "checkbox",
          "label": "Show line number and context",
          "default": true
        },
        {
          "key": "maskValues",
          "kind": "checkbox",
          "label": "Mask found values",
          "default": true
        },
        {
          "key": "ignoreTestValues",
          "kind": "checkbox",
          "label": "Ignore sample and test values",
          "default": true
        },
        {
          "key": "outputMode",
          "kind": "select",
          "label": "Output",
          "default": "findings",
          "choices": [
            {
              "value": "findings",
              "label": "List of findings"
            },
            {
              "value": "cleaned",
              "label": "Cleaned text"
            }
          ]
        }
      ],
      "keywords": [
        "secret scanner",
        "api key detector",
        "find api keys in text",
        "leaked credentials scanner",
        "aws access key detector",
        "github token scanner",
        "jwt detector",
        "high entropy string detector",
        "detect secrets in code",
        "pem private key finder",
        "aws",
        "github",
        "slack",
        "stripe",
        "jwt",
        "pem"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "changelog-generator",
      "name": "Changelog generator",
      "description": "Turn a pasted git log into a grouped, readable changelog.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/changelog-generator",
      "embed": "https://textarray.com/embed/changelog-generator",
      "mode": "transform",
      "action": "Generate changelog",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "typeSource",
          "kind": "select",
          "label": "Detect types by",
          "default": "conventional",
          "choices": [
            {
              "value": "conventional",
              "label": "Conventional Commits"
            },
            {
              "value": "custom",
              "label": "Custom prefixes"
            }
          ]
        },
        {
          "key": "customPrefixes",
          "kind": "text",
          "label": "Custom prefixes (prefix=Label, …)",
          "default": ""
        },
        {
          "key": "groupBy",
          "kind": "select",
          "label": "Group by",
          "default": "type",
          "choices": [
            {
              "value": "type",
              "label": "Type"
            },
            {
              "value": "scope",
              "label": "Scope"
            }
          ]
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "keepachangelog",
          "choices": [
            {
              "value": "keepachangelog",
              "label": "Keep a Changelog (Markdown)"
            },
            {
              "value": "plain",
              "label": "Plain list"
            }
          ]
        },
        {
          "key": "skipMerges",
          "kind": "checkbox",
          "label": "Skip merge commits",
          "default": true
        },
        {
          "key": "skipChores",
          "kind": "checkbox",
          "label": "Skip chores",
          "default": false
        },
        {
          "key": "highlightBreaking",
          "kind": "checkbox",
          "label": "Highlight breaking changes",
          "default": true
        },
        {
          "key": "showAuthors",
          "kind": "checkbox",
          "label": "Show authors",
          "default": false
        },
        {
          "key": "ticketUrlTemplate",
          "kind": "text",
          "label": "Ticket link template",
          "default": ""
        },
        {
          "key": "version",
          "kind": "text",
          "label": "Version",
          "default": ""
        },
        {
          "key": "date",
          "kind": "text",
          "label": "Date",
          "default": ""
        }
      ],
      "keywords": [
        "changelog generator",
        "git log to changelog",
        "conventional commits",
        "keep a changelog",
        "release notes generator",
        "commit history",
        "git log parser",
        "markdown"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "html-accessibility-checker",
      "name": "HTML accessibility checker",
      "description": "Scan an HTML fragment for issues that block screen readers and keyboard users.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/html-accessibility-checker",
      "embed": "https://textarray.com/embed/html-accessibility-checker",
      "mode": "transform",
      "action": "Check accessibility",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "checkImages",
          "kind": "checkbox",
          "label": "Image alt text",
          "default": true
        },
        {
          "key": "checkHeadings",
          "kind": "checkbox",
          "label": "Heading order",
          "default": true
        },
        {
          "key": "checkInteractive",
          "kind": "checkbox",
          "label": "Buttons and links without text",
          "default": true
        },
        {
          "key": "checkForms",
          "kind": "checkbox",
          "label": "Form fields without a label",
          "default": true
        },
        {
          "key": "checkLinkText",
          "kind": "checkbox",
          "label": "\"Click here\"-style link text",
          "default": true
        },
        {
          "key": "checkTables",
          "kind": "checkbox",
          "label": "Tables without header cells",
          "default": true
        },
        {
          "key": "checkLang",
          "kind": "checkbox",
          "label": "Document language",
          "default": true
        },
        {
          "key": "checkDuplicateIds",
          "kind": "checkbox",
          "label": "Duplicate ids",
          "default": true
        },
        {
          "key": "minSeverity",
          "kind": "select",
          "label": "Minimum severity",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All findings"
            },
            {
              "value": "warning",
              "label": "Warnings and errors"
            },
            {
              "value": "error",
              "label": "Errors only"
            }
          ]
        }
      ],
      "keywords": [
        "html accessibility checker",
        "a11y checker",
        "accessibility audit",
        "wcag checker",
        "alt text checker",
        "aria checker",
        "heading structure checker",
        "html",
        "aria",
        "wcag"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "markdown-linter",
      "name": "Markdown linter",
      "description": "Find broken links, skipped heading levels and unclosed code blocks in Markdown.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/markdown-linter",
      "embed": "https://textarray.com/embed/markdown-linter",
      "mode": "transform",
      "action": "Check syntax",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Existing file paths (one per line, optional)"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "checkLinkDefinitions",
          "kind": "checkbox",
          "label": "Check link reference definitions",
          "default": true
        },
        {
          "key": "checkDuplicateHeadings",
          "kind": "checkbox",
          "label": "Check duplicate & multiple top-level headings",
          "default": true
        },
        {
          "key": "checkListConsistency",
          "kind": "checkbox",
          "label": "Check consistent list markers & numbering",
          "default": true
        },
        {
          "key": "checkCodeLanguage",
          "kind": "checkbox",
          "label": "Check code blocks have a language",
          "default": true
        },
        {
          "key": "checkTrailingWhitespace",
          "kind": "checkbox",
          "label": "Check trailing whitespace",
          "default": true
        },
        {
          "key": "maxLineLength",
          "kind": "number",
          "label": "Max line length (0 = off)",
          "default": 0,
          "min": 0,
          "max": 500,
          "step": 10
        }
      ],
      "keywords": [
        "markdown linter",
        "markdown syntax checker",
        "markdown validator",
        "broken links checker",
        "lint markdown",
        "markdown formatting checker",
        "markdown",
        "readme"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "spf-dmarc-checker",
      "name": "SPF and DMARC checker",
      "description": "Check a pasted SPF, DMARC or DKIM DNS record and explain what each part means.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/spf-dmarc-checker",
      "embed": "https://textarray.com/embed/spf-dmarc-checker",
      "mode": "transform",
      "action": "Check record",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "recordType",
          "kind": "select",
          "label": "Record type",
          "default": "spf",
          "choices": [
            {
              "value": "spf",
              "label": "SPF"
            },
            {
              "value": "dmarc",
              "label": "DMARC"
            },
            {
              "value": "dkim",
              "label": "DKIM"
            }
          ]
        }
      ],
      "keywords": [
        "spf checker",
        "dmarc checker",
        "dkim checker",
        "spf record validator",
        "dmarc record validator",
        "dns lookup limit",
        "email authentication",
        "spam protection",
        "spf",
        "dmarc",
        "dkim"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "email-header-analyzer",
      "name": "Email header analyzer",
      "description": "Trace an email’s delivery path and check its SPF, DKIM and DMARC results.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/email-header-analyzer",
      "embed": "https://textarray.com/embed/email-header-analyzer",
      "mode": "transform",
      "action": "Analyze headers",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "showChain",
          "kind": "checkbox",
          "label": "Show Received chain",
          "default": true
        },
        {
          "key": "showAuth",
          "kind": "checkbox",
          "label": "Show SPF / DKIM / DMARC results",
          "default": true
        },
        {
          "key": "showEnvelope",
          "kind": "checkbox",
          "label": "Show From, To, Subject, Message-ID",
          "default": true
        },
        {
          "key": "decodeEncoded",
          "kind": "checkbox",
          "label": "Decode encoded headers (MIME encoded-word)",
          "default": true
        },
        {
          "key": "showSpamScore",
          "kind": "checkbox",
          "label": "Show spam filter score",
          "default": true
        },
        {
          "key": "warnMismatch",
          "kind": "checkbox",
          "label": "Warn on From / Return-Path mismatch",
          "default": true
        }
      ],
      "keywords": [
        "email header analyzer",
        "received header",
        "spf dkim dmarc",
        "mail trace",
        "email delivery path",
        "authentication-results",
        "mime encoded word",
        "email delay"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "csv-profiler",
      "name": "CSV profiler",
      "description": "Scan a CSV and get per-column type, missing values, unique counts and top values.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/csv-profiler",
      "embed": "https://textarray.com/embed/csv-profiler",
      "mode": "transform",
      "action": "Profile CSV",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "header",
          "kind": "checkbox",
          "label": "First row is header",
          "default": true
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "comma",
              "label": "Comma (,)"
            },
            {
              "value": "semicolon",
              "label": "Semicolon (;)"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe (|)"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "overview",
          "choices": [
            {
              "value": "overview",
              "label": "Overview"
            },
            {
              "value": "table",
              "label": "Table"
            }
          ]
        },
        {
          "key": "topN",
          "kind": "number",
          "label": "Top values per column",
          "default": 3,
          "min": 1,
          "max": 10,
          "step": 1
        }
      ],
      "keywords": [
        "csv profiler",
        "csv statistics",
        "column type detection",
        "data quality check",
        "missing values",
        "unique values",
        "primary key candidate",
        "csv",
        "data profiling"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "email-subject-checker",
      "name": "Email subject line checker",
      "description": "Check subject lines for length, mobile/desktop truncation and spam trigger words.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/email-subject-checker",
      "embed": "https://textarray.com/embed/email-subject-checker",
      "mode": "transform",
      "action": "Check subject lines",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "spamLang",
          "kind": "select",
          "label": "Spam word list",
          "default": "en",
          "choices": [
            {
              "value": "en",
              "label": "English"
            },
            {
              "value": "sk",
              "label": "Slovak"
            },
            {
              "value": "cs",
              "label": "Czech"
            },
            {
              "value": "de",
              "label": "German"
            },
            {
              "value": "es",
              "label": "Spanish"
            },
            {
              "value": "fr",
              "label": "French"
            },
            {
              "value": "it",
              "label": "Italian"
            },
            {
              "value": "pt",
              "label": "Portuguese"
            },
            {
              "value": "pl",
              "label": "Polish"
            },
            {
              "value": "nl",
              "label": "Dutch"
            }
          ]
        },
        {
          "key": "mobileLimit",
          "kind": "number",
          "label": "Mobile character limit",
          "default": 40,
          "min": 10,
          "max": 200,
          "step": 1
        },
        {
          "key": "desktopLimit",
          "kind": "number",
          "label": "Desktop character limit",
          "default": 60,
          "min": 10,
          "max": 300,
          "step": 1
        },
        {
          "key": "warnAllCaps",
          "kind": "checkbox",
          "label": "Warn about ALL CAPS words",
          "default": true
        },
        {
          "key": "warnPunctuation",
          "kind": "checkbox",
          "label": "Warn about excessive punctuation",
          "default": true
        },
        {
          "key": "warnEmoji",
          "kind": "checkbox",
          "label": "Count emoji and warn above 2",
          "default": true
        },
        {
          "key": "checkPreheader",
          "kind": "checkbox",
          "label": "Check preheader (Subject|Preheader)",
          "default": false
        },
        {
          "key": "showPreview",
          "kind": "checkbox",
          "label": "Show truncation preview",
          "default": true
        },
        {
          "key": "sortByRisk",
          "kind": "checkbox",
          "label": "Sort by risk",
          "default": true
        }
      ],
      "keywords": [
        "email subject line checker",
        "subject line tester",
        "spam trigger words",
        "email subject length",
        "preheader checker",
        "subject line preview",
        "email marketing checklist",
        "inbox preview"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "sms-counter",
      "name": "SMS message counter",
      "description": "Count how many characters and text messages your text takes up.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/sms-counter",
      "embed": "https://textarray.com/embed/sms-counter",
      "mode": "transform",
      "action": "Count SMS",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "encoding",
          "kind": "select",
          "label": "Encoding",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "gsm7",
              "label": "Force GSM-7"
            },
            {
              "value": "ucs2",
              "label": "Force UCS-2"
            }
          ]
        },
        {
          "key": "suggestReplacements",
          "kind": "checkbox",
          "label": "Suggest GSM-7 replacements",
          "default": true
        },
        {
          "key": "showParts",
          "kind": "checkbox",
          "label": "Show message parts",
          "default": false
        }
      ],
      "keywords": [
        "sms counter",
        "sms character counter",
        "text message counter",
        "gsm-7",
        "ucs-2",
        "sms segments",
        "sms parts",
        "concatenated sms",
        "multipart sms",
        "160 characters"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "bionic-reading",
      "name": "Bionic reading",
      "description": "Bold the leading part of each word so your eyes move through text faster.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/bionic-reading",
      "embed": "https://textarray.com/embed/bionic-reading",
      "mode": "transform",
      "action": "Apply bionic reading",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "boldRatio",
          "kind": "range",
          "label": "Bolded portion",
          "default": 50,
          "min": 20,
          "max": 80
        },
        {
          "key": "minLength",
          "kind": "number",
          "label": "Minimum word length",
          "default": 4,
          "min": 1,
          "max": 12,
          "step": 1
        },
        {
          "key": "skipStopWords",
          "kind": "checkbox",
          "label": "Skip short conjunctions and prepositions",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "html",
          "choices": [
            {
              "value": "html",
              "label": "HTML (<strong>)"
            },
            {
              "value": "markdown",
              "label": "Markdown (**bold**)"
            },
            {
              "value": "unicode",
              "label": "Unicode bold characters"
            }
          ]
        },
        {
          "key": "highlightNumbers",
          "kind": "checkbox",
          "label": "Also highlight numbers",
          "default": true
        }
      ],
      "keywords": [
        "bionic reading",
        "speed reading",
        "fast reading text",
        "bold first letters",
        "reading speed tool",
        "text highlighter",
        "html",
        "markdown",
        "unicode bold"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "markdown-to-slack",
      "name": "Markdown to Slack or Discord",
      "description": "Convert Markdown formatting to Slack or Discord message syntax, and back.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/markdown-to-slack",
      "embed": "https://textarray.com/embed/markdown-to-slack",
      "mode": "transform",
      "action": "Convert formatting",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "toPlatform",
          "choices": [
            {
              "value": "toPlatform",
              "label": "Markdown → chat message"
            },
            {
              "value": "toMarkdown",
              "label": "Chat message → Markdown"
            }
          ]
        },
        {
          "key": "platform",
          "kind": "select",
          "label": "Platform",
          "default": "slack",
          "choices": [
            {
              "value": "slack",
              "label": "Slack"
            },
            {
              "value": "discord",
              "label": "Discord"
            },
            {
              "value": "jira",
              "label": "Jira"
            },
            {
              "value": "confluence",
              "label": "Confluence"
            }
          ]
        },
        {
          "key": "headingsToBold",
          "kind": "checkbox",
          "label": "Convert headings to a bold line",
          "default": true
        },
        {
          "key": "convertLinks",
          "kind": "checkbox",
          "label": "Convert links to Slack's <url|text> syntax",
          "default": true
        },
        {
          "key": "preserveCodeLanguage",
          "kind": "checkbox",
          "label": "Keep the language tag on code blocks",
          "default": true
        },
        {
          "key": "convertLists",
          "kind": "checkbox",
          "label": "Normalize list markers to a dash bullet",
          "default": true
        },
        {
          "key": "escapeChars",
          "kind": "checkbox",
          "label": "Escape characters the platform would otherwise interpret",
          "default": false
        },
        {
          "key": "convertSpoilers",
          "kind": "checkbox",
          "label": "Convert spoiler markup for Discord",
          "default": true
        }
      ],
      "keywords": [
        "jira wiki markup",
        "confluence wiki markup",
        "markdown to jira",
        "markdown to confluence",
        "markdown to slack",
        "markdown to discord",
        "slack mrkdwn converter",
        "discord markdown converter",
        "convert markdown to slack",
        "markdown formatting converter",
        "mrkdwn",
        "markdown",
        "slack",
        "discord"
      ],
      "updated": "2026-08-22"
    },
    {
      "slug": "gps-coordinate-converter",
      "name": "GPS coordinate converter",
      "description": "Convert GPS coordinates between decimal degrees and degrees-minutes-seconds, for one pair or a whole list.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/gps-coordinate-converter",
      "embed": "https://textarray.com/embed/gps-coordinate-converter",
      "mode": "transform",
      "action": "Convert coordinates",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "toDecimal",
              "label": "To decimal degrees"
            },
            {
              "value": "toDms",
              "label": "To degrees, minutes, seconds"
            }
          ]
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 6,
          "min": 0,
          "max": 8,
          "step": 1
        },
        {
          "key": "order",
          "kind": "select",
          "label": "Component order",
          "default": "latLon",
          "choices": [
            {
              "value": "latLon",
              "label": "Latitude first"
            },
            {
              "value": "lonLat",
              "label": "Longitude first"
            }
          ]
        },
        {
          "key": "hemisphere",
          "kind": "select",
          "label": "Hemisphere notation",
          "default": "letter",
          "choices": [
            {
              "value": "letter",
              "label": "Letter (N/S/E/W)"
            },
            {
              "value": "sign",
              "label": "Sign (+/-)"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "text",
          "label": "Separator",
          "default": ", "
        },
        {
          "key": "mapLink",
          "kind": "checkbox",
          "label": "Add map link",
          "default": false
        },
        {
          "key": "warnOutOfRange",
          "kind": "checkbox",
          "label": "Flag out-of-range values",
          "default": true
        }
      ],
      "keywords": [
        "gps coordinate converter",
        "lat long converter",
        "decimal degrees to dms",
        "dms to decimal degrees",
        "latitude longitude converter",
        "coordinate format converter",
        "degrees minutes seconds",
        "gps",
        "dms"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "citation-generator",
      "name": "Citation generator",
      "description": "Turn source details into a formatted APA, MLA or Chicago citation.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/citation-generator",
      "embed": "https://textarray.com/embed/citation-generator",
      "mode": "transform",
      "action": "Generate citations",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Citation style",
          "default": "apa",
          "choices": [
            {
              "value": "apa",
              "label": "APA"
            },
            {
              "value": "mla",
              "label": "MLA"
            },
            {
              "value": "chicago",
              "label": "Chicago"
            }
          ]
        },
        {
          "key": "sourceType",
          "kind": "select",
          "label": "Source type",
          "default": "book",
          "choices": [
            {
              "value": "book",
              "label": "Book"
            },
            {
              "value": "journal-article",
              "label": "Journal article"
            },
            {
              "value": "website",
              "label": "Website"
            },
            {
              "value": "video",
              "label": "Video"
            },
            {
              "value": "conference-paper",
              "label": "Conference paper"
            }
          ]
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Field delimiter",
          "default": "pipe",
          "choices": [
            {
              "value": "pipe",
              "label": "Pipe ( | )"
            },
            {
              "value": "semicolon",
              "label": "Semicolon ( ; )"
            },
            {
              "value": "comma",
              "label": "Comma ( , )"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "shortCitation",
          "kind": "checkbox",
          "label": "Add short in-text citation",
          "default": false
        },
        {
          "key": "sortAlphabetically",
          "kind": "checkbox",
          "label": "Sort alphabetically by author",
          "default": false
        },
        {
          "key": "hangingIndent",
          "kind": "checkbox",
          "label": "Hanging indent",
          "default": false
        },
        {
          "key": "warnMissing",
          "kind": "checkbox",
          "label": "Flag missing required fields",
          "default": true
        }
      ],
      "keywords": [
        "citation generator",
        "apa citation",
        "mla citation",
        "chicago citation",
        "bibliography generator",
        "reference generator",
        "works cited",
        "cite a source"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "csv-pivot-table",
      "name": "CSV group and sum",
      "description": "Group CSV rows by one or more columns and sum, count or average the rest.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/csv-pivot-table",
      "embed": "https://textarray.com/embed/csv-pivot-table",
      "mode": "transform",
      "action": "Group and summarize",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "groupColumns",
          "kind": "text",
          "label": "Group by column(s)",
          "default": ""
        },
        {
          "key": "aggregate",
          "kind": "select",
          "label": "Aggregate",
          "default": "count",
          "choices": [
            {
              "value": "count",
              "label": "Count rows"
            },
            {
              "value": "sum",
              "label": "Sum"
            },
            {
              "value": "avg",
              "label": "Average"
            },
            {
              "value": "min",
              "label": "Minimum"
            },
            {
              "value": "max",
              "label": "Maximum"
            },
            {
              "value": "distinct",
              "label": "Count distinct"
            }
          ]
        },
        {
          "key": "valueColumn",
          "kind": "text",
          "label": "Column to aggregate",
          "default": ""
        },
        {
          "key": "pivotColumn",
          "kind": "text",
          "label": "Cross-tab column (optional)",
          "default": ""
        },
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "group",
          "choices": [
            {
              "value": "group",
              "label": "Group name"
            },
            {
              "value": "value",
              "label": "Aggregated value"
            }
          ]
        },
        {
          "key": "totalRow",
          "kind": "checkbox",
          "label": "Add a grand-total row",
          "default": false
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 2,
          "min": 0,
          "max": 6,
          "step": 1
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Input delimiter",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Aligned table"
            },
            {
              "value": "csv",
              "label": "CSV"
            },
            {
              "value": "markdown",
              "label": "Markdown"
            }
          ]
        }
      ],
      "keywords": [
        "csv pivot table",
        "group by",
        "sum csv column",
        "csv aggregate",
        "cross tab",
        "csv report",
        "csv",
        "group and sum"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "csv-join",
      "name": "CSV join by key",
      "description": "Join two CSV tables into one using a shared key column.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/csv-join",
      "embed": "https://textarray.com/embed/csv-join",
      "mode": "transform",
      "action": "Join tables",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Second CSV table"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "joinType",
          "kind": "select",
          "label": "Join type",
          "default": "inner",
          "choices": [
            {
              "value": "inner",
              "label": "Inner (matching keys only)"
            },
            {
              "value": "left",
              "label": "Left (all of the first table)"
            },
            {
              "value": "right",
              "label": "Right (all of the second table)"
            },
            {
              "value": "full",
              "label": "Full (all rows from both)"
            }
          ]
        },
        {
          "key": "keyColumn1",
          "kind": "text",
          "label": "Key column in first table",
          "default": "id"
        },
        {
          "key": "keyColumn2",
          "kind": "text",
          "label": "Key column in second table",
          "default": "id"
        },
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case-sensitive key comparison",
          "default": false
        },
        {
          "key": "trim",
          "kind": "checkbox",
          "label": "Trim whitespace before comparing",
          "default": true
        },
        {
          "key": "prefix",
          "kind": "text",
          "label": "Prefix for colliding column names",
          "default": "right_"
        },
        {
          "key": "fillValue",
          "kind": "text",
          "label": "Fill value for empty cells",
          "default": ""
        },
        {
          "key": "columnOrder",
          "kind": "select",
          "label": "Column order",
          "default": "leftFirst",
          "choices": [
            {
              "value": "leftFirst",
              "label": "First table’s columns first"
            },
            {
              "value": "rightFirst",
              "label": "Second table’s columns first"
            }
          ]
        },
        {
          "key": "flagDuplicates",
          "kind": "checkbox",
          "label": "Flag rows with duplicate keys",
          "default": false
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Input delimiter",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        },
        {
          "key": "outputDelimiter",
          "kind": "select",
          "label": "Output delimiter",
          "default": "comma",
          "choices": [
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        }
      ],
      "keywords": [
        "csv join",
        "join csv files",
        "merge csv by key",
        "csv vlookup",
        "combine csv tables",
        "left join csv",
        "inner join csv",
        "csv",
        "vlookup",
        "sql join"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "csv-filter",
      "name": "CSV row filter",
      "description": "Keep only the CSV rows whose column values match a condition you set.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/csv-filter",
      "embed": "https://textarray.com/embed/csv-filter",
      "mode": "transform",
      "action": "Filter rows",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "delimiter",
          "kind": "text",
          "label": "Delimiter",
          "default": ","
        },
        {
          "key": "column",
          "kind": "text",
          "label": "Column",
          "default": "1"
        },
        {
          "key": "operator",
          "kind": "select",
          "label": "Condition",
          "default": "equals",
          "choices": [
            {
              "value": "equals",
              "label": "Equals"
            },
            {
              "value": "notEquals",
              "label": "Does not equal"
            },
            {
              "value": "contains",
              "label": "Contains"
            },
            {
              "value": "startsWith",
              "label": "Starts with"
            },
            {
              "value": "greaterThan",
              "label": "Greater than"
            },
            {
              "value": "lessThan",
              "label": "Less than"
            },
            {
              "value": "isEmpty",
              "label": "Is empty"
            },
            {
              "value": "regex",
              "label": "Matches regex"
            }
          ]
        },
        {
          "key": "value",
          "kind": "text",
          "label": "Value",
          "default": ""
        },
        {
          "key": "logic",
          "kind": "select",
          "label": "Combine with second condition using",
          "default": "and",
          "choices": [
            {
              "value": "and",
              "label": "And"
            },
            {
              "value": "or",
              "label": "Or"
            }
          ]
        },
        {
          "key": "column2",
          "kind": "text",
          "label": "Second column (optional)",
          "default": ""
        },
        {
          "key": "operator2",
          "kind": "select",
          "label": "Second condition",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "equals",
              "label": "Equals"
            },
            {
              "value": "notEquals",
              "label": "Does not equal"
            },
            {
              "value": "contains",
              "label": "Contains"
            },
            {
              "value": "startsWith",
              "label": "Starts with"
            },
            {
              "value": "greaterThan",
              "label": "Greater than"
            },
            {
              "value": "lessThan",
              "label": "Less than"
            },
            {
              "value": "isEmpty",
              "label": "Is empty"
            },
            {
              "value": "regex",
              "label": "Matches regex"
            }
          ]
        },
        {
          "key": "value2",
          "kind": "text",
          "label": "Second value",
          "default": ""
        },
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case-sensitive",
          "default": false
        },
        {
          "key": "numeric",
          "kind": "checkbox",
          "label": "Compare as numbers",
          "default": false
        },
        {
          "key": "invert",
          "kind": "checkbox",
          "label": "Invert selection",
          "default": false
        },
        {
          "key": "keepHeader",
          "kind": "checkbox",
          "label": "Keep header row",
          "default": true
        },
        {
          "key": "showCount",
          "kind": "checkbox",
          "label": "Show match count in output",
          "default": false
        }
      ],
      "keywords": [
        "csv filter",
        "filter csv rows",
        "csv row filter",
        "filter spreadsheet rows",
        "csv where clause",
        "filter table rows",
        "csv",
        "tsv"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "unit-converter",
      "name": "Unit converter",
      "description": "Convert values between length, mass, volume, area, speed, pressure and energy units.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/unit-converter",
      "embed": "https://textarray.com/embed/unit-converter",
      "mode": "transform",
      "action": "Convert units",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "quantity",
          "kind": "select",
          "label": "Quantity",
          "default": "length",
          "choices": [
            {
              "value": "length",
              "label": "Length"
            },
            {
              "value": "mass",
              "label": "Mass"
            },
            {
              "value": "volume",
              "label": "Volume"
            },
            {
              "value": "area",
              "label": "Area"
            },
            {
              "value": "speed",
              "label": "Speed"
            },
            {
              "value": "pressure",
              "label": "Pressure"
            },
            {
              "value": "energy",
              "label": "Energy"
            }
          ]
        },
        {
          "key": "from",
          "kind": "select",
          "label": "From unit",
          "default": "km",
          "choices": [
            {
              "value": "mm",
              "label": "Millimeters (mm)"
            },
            {
              "value": "cm",
              "label": "Centimeters (cm)"
            },
            {
              "value": "m",
              "label": "Meters (m)"
            },
            {
              "value": "km",
              "label": "Kilometers (km)"
            },
            {
              "value": "in",
              "label": "Inches (in)"
            },
            {
              "value": "ft",
              "label": "Feet (ft)"
            },
            {
              "value": "yd",
              "label": "Yards (yd)"
            },
            {
              "value": "mi",
              "label": "Miles (mi)"
            },
            {
              "value": "mg",
              "label": "Milligrams (mg)"
            },
            {
              "value": "g",
              "label": "Grams (g)"
            },
            {
              "value": "kg",
              "label": "Kilograms (kg)"
            },
            {
              "value": "t",
              "label": "Metric tons (t)"
            },
            {
              "value": "oz",
              "label": "Ounces (oz)"
            },
            {
              "value": "lb",
              "label": "Pounds (lb)"
            },
            {
              "value": "ml",
              "label": "Milliliters (ml)"
            },
            {
              "value": "l",
              "label": "Liters (l)"
            },
            {
              "value": "m3",
              "label": "Cubic meters (m³)"
            },
            {
              "value": "gal",
              "label": "Gallons (gal)"
            },
            {
              "value": "qt",
              "label": "Quarts (qt)"
            },
            {
              "value": "pt",
              "label": "Pints (pt)"
            },
            {
              "value": "cm2",
              "label": "Square centimeters (cm²)"
            },
            {
              "value": "m2",
              "label": "Square meters (m²)"
            },
            {
              "value": "km2",
              "label": "Square kilometers (km²)"
            },
            {
              "value": "ha",
              "label": "Hectares (ha)"
            },
            {
              "value": "ft2",
              "label": "Square feet (ft²)"
            },
            {
              "value": "ac",
              "label": "Acres (ac)"
            },
            {
              "value": "mi2",
              "label": "Square miles (mi²)"
            },
            {
              "value": "mps",
              "label": "Meters per second (m/s)"
            },
            {
              "value": "kph",
              "label": "Kilometers per hour (km/h)"
            },
            {
              "value": "mph",
              "label": "Miles per hour (mph)"
            },
            {
              "value": "kn",
              "label": "Knots (kn)"
            },
            {
              "value": "pa",
              "label": "Pascals (Pa)"
            },
            {
              "value": "kpa",
              "label": "Kilopascals (kPa)"
            },
            {
              "value": "bar",
              "label": "Bar (bar)"
            },
            {
              "value": "atm",
              "label": "Atmospheres (atm)"
            },
            {
              "value": "psi",
              "label": "PSI (psi)"
            },
            {
              "value": "mmhg",
              "label": "mmHg (mmhg)"
            },
            {
              "value": "j",
              "label": "Joules (J)"
            },
            {
              "value": "kj",
              "label": "Kilojoules (kJ)"
            },
            {
              "value": "cal",
              "label": "Calories (cal)"
            },
            {
              "value": "kcal",
              "label": "Kilocalories (kcal)"
            },
            {
              "value": "wh",
              "label": "Watt-hours (Wh)"
            },
            {
              "value": "kwh",
              "label": "Kilowatt-hours (kWh)"
            },
            {
              "value": "btu",
              "label": "BTU (btu)"
            }
          ]
        },
        {
          "key": "to",
          "kind": "select",
          "label": "To unit",
          "default": "mi",
          "choices": [
            {
              "value": "all",
              "label": "All units in category"
            },
            {
              "value": "mm",
              "label": "Millimeters (mm)"
            },
            {
              "value": "cm",
              "label": "Centimeters (cm)"
            },
            {
              "value": "m",
              "label": "Meters (m)"
            },
            {
              "value": "km",
              "label": "Kilometers (km)"
            },
            {
              "value": "in",
              "label": "Inches (in)"
            },
            {
              "value": "ft",
              "label": "Feet (ft)"
            },
            {
              "value": "yd",
              "label": "Yards (yd)"
            },
            {
              "value": "mi",
              "label": "Miles (mi)"
            },
            {
              "value": "mg",
              "label": "Milligrams (mg)"
            },
            {
              "value": "g",
              "label": "Grams (g)"
            },
            {
              "value": "kg",
              "label": "Kilograms (kg)"
            },
            {
              "value": "t",
              "label": "Metric tons (t)"
            },
            {
              "value": "oz",
              "label": "Ounces (oz)"
            },
            {
              "value": "lb",
              "label": "Pounds (lb)"
            },
            {
              "value": "ml",
              "label": "Milliliters (ml)"
            },
            {
              "value": "l",
              "label": "Liters (l)"
            },
            {
              "value": "m3",
              "label": "Cubic meters (m³)"
            },
            {
              "value": "gal",
              "label": "Gallons (gal)"
            },
            {
              "value": "qt",
              "label": "Quarts (qt)"
            },
            {
              "value": "pt",
              "label": "Pints (pt)"
            },
            {
              "value": "cm2",
              "label": "Square centimeters (cm²)"
            },
            {
              "value": "m2",
              "label": "Square meters (m²)"
            },
            {
              "value": "km2",
              "label": "Square kilometers (km²)"
            },
            {
              "value": "ha",
              "label": "Hectares (ha)"
            },
            {
              "value": "ft2",
              "label": "Square feet (ft²)"
            },
            {
              "value": "ac",
              "label": "Acres (ac)"
            },
            {
              "value": "mi2",
              "label": "Square miles (mi²)"
            },
            {
              "value": "mps",
              "label": "Meters per second (m/s)"
            },
            {
              "value": "kph",
              "label": "Kilometers per hour (km/h)"
            },
            {
              "value": "mph",
              "label": "Miles per hour (mph)"
            },
            {
              "value": "kn",
              "label": "Knots (kn)"
            },
            {
              "value": "pa",
              "label": "Pascals (Pa)"
            },
            {
              "value": "kpa",
              "label": "Kilopascals (kPa)"
            },
            {
              "value": "bar",
              "label": "Bar (bar)"
            },
            {
              "value": "atm",
              "label": "Atmospheres (atm)"
            },
            {
              "value": "psi",
              "label": "PSI (psi)"
            },
            {
              "value": "mmhg",
              "label": "mmHg (mmhg)"
            },
            {
              "value": "j",
              "label": "Joules (J)"
            },
            {
              "value": "kj",
              "label": "Kilojoules (kJ)"
            },
            {
              "value": "cal",
              "label": "Calories (cal)"
            },
            {
              "value": "kcal",
              "label": "Kilocalories (kcal)"
            },
            {
              "value": "wh",
              "label": "Watt-hours (Wh)"
            },
            {
              "value": "kwh",
              "label": "Kilowatt-hours (kWh)"
            },
            {
              "value": "btu",
              "label": "BTU (btu)"
            }
          ]
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 2,
          "min": 0,
          "max": 8,
          "step": 1
        },
        {
          "key": "detectUnit",
          "kind": "checkbox",
          "label": "Detect unit in text",
          "default": true
        },
        {
          "key": "keepOriginal",
          "kind": "checkbox",
          "label": "Keep original line",
          "default": true
        }
      ],
      "keywords": [
        "unit converter",
        "convert units",
        "metric to imperial",
        "km to miles",
        "kg to lbs",
        "measurement converter",
        "length converter",
        "weight converter"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "hcl-to-json",
      "name": "HCL to JSON",
      "description": "Convert Terraform-style HCL configuration into equivalent JSON.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/hcl-to-json",
      "embed": "https://textarray.com/embed/hcl-to-json",
      "mode": "transform",
      "action": "Convert to JSON",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "indent",
          "kind": "select",
          "label": "Indent",
          "default": "2",
          "choices": [
            {
              "value": "2",
              "label": "2 spaces"
            },
            {
              "value": "4",
              "label": "4 spaces"
            },
            {
              "value": "tabs",
              "label": "Tabs"
            },
            {
              "value": "minified",
              "label": "Minified"
            }
          ]
        },
        {
          "key": "sortKeys",
          "kind": "checkbox",
          "label": "Sort keys alphabetically",
          "default": false
        },
        {
          "key": "keepComments",
          "kind": "checkbox",
          "label": "Keep comments",
          "default": false
        },
        {
          "key": "outputShape",
          "kind": "select",
          "label": "Output shape",
          "default": "object",
          "choices": [
            {
              "value": "object",
              "label": "Single object"
            },
            {
              "value": "list",
              "label": "List of blocks"
            }
          ]
        }
      ],
      "keywords": [
        "hcl to json",
        "terraform to json",
        "hcl converter",
        "terraform json",
        "hcl parser",
        "tf to json",
        "hcl",
        "terraform",
        "json"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "csp-report-parser",
      "name": "CSP violation report parser",
      "description": "Turn pasted CSP violation reports into a readable summary of which directives and sources are blocked.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/csp-report-parser",
      "embed": "https://textarray.com/embed/csp-report-parser",
      "mode": "transform",
      "action": "Parse reports",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "groupBy",
          "kind": "select",
          "label": "Group by",
          "default": "directive",
          "choices": [
            {
              "value": "directive",
              "label": "Directive"
            },
            {
              "value": "source",
              "label": "Blocked source"
            }
          ]
        },
        {
          "key": "hideExtensions",
          "kind": "checkbox",
          "label": "Hide browser-extension reports",
          "default": true
        },
        {
          "key": "showAffectedPages",
          "kind": "checkbox",
          "label": "Show affected pages",
          "default": false
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Summary table"
            },
            {
              "value": "rules",
              "label": "Suggested rules"
            }
          ]
        }
      ],
      "keywords": [
        "csp violation report parser",
        "content security policy",
        "csp report-uri",
        "csp reporting api",
        "csp report analyzer",
        "blocked-uri",
        "json",
        "security headers"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "log-timestamp-normalizer",
      "name": "Log timestamp normalizer",
      "description": "Find timestamps in pasted logs and rewrite them all in one format and timezone.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/log-timestamp-normalizer",
      "embed": "https://textarray.com/embed/log-timestamp-normalizer",
      "mode": "transform",
      "action": "Normalize timestamps",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Target format",
          "default": "iso",
          "choices": [
            {
              "value": "iso",
              "label": "ISO 8601"
            },
            {
              "value": "unix-s",
              "label": "Unix (seconds)"
            },
            {
              "value": "unix-ms",
              "label": "Unix (milliseconds)"
            },
            {
              "value": "human",
              "label": "Human-readable"
            }
          ]
        },
        {
          "key": "targetZone",
          "kind": "select",
          "label": "Target timezone",
          "default": "UTC",
          "choices": [
            {
              "value": "UTC",
              "label": "UTC"
            },
            {
              "value": "Europe/London",
              "label": "Europe/London"
            },
            {
              "value": "Europe/Berlin",
              "label": "Europe/Berlin"
            },
            {
              "value": "Europe/Bratislava",
              "label": "Europe/Bratislava"
            },
            {
              "value": "America/New_York",
              "label": "America/New_York"
            },
            {
              "value": "America/Los_Angeles",
              "label": "America/Los_Angeles"
            },
            {
              "value": "Asia/Tokyo",
              "label": "Asia/Tokyo"
            },
            {
              "value": "Australia/Sydney",
              "label": "Australia/Sydney"
            }
          ]
        },
        {
          "key": "assumedZone",
          "kind": "select",
          "label": "Assumed timezone for timestamps without an offset",
          "default": "UTC",
          "choices": [
            {
              "value": "UTC",
              "label": "UTC"
            },
            {
              "value": "Europe/London",
              "label": "Europe/London"
            },
            {
              "value": "Europe/Berlin",
              "label": "Europe/Berlin"
            },
            {
              "value": "Europe/Bratislava",
              "label": "Europe/Bratislava"
            },
            {
              "value": "America/New_York",
              "label": "America/New_York"
            },
            {
              "value": "America/Los_Angeles",
              "label": "America/Los_Angeles"
            },
            {
              "value": "Asia/Tokyo",
              "label": "Asia/Tokyo"
            },
            {
              "value": "Australia/Sydney",
              "label": "Australia/Sydney"
            }
          ]
        },
        {
          "key": "shiftMinutes",
          "kind": "number",
          "label": "Shift all times by (minutes)",
          "default": 0,
          "min": -10080,
          "max": 10080,
          "step": 1
        },
        {
          "key": "relativeToFirst",
          "kind": "checkbox",
          "label": "Show time relative to the first line",
          "default": false
        },
        {
          "key": "sortByTime",
          "kind": "checkbox",
          "label": "Sort lines by time",
          "default": false
        },
        {
          "key": "warnUnrecognized",
          "kind": "checkbox",
          "label": "Flag lines without a recognized timestamp",
          "default": true
        }
      ],
      "keywords": [
        "log timestamp normalizer",
        "normalize log timestamps",
        "convert log timestamps",
        "syslog timestamp converter",
        "apache log time converter",
        "align log timezones",
        "iso 8601",
        "unix timestamp"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "css-box-shadow-generator",
      "name": "CSS box-shadow generator",
      "description": "Build a CSS box-shadow value from offset, blur, spread and color, with multiple layers and presets.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-box-shadow-generator",
      "embed": "https://textarray.com/embed/css-box-shadow-generator",
      "mode": "generate",
      "action": "Generate box-shadow",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "preset",
          "kind": "select",
          "label": "Preset",
          "default": "medium",
          "choices": [
            {
              "value": "custom",
              "label": "Custom"
            },
            {
              "value": "subtle",
              "label": "Subtle"
            },
            {
              "value": "medium",
              "label": "Medium"
            },
            {
              "value": "strong",
              "label": "Strong"
            }
          ]
        },
        {
          "key": "inset",
          "kind": "checkbox",
          "label": "Inset (inner shadow)",
          "default": false
        },
        {
          "key": "layers",
          "kind": "number",
          "label": "Layers",
          "default": 2,
          "min": 1,
          "max": 5,
          "step": 1
        },
        {
          "key": "offsetX",
          "kind": "number",
          "label": "Horizontal offset",
          "default": 0,
          "min": -50,
          "max": 50,
          "step": 1
        },
        {
          "key": "offsetY",
          "kind": "number",
          "label": "Vertical offset",
          "default": 4,
          "min": -50,
          "max": 50,
          "step": 1
        },
        {
          "key": "blur",
          "kind": "number",
          "label": "Blur radius",
          "default": 8,
          "min": 0,
          "max": 100,
          "step": 1
        },
        {
          "key": "spread",
          "kind": "number",
          "label": "Spread radius",
          "default": 0,
          "min": -50,
          "max": 50,
          "step": 1
        },
        {
          "key": "color",
          "kind": "text",
          "label": "Shadow color",
          "default": "#000000"
        },
        {
          "key": "opacity",
          "kind": "range",
          "label": "Opacity",
          "default": 15,
          "min": 0,
          "max": 100
        },
        {
          "key": "unit",
          "kind": "select",
          "label": "Unit",
          "default": "px",
          "choices": [
            {
              "value": "px",
              "label": "px"
            },
            {
              "value": "rem",
              "label": "rem"
            }
          ]
        },
        {
          "key": "darkMode",
          "kind": "checkbox",
          "label": "Add dark mode variant",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "line",
          "choices": [
            {
              "value": "line",
              "label": "Single line"
            },
            {
              "value": "variable",
              "label": "CSS variable"
            },
            {
              "value": "class",
              "label": "CSS class"
            }
          ]
        },
        {
          "key": "includeFilter",
          "kind": "checkbox",
          "label": "Include filter: drop-shadow",
          "default": false
        }
      ],
      "keywords": [
        "css box-shadow generator",
        "box shadow css",
        "css shadow generator",
        "css elevation shadow",
        "material design shadow",
        "multiple shadow layers",
        "css drop-shadow filter",
        "box-shadow",
        "css"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "x509-certificate-decoder",
      "name": "X.509 certificate decoder",
      "description": "Decode a PEM certificate and inspect its subject, issuer, validity, extensions and fingerprint.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/x509-certificate-decoder",
      "embed": "https://textarray.com/embed/x509-certificate-decoder",
      "mode": "transform",
      "action": "Decode certificate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "allCertificates",
          "kind": "checkbox",
          "label": "List all certificates in the chain",
          "default": false
        },
        {
          "key": "showValidityDays",
          "kind": "checkbox",
          "label": "Show days remaining and warn near expiry",
          "default": true
        },
        {
          "key": "showExtensions",
          "kind": "checkbox",
          "label": "Show extensions (key usage, basic constraints)",
          "default": true
        },
        {
          "key": "warnSelfSigned",
          "kind": "checkbox",
          "label": "Warn on self-signed certificates",
          "default": true
        },
        {
          "key": "fingerprintFormat",
          "kind": "select",
          "label": "Fingerprint format",
          "default": "sha256",
          "choices": [
            {
              "value": "sha256",
              "label": "SHA-256"
            },
            {
              "value": "sha1",
              "label": "SHA-1"
            }
          ]
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "overview",
          "choices": [
            {
              "value": "overview",
              "label": "Overview"
            },
            {
              "value": "json",
              "label": "JSON"
            }
          ]
        }
      ],
      "keywords": [
        "x.509 certificate decoder",
        "ssl certificate decoder",
        "tls certificate viewer",
        "pem certificate parser",
        "certificate fingerprint",
        "certificate expiry checker",
        "certificate chain viewer",
        "pem",
        "der",
        "base64",
        "json"
      ],
      "updated": "2026-08-17"
    },
    {
      "slug": "language-detector",
      "name": "Language detector",
      "description": "Estimate which language a piece of text is written in, ranked by confidence.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/language-detector",
      "embed": "https://textarray.com/embed/language-detector",
      "mode": "transform",
      "action": "Detect language",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "languageGroup",
          "kind": "select",
          "label": "Language group",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All languages"
            },
            {
              "value": "slavic",
              "label": "Slavic"
            },
            {
              "value": "germanic",
              "label": "Germanic"
            },
            {
              "value": "romance",
              "label": "Romance"
            },
            {
              "value": "other",
              "label": "Other"
            }
          ]
        },
        {
          "key": "minLength",
          "kind": "number",
          "label": "Minimum length for a reliable estimate (chars)",
          "default": 20,
          "min": 0,
          "max": 500,
          "step": 5
        },
        {
          "key": "scope",
          "kind": "select",
          "label": "Evaluate",
          "default": "whole",
          "choices": [
            {
              "value": "whole",
              "label": "Whole text"
            },
            {
              "value": "line",
              "label": "Each line separately"
            },
            {
              "value": "paragraph",
              "label": "Each paragraph separately"
            }
          ]
        },
        {
          "key": "distinguishClose",
          "kind": "checkbox",
          "label": "Sharpen close languages (Slovak/Czech, Croatian/Slovenian)",
          "default": false
        },
        {
          "key": "showPercent",
          "kind": "checkbox",
          "label": "Show scores as percentages",
          "default": true
        },
        {
          "key": "detectMixed",
          "kind": "checkbox",
          "label": "Warn about mixed-language text",
          "default": true
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output",
          "default": "ranking",
          "choices": [
            {
              "value": "ranking",
              "label": "Ranked list with scores"
            },
            {
              "value": "code",
              "label": "Language code only"
            }
          ]
        }
      ],
      "keywords": [
        "language detector",
        "detect language",
        "identify language",
        "what language is this",
        "language identification",
        "text language checker"
      ],
      "updated": "2026-08-18"
    },
    {
      "slug": "reverse-outline",
      "name": "Reverse outline",
      "description": "Turn a draft into a list of its opening sentences, so its structure becomes visible.",
      "category": "basic-tools",
      "categoryName": "Basic tools",
      "url": "https://textarray.com/reverse-outline",
      "embed": "https://textarray.com/embed/reverse-outline",
      "mode": "transform",
      "action": "Build outline",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "sentenceCount",
          "kind": "select",
          "label": "Sentences per paragraph",
          "default": "first",
          "choices": [
            {
              "value": "first",
              "label": "First sentence"
            },
            {
              "value": "firstLast",
              "label": "First and last sentence"
            }
          ]
        },
        {
          "key": "maxWords",
          "kind": "number",
          "label": "Truncate sentence to N words (0 = off)",
          "default": 0,
          "min": 0,
          "max": 60,
          "step": 1
        },
        {
          "key": "showStats",
          "kind": "checkbox",
          "label": "Show paragraph number and word count",
          "default": false
        },
        {
          "key": "keepHeadings",
          "kind": "checkbox",
          "label": "Keep headings as outline levels",
          "default": true
        },
        {
          "key": "skipShort",
          "kind": "checkbox",
          "label": "Skip short paragraphs and quotes",
          "default": false
        },
        {
          "key": "highlightWeak",
          "kind": "checkbox",
          "label": "Highlight weak openings (conjunction or pronoun)",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "numbered",
          "choices": [
            {
              "value": "numbered",
              "label": "Numbered list"
            },
            {
              "value": "markdown",
              "label": "Markdown outline"
            }
          ]
        }
      ],
      "keywords": [
        "reverse outline",
        "paragraph outline",
        "topic sentence extractor",
        "essay structure checker",
        "document skeleton",
        "outline generator",
        "first sentence of each paragraph",
        "markdown"
      ],
      "updated": "2026-08-18"
    },
    {
      "slug": "keyboard-layout-fixer",
      "name": "Keyboard layout fixer",
      "description": "Turn text typed with the wrong keyboard layout active back into what you meant to type.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/keyboard-layout-fixer",
      "embed": "https://textarray.com/embed/keyboard-layout-fixer",
      "mode": "transform",
      "action": "Fix layout",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "sourceLayout",
          "kind": "select",
          "label": "Typed as (wrong layout)",
          "default": "qwerty",
          "choices": [
            {
              "value": "qwerty",
              "label": "QWERTY"
            },
            {
              "value": "qwertz",
              "label": "QWERTZ"
            },
            {
              "value": "azerty",
              "label": "AZERTY"
            },
            {
              "value": "sk",
              "label": "Slovak"
            },
            {
              "value": "cs",
              "label": "Czech"
            },
            {
              "value": "de",
              "label": "German"
            },
            {
              "value": "ru",
              "label": "Russian"
            }
          ]
        },
        {
          "key": "targetLayout",
          "kind": "select",
          "label": "Meant to type on (correct layout)",
          "default": "ru",
          "choices": [
            {
              "value": "qwerty",
              "label": "QWERTY"
            },
            {
              "value": "qwertz",
              "label": "QWERTZ"
            },
            {
              "value": "azerty",
              "label": "AZERTY"
            },
            {
              "value": "sk",
              "label": "Slovak"
            },
            {
              "value": "cs",
              "label": "Czech"
            },
            {
              "value": "de",
              "label": "German"
            },
            {
              "value": "ru",
              "label": "Russian"
            }
          ]
        },
        {
          "key": "autoDetect",
          "kind": "checkbox",
          "label": "Guess the wrong layout automatically",
          "default": false
        },
        {
          "key": "preserveCase",
          "kind": "checkbox",
          "label": "Preserve capitalization",
          "default": true
        },
        {
          "key": "keepNumbersUntouched",
          "kind": "checkbox",
          "label": "Keep numbers untouched",
          "default": true
        }
      ],
      "keywords": [
        "keyboard layout fixer",
        "wrong keyboard layout",
        "fix typed in wrong layout",
        "qwerty to cyrillic",
        "layout converter",
        "punto switcher",
        "switch keyboard layout text",
        "jcuken",
        "qwertz",
        "azerty"
      ],
      "updated": "2026-08-18"
    },
    {
      "slug": "glossary-checker",
      "name": "Glossary checker",
      "description": "Check text against a glossary of forbidden and recommended terms.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/glossary-checker",
      "embed": "https://textarray.com/embed/glossary-checker",
      "mode": "transform",
      "action": "Check glossary",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Glossary (one pair per line)"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case-sensitive matching",
          "default": false
        },
        {
          "key": "matchInflections",
          "kind": "checkbox",
          "label": "Match inflected forms",
          "default": true
        },
        {
          "key": "ignoreQuoted",
          "kind": "checkbox",
          "label": "Ignore quotes and code blocks",
          "default": true
        },
        {
          "key": "delimiter",
          "kind": "text",
          "label": "Glossary delimiter",
          "default": "->"
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output",
          "default": "corrected",
          "choices": [
            {
              "value": "corrected",
              "label": "Corrected text"
            },
            {
              "value": "highlighted",
              "label": "Highlighted text"
            },
            {
              "value": "list",
              "label": "Findings list"
            }
          ]
        },
        {
          "key": "sortByCount",
          "kind": "checkbox",
          "label": "Sort findings by count",
          "default": false
        }
      ],
      "keywords": [
        "glossary checker",
        "terminology checker",
        "style guide enforcement",
        "preferred terms",
        "forbidden words",
        "term consistency",
        "controlled vocabulary",
        "find and replace terms"
      ],
      "updated": "2026-08-18"
    },
    {
      "slug": "inclusive-language-checker",
      "name": "Inclusive language checker",
      "description": "Scan text for outdated or exclusionary terms and get neutral alternatives.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/inclusive-language-checker",
      "embed": "https://textarray.com/embed/inclusive-language-checker",
      "mode": "transform",
      "action": "Check language",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "gendered",
          "kind": "checkbox",
          "label": "Gendered terms",
          "default": true
        },
        {
          "key": "technical",
          "kind": "checkbox",
          "label": "Technical terminology (whitelist, master…)",
          "default": true
        },
        {
          "key": "healthAge",
          "kind": "checkbox",
          "label": "Health and age-related terms",
          "default": true
        },
        {
          "key": "strictness",
          "kind": "select",
          "label": "Strictness",
          "default": "moderate",
          "choices": [
            {
              "value": "lenient",
              "label": "Lenient — clear-cut terms only"
            },
            {
              "value": "moderate",
              "label": "Moderate"
            },
            {
              "value": "strict",
              "label": "Strict — include mild and contextual terms"
            }
          ]
        },
        {
          "key": "outputMode",
          "kind": "select",
          "label": "Output",
          "default": "findings",
          "choices": [
            {
              "value": "findings",
              "label": "List of findings with explanation"
            },
            {
              "value": "text",
              "label": "Marked-up text"
            }
          ]
        },
        {
          "key": "action",
          "kind": "select",
          "label": "In marked-up text, flagged terms are",
          "default": "highlight",
          "choices": [
            {
              "value": "highlight",
              "label": "Highlighted with a suggestion"
            },
            {
              "value": "replace",
              "label": "Replaced with the first suggestion"
            }
          ]
        },
        {
          "key": "ignoreCode",
          "kind": "checkbox",
          "label": "Ignore code blocks and inline code",
          "default": false
        },
        {
          "key": "ignoreQuotes",
          "kind": "checkbox",
          "label": "Ignore quoted lines",
          "default": false
        },
        {
          "key": "customPairs",
          "kind": "text",
          "label": "Custom terms (one per line: term=>replacement)",
          "default": ""
        }
      ],
      "keywords": [
        "inclusive language checker",
        "inclusive language",
        "bias language checker",
        "non-inclusive terms",
        "gender-neutral language",
        "allowlist blacklist replacement",
        "person-first language",
        "sensitivity reader"
      ],
      "updated": "2026-08-18"
    },
    {
      "slug": "chord-transposer",
      "name": "Chord transposer",
      "description": "Shift guitar chords in a song to a different key without changing the lyrics.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/chord-transposer",
      "embed": "https://textarray.com/embed/chord-transposer",
      "mode": "transform",
      "action": "Transpose chords",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Transpose by",
          "default": "semitones",
          "choices": [
            {
              "value": "semitones",
              "label": "Semitones"
            },
            {
              "value": "key",
              "label": "Target key"
            }
          ]
        },
        {
          "key": "semitones",
          "kind": "number",
          "label": "Semitones",
          "default": 0,
          "min": -11,
          "max": 11,
          "step": 1
        },
        {
          "key": "targetKey",
          "kind": "select",
          "label": "Target key",
          "default": "C",
          "choices": [
            {
              "value": "C",
              "label": "C"
            },
            {
              "value": "C#",
              "label": "C# / Db"
            },
            {
              "value": "D",
              "label": "D"
            },
            {
              "value": "D#",
              "label": "D# / Eb"
            },
            {
              "value": "E",
              "label": "E"
            },
            {
              "value": "F",
              "label": "F"
            },
            {
              "value": "F#",
              "label": "F# / Gb"
            },
            {
              "value": "G",
              "label": "G"
            },
            {
              "value": "G#",
              "label": "G# / Ab"
            },
            {
              "value": "A",
              "label": "A"
            },
            {
              "value": "A#",
              "label": "A# / Bb"
            },
            {
              "value": "B",
              "label": "B"
            }
          ]
        },
        {
          "key": "preferSharp",
          "kind": "checkbox",
          "label": "Prefer sharps (C#) over flats (Db)",
          "default": true
        },
        {
          "key": "inputNotation",
          "kind": "select",
          "label": "Input notation",
          "default": "english",
          "choices": [
            {
              "value": "english",
              "label": "English (B)"
            },
            {
              "value": "german",
              "label": "German (H)"
            }
          ]
        },
        {
          "key": "outputNotation",
          "kind": "select",
          "label": "Output notation",
          "default": "english",
          "choices": [
            {
              "value": "english",
              "label": "English (B)"
            },
            {
              "value": "german",
              "label": "German (H)"
            }
          ]
        },
        {
          "key": "wrapMode",
          "kind": "select",
          "label": "Chord placement",
          "default": "keep",
          "choices": [
            {
              "value": "keep",
              "label": "Keep original placement"
            },
            {
              "value": "brackets",
              "label": "Wrap in [brackets]"
            },
            {
              "value": "above",
              "label": "Move above the line"
            }
          ]
        },
        {
          "key": "listUsedChords",
          "kind": "checkbox",
          "label": "List chords used",
          "default": true
        }
      ],
      "keywords": [
        "chord transposer",
        "transpose chords",
        "guitar chord changer",
        "change key of song",
        "capo calculator",
        "chord chart transposer",
        "sharps and flats",
        "song key changer"
      ],
      "updated": "2026-08-18"
    },
    {
      "slug": "subtitle-generator",
      "name": "Subtitle generator",
      "description": "Turn a plain-text transcript into a timed SRT or VTT subtitle file.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/subtitle-generator",
      "embed": "https://textarray.com/embed/subtitle-generator",
      "mode": "transform",
      "action": "Generate subtitles",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "srt",
          "choices": [
            {
              "value": "srt",
              "label": "SRT (.srt)"
            },
            {
              "value": "vtt",
              "label": "WebVTT (.vtt)"
            }
          ]
        },
        {
          "key": "cps",
          "kind": "number",
          "label": "Reading speed (characters/second)",
          "default": 17,
          "min": 5,
          "max": 40,
          "step": 1
        },
        {
          "key": "maxLineChars",
          "kind": "number",
          "label": "Max characters per line",
          "default": 42,
          "min": 10,
          "max": 100,
          "step": 1
        },
        {
          "key": "maxLines",
          "kind": "number",
          "label": "Max lines per subtitle",
          "default": 2,
          "min": 1,
          "max": 4,
          "step": 1
        },
        {
          "key": "minDuration",
          "kind": "number",
          "label": "Minimum duration (seconds)",
          "default": 1.2,
          "min": 0.2,
          "max": 20,
          "step": 0.1
        },
        {
          "key": "maxDuration",
          "kind": "number",
          "label": "Maximum duration (seconds)",
          "default": 7,
          "min": 0.5,
          "max": 30,
          "step": 0.5
        },
        {
          "key": "gapSec",
          "kind": "number",
          "label": "Gap between subtitles (seconds)",
          "default": 0.12,
          "min": 0,
          "max": 5,
          "step": 0.05
        },
        {
          "key": "startTimeSec",
          "kind": "number",
          "label": "Start time (seconds)",
          "default": 0,
          "min": 0,
          "max": 86400,
          "step": 1
        },
        {
          "key": "shiftSec",
          "kind": "number",
          "label": "Time shift (seconds)",
          "default": 0,
          "min": -3600,
          "max": 3600,
          "step": 0.1
        },
        {
          "key": "splitOnSentences",
          "kind": "checkbox",
          "label": "Split at sentence boundaries",
          "default": true
        },
        {
          "key": "blankLineAsPause",
          "kind": "checkbox",
          "label": "Treat blank lines as pauses",
          "default": true
        },
        {
          "key": "numberSubtitles",
          "kind": "checkbox",
          "label": "Number subtitles",
          "default": true
        }
      ],
      "keywords": [
        "subtitle generator",
        "transcript to srt",
        "text to subtitles",
        "srt generator",
        "vtt generator",
        "auto subtitle timing",
        "subtitle maker",
        "closed captions from text",
        "srt",
        "vtt",
        "webvtt"
      ],
      "updated": "2026-08-18"
    },
    {
      "slug": "smpte-timecode-converter",
      "name": "SMPTE timecode converter",
      "description": "Convert between SMPTE timecode, frame numbers and seconds at any broadcast frame rate.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/smpte-timecode-converter",
      "embed": "https://textarray.com/embed/smpte-timecode-converter",
      "mode": "transform",
      "action": "Convert timecodes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "frameRate",
          "kind": "select",
          "label": "Frame rate",
          "default": "25",
          "choices": [
            {
              "value": "23.976",
              "label": "23.976 fps"
            },
            {
              "value": "24",
              "label": "24 fps"
            },
            {
              "value": "25",
              "label": "25 fps"
            },
            {
              "value": "29.97",
              "label": "29.97 fps"
            },
            {
              "value": "30",
              "label": "30 fps"
            },
            {
              "value": "50",
              "label": "50 fps"
            },
            {
              "value": "59.94",
              "label": "59.94 fps"
            },
            {
              "value": "60",
              "label": "60 fps"
            }
          ]
        },
        {
          "key": "dropFrame",
          "kind": "checkbox",
          "label": "Drop-frame notation",
          "default": false
        },
        {
          "key": "operation",
          "kind": "select",
          "label": "Operation",
          "default": "convert",
          "choices": [
            {
              "value": "convert",
              "label": "Convert format"
            },
            {
              "value": "shift",
              "label": "Shift by offset"
            },
            {
              "value": "rebase",
              "label": "Convert frame rate"
            }
          ]
        },
        {
          "key": "inputFormat",
          "kind": "select",
          "label": "Input format",
          "default": "timecode",
          "choices": [
            {
              "value": "timecode",
              "label": "Timecode (HH:MM:SS:FF)"
            },
            {
              "value": "frames",
              "label": "Frame number"
            },
            {
              "value": "seconds",
              "label": "Seconds"
            }
          ]
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "frames",
          "choices": [
            {
              "value": "timecode",
              "label": "Timecode (HH:MM:SS:FF)"
            },
            {
              "value": "frames",
              "label": "Frame number"
            },
            {
              "value": "seconds",
              "label": "Seconds"
            }
          ]
        },
        {
          "key": "offset",
          "kind": "text",
          "label": "Offset (±HH:MM:SS:FF, for \"Shift by offset\")",
          "default": "00:00:01:00"
        },
        {
          "key": "targetFrameRate",
          "kind": "select",
          "label": "Target frame rate (for \"Convert frame rate\")",
          "default": "30",
          "choices": [
            {
              "value": "23.976",
              "label": "23.976 fps"
            },
            {
              "value": "24",
              "label": "24 fps"
            },
            {
              "value": "25",
              "label": "25 fps"
            },
            {
              "value": "29.97",
              "label": "29.97 fps"
            },
            {
              "value": "30",
              "label": "30 fps"
            },
            {
              "value": "50",
              "label": "50 fps"
            },
            {
              "value": "59.94",
              "label": "59.94 fps"
            },
            {
              "value": "60",
              "label": "60 fps"
            }
          ]
        }
      ],
      "keywords": [
        "smpte timecode converter",
        "timecode to frames",
        "frames to timecode",
        "drop frame calculator",
        "non-drop frame timecode",
        "frame rate converter",
        "timecode offset",
        "fps",
        "29.97",
        "23.976"
      ],
      "updated": "2026-08-18"
    },
    {
      "slug": "recipe-scaler",
      "name": "Recipe scaler",
      "description": "Scale ingredient quantities in a recipe up or down for a different number of servings.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/recipe-scaler",
      "embed": "https://textarray.com/embed/recipe-scaler",
      "mode": "transform",
      "action": "Scale recipe",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "scaleMode",
          "kind": "select",
          "label": "Scale by",
          "default": "servings",
          "choices": [
            {
              "value": "servings",
              "label": "Servings"
            },
            {
              "value": "multiplier",
              "label": "Multiplier"
            }
          ]
        },
        {
          "key": "originalServings",
          "kind": "number",
          "label": "Original servings",
          "default": 4,
          "min": 1,
          "max": 1000,
          "step": 1
        },
        {
          "key": "targetServings",
          "kind": "number",
          "label": "Target servings",
          "default": 8,
          "min": 1,
          "max": 1000,
          "step": 1
        },
        {
          "key": "multiplier",
          "kind": "number",
          "label": "Multiplier",
          "default": 2,
          "min": 0.1,
          "max": 100,
          "step": 0.1
        },
        {
          "key": "rounding",
          "kind": "checkbox",
          "label": "Round to sensible values",
          "default": true
        },
        {
          "key": "fractionFormat",
          "kind": "select",
          "label": "Quantity format",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Match input"
            },
            {
              "value": "decimal",
              "label": "Decimal"
            },
            {
              "value": "fraction",
              "label": "Fraction"
            }
          ]
        },
        {
          "key": "unitSystem",
          "kind": "select",
          "label": "Unit system",
          "default": "keep",
          "choices": [
            {
              "value": "keep",
              "label": "Keep as written"
            },
            {
              "value": "metric",
              "label": "Convert to metric"
            },
            {
              "value": "imperial",
              "label": "Convert to imperial"
            }
          ]
        },
        {
          "key": "unifyUnits",
          "kind": "checkbox",
          "label": "Unify units (g instead of dkg)",
          "default": false
        }
      ],
      "keywords": [
        "recipe scaler",
        "recipe converter",
        "scale recipe",
        "ingredient calculator",
        "servings converter",
        "double a recipe",
        "halve a recipe",
        "cup to gram",
        "metric to imperial"
      ],
      "updated": "2026-08-18"
    },
    {
      "slug": "translation-qa-checker",
      "name": "Translation QA checker",
      "description": "Compare an original text with its translation and flag errors that are wrong in any language.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/translation-qa-checker",
      "embed": "https://textarray.com/embed/translation-qa-checker",
      "mode": "transform",
      "action": "Check translation",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Translation"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "select",
          "label": "Segment separator",
          "default": "line",
          "choices": [
            {
              "value": "line",
              "label": "Line"
            },
            {
              "value": "blank",
              "label": "Blank line"
            },
            {
              "value": "tab",
              "label": "Tab"
            }
          ]
        },
        {
          "key": "checkNumbers",
          "kind": "checkbox",
          "label": "Check numbers and units",
          "default": true
        },
        {
          "key": "checkPlaceholders",
          "kind": "checkbox",
          "label": "Check placeholders and variables",
          "default": true
        },
        {
          "key": "checkHtmlTags",
          "kind": "checkbox",
          "label": "Check HTML tags and their order",
          "default": true
        },
        {
          "key": "checkPunctuation",
          "kind": "checkbox",
          "label": "Check terminal punctuation and capitalization",
          "default": true
        },
        {
          "key": "checkUntranslated",
          "kind": "checkbox",
          "label": "Flag untranslated segments",
          "default": true
        },
        {
          "key": "checkEmptyAndSpaces",
          "kind": "checkbox",
          "label": "Flag empty segments and double spaces",
          "default": true
        }
      ],
      "keywords": [
        "translation qa checker",
        "translation quality assurance",
        "localization qa",
        "compare translation to original",
        "placeholder check",
        "html tag check",
        "i18n qa tool",
        "localization testing",
        "json",
        "html"
      ],
      "updated": "2026-08-18"
    },
    {
      "slug": "access-log-analyzer",
      "name": "Access log analyzer",
      "description": "Summarize Apache and Nginx access logs into top paths, status codes, IPs and browsers.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/access-log-analyzer",
      "embed": "https://textarray.com/embed/access-log-analyzer",
      "mode": "transform",
      "action": "Analyze log",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Log format",
          "default": "combined",
          "choices": [
            {
              "value": "common",
              "label": "Common log format"
            },
            {
              "value": "combined",
              "label": "Combined log format"
            },
            {
              "value": "custom",
              "label": "Custom pattern"
            }
          ]
        },
        {
          "key": "customPattern",
          "kind": "text",
          "label": "Custom pattern",
          "default": ""
        },
        {
          "key": "topN",
          "kind": "number",
          "label": "Items per ranking",
          "default": 5,
          "min": 1,
          "max": 50,
          "step": 1
        },
        {
          "key": "filterStatus",
          "kind": "text",
          "label": "Filter by status code",
          "default": ""
        },
        {
          "key": "filterPath",
          "kind": "text",
          "label": "Filter by path",
          "default": ""
        },
        {
          "key": "groupBy",
          "kind": "select",
          "label": "Group requests by",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "No grouping"
            },
            {
              "value": "hour",
              "label": "Hour"
            },
            {
              "value": "day",
              "label": "Day"
            }
          ]
        },
        {
          "key": "separateBots",
          "kind": "checkbox",
          "label": "Separate bots from human visitors",
          "default": true
        },
        {
          "key": "countBytes",
          "kind": "checkbox",
          "label": "Count bytes transferred",
          "default": true
        },
        {
          "key": "excludeStaticExtensions",
          "kind": "checkbox",
          "label": "Skip static files (css, js, images…)",
          "default": true
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output as",
          "default": "summary",
          "choices": [
            {
              "value": "summary",
              "label": "Summary"
            },
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "access log analyzer",
        "apache log parser",
        "nginx log parser",
        "log file analyzer",
        "combined log format",
        "common log format",
        "web server logs",
        "status code breakdown",
        "top requested paths",
        "log viewer online"
      ],
      "updated": "2026-08-19"
    },
    {
      "slug": "docker-run-to-compose",
      "name": "docker run to Compose",
      "description": "Convert a docker run command into a docker-compose.yml service, or the other way round.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/docker-run-to-compose",
      "embed": "https://textarray.com/embed/docker-run-to-compose",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "run-to-compose",
          "choices": [
            {
              "value": "run-to-compose",
              "label": "docker run → compose"
            },
            {
              "value": "compose-to-run",
              "label": "compose → docker run"
            }
          ]
        },
        {
          "key": "composeVersion",
          "kind": "select",
          "label": "Compose file format",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "No version key (Compose v2)"
            },
            {
              "value": "3.8",
              "label": "Version 3.8"
            },
            {
              "value": "3.9",
              "label": "Version 3.9"
            }
          ]
        },
        {
          "key": "envMode",
          "kind": "select",
          "label": "Environment variables",
          "default": "inline",
          "choices": [
            {
              "value": "inline",
              "label": "Inline in the service"
            },
            {
              "value": "env-file",
              "label": "Separate .env file"
            }
          ]
        },
        {
          "key": "preserveOrder",
          "kind": "checkbox",
          "label": "Preserve original flag order",
          "default": true
        }
      ],
      "keywords": [
        "docker run to compose",
        "docker compose generator",
        "docker run converter",
        "docker-compose.yml",
        "compose to docker run",
        "container",
        "yaml",
        "dockerfile"
      ],
      "updated": "2026-08-19"
    },
    {
      "slug": "package-json-inspector",
      "name": "package.json dependency overview",
      "description": "Split a package.json into production, dev, peer and optional dependencies with their version ranges.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/package-json-inspector",
      "embed": "https://textarray.com/embed/package-json-inspector",
      "mode": "transform",
      "action": "Inspect dependencies",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Order",
          "default": "type",
          "choices": [
            {
              "value": "type",
              "label": "By type"
            },
            {
              "value": "alphabetical",
              "label": "Alphabetical"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "list",
              "label": "List"
            },
            {
              "value": "markdown",
              "label": "Markdown"
            }
          ]
        },
        {
          "key": "showCounts",
          "kind": "checkbox",
          "label": "Show counts per group",
          "default": false
        },
        {
          "key": "explainRanges",
          "kind": "checkbox",
          "label": "Explain version ranges",
          "default": false
        },
        {
          "key": "flagPinned",
          "kind": "checkbox",
          "label": "Flag exact or wildcard versions",
          "default": false
        },
        {
          "key": "flagDuplicates",
          "kind": "checkbox",
          "label": "Flag packages listed twice",
          "default": false
        },
        {
          "key": "showEngines",
          "kind": "checkbox",
          "label": "Show engines and packageManager",
          "default": false
        }
      ],
      "keywords": [
        "package.json dependency overview",
        "package.json inspector",
        "npm dependency list",
        "dependencies vs devDependencies",
        "semver range explainer",
        "peer dependencies",
        "optional dependencies",
        "package.json",
        "json",
        "npm",
        "yarn",
        "pnpm"
      ],
      "updated": "2026-08-19"
    },
    {
      "slug": "github-actions-generator",
      "name": "GitHub Actions workflow generator",
      "description": "Assemble a ready-to-use GitHub Actions workflow file from your triggers, language and steps.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/github-actions-generator",
      "embed": "https://textarray.com/embed/github-actions-generator",
      "mode": "generate",
      "action": "Generate workflow",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "workflowName",
          "kind": "text",
          "label": "Workflow name",
          "default": "CI"
        },
        {
          "key": "triggerPush",
          "kind": "checkbox",
          "label": "Trigger on push",
          "default": true
        },
        {
          "key": "pushBranches",
          "kind": "text",
          "label": "Push branches",
          "default": "main"
        },
        {
          "key": "triggerPullRequest",
          "kind": "checkbox",
          "label": "Trigger on pull request",
          "default": true
        },
        {
          "key": "pullRequestBranches",
          "kind": "text",
          "label": "Pull request branches",
          "default": "main"
        },
        {
          "key": "paths",
          "kind": "text",
          "label": "Path filter (optional)",
          "default": ""
        },
        {
          "key": "triggerSchedule",
          "kind": "checkbox",
          "label": "Trigger on schedule",
          "default": false
        },
        {
          "key": "cronExpression",
          "kind": "text",
          "label": "Cron expression",
          "default": "0 0 * * *"
        },
        {
          "key": "triggerManual",
          "kind": "checkbox",
          "label": "Allow manual run",
          "default": true
        },
        {
          "key": "language",
          "kind": "select",
          "label": "Language",
          "default": "node",
          "choices": [
            {
              "value": "node",
              "label": "Node.js"
            },
            {
              "value": "python",
              "label": "Python"
            },
            {
              "value": "go",
              "label": "Go"
            },
            {
              "value": "rust",
              "label": "Rust"
            },
            {
              "value": "java",
              "label": "Java"
            },
            {
              "value": "generic",
              "label": "Generic (no setup step)"
            }
          ]
        },
        {
          "key": "versions",
          "kind": "text",
          "label": "Version matrix",
          "default": "20"
        },
        {
          "key": "os",
          "kind": "select",
          "label": "Operating system",
          "default": "ubuntu-latest",
          "choices": [
            {
              "value": "ubuntu-latest",
              "label": "Ubuntu"
            },
            {
              "value": "windows-latest",
              "label": "Windows"
            },
            {
              "value": "macos-latest",
              "label": "macOS"
            },
            {
              "value": "matrix",
              "label": "All three (matrix)"
            }
          ]
        },
        {
          "key": "packageManager",
          "kind": "select",
          "label": "Package manager (Node.js)",
          "default": "npm",
          "choices": [
            {
              "value": "npm",
              "label": "npm"
            },
            {
              "value": "yarn",
              "label": "Yarn"
            },
            {
              "value": "pnpm",
              "label": "pnpm"
            }
          ]
        },
        {
          "key": "cacheDependencies",
          "kind": "checkbox",
          "label": "Cache dependencies",
          "default": true
        },
        {
          "key": "runTests",
          "kind": "checkbox",
          "label": "Run tests",
          "default": true
        },
        {
          "key": "testCommand",
          "kind": "text",
          "label": "Test command (optional)",
          "default": ""
        },
        {
          "key": "runBuild",
          "kind": "checkbox",
          "label": "Run build",
          "default": false
        },
        {
          "key": "buildCommand",
          "kind": "text",
          "label": "Build command (optional)",
          "default": ""
        },
        {
          "key": "permissions",
          "kind": "select",
          "label": "Token permissions",
          "default": "read",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "read",
              "label": "Read contents"
            },
            {
              "value": "write",
              "label": "Write contents"
            }
          ]
        },
        {
          "key": "cancelInProgress",
          "kind": "checkbox",
          "label": "Cancel in-progress runs",
          "default": true
        },
        {
          "key": "uploadArtifact",
          "kind": "checkbox",
          "label": "Upload build artifact",
          "default": false
        },
        {
          "key": "artifactPath",
          "kind": "text",
          "label": "Artifact path",
          "default": "dist"
        }
      ],
      "keywords": [
        "github actions generator",
        "ci workflow generator",
        "github actions yaml",
        "workflow file generator",
        "ci/cd pipeline generator",
        "github workflow builder",
        "actions yml",
        "github actions",
        "yaml"
      ],
      "updated": "2026-08-19"
    },
    {
      "slug": "sql-to-prisma-schema",
      "name": "SQL CREATE TABLE to Prisma schema",
      "description": "Convert SQL CREATE TABLE statements into Prisma schema models.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sql-to-prisma-schema",
      "embed": "https://textarray.com/embed/sql-to-prisma-schema",
      "mode": "transform",
      "action": "Convert to Prisma schema",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "dialect",
          "kind": "select",
          "label": "Source database",
          "default": "postgresql",
          "choices": [
            {
              "value": "postgresql",
              "label": "PostgreSQL"
            },
            {
              "value": "mysql",
              "label": "MySQL"
            },
            {
              "value": "sqlite",
              "label": "SQLite"
            }
          ]
        },
        {
          "key": "singularPascalCase",
          "kind": "checkbox",
          "label": "Name models in singular PascalCase",
          "default": true
        },
        {
          "key": "camelCaseFields",
          "kind": "checkbox",
          "label": "Convert column names to camelCase",
          "default": true
        },
        {
          "key": "deriveRelations",
          "kind": "checkbox",
          "label": "Derive relations from foreign keys",
          "default": true
        },
        {
          "key": "includeIndexes",
          "kind": "checkbox",
          "label": "Include indexes and unique constraints",
          "default": true
        }
      ],
      "keywords": [
        "sql to prisma",
        "create table to prisma schema",
        "prisma schema generator",
        "prisma model from sql",
        "sql ddl to prisma",
        "convert mysql to prisma",
        "convert postgres to prisma",
        "prisma",
        "sql",
        "orm"
      ],
      "updated": "2026-08-19"
    },
    {
      "slug": "env-file-diff",
      "name": ".env file diff",
      "description": "Compare two .env files and list the variables that are missing or differ.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/env-file-diff",
      "embed": "https://textarray.com/embed/env-file-diff",
      "mode": "transform",
      "action": "Compare .env files",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "File B (.env)"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Result",
          "default": "diff",
          "choices": [
            {
              "value": "diff",
              "label": "Differences"
            },
            {
              "value": "merged",
              "label": "Merged .env file"
            },
            {
              "value": "template",
              "label": ".env.example template"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Diff format",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List"
            },
            {
              "value": "table",
              "label": "Table"
            }
          ]
        },
        {
          "key": "compareValues",
          "kind": "checkbox",
          "label": "Compare values, not just names",
          "default": true
        },
        {
          "key": "treatEmptyAsMissing",
          "kind": "checkbox",
          "label": "Treat empty values as missing",
          "default": false
        },
        {
          "key": "maskValues",
          "kind": "checkbox",
          "label": "Mask values in output",
          "default": false
        },
        {
          "key": "ignorePattern",
          "kind": "text",
          "label": "Ignore variables matching",
          "default": ""
        }
      ],
      "keywords": [
        ".env diff",
        "env file diff",
        "compare env files",
        "dotenv diff",
        "compare .env",
        "environment variables diff",
        "env file comparison",
        "diff two env files",
        "dotenv",
        "env"
      ],
      "updated": "2026-08-19"
    },
    {
      "slug": "gitignore-tester",
      "name": ".gitignore rule tester",
      "description": "Check which of your .gitignore rules ignores or allows each path, and why.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/gitignore-tester",
      "embed": "https://textarray.com/embed/gitignore-tester",
      "mode": "transform",
      "action": "Test paths",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Paths to test"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case-sensitive matching",
          "default": true
        },
        {
          "key": "showUnmatched",
          "kind": "checkbox",
          "label": "Show paths no rule caught",
          "default": true
        },
        {
          "key": "warnUnusedRules",
          "kind": "checkbox",
          "label": "Warn about rules that never match",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "lists",
              "label": "Two lists"
            }
          ]
        }
      ],
      "keywords": [
        "gitignore tester",
        "test gitignore rules",
        "gitignore pattern checker",
        "gitignore simulator",
        "check if file is ignored",
        "git ignore rules",
        "gitignore",
        "glob pattern"
      ],
      "updated": "2026-08-19"
    },
    {
      "slug": "kubernetes-manifest-inspector",
      "name": "Kubernetes manifest overview",
      "description": "Summarize the resources, images and settings in a Kubernetes YAML manifest.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/kubernetes-manifest-inspector",
      "embed": "https://textarray.com/embed/kubernetes-manifest-inspector",
      "mode": "transform",
      "action": "Inspect manifest",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "kindFilter",
          "kind": "text",
          "label": "Filter by kind",
          "default": ""
        },
        {
          "key": "namespaceFilter",
          "kind": "text",
          "label": "Filter by namespace",
          "default": ""
        },
        {
          "key": "showImages",
          "kind": "checkbox",
          "label": "Show container images and tags",
          "default": true
        },
        {
          "key": "showResources",
          "kind": "checkbox",
          "label": "Show resource requests and limits",
          "default": true
        },
        {
          "key": "showPortsVolumes",
          "kind": "checkbox",
          "label": "Show ports and volumes",
          "default": false
        },
        {
          "key": "showRefs",
          "kind": "checkbox",
          "label": "Show ConfigMap / Secret references",
          "default": false
        },
        {
          "key": "warnings",
          "kind": "checkbox",
          "label": "Warn about latest tags and missing limits",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output as",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "list",
              "label": "List"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "kubernetes manifest overview",
        "k8s yaml inspector",
        "kubernetes resource summary",
        "deployment container images",
        "kubernetes resource requests and limits",
        "k8s configmap secret references",
        "kubernetes",
        "yaml",
        "csv"
      ],
      "updated": "2026-08-19"
    },
    {
      "slug": "css-color-variables",
      "name": "CSS color variable extractor",
      "description": "Find every color in your CSS and turn it into reusable custom properties.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-color-variables",
      "embed": "https://textarray.com/embed/css-color-variables",
      "mode": "transform",
      "action": "Extract color variables",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "naming",
          "kind": "select",
          "label": "Variable names",
          "default": "order",
          "choices": [
            {
              "value": "order",
              "label": "By order"
            },
            {
              "value": "hue",
              "label": "By hue"
            },
            {
              "value": "usage",
              "label": "By property"
            }
          ]
        },
        {
          "key": "mergeEquivalent",
          "kind": "checkbox",
          "label": "Merge equal colors written differently (hex, rgb, hsl)",
          "default": true
        },
        {
          "key": "threshold",
          "kind": "range",
          "label": "Merge similar shades within",
          "default": 0,
          "min": 0,
          "max": 60
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Variable value notation",
          "default": "original",
          "choices": [
            {
              "value": "original",
              "label": "Keep original notation"
            },
            {
              "value": "hex",
              "label": "Hex"
            },
            {
              "value": "rgb",
              "label": "RGB"
            },
            {
              "value": "hsl",
              "label": "HSL"
            }
          ]
        },
        {
          "key": "selector",
          "kind": "text",
          "label": "Variable block selector",
          "default": ":root"
        },
        {
          "key": "listOnly",
          "kind": "checkbox",
          "label": "List colors only, don’t rewrite the CSS",
          "default": false
        }
      ],
      "keywords": [
        "css color variable extractor",
        "extract css colors",
        "css custom properties",
        "css color to variable",
        "root variables generator",
        "deduplicate css colors",
        "hex to css variable",
        "design tokens from css"
      ],
      "updated": "2026-08-19"
    },
    {
      "slug": "unused-css-finder",
      "name": "Unused CSS selector finder",
      "description": "Compare a stylesheet against a page of HTML and list the selectors that match nothing.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/unused-css-finder",
      "embed": "https://textarray.com/embed/unused-css-finder",
      "mode": "transform",
      "action": "Find unused selectors",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "HTML"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "ignorePseudo",
          "kind": "checkbox",
          "label": "Ignore pseudo-classes and pseudo-elements",
          "default": true
        },
        {
          "key": "ignorePattern",
          "kind": "text",
          "label": "Ignore selectors matching (regex)",
          "default": ""
        },
        {
          "key": "showInverse",
          "kind": "checkbox",
          "label": "Show HTML classes/IDs with no CSS rule",
          "default": false
        },
        {
          "key": "countOccurrences",
          "kind": "checkbox",
          "label": "Show match counts for used selectors",
          "default": false
        },
        {
          "key": "considerMediaQueries",
          "kind": "checkbox",
          "label": "Include selectors inside @media",
          "default": true
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output as",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "Unused selectors"
            },
            {
              "value": "css",
              "label": "Cleaned CSS"
            }
          ]
        }
      ],
      "keywords": [
        "unused css finder",
        "unused css selectors",
        "dead css finder",
        "remove unused css",
        "css audit tool",
        "css cleanup tool",
        "find unused selectors",
        "css",
        "html"
      ],
      "updated": "2026-08-19"
    },
    {
      "slug": "bibtex-to-citations",
      "name": "BibTeX to citations",
      "description": "Turn pasted BibTeX entries into a formatted, ready-to-paste reference list.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/bibtex-to-citations",
      "embed": "https://textarray.com/embed/bibtex-to-citations",
      "mode": "transform",
      "action": "Format citations",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Citation style",
          "default": "apa",
          "choices": [
            {
              "value": "apa",
              "label": "APA"
            },
            {
              "value": "mla",
              "label": "MLA"
            },
            {
              "value": "chicago",
              "label": "Chicago"
            },
            {
              "value": "iso690",
              "label": "ISO 690"
            }
          ]
        },
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Original order"
            },
            {
              "value": "author",
              "label": "Author"
            },
            {
              "value": "year",
              "label": "Year"
            }
          ]
        },
        {
          "key": "numbered",
          "kind": "checkbox",
          "label": "Number the list",
          "default": false
        },
        {
          "key": "initials",
          "kind": "checkbox",
          "label": "Abbreviate first names to initials",
          "default": false
        },
        {
          "key": "maxAuthors",
          "kind": "number",
          "label": "Max authors before \"et al.\" (0 = no limit)",
          "default": 0,
          "min": 0,
          "max": 20,
          "step": 1
        },
        {
          "key": "skipExtras",
          "kind": "checkbox",
          "label": "Omit abstract and keywords",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "text",
          "choices": [
            {
              "value": "text",
              "label": "Plain text"
            },
            {
              "value": "markdown",
              "label": "Markdown"
            },
            {
              "value": "html",
              "label": "HTML"
            }
          ]
        }
      ],
      "keywords": [
        "bibtex to citations",
        "bibtex converter",
        "reference list generator",
        "bibliography generator",
        "apa citation generator",
        "mla citation generator",
        "chicago style citation",
        "iso 690 citation",
        "bibtex parser",
        "latex bibliography",
        "bibtex",
        "apa",
        "mla",
        "markdown",
        "html"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "outline-numbering",
      "name": "Multi-level outline numbering",
      "description": "Add hierarchical numbers like 1, 1.1 and 1.2 to an indented outline.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/outline-numbering",
      "embed": "https://textarray.com/embed/outline-numbering",
      "mode": "transform",
      "action": "Number outline",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Numbering style",
          "default": "arabic",
          "choices": [
            {
              "value": "arabic",
              "label": "Arabic at every level (1.2.3)"
            },
            {
              "value": "alpha",
              "label": "Lowercase letters (a.b.c)"
            },
            {
              "value": "roman",
              "label": "Roman numerals (i.ii.iii)"
            },
            {
              "value": "mixed",
              "label": "Mixed: digits, letters, roman (1.a.i)"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "text",
          "label": "Separator between levels",
          "default": "."
        },
        {
          "key": "trailingDot",
          "kind": "checkbox",
          "label": "Period after the number",
          "default": true
        },
        {
          "key": "startNumber",
          "kind": "number",
          "label": "Starting number",
          "default": 1,
          "min": 0,
          "max": 999,
          "step": 1
        },
        {
          "key": "indentSize",
          "kind": "number",
          "label": "Spaces per indent level",
          "default": 2,
          "min": 1,
          "max": 12,
          "step": 1
        },
        {
          "key": "renumber",
          "kind": "checkbox",
          "label": "Renumber existing numbers",
          "default": true
        },
        {
          "key": "keepEmptyLines",
          "kind": "checkbox",
          "label": "Keep empty lines",
          "default": true
        },
        {
          "key": "reverse",
          "kind": "checkbox",
          "label": "Remove numbering instead",
          "default": false
        }
      ],
      "keywords": [
        "outline numbering",
        "multilevel list",
        "numbered outline",
        "legal numbering",
        "multi-level numbering",
        "renumber list",
        "outline numbers generator",
        "numbered headings"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "split-by-heading",
      "name": "Split document by headings",
      "description": "Break a document into separate parts, starting a new one at every heading of the level you pick.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/split-by-heading",
      "embed": "https://textarray.com/embed/split-by-heading",
      "mode": "transform",
      "action": "Split document",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "level",
          "kind": "select",
          "label": "Split at heading level",
          "default": "2",
          "choices": [
            {
              "value": "1",
              "label": "Level 1"
            },
            {
              "value": "2",
              "label": "Level 2"
            },
            {
              "value": "3",
              "label": "Level 3"
            },
            {
              "value": "4",
              "label": "Level 4"
            },
            {
              "value": "5",
              "label": "Level 5"
            },
            {
              "value": "6",
              "label": "Level 6"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Heading format",
          "default": "markdown",
          "choices": [
            {
              "value": "markdown",
              "label": "Markdown (#, ##, …)"
            },
            {
              "value": "underlined",
              "label": "Underlined (===, ---)"
            },
            {
              "value": "uppercase",
              "label": "Uppercase line"
            },
            {
              "value": "numbered",
              "label": "Numbered (1., 1.1)"
            }
          ]
        },
        {
          "key": "headingPlacement",
          "kind": "select",
          "label": "Heading in each part",
          "default": "keep",
          "choices": [
            {
              "value": "keep",
              "label": "Keep original heading"
            },
            {
              "value": "title",
              "label": "Show as plain title"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "text",
          "label": "Separator between parts",
          "default": "\n\n---\n\n"
        },
        {
          "key": "numberSections",
          "kind": "checkbox",
          "label": "Number each part",
          "default": false
        },
        {
          "key": "wordCount",
          "kind": "checkbox",
          "label": "Show word count per part",
          "default": false
        },
        {
          "key": "skipEmpty",
          "kind": "checkbox",
          "label": "Skip empty parts",
          "default": false
        },
        {
          "key": "maxLength",
          "kind": "number",
          "label": "Max part length in characters (0 = no limit)",
          "default": 0,
          "min": 0,
          "max": 20000,
          "step": 100
        },
        {
          "key": "outputMode",
          "kind": "select",
          "label": "Output as",
          "default": "blocks",
          "choices": [
            {
              "value": "blocks",
              "label": "Separate blocks"
            },
            {
              "value": "list",
              "label": "List of titles with lengths"
            }
          ]
        }
      ],
      "keywords": [
        "split by heading",
        "split document by headings",
        "break document into sections",
        "markdown splitter",
        "heading splitter",
        "split markdown into sections",
        "divide text by heading",
        "markdown"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "geohash-converter",
      "name": "Geohash encoder and decoder",
      "description": "Convert latitude/longitude coordinates to a geohash string, or a geohash back to coordinates.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/geohash-converter",
      "embed": "https://textarray.com/embed/geohash-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "encode",
              "label": "Coordinates → geohash"
            },
            {
              "value": "decode",
              "label": "Geohash → coordinates"
            }
          ]
        },
        {
          "key": "precision",
          "kind": "number",
          "label": "Geohash length",
          "default": 9,
          "min": 1,
          "max": 12
        },
        {
          "key": "bbox",
          "kind": "checkbox",
          "label": "Show bounding box",
          "default": false
        },
        {
          "key": "neighbors",
          "kind": "checkbox",
          "label": "Show neighboring geohashes",
          "default": false
        },
        {
          "key": "commonPrefix",
          "kind": "checkbox",
          "label": "Show common prefix for the group",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "geohash",
        "geohash encoder",
        "geohash decoder",
        "geohash to coordinates",
        "coordinates to geohash",
        "latitude longitude geohash",
        "geohash bounding box",
        "geohash neighbors",
        "gps",
        "base32",
        "csv"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "date-sequence-generator",
      "name": "Date sequence generator",
      "description": "Generate a list of dates between two dates at a fixed step.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/date-sequence-generator",
      "embed": "https://textarray.com/embed/date-sequence-generator",
      "mode": "generate",
      "action": "Generate dates",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "start",
          "kind": "text",
          "label": "Start date",
          "default": "2026-01-01"
        },
        {
          "key": "end",
          "kind": "text",
          "label": "End date",
          "default": "2026-01-31"
        },
        {
          "key": "stepUnit",
          "kind": "select",
          "label": "Step",
          "default": "day",
          "choices": [
            {
              "value": "day",
              "label": "Day"
            },
            {
              "value": "week",
              "label": "Week"
            },
            {
              "value": "month",
              "label": "Month"
            },
            {
              "value": "year",
              "label": "Year"
            }
          ]
        },
        {
          "key": "stepAmount",
          "kind": "number",
          "label": "Every N steps",
          "default": 1,
          "min": 1,
          "max": 1000
        },
        {
          "key": "weekendMode",
          "kind": "select",
          "label": "Weekends",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "Include weekends"
            },
            {
              "value": "skip",
              "label": "Skip weekends"
            },
            {
              "value": "only",
              "label": "Only weekends"
            }
          ]
        },
        {
          "key": "weekdaysOnly",
          "kind": "text",
          "label": "Only these weekdays",
          "default": ""
        },
        {
          "key": "holidays",
          "kind": "text",
          "label": "Skip these dates",
          "default": ""
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Format",
          "default": "iso",
          "choices": [
            {
              "value": "iso",
              "label": "ISO 8601 (YYYY-MM-DD)"
            },
            {
              "value": "local",
              "label": "Local format"
            },
            {
              "value": "custom",
              "label": "Custom mask"
            }
          ]
        },
        {
          "key": "customFormat",
          "kind": "text",
          "label": "Custom mask",
          "default": "DD.MM.YYYY"
        },
        {
          "key": "includeDayName",
          "kind": "checkbox",
          "label": "Add weekday name",
          "default": false
        },
        {
          "key": "includeWeekNumber",
          "kind": "checkbox",
          "label": "Add week number",
          "default": false
        },
        {
          "key": "limit",
          "kind": "number",
          "label": "Limit results (0 = no limit)",
          "default": 0,
          "min": 0,
          "max": 100000
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output as",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List"
            },
            {
              "value": "csv",
              "label": "CSV"
            },
            {
              "value": "table",
              "label": "Table rows (tab-separated)"
            }
          ]
        }
      ],
      "keywords": [
        "date sequence generator",
        "date range generator",
        "generate list of dates",
        "recurring dates generator",
        "date series",
        "date list csv",
        "iso 8601 dates",
        "weekly monthly yearly dates"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "fuzzy-list-match",
      "name": "Fuzzy list match",
      "description": "Pair up items from two lists even when they differ by typos, spacing, or accents.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/fuzzy-list-match",
      "embed": "https://textarray.com/embed/fuzzy-list-match",
      "mode": "transform",
      "action": "Match lists",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "List B"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "threshold",
          "kind": "range",
          "label": "Similarity threshold",
          "default": 70,
          "min": 0,
          "max": 100
        },
        {
          "key": "metric",
          "kind": "select",
          "label": "Metric",
          "default": "levenshtein",
          "choices": [
            {
              "value": "levenshtein",
              "label": "Levenshtein distance"
            },
            {
              "value": "trigram",
              "label": "Character-trigram similarity"
            }
          ]
        },
        {
          "key": "ignoreDiacritics",
          "kind": "checkbox",
          "label": "Ignore diacritics",
          "default": true
        },
        {
          "key": "ignoreCase",
          "kind": "checkbox",
          "label": "Ignore case",
          "default": true
        },
        {
          "key": "ignorePunctuation",
          "kind": "checkbox",
          "label": "Ignore punctuation",
          "default": false
        },
        {
          "key": "normalizeWordOrder",
          "kind": "checkbox",
          "label": "Normalize word order",
          "default": false
        },
        {
          "key": "showUnmatched",
          "kind": "checkbox",
          "label": "Show unmatched items",
          "default": true
        },
        {
          "key": "uniqueMatch",
          "kind": "checkbox",
          "label": "Match each item at most once",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "pairs",
          "choices": [
            {
              "value": "pairs",
              "label": "Pairs"
            },
            {
              "value": "csv",
              "label": "CSV with score"
            }
          ]
        }
      ],
      "keywords": [
        "fuzzy list match",
        "fuzzy matching",
        "match two lists",
        "approximate string matching",
        "typo tolerant matching",
        "record linkage",
        "deduplicate similar entries",
        "levenshtein",
        "csv"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "csv-splitter",
      "name": "CSV splitter by column",
      "description": "Split a CSV into separate tables grouped by the value of one column.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/csv-splitter",
      "embed": "https://textarray.com/embed/csv-splitter",
      "mode": "transform",
      "action": "Split CSV",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "column",
          "kind": "text",
          "label": "Column to split by",
          "default": "1"
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Input delimiter",
          "default": ",",
          "choices": [
            {
              "value": ",",
              "label": "Comma (,)"
            },
            {
              "value": ";",
              "label": "Semicolon (;)"
            },
            {
              "value": "\t",
              "label": "Tab"
            },
            {
              "value": "|",
              "label": "Pipe (|)"
            }
          ]
        },
        {
          "key": "repeatHeader",
          "kind": "checkbox",
          "label": "Repeat header in every part",
          "default": true
        },
        {
          "key": "keepColumn",
          "kind": "checkbox",
          "label": "Keep the split column in the output",
          "default": true
        },
        {
          "key": "showHeading",
          "kind": "checkbox",
          "label": "Show a heading with value and row count",
          "default": true
        },
        {
          "key": "order",
          "kind": "select",
          "label": "Order parts by",
          "default": "appearance",
          "choices": [
            {
              "value": "appearance",
              "label": "First appearance"
            },
            {
              "value": "value",
              "label": "Value (A–Z)"
            },
            {
              "value": "count",
              "label": "Row count (most first)"
            }
          ]
        },
        {
          "key": "mergeThreshold",
          "kind": "number",
          "label": "Merge groups smaller than",
          "default": 0,
          "min": 0,
          "step": 1
        },
        {
          "key": "partSeparator",
          "kind": "text",
          "label": "Separator between parts",
          "default": ""
        }
      ],
      "keywords": [
        "csv splitter",
        "split csv by column",
        "split csv into files",
        "csv by category",
        "group csv rows",
        "divide csv",
        "csv"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "csv-merger",
      "name": "CSV merger",
      "description": "Stack several CSV tables into one, reconciling different or reordered columns.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/csv-merger",
      "embed": "https://textarray.com/embed/csv-merger",
      "mode": "transform",
      "action": "Merge CSV",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "tableSeparator",
          "kind": "text",
          "label": "Separator between input tables",
          "default": ""
        },
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Input delimiter",
          "default": ",",
          "choices": [
            {
              "value": ",",
              "label": "Comma (,)"
            },
            {
              "value": ";",
              "label": "Semicolon (;)"
            },
            {
              "value": "\t",
              "label": "Tab"
            },
            {
              "value": "|",
              "label": "Pipe (|)"
            }
          ]
        },
        {
          "key": "outDelimiter",
          "kind": "select",
          "label": "Output delimiter",
          "default": "",
          "choices": [
            {
              "value": "",
              "label": "Same as input"
            },
            {
              "value": ",",
              "label": "Comma (,)"
            },
            {
              "value": ";",
              "label": "Semicolon (;)"
            },
            {
              "value": "\t",
              "label": "Tab"
            },
            {
              "value": "|",
              "label": "Pipe (|)"
            }
          ]
        },
        {
          "key": "columns",
          "kind": "select",
          "label": "Columns to keep",
          "default": "union",
          "choices": [
            {
              "value": "union",
              "label": "All columns from every table"
            },
            {
              "value": "intersection",
              "label": "Only columns shared by all tables"
            }
          ]
        },
        {
          "key": "looseHeaders",
          "kind": "checkbox",
          "label": "Match header names ignoring case and spaces",
          "default": true
        },
        {
          "key": "fill",
          "kind": "text",
          "label": "Fill missing cells with",
          "default": ""
        },
        {
          "key": "addSource",
          "kind": "checkbox",
          "label": "Add a source table column",
          "default": false
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicate rows after merging",
          "default": false
        },
        {
          "key": "order",
          "kind": "select",
          "label": "Column order",
          "default": "first",
          "choices": [
            {
              "value": "first",
              "label": "First table, then new columns"
            },
            {
              "value": "alpha",
              "label": "Alphabetical (A–Z)"
            }
          ]
        }
      ],
      "keywords": [
        "csv merger",
        "merge csv files",
        "combine csv tables",
        "concatenate csv",
        "stack csv rows",
        "union csv columns",
        "csv"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "ab-test-calculator",
      "name": "A/B test significance calculator",
      "description": "Calculate conversion rates, lift and statistical significance across A/B test variants.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/ab-test-calculator",
      "embed": "https://textarray.com/embed/ab-test-calculator",
      "mode": "transform",
      "action": "Calculate significance",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "confidenceLevel",
          "kind": "select",
          "label": "Confidence level",
          "default": "95",
          "choices": [
            {
              "value": "90",
              "label": "90%"
            },
            {
              "value": "95",
              "label": "95%"
            },
            {
              "value": "99",
              "label": "99%"
            }
          ]
        },
        {
          "key": "tailed",
          "kind": "select",
          "label": "Test type",
          "default": "two",
          "choices": [
            {
              "value": "two",
              "label": "Two-tailed"
            },
            {
              "value": "one",
              "label": "One-tailed"
            }
          ]
        },
        {
          "key": "showCI",
          "kind": "checkbox",
          "label": "Show confidence interval",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "sentence",
              "label": "Sentence"
            }
          ]
        }
      ],
      "keywords": [
        "ab test calculator",
        "a/b test significance",
        "split test calculator",
        "conversion rate calculator",
        "statistical significance test",
        "two-proportion z-test",
        "confidence interval calculator",
        "p-value calculator"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "vat-calculator",
      "name": "VAT calculator",
      "description": "Calculate the net, VAT and gross amount for a whole list of prices at once.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/vat-calculator",
      "embed": "https://textarray.com/embed/vat-calculator",
      "mode": "transform",
      "action": "Calculate VAT",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "ratePreset",
          "kind": "select",
          "label": "VAT rate",
          "default": "20",
          "choices": [
            {
              "value": "19",
              "label": "19%"
            },
            {
              "value": "20",
              "label": "20%"
            },
            {
              "value": "21",
              "label": "21%"
            },
            {
              "value": "23",
              "label": "23%"
            },
            {
              "value": "25",
              "label": "25%"
            },
            {
              "value": "27",
              "label": "27%"
            },
            {
              "value": "custom",
              "label": "Custom rate"
            }
          ]
        },
        {
          "key": "rate",
          "kind": "number",
          "label": "Custom rate (%)",
          "default": 20,
          "min": 0,
          "max": 100,
          "step": 0.01
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "add",
          "choices": [
            {
              "value": "add",
              "label": "Add VAT to net amount"
            },
            {
              "value": "extract",
              "label": "Extract VAT from gross amount"
            }
          ]
        },
        {
          "key": "roundCents",
          "kind": "checkbox",
          "label": "Round to cents",
          "default": true
        },
        {
          "key": "roundMode",
          "kind": "select",
          "label": "Rounding",
          "default": "nearest",
          "choices": [
            {
              "value": "nearest",
              "label": "Nearest cent"
            },
            {
              "value": "up",
              "label": "Round up"
            },
            {
              "value": "down",
              "label": "Round down"
            }
          ]
        },
        {
          "key": "currency",
          "kind": "select",
          "label": "Currency",
          "default": "EUR",
          "choices": [
            {
              "value": "EUR",
              "label": "EUR — Euro"
            },
            {
              "value": "USD",
              "label": "USD — US dollar"
            },
            {
              "value": "GBP",
              "label": "GBP — British pound"
            },
            {
              "value": "CZK",
              "label": "CZK — Czech koruna"
            },
            {
              "value": "PLN",
              "label": "PLN — Polish złoty"
            },
            {
              "value": "HUF",
              "label": "HUF — Hungarian forint"
            },
            {
              "value": "CHF",
              "label": "CHF — Swiss franc"
            },
            {
              "value": "RON",
              "label": "RON — Romanian leu"
            }
          ]
        },
        {
          "key": "csvColumn",
          "kind": "number",
          "label": "CSV column (0 = one amount per line)",
          "default": 0,
          "min": 0,
          "max": 50,
          "step": 1
        },
        {
          "key": "showTotals",
          "kind": "checkbox",
          "label": "Add totals row",
          "default": true
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "vat calculator",
        "vat",
        "value added tax",
        "sales tax calculator",
        "add tax",
        "remove tax",
        "net to gross",
        "gross to net",
        "tax rate",
        "csv",
        "invoice"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "loan-payment-calculator",
      "name": "Loan payment calculator",
      "description": "Calculate the monthly payment and full amortization schedule for a loan.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/loan-payment-calculator",
      "embed": "https://textarray.com/embed/loan-payment-calculator",
      "mode": "transform",
      "action": "Calculate payments",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "frequency",
          "kind": "select",
          "label": "Payment frequency",
          "default": "monthly",
          "choices": [
            {
              "value": "monthly",
              "label": "Monthly"
            },
            {
              "value": "quarterly",
              "label": "Quarterly"
            },
            {
              "value": "annually",
              "label": "Annually"
            }
          ]
        },
        {
          "key": "method",
          "kind": "select",
          "label": "Repayment method",
          "default": "annuity",
          "choices": [
            {
              "value": "annuity",
              "label": "Annuity (equal payments)"
            },
            {
              "value": "equal-principal",
              "label": "Equal principal"
            }
          ]
        },
        {
          "key": "extraPayment",
          "kind": "number",
          "label": "Extra payment per period",
          "default": 0,
          "min": 0,
          "step": 10
        },
        {
          "key": "summaryOnly",
          "kind": "checkbox",
          "label": "Summary only (hide the schedule)",
          "default": false
        },
        {
          "key": "annualTotals",
          "kind": "checkbox",
          "label": "Show yearly totals instead of every payment",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Schedule format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "loan payment calculator",
        "amortization schedule",
        "mortgage calculator",
        "monthly payment calculator",
        "loan repayment schedule",
        "interest calculator",
        "extra payment calculator",
        "annuity calculator"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "weighted-average-calculator",
      "name": "Weighted average calculator",
      "description": "Calculate a weighted average from a list of values and their weights.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/weighted-average-calculator",
      "embed": "https://textarray.com/embed/weighted-average-calculator",
      "mode": "transform",
      "action": "Calculate weighted average",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "pairSeparator",
          "kind": "select",
          "label": "Value/weight separator",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "comma",
              "label": "Comma (,)"
            },
            {
              "value": "semicolon",
              "label": "Semicolon (;)"
            },
            {
              "value": "colon",
              "label": "Colon (:)"
            },
            {
              "value": "space",
              "label": "Space or tab"
            }
          ]
        },
        {
          "key": "missingWeight",
          "kind": "select",
          "label": "Line with no weight",
          "default": "one",
          "choices": [
            {
              "value": "one",
              "label": "Use weight 1"
            },
            {
              "value": "skip",
              "label": "Skip the line"
            }
          ]
        },
        {
          "key": "invertScale",
          "kind": "checkbox",
          "label": "Lower value is better (invert scale)",
          "default": false
        },
        {
          "key": "normalizeWeights",
          "kind": "checkbox",
          "label": "Show weights normalized to 100%",
          "default": false
        },
        {
          "key": "showContribution",
          "kind": "checkbox",
          "label": "Show each item's contribution",
          "default": false
        },
        {
          "key": "showStats",
          "kind": "checkbox",
          "label": "Also show average, median and sum of weights",
          "default": false
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 2,
          "min": 0,
          "max": 10,
          "step": 1
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output as",
          "default": "breakdown",
          "choices": [
            {
              "value": "breakdown",
              "label": "Result with breakdown"
            },
            {
              "value": "table",
              "label": "Table"
            }
          ]
        }
      ],
      "keywords": [
        "weighted average calculator",
        "weighted mean",
        "grade calculator",
        "gpa calculator",
        "weighted score",
        "average by weight",
        "credits weighted average"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "bill-splitter",
      "name": "Bill splitter",
      "description": "Work out who owes who from a shared list of expenses, with as few transfers as possible.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/bill-splitter",
      "embed": "https://textarray.com/embed/bill-splitter",
      "mode": "transform",
      "action": "Split the bill",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "splitMode",
          "kind": "select",
          "label": "Split",
          "default": "equal",
          "choices": [
            {
              "value": "equal",
              "label": "Equal split"
            },
            {
              "value": "shares",
              "label": "By shares (weights)"
            }
          ]
        },
        {
          "key": "currency",
          "kind": "text",
          "label": "Currency",
          "default": ""
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Round to decimals",
          "default": 2,
          "min": 0,
          "max": 4,
          "step": 1
        },
        {
          "key": "feePercent",
          "kind": "number",
          "label": "Tip or fee (%)",
          "default": 0,
          "min": 0,
          "max": 100,
          "step": 0.5
        },
        {
          "key": "minimizeTransfers",
          "kind": "checkbox",
          "label": "Minimize number of transfers",
          "default": true
        },
        {
          "key": "showBalances",
          "kind": "checkbox",
          "label": "Show balances before settling",
          "default": true
        }
      ],
      "keywords": [
        "bill splitter",
        "split the bill",
        "split expenses",
        "expense splitter",
        "who owes who calculator",
        "group expense calculator",
        "settle up calculator",
        "shared expenses calculator",
        "divide bill between friends"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "css-inliner",
      "name": "CSS inliner for email",
      "description": "Move CSS from a style block into inline style attributes so it survives in email clients.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-inliner",
      "embed": "https://textarray.com/embed/css-inliner",
      "mode": "transform",
      "action": "Inline CSS",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "stripStyleBlock",
          "kind": "checkbox",
          "label": "Remove original <style> block",
          "default": true
        },
        {
          "key": "keepUnsupported",
          "kind": "checkbox",
          "label": "Keep rules that can't be inlined",
          "default": true
        },
        {
          "key": "respectSpecificity",
          "kind": "checkbox",
          "label": "Respect selector specificity",
          "default": true
        },
        {
          "key": "addLegacyAttributes",
          "kind": "checkbox",
          "label": "Add legacy width/bgcolor attributes",
          "default": false
        },
        {
          "key": "removeUnusedAttrs",
          "kind": "checkbox",
          "label": "Remove unused classes and IDs",
          "default": false
        },
        {
          "key": "minify",
          "kind": "checkbox",
          "label": "Minify output",
          "default": false
        },
        {
          "key": "showWarnings",
          "kind": "checkbox",
          "label": "Show unsupported-property warnings",
          "default": true
        }
      ],
      "keywords": [
        "css inliner",
        "inline css for email",
        "style to inline style",
        "email css inliner",
        "html email css",
        "inline stylesheet",
        "email template css",
        "juice css inliner"
      ],
      "updated": "2026-08-20"
    },
    {
      "slug": "text-sparkline",
      "name": "Text sparkline",
      "description": "Draw a miniature character bar chart from a list of numbers.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/text-sparkline",
      "embed": "https://textarray.com/embed/text-sparkline",
      "mode": "transform",
      "action": "Draw sparkline",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "charset",
          "kind": "select",
          "label": "Character set",
          "default": "blocks",
          "choices": [
            {
              "value": "blocks",
              "label": "Blocks ▁▂▃"
            },
            {
              "value": "dots",
              "label": "Dots ·◑●"
            },
            {
              "value": "ascii",
              "label": "ASCII .+@"
            }
          ]
        },
        {
          "key": "levels",
          "kind": "number",
          "label": "Levels",
          "default": 8,
          "min": 2,
          "max": 8,
          "step": 1
        },
        {
          "key": "scaleFromZero",
          "kind": "checkbox",
          "label": "Scale from zero",
          "default": false
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Value separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Spaces"
            },
            {
              "value": "comma",
              "label": "Commas"
            },
            {
              "value": "newline",
              "label": "New lines"
            }
          ]
        },
        {
          "key": "showStats",
          "kind": "checkbox",
          "label": "Show min / max / average",
          "default": false
        },
        {
          "key": "showTrend",
          "kind": "checkbox",
          "label": "Show trend arrow",
          "default": false
        },
        {
          "key": "maxLength",
          "kind": "number",
          "label": "Max length (0 = unlimited)",
          "default": 0,
          "min": 0,
          "max": 200,
          "step": 1
        }
      ],
      "keywords": [
        "text sparkline",
        "ascii sparkline",
        "sparkline generator",
        "text bar chart",
        "unicode bar chart",
        "number to chart",
        "inline chart maker",
        "block chart text",
        "ascii chart"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "vin-decoder",
      "name": "VIN decoder",
      "description": "Decode a vehicle identification number into its country, manufacturer, model year and check digit.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/vin-decoder",
      "embed": "https://textarray.com/embed/vin-decoder",
      "mode": "transform",
      "action": "Decode VIN",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "checkDigit",
          "kind": "checkbox",
          "label": "Verify check digit",
          "default": true
        },
        {
          "key": "explainPositions",
          "kind": "checkbox",
          "label": "Explain every position",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "breakdown",
          "choices": [
            {
              "value": "breakdown",
              "label": "Breakdown"
            },
            {
              "value": "table",
              "label": "Table"
            }
          ]
        }
      ],
      "keywords": [
        "vin decoder",
        "vin number lookup",
        "vin check digit",
        "vehicle identification number",
        "decode vin",
        "vin validator",
        "wmi lookup",
        "model year decoder"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "campaign-cost-calculator",
      "name": "Campaign cost calculator",
      "description": "Turn a list of ad campaigns into CPC, CPM, CTR, CPA, conversion rate, ROAS and margin, computed instantly in your browser.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/campaign-cost-calculator",
      "embed": "https://textarray.com/embed/campaign-cost-calculator",
      "mode": "transform",
      "action": "Calculate campaign costs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Input separator",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        },
        {
          "key": "currency",
          "kind": "select",
          "label": "Currency",
          "default": "usd",
          "choices": [
            {
              "value": "usd",
              "label": "$ USD"
            },
            {
              "value": "eur",
              "label": "€ EUR"
            },
            {
              "value": "gbp",
              "label": "£ GBP"
            },
            {
              "value": "none",
              "label": "No symbol"
            }
          ]
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 2,
          "min": 0,
          "max": 4,
          "step": 1
        },
        {
          "key": "includeRevenue",
          "kind": "checkbox",
          "label": "Parse revenue (6th column) for ROAS and margin",
          "default": false
        },
        {
          "key": "showCPC",
          "kind": "checkbox",
          "label": "Show CPC (cost per click)",
          "default": true
        },
        {
          "key": "showCPM",
          "kind": "checkbox",
          "label": "Show CPM (cost per 1,000 impressions)",
          "default": true
        },
        {
          "key": "showCTR",
          "kind": "checkbox",
          "label": "Show CTR (click-through rate)",
          "default": true
        },
        {
          "key": "showCPA",
          "kind": "checkbox",
          "label": "Show CPA (cost per acquisition)",
          "default": true
        },
        {
          "key": "showConvRate",
          "kind": "checkbox",
          "label": "Show conversion rate",
          "default": true
        },
        {
          "key": "showROAS",
          "kind": "checkbox",
          "label": "Show ROAS (needs revenue)",
          "default": false
        },
        {
          "key": "showMargin",
          "kind": "checkbox",
          "label": "Show margin (needs revenue)",
          "default": false
        },
        {
          "key": "includeTotal",
          "kind": "checkbox",
          "label": "Add a totals row for all campaigns",
          "default": true
        },
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Input order"
            },
            {
              "value": "cost",
              "label": "Cost"
            },
            {
              "value": "impressions",
              "label": "Impressions"
            },
            {
              "value": "clicks",
              "label": "Clicks"
            },
            {
              "value": "conversions",
              "label": "Conversions"
            },
            {
              "value": "cpc",
              "label": "CPC"
            },
            {
              "value": "cpm",
              "label": "CPM"
            },
            {
              "value": "ctr",
              "label": "CTR"
            },
            {
              "value": "cpa",
              "label": "CPA"
            },
            {
              "value": "convRate",
              "label": "Conversion rate"
            },
            {
              "value": "roas",
              "label": "ROAS"
            },
            {
              "value": "margin",
              "label": "Margin"
            }
          ]
        },
        {
          "key": "flagMetric",
          "kind": "select",
          "label": "Flag campaigns by",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Don't flag"
            },
            {
              "value": "cost",
              "label": "Cost"
            },
            {
              "value": "impressions",
              "label": "Impressions"
            },
            {
              "value": "clicks",
              "label": "Clicks"
            },
            {
              "value": "conversions",
              "label": "Conversions"
            },
            {
              "value": "cpc",
              "label": "CPC"
            },
            {
              "value": "cpm",
              "label": "CPM"
            },
            {
              "value": "ctr",
              "label": "CTR"
            },
            {
              "value": "cpa",
              "label": "CPA"
            },
            {
              "value": "convRate",
              "label": "Conversion rate"
            },
            {
              "value": "roas",
              "label": "ROAS"
            },
            {
              "value": "margin",
              "label": "Margin"
            }
          ]
        },
        {
          "key": "flagMode",
          "kind": "select",
          "label": "Flag when",
          "default": "above",
          "choices": [
            {
              "value": "above",
              "label": "Above the threshold"
            },
            {
              "value": "below",
              "label": "Below the threshold"
            }
          ]
        },
        {
          "key": "flagValue",
          "kind": "number",
          "label": "Threshold value",
          "default": 0,
          "step": 0.01
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "campaign cost calculator",
        "cpc calculator",
        "cpm calculator",
        "ctr calculator",
        "cpa calculator",
        "roas calculator",
        "ad spend calculator",
        "marketing metrics calculator",
        "csv"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "recipe-schema-generator",
      "name": "Recipe schema generator",
      "description": "Turn recipe details into a ready-to-paste Recipe JSON-LD block.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/recipe-schema-generator",
      "embed": "https://textarray.com/embed/recipe-schema-generator",
      "mode": "generate",
      "action": "Generate schema",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "name",
          "kind": "text",
          "label": "Recipe name",
          "default": ""
        },
        {
          "key": "author",
          "kind": "text",
          "label": "Author",
          "default": ""
        },
        {
          "key": "imageUrls",
          "kind": "text",
          "label": "Image URLs",
          "default": ""
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "prepTime",
          "kind": "text",
          "label": "Prep time (ISO 8601)",
          "default": ""
        },
        {
          "key": "cookTime",
          "kind": "text",
          "label": "Cook time (ISO 8601)",
          "default": ""
        },
        {
          "key": "totalTime",
          "kind": "text",
          "label": "Total time (ISO 8601)",
          "default": ""
        },
        {
          "key": "recipeYield",
          "kind": "text",
          "label": "Servings",
          "default": ""
        },
        {
          "key": "recipeCategory",
          "kind": "text",
          "label": "Category",
          "default": ""
        },
        {
          "key": "recipeCuisine",
          "kind": "text",
          "label": "Cuisine",
          "default": ""
        },
        {
          "key": "ingredients",
          "kind": "text",
          "label": "Ingredients (one per line, or separated by \"|\")",
          "default": ""
        },
        {
          "key": "instructions",
          "kind": "text",
          "label": "Steps (one per line, or separated by \"|\")",
          "default": ""
        },
        {
          "key": "calories",
          "kind": "text",
          "label": "Calories",
          "default": ""
        },
        {
          "key": "ratingValue",
          "kind": "number",
          "label": "Rating value",
          "default": 0,
          "min": 0,
          "max": 5,
          "step": 0.1
        },
        {
          "key": "reviewCount",
          "kind": "number",
          "label": "Review count",
          "default": 0,
          "min": 0
        },
        {
          "key": "videoUrl",
          "kind": "text",
          "label": "Video URL",
          "default": ""
        },
        {
          "key": "videoUploadDate",
          "kind": "text",
          "label": "Video upload date",
          "default": ""
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print JSON",
          "default": true
        },
        {
          "key": "wrapScript",
          "kind": "checkbox",
          "label": "Wrap in <script> tag",
          "default": true
        }
      ],
      "keywords": [
        "recipe schema generator",
        "recipe structured data",
        "recipe json-ld",
        "schema.org recipe",
        "recipe rich results",
        "google recipe snippet",
        "json-ld",
        "json",
        "schema markup"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "event-schema-generator",
      "name": "Event schema generator",
      "description": "Turn event details into a schema.org Event JSON-LD block ready to paste into your page.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/event-schema-generator",
      "embed": "https://textarray.com/embed/event-schema-generator",
      "mode": "generate",
      "action": "Generate schema",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "name",
          "kind": "text",
          "label": "Event name",
          "default": ""
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "imageUrls",
          "kind": "text",
          "label": "Image URL(s)",
          "default": ""
        },
        {
          "key": "start",
          "kind": "text",
          "label": "Start date and time",
          "default": ""
        },
        {
          "key": "end",
          "kind": "text",
          "label": "End date and time",
          "default": ""
        },
        {
          "key": "attendanceMode",
          "kind": "select",
          "label": "How it takes place",
          "default": "offline",
          "choices": [
            {
              "value": "offline",
              "label": "In person"
            },
            {
              "value": "online",
              "label": "Online"
            },
            {
              "value": "mixed",
              "label": "Both (hybrid)"
            }
          ]
        },
        {
          "key": "locationName",
          "kind": "text",
          "label": "Venue name",
          "default": ""
        },
        {
          "key": "locationAddress",
          "kind": "text",
          "label": "Venue address",
          "default": ""
        },
        {
          "key": "onlineUrl",
          "kind": "text",
          "label": "Online / stream URL",
          "default": ""
        },
        {
          "key": "organizerName",
          "kind": "text",
          "label": "Organizer name",
          "default": ""
        },
        {
          "key": "organizerUrl",
          "kind": "text",
          "label": "Organizer URL",
          "default": ""
        },
        {
          "key": "ticketUrl",
          "kind": "text",
          "label": "Ticket URL",
          "default": ""
        },
        {
          "key": "price",
          "kind": "text",
          "label": "Ticket price",
          "default": ""
        },
        {
          "key": "currency",
          "kind": "text",
          "label": "Currency",
          "default": ""
        },
        {
          "key": "availability",
          "kind": "select",
          "label": "Ticket availability",
          "default": "InStock",
          "choices": [
            {
              "value": "InStock",
              "label": "Available"
            },
            {
              "value": "SoldOut",
              "label": "Sold out"
            },
            {
              "value": "PreOrder",
              "label": "Pre-order"
            },
            {
              "value": "LimitedAvailability",
              "label": "Limited availability"
            },
            {
              "value": "Discontinued",
              "label": "Discontinued"
            }
          ]
        },
        {
          "key": "status",
          "kind": "select",
          "label": "Event status",
          "default": "scheduled",
          "choices": [
            {
              "value": "scheduled",
              "label": "Scheduled"
            },
            {
              "value": "cancelled",
              "label": "Cancelled"
            },
            {
              "value": "postponed",
              "label": "Postponed"
            }
          ]
        },
        {
          "key": "additionalDates",
          "kind": "text",
          "label": "More dates (series)",
          "default": ""
        },
        {
          "key": "wrapScript",
          "kind": "checkbox",
          "label": "Wrap in <script> tag",
          "default": true
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print JSON",
          "default": true
        }
      ],
      "keywords": [
        "event schema generator",
        "event json-ld",
        "schema.org event",
        "event structured data",
        "google rich results event",
        "event markup generator",
        "json-ld",
        "seo"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "css-grid-generator",
      "name": "CSS grid generator",
      "description": "Turn a text layout sketch into a real CSS grid with named areas.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-grid-generator",
      "embed": "https://textarray.com/embed/css-grid-generator",
      "mode": "transform",
      "action": "Generate CSS grid",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "gap",
          "kind": "number",
          "label": "Gap (px)",
          "default": 16,
          "min": 0,
          "max": 200,
          "step": 1
        },
        {
          "key": "columnWidths",
          "kind": "text",
          "label": "Column widths",
          "default": ""
        },
        {
          "key": "rowHeights",
          "kind": "text",
          "label": "Row heights",
          "default": ""
        },
        {
          "key": "areaRules",
          "kind": "checkbox",
          "label": "Add grid-area rules per section",
          "default": true
        },
        {
          "key": "responsive",
          "kind": "checkbox",
          "label": "Add single-column responsive variant",
          "default": true
        },
        {
          "key": "classPrefix",
          "kind": "text",
          "label": "Class name prefix",
          "default": "grid"
        },
        {
          "key": "includeHtml",
          "kind": "checkbox",
          "label": "Include sample HTML",
          "default": false
        }
      ],
      "keywords": [
        "css grid generator",
        "grid-template-areas",
        "css grid layout",
        "grid from ascii",
        "css layout generator",
        "responsive grid css",
        "grid-template-columns",
        "grid-area"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "sql-table-column-extractor",
      "name": "SQL table and column extractor",
      "description": "List every table, join and column a SQL query reads, grouped by clause.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sql-table-column-extractor",
      "embed": "https://textarray.com/embed/sql-table-column-extractor",
      "mode": "transform",
      "action": "Extract tables and columns",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output as",
          "default": "overview",
          "choices": [
            {
              "value": "overview",
              "label": "Overview"
            },
            {
              "value": "dependencies",
              "label": "Dependency list"
            }
          ]
        },
        {
          "key": "showClauseColumns",
          "kind": "checkbox",
          "label": "Show WHERE / GROUP BY / ORDER BY columns",
          "default": true
        },
        {
          "key": "showJoinConditions",
          "kind": "checkbox",
          "label": "Show join conditions",
          "default": true
        },
        {
          "key": "warnAmbiguous",
          "kind": "checkbox",
          "label": "Warn about columns without a table",
          "default": true
        }
      ],
      "keywords": [
        "sql table extractor",
        "sql column extractor",
        "list tables in sql query",
        "sql query analyzer",
        "sql join analyzer",
        "sql dependency list",
        "find tables used in query",
        "sql",
        "select",
        "join",
        "cte"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "har-analyzer",
      "name": "HAR analyzer",
      "description": "Break down a HAR file into method, status, size and timing per network call.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/har-analyzer",
      "embed": "https://textarray.com/embed/har-analyzer",
      "mode": "transform",
      "action": "Analyze HAR file",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "order",
          "choices": [
            {
              "value": "order",
              "label": "Original order"
            },
            {
              "value": "duration",
              "label": "Duration"
            },
            {
              "value": "size",
              "label": "Size"
            }
          ]
        },
        {
          "key": "filterType",
          "kind": "text",
          "label": "Filter by content type",
          "default": ""
        },
        {
          "key": "filterDomain",
          "kind": "text",
          "label": "Filter by domain",
          "default": ""
        },
        {
          "key": "showTotals",
          "kind": "checkbox",
          "label": "Show totals by content type and domain",
          "default": false
        },
        {
          "key": "showTopCalls",
          "kind": "checkbox",
          "label": "Show slowest and largest calls",
          "default": false
        },
        {
          "key": "topN",
          "kind": "number",
          "label": "How many to list",
          "default": 5,
          "min": 1,
          "max": 50,
          "step": 1
        },
        {
          "key": "showTiming",
          "kind": "checkbox",
          "label": "Break down time (wait vs. download)",
          "default": false
        },
        {
          "key": "separateThirdParty",
          "kind": "checkbox",
          "label": "Show third-party calls separately",
          "default": false
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "har analyzer",
        "har file viewer",
        "network calls",
        "network waterfall",
        "devtools export",
        "response time",
        "content type breakdown",
        "har",
        "json",
        "csv"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "openapi-to-postman",
      "name": "OpenAPI to Postman collection",
      "description": "Convert an OpenAPI or Swagger document into a ready-to-import Postman v2.1 collection.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/openapi-to-postman",
      "embed": "https://textarray.com/embed/openapi-to-postman",
      "mode": "transform",
      "action": "Convert to Postman collection",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "groupBy",
          "kind": "select",
          "label": "Group requests by",
          "default": "tag",
          "choices": [
            {
              "value": "tag",
              "label": "Tag"
            },
            {
              "value": "path",
              "label": "Path"
            }
          ]
        },
        {
          "key": "baseUrlAsVariable",
          "kind": "checkbox",
          "label": "Insert base URL as an environment variable",
          "default": true
        },
        {
          "key": "addAuthHeaders",
          "kind": "checkbox",
          "label": "Add auth headers from the security scheme",
          "default": true
        },
        {
          "key": "generateSampleBodies",
          "kind": "checkbox",
          "label": "Generate sample request bodies from schemas",
          "default": true
        },
        {
          "key": "includeQueryParams",
          "kind": "checkbox",
          "label": "Include query parameters with descriptions",
          "default": true
        },
        {
          "key": "skipDeprecated",
          "kind": "checkbox",
          "label": "Skip endpoints marked deprecated",
          "default": false
        },
        {
          "key": "addTestScripts",
          "kind": "checkbox",
          "label": "Add a basic status-code test script",
          "default": false
        }
      ],
      "keywords": [
        "openapi to postman",
        "swagger to postman",
        "postman collection generator",
        "openapi converter",
        "api collection",
        "postman v2.1",
        "json",
        "yaml"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "dockerfile-generator",
      "name": "Dockerfile generator",
      "description": "Build a production-ready Dockerfile for your language, with multi-stage builds and sane defaults.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/dockerfile-generator",
      "embed": "https://textarray.com/embed/dockerfile-generator",
      "mode": "generate",
      "action": "Generate Dockerfile",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "language",
          "kind": "select",
          "label": "Language / runtime",
          "default": "node",
          "choices": [
            {
              "value": "node",
              "label": "Node.js"
            },
            {
              "value": "python",
              "label": "Python"
            },
            {
              "value": "go",
              "label": "Go"
            },
            {
              "value": "php",
              "label": "PHP"
            },
            {
              "value": "java",
              "label": "Java"
            },
            {
              "value": "static",
              "label": "Static site (nginx)"
            }
          ]
        },
        {
          "key": "version",
          "kind": "text",
          "label": "Base image version",
          "default": ""
        },
        {
          "key": "packageManager",
          "kind": "select",
          "label": "Package manager",
          "default": "npm",
          "choices": [
            {
              "value": "npm",
              "label": "npm"
            },
            {
              "value": "yarn",
              "label": "Yarn"
            },
            {
              "value": "pnpm",
              "label": "pnpm"
            },
            {
              "value": "pip",
              "label": "pip"
            },
            {
              "value": "poetry",
              "label": "Poetry"
            },
            {
              "value": "none",
              "label": "None"
            }
          ]
        },
        {
          "key": "multistage",
          "kind": "checkbox",
          "label": "Multi-stage build (minimal runtime image)",
          "default": true
        },
        {
          "key": "nonRoot",
          "kind": "checkbox",
          "label": "Run as non-root user",
          "default": true
        },
        {
          "key": "port",
          "kind": "number",
          "label": "Port",
          "default": 3000,
          "min": 1,
          "max": 65535
        },
        {
          "key": "startCommand",
          "kind": "text",
          "label": "Start command",
          "default": ""
        },
        {
          "key": "healthcheck",
          "kind": "checkbox",
          "label": "Add a HEALTHCHECK instruction",
          "default": true
        },
        {
          "key": "envVars",
          "kind": "text",
          "label": "Environment variables",
          "default": ""
        },
        {
          "key": "dockerignore",
          "kind": "checkbox",
          "label": "Also generate a .dockerignore",
          "default": true
        },
        {
          "key": "comments",
          "kind": "checkbox",
          "label": "Explain each layer with comments",
          "default": true
        }
      ],
      "keywords": [
        "dockerfile generator",
        "docker",
        "dockerfile",
        "multi-stage build",
        "docker best practices",
        "containerize app",
        "dockerignore generator",
        "node dockerfile",
        "python dockerfile",
        "go dockerfile"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "regex-from-examples",
      "name": "Regex from examples",
      "description": "Turn sample strings into a regular expression, and see which examples it matches.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/regex-from-examples",
      "embed": "https://textarray.com/embed/regex-from-examples",
      "mode": "transform",
      "action": "Generate regex",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Examples the pattern should NOT match"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "strictness",
          "kind": "select",
          "label": "Generalization",
          "default": "classes",
          "choices": [
            {
              "value": "exact",
              "label": "Exact characters"
            },
            {
              "value": "classes",
              "label": "Character classes"
            },
            {
              "value": "quantifiers",
              "label": "Flexible quantifiers"
            }
          ]
        },
        {
          "key": "anchored",
          "kind": "checkbox",
          "label": "Anchor to start and end (^…$)",
          "default": true
        },
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case-sensitive",
          "default": true
        },
        {
          "key": "namedGroups",
          "kind": "checkbox",
          "label": "Named groups for variable parts",
          "default": false
        },
        {
          "key": "dialect",
          "kind": "select",
          "label": "Dialect",
          "default": "js",
          "choices": [
            {
              "value": "js",
              "label": "JavaScript"
            },
            {
              "value": "pcre",
              "label": "PCRE"
            },
            {
              "value": "python",
              "label": "Python"
            }
          ]
        },
        {
          "key": "explain",
          "kind": "checkbox",
          "label": "Explain the pattern part by part",
          "default": true
        }
      ],
      "keywords": [
        "regex generator",
        "regex from examples",
        "regex builder",
        "pattern from samples",
        "generate regular expression",
        "infer regex",
        "named capture groups",
        "regex dialect",
        "javascript regex",
        "python regex",
        "pcre"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "glob-to-regex",
      "name": "Glob to regex converter",
      "description": "Turn glob patterns like *.js or **/*.test.ts into the matching regular expression.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/glob-to-regex",
      "embed": "https://textarray.com/embed/glob-to-regex",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Test paths (optional)"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "toRegex",
          "choices": [
            {
              "value": "toRegex",
              "label": "Glob → regex"
            },
            {
              "value": "toGlob",
              "label": "Regex → glob"
            }
          ]
        },
        {
          "key": "style",
          "kind": "select",
          "label": "Glob style",
          "default": "shell",
          "choices": [
            {
              "value": "shell",
              "label": "Shell"
            },
            {
              "value": "gitignore",
              "label": ".gitignore"
            },
            {
              "value": "minimatch",
              "label": "Minimatch"
            }
          ]
        },
        {
          "key": "globstar",
          "kind": "checkbox",
          "label": "Double star (**) crosses slashes",
          "default": true
        },
        {
          "key": "matchDot",
          "kind": "checkbox",
          "label": "Wildcards match hidden (dot) files",
          "default": false
        },
        {
          "key": "caseSensitive",
          "kind": "checkbox",
          "label": "Case sensitive",
          "default": true
        },
        {
          "key": "anchored",
          "kind": "checkbox",
          "label": "Anchor to the full string",
          "default": true
        }
      ],
      "keywords": [
        "glob to regex",
        "glob pattern converter",
        "wildcard to regex",
        "glob syntax",
        "gitignore pattern",
        "minimatch",
        "shell glob",
        "regex"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "graphql-to-typescript",
      "name": "GraphQL SDL to TypeScript types",
      "description": "Convert a GraphQL schema into matching TypeScript types, interfaces and enums.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/graphql-to-typescript",
      "embed": "https://textarray.com/embed/graphql-to-typescript",
      "mode": "transform",
      "action": "Convert to TypeScript",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "preserveComments",
          "kind": "checkbox",
          "label": "Preserve comments as doc comments",
          "default": true
        },
        {
          "key": "nullableStyle",
          "kind": "select",
          "label": "Nullable fields",
          "default": "optional",
          "choices": [
            {
              "value": "optional",
              "label": "Optional property"
            },
            {
              "value": "union",
              "label": "Union with null"
            }
          ]
        },
        {
          "key": "declarationKind",
          "kind": "select",
          "label": "Declaration kind",
          "default": "type",
          "choices": [
            {
              "value": "type",
              "label": "Type aliases"
            },
            {
              "value": "interface",
              "label": "Interfaces"
            }
          ]
        },
        {
          "key": "enumStyle",
          "kind": "select",
          "label": "Enum style",
          "default": "union",
          "choices": [
            {
              "value": "union",
              "label": "String union"
            },
            {
              "value": "enum",
              "label": "TypeScript enum"
            }
          ]
        },
        {
          "key": "namePrefix",
          "kind": "text",
          "label": "Name prefix",
          "default": ""
        },
        {
          "key": "nameSuffix",
          "kind": "text",
          "label": "Name suffix",
          "default": ""
        },
        {
          "key": "customScalarType",
          "kind": "text",
          "label": "Custom scalar type",
          "default": "unknown"
        },
        {
          "key": "skipUnderscoreTypes",
          "kind": "checkbox",
          "label": "Skip types starting with _",
          "default": true
        },
        {
          "key": "sortTypes",
          "kind": "checkbox",
          "label": "Sort types alphabetically",
          "default": false
        }
      ],
      "keywords": [
        "graphql to typescript",
        "graphql sdl converter",
        "graphql schema to types",
        "graphql type generator",
        "graphql interfaces",
        "graphql enums",
        "graphql",
        "typescript",
        "sdl",
        "codegen"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "spf-dmarc-generator",
      "name": "SPF and DMARC record generator",
      "description": "Build ready-to-paste SPF and DMARC DNS records from your senders and policy.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/spf-dmarc-generator",
      "embed": "https://textarray.com/embed/spf-dmarc-generator",
      "mode": "generate",
      "action": "Generate records",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "domain",
          "kind": "text",
          "label": "Domain",
          "default": ""
        },
        {
          "key": "senders",
          "kind": "text",
          "label": "Permitted senders",
          "default": ""
        },
        {
          "key": "googleWorkspace",
          "kind": "checkbox",
          "label": "Google Workspace",
          "default": false
        },
        {
          "key": "microsoft365",
          "kind": "checkbox",
          "label": "Microsoft 365",
          "default": false
        },
        {
          "key": "sendgrid",
          "kind": "checkbox",
          "label": "SendGrid",
          "default": false
        },
        {
          "key": "mailgun",
          "kind": "checkbox",
          "label": "Mailgun",
          "default": false
        },
        {
          "key": "spfFail",
          "kind": "select",
          "label": "SPF fail strictness",
          "default": "hard",
          "choices": [
            {
              "value": "hard",
              "label": "Hard fail (-all)"
            },
            {
              "value": "soft",
              "label": "Soft fail (~all)"
            },
            {
              "value": "neutral",
              "label": "Neutral (?all)"
            },
            {
              "value": "pass",
              "label": "Pass (+all) — not recommended"
            }
          ]
        },
        {
          "key": "dmarcPolicy",
          "kind": "select",
          "label": "DMARC policy",
          "default": "quarantine",
          "choices": [
            {
              "value": "none",
              "label": "None (monitor only)"
            },
            {
              "value": "quarantine",
              "label": "Quarantine"
            },
            {
              "value": "reject",
              "label": "Reject"
            }
          ]
        },
        {
          "key": "dmarcPct",
          "kind": "number",
          "label": "DMARC policy share (%)",
          "default": 100,
          "min": 1,
          "max": 100,
          "step": 1
        },
        {
          "key": "subdomainPolicy",
          "kind": "select",
          "label": "Subdomain policy",
          "default": "inherit",
          "choices": [
            {
              "value": "inherit",
              "label": "Same as domain policy"
            },
            {
              "value": "none",
              "label": "None (monitor only)"
            },
            {
              "value": "quarantine",
              "label": "Quarantine"
            },
            {
              "value": "reject",
              "label": "Reject"
            }
          ]
        },
        {
          "key": "dmarcRua",
          "kind": "text",
          "label": "Aggregate report addresses",
          "default": ""
        },
        {
          "key": "dmarcRuf",
          "kind": "text",
          "label": "Forensic report addresses",
          "default": ""
        },
        {
          "key": "dmarcRi",
          "kind": "number",
          "label": "Report interval (seconds)",
          "default": 86400,
          "min": 3600,
          "max": 604800,
          "step": 3600
        },
        {
          "key": "aspf",
          "kind": "select",
          "label": "SPF alignment",
          "default": "r",
          "choices": [
            {
              "value": "r",
              "label": "Relaxed"
            },
            {
              "value": "s",
              "label": "Strict"
            }
          ]
        },
        {
          "key": "adkim",
          "kind": "select",
          "label": "DKIM alignment",
          "default": "r",
          "choices": [
            {
              "value": "r",
              "label": "Relaxed"
            },
            {
              "value": "s",
              "label": "Strict"
            }
          ]
        },
        {
          "key": "showHostname",
          "kind": "checkbox",
          "label": "Show hostname for each record",
          "default": true
        }
      ],
      "keywords": [
        "spf record generator",
        "dmarc record generator",
        "spf generator",
        "dmarc generator",
        "dns txt record",
        "email authentication",
        "spf record",
        "dmarc policy",
        "mailto rua",
        "dkim alignment"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "json-size-analyzer",
      "name": "JSON size analyzer",
      "description": "See exactly which keys and branches make a JSON document big.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/json-size-analyzer",
      "embed": "https://textarray.com/embed/json-size-analyzer",
      "mode": "transform",
      "action": "Analyze size",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "depth",
          "kind": "number",
          "label": "Expand to depth",
          "default": 5,
          "min": 1,
          "max": 10,
          "step": 1
        },
        {
          "key": "showPercent",
          "kind": "checkbox",
          "label": "Show size as % of total",
          "default": true
        },
        {
          "key": "sortBySize",
          "kind": "checkbox",
          "label": "Sort by size",
          "default": true
        },
        {
          "key": "groupArrays",
          "kind": "checkbox",
          "label": "Group array items",
          "default": true
        },
        {
          "key": "countKeyNames",
          "kind": "checkbox",
          "label": "Count key names separately",
          "default": false
        },
        {
          "key": "showCounts",
          "kind": "checkbox",
          "label": "Show item and key counts",
          "default": true
        },
        {
          "key": "flagDuplicates",
          "kind": "checkbox",
          "label": "Flag repeated values",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "tree",
          "choices": [
            {
              "value": "tree",
              "label": "Tree"
            },
            {
              "value": "table",
              "label": "Table"
            }
          ]
        }
      ],
      "keywords": [
        "json size analyzer",
        "json size",
        "json byte size",
        "json weight",
        "json bloat",
        "analyze json payload",
        "json",
        "payload size"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "har-to-curl",
      "name": "HAR to curl converter",
      "description": "Turn every request in an exported HAR file into a runnable curl command.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/har-to-curl",
      "embed": "https://textarray.com/embed/har-to-curl",
      "mode": "transform",
      "action": "Generate commands",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "domain",
          "kind": "text",
          "label": "Filter by domain",
          "default": ""
        },
        {
          "key": "method",
          "kind": "select",
          "label": "Method",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All methods"
            },
            {
              "value": "GET",
              "label": "GET"
            },
            {
              "value": "POST",
              "label": "POST"
            },
            {
              "value": "PUT",
              "label": "PUT"
            },
            {
              "value": "PATCH",
              "label": "PATCH"
            },
            {
              "value": "DELETE",
              "label": "DELETE"
            },
            {
              "value": "HEAD",
              "label": "HEAD"
            },
            {
              "value": "OPTIONS",
              "label": "OPTIONS"
            }
          ]
        },
        {
          "key": "contentType",
          "kind": "select",
          "label": "Content type",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All content types"
            },
            {
              "value": "json",
              "label": "JSON"
            },
            {
              "value": "form",
              "label": "Form-encoded"
            },
            {
              "value": "multipart",
              "label": "Multipart"
            },
            {
              "value": "text",
              "label": "Text"
            }
          ]
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "curl",
          "choices": [
            {
              "value": "curl",
              "label": "curl"
            },
            {
              "value": "fetch",
              "label": "fetch()"
            },
            {
              "value": "httpie",
              "label": "HTTPie"
            }
          ]
        },
        {
          "key": "includeBrowserHeaders",
          "kind": "checkbox",
          "label": "Include browser headers (User-Agent, Accept, Sec-*)",
          "default": false
        },
        {
          "key": "excludeCookies",
          "kind": "checkbox",
          "label": "Exclude cookies",
          "default": true
        },
        {
          "key": "excludeAuth",
          "kind": "checkbox",
          "label": "Exclude authentication headers",
          "default": false
        },
        {
          "key": "dataRaw",
          "kind": "checkbox",
          "label": "Use --data-raw for the request body",
          "default": true
        },
        {
          "key": "multiline",
          "kind": "checkbox",
          "label": "Wrap command across multiple lines",
          "default": false
        },
        {
          "key": "compressed",
          "kind": "checkbox",
          "label": "Add --compressed",
          "default": false
        },
        {
          "key": "location",
          "kind": "checkbox",
          "label": "Add --location (follow redirects)",
          "default": false
        }
      ],
      "keywords": [
        "har to curl",
        "har file converter",
        "convert har to curl",
        "curl command generator",
        "network request to curl",
        "export har as curl",
        "har viewer",
        "curl",
        "json",
        "fetch",
        "httpie"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "htaccess-to-nginx",
      "name": "htaccess to Nginx converter",
      "description": "Convert Apache .htaccess rules into an equivalent Nginx configuration.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/htaccess-to-nginx",
      "embed": "https://textarray.com/embed/htaccess-to-nginx",
      "mode": "transform",
      "action": "Convert to Nginx",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "convertRewrite",
          "kind": "checkbox",
          "label": "Convert RewriteRule / RewriteCond",
          "default": true
        },
        {
          "key": "convertRedirects",
          "kind": "checkbox",
          "label": "Convert Redirect / RedirectMatch",
          "default": true
        },
        {
          "key": "convertErrorPages",
          "kind": "checkbox",
          "label": "Convert error pages",
          "default": true
        },
        {
          "key": "convertHeaders",
          "kind": "checkbox",
          "label": "Convert headers and expiry",
          "default": true
        },
        {
          "key": "convertAccess",
          "kind": "checkbox",
          "label": "Convert access rules",
          "default": true
        },
        {
          "key": "convertAuth",
          "kind": "checkbox",
          "label": "Convert password protection",
          "default": true
        },
        {
          "key": "wrap",
          "kind": "select",
          "label": "Wrap output in",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Nothing (fragment)"
            },
            {
              "value": "server",
              "label": "server { } block"
            },
            {
              "value": "location",
              "label": "location { } block"
            }
          ]
        },
        {
          "key": "showWarnings",
          "kind": "checkbox",
          "label": "Show warnings for unsupported rules",
          "default": true
        }
      ],
      "keywords": [
        "htaccess to nginx",
        "htaccess converter",
        "apache to nginx",
        "nginx rewrite rule",
        "mod_rewrite to nginx",
        "nginx config converter",
        "rewriterule",
        "rewritecond"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "openapi-to-typescript",
      "name": "OpenAPI to TypeScript types",
      "description": "Turn an OpenAPI or Swagger document into TypeScript interfaces and types.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/openapi-to-typescript",
      "embed": "https://textarray.com/embed/openapi-to-typescript",
      "mode": "transform",
      "action": "Generate types",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "declaration",
          "kind": "select",
          "label": "Declaration style",
          "default": "interface",
          "choices": [
            {
              "value": "interface",
              "label": "interface"
            },
            {
              "value": "type",
              "label": "type"
            }
          ]
        },
        {
          "key": "nullableMode",
          "kind": "select",
          "label": "Nullable fields",
          "default": "optional",
          "choices": [
            {
              "value": "optional",
              "label": "As optional (x?: T)"
            },
            {
              "value": "union",
              "label": "As union with null (x: T | null)"
            }
          ]
        },
        {
          "key": "expandRefs",
          "kind": "checkbox",
          "label": "Expand $ref instead of naming it",
          "default": false
        },
        {
          "key": "generatePathTypes",
          "kind": "checkbox",
          "label": "Generate path, parameter and response types",
          "default": true
        },
        {
          "key": "generateStatusUnion",
          "kind": "checkbox",
          "label": "Generate a status code union per endpoint",
          "default": false
        },
        {
          "key": "keepDescriptions",
          "kind": "checkbox",
          "label": "Keep descriptions as doc comments",
          "default": true
        },
        {
          "key": "namePrefix",
          "kind": "text",
          "label": "Name prefix",
          "default": ""
        },
        {
          "key": "skipDeprecated",
          "kind": "checkbox",
          "label": "Skip deprecated endpoints",
          "default": false
        }
      ],
      "keywords": [
        "openapi to typescript",
        "swagger to typescript",
        "openapi types generator",
        "openapi schema to interface",
        "api client types",
        "rest api types",
        "openapi",
        "swagger",
        "typescript",
        "json schema"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "indented-list-to-json",
      "name": "Indented list to JSON tree",
      "description": "Turn an indented or bulleted list into a nested JSON (or YAML) tree, and back again.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/indented-list-to-json",
      "embed": "https://textarray.com/embed/indented-list-to-json",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "listToTree",
          "choices": [
            {
              "value": "listToTree",
              "label": "List to tree"
            },
            {
              "value": "treeToList",
              "label": "Tree to list"
            }
          ]
        },
        {
          "key": "indentSize",
          "kind": "number",
          "label": "Indent size",
          "default": 2,
          "min": 1,
          "max": 8,
          "step": 1
        },
        {
          "key": "bullets",
          "kind": "select",
          "label": "Bullets and numbering",
          "default": "ignore",
          "choices": [
            {
              "value": "ignore",
              "label": "Ignore"
            },
            {
              "value": "keep",
              "label": "Keep"
            }
          ]
        },
        {
          "key": "outputShape",
          "kind": "select",
          "label": "Output shape",
          "default": "nested",
          "choices": [
            {
              "value": "nested",
              "label": "Object with children"
            },
            {
              "value": "arrayOfArrays",
              "label": "Array of arrays"
            },
            {
              "value": "map",
              "label": "Name map"
            }
          ]
        },
        {
          "key": "childrenKey",
          "kind": "text",
          "label": "Children key name",
          "default": "children"
        },
        {
          "key": "splitDelimiter",
          "kind": "text",
          "label": "Split name/value at",
          "default": ""
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "json",
          "choices": [
            {
              "value": "json",
              "label": "JSON"
            },
            {
              "value": "yaml",
              "label": "YAML"
            }
          ]
        }
      ],
      "keywords": [
        "indented list to json",
        "nested list converter",
        "outline to json",
        "tree to json",
        "json to indented list",
        "yaml tree",
        "indentation to tree structure",
        "json",
        "yaml"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "security-txt-validator",
      "name": "security.txt validator",
      "description": "Check a security.txt file against RFC 9116 and list what is missing, invalid or deprecated.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/security-txt-validator",
      "embed": "https://textarray.com/embed/security-txt-validator",
      "mode": "transform",
      "action": "Validate security.txt",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "checkRequired",
          "kind": "checkbox",
          "label": "Check required fields (Contact, Expires)",
          "default": true
        },
        {
          "key": "checkExpiry",
          "kind": "checkbox",
          "label": "Flag an invalid or expired \"Expires\" date",
          "default": true
        },
        {
          "key": "checkAddresses",
          "kind": "checkbox",
          "label": "Validate addresses (Encryption, Policy, Hiring…)",
          "default": true
        },
        {
          "key": "warnUnknownFields",
          "kind": "checkbox",
          "label": "Warn about unknown or deprecated fields",
          "default": true
        },
        {
          "key": "checkOrderDuplicates",
          "kind": "checkbox",
          "label": "Check field order and duplicates",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output",
          "default": "findings",
          "choices": [
            {
              "value": "findings",
              "label": "List of findings"
            },
            {
              "value": "fixed",
              "label": "Corrected file"
            }
          ]
        }
      ],
      "keywords": [
        "security.txt validator",
        "security.txt checker",
        "rfc 9116",
        "well-known security.txt",
        "vulnerability disclosure file",
        "security contact file",
        "security.txt syntax",
        "security.txt generator"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "ssh-config-generator",
      "name": "SSH config generator",
      "description": "Turn a list of servers into ready-to-use Host blocks for ~/.ssh/config.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ssh-config-generator",
      "embed": "https://textarray.com/embed/ssh-config-generator",
      "mode": "transform",
      "action": "Generate SSH config",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "port",
          "kind": "number",
          "label": "Default port",
          "default": 22,
          "min": 1,
          "max": 65535,
          "step": 1
        },
        {
          "key": "identityFile",
          "kind": "text",
          "label": "Default private key path",
          "default": "~/.ssh/id_ed25519"
        },
        {
          "key": "proxyJump",
          "kind": "text",
          "label": "Jump host (ProxyJump)",
          "default": ""
        },
        {
          "key": "localForward",
          "kind": "text",
          "label": "Port forwarding (LocalForward)",
          "default": ""
        },
        {
          "key": "serverAliveInterval",
          "kind": "number",
          "label": "Keep-alive interval in seconds (0 = off)",
          "default": 60,
          "min": 0,
          "max": 3600,
          "step": 10
        },
        {
          "key": "controlMaster",
          "kind": "checkbox",
          "label": "Share connections (ControlMaster)",
          "default": false
        },
        {
          "key": "disableAgentForwarding",
          "kind": "checkbox",
          "label": "Disable agent forwarding",
          "default": false
        },
        {
          "key": "sortAlphabetically",
          "kind": "checkbox",
          "label": "Sort blocks alphabetically",
          "default": false
        },
        {
          "key": "addComment",
          "kind": "checkbox",
          "label": "Add a comment above each block",
          "default": true
        }
      ],
      "keywords": [
        "ssh config generator",
        "ssh config file",
        "~/.ssh/config",
        "ssh host block",
        "proxyjump generator",
        "ssh keep-alive",
        "ssh agent forwarding",
        "controlmaster"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "csv-to-merchant-feed",
      "name": "CSV to Google Merchant XML feed",
      "description": "Convert a product spreadsheet into an XML feed Google Merchant Center accepts.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/csv-to-merchant-feed",
      "embed": "https://textarray.com/embed/csv-to-merchant-feed",
      "mode": "transform",
      "action": "Generate feed",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "delimiter",
          "kind": "select",
          "label": "Delimiter",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "semicolon",
              "label": "Semicolon"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        },
        {
          "key": "storeName",
          "kind": "text",
          "label": "Store name",
          "default": "My store"
        },
        {
          "key": "colId",
          "kind": "text",
          "label": "ID column",
          "default": ""
        },
        {
          "key": "colTitle",
          "kind": "text",
          "label": "Title column",
          "default": ""
        },
        {
          "key": "colDescription",
          "kind": "text",
          "label": "Description column",
          "default": ""
        },
        {
          "key": "colLink",
          "kind": "text",
          "label": "Link column",
          "default": ""
        },
        {
          "key": "colImage",
          "kind": "text",
          "label": "Image link column",
          "default": ""
        },
        {
          "key": "colPrice",
          "kind": "text",
          "label": "Price column",
          "default": ""
        },
        {
          "key": "colAvailability",
          "kind": "text",
          "label": "Availability column",
          "default": ""
        },
        {
          "key": "colBrand",
          "kind": "text",
          "label": "Brand column",
          "default": ""
        },
        {
          "key": "colGtin",
          "kind": "text",
          "label": "GTIN column",
          "default": ""
        },
        {
          "key": "colCondition",
          "kind": "text",
          "label": "Condition column",
          "default": ""
        },
        {
          "key": "currency",
          "kind": "text",
          "label": "Currency code",
          "default": "USD"
        },
        {
          "key": "decimalComma",
          "kind": "checkbox",
          "label": "Price uses comma as decimal separator",
          "default": false
        },
        {
          "key": "defaultValue",
          "kind": "text",
          "label": "Default value for missing fields",
          "default": ""
        },
        {
          "key": "truncate",
          "kind": "checkbox",
          "label": "Trim titles and descriptions to Google's length limits",
          "default": true
        },
        {
          "key": "encoding",
          "kind": "select",
          "label": "Text encoding",
          "default": "escape",
          "choices": [
            {
              "value": "escape",
              "label": "Escape special characters"
            },
            {
              "value": "cdata",
              "label": "Wrap in CDATA"
            }
          ]
        },
        {
          "key": "outputMode",
          "kind": "select",
          "label": "Output",
          "default": "xml",
          "choices": [
            {
              "value": "xml",
              "label": "XML feed"
            },
            {
              "value": "errors",
              "label": "List of errors"
            }
          ]
        }
      ],
      "keywords": [
        "google merchant center feed",
        "csv to xml",
        "product feed generator",
        "shopping feed",
        "google shopping xml",
        "rss product feed",
        "merchant center csv",
        "csv",
        "xml",
        "gtin"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "junit-xml-report",
      "name": "JUnit XML report summary",
      "description": "Summarize a JUnit XML test report: pass/fail/skip counts, durations and failure details.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/junit-xml-report",
      "embed": "https://textarray.com/embed/junit-xml-report",
      "mode": "transform",
      "action": "Summarize report",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "onlyFailed",
          "kind": "checkbox",
          "label": "Show only failed tests",
          "default": false
        },
        {
          "key": "sortByDuration",
          "kind": "checkbox",
          "label": "Sort by duration (slowest first)",
          "default": false
        },
        {
          "key": "groupBy",
          "kind": "select",
          "label": "Group by",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "No grouping"
            },
            {
              "value": "class",
              "label": "Test class"
            },
            {
              "value": "file",
              "label": "File"
            }
          ]
        },
        {
          "key": "truncateLines",
          "kind": "number",
          "label": "Truncate error messages to (lines)",
          "default": 0,
          "min": 0,
          "max": 50,
          "step": 1
        },
        {
          "key": "limit",
          "kind": "number",
          "label": "Limit tests shown",
          "default": 0,
          "min": 0,
          "max": 1000,
          "step": 10
        },
        {
          "key": "showSuccessRate",
          "kind": "checkbox",
          "label": "Show success rate",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "summary",
          "choices": [
            {
              "value": "summary",
              "label": "Summary"
            },
            {
              "value": "markdown",
              "label": "Markdown"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "junit xml report",
        "junit xml summary",
        "test report viewer",
        "test results summary",
        "ci test report",
        "failed tests",
        "junit",
        "xml",
        "csv",
        "markdown"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "protobuf-to-typescript",
      "name": "Protobuf schema to TypeScript types",
      "description": "Turn a Protobuf schema into matching TypeScript interfaces, enums and unions.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/protobuf-to-typescript",
      "embed": "https://textarray.com/embed/protobuf-to-typescript",
      "mode": "transform",
      "action": "Convert to TypeScript",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "syntax",
          "kind": "select",
          "label": "Syntax version",
          "default": "proto3",
          "choices": [
            {
              "value": "proto3",
              "label": "proto3"
            },
            {
              "value": "proto2",
              "label": "proto2"
            }
          ]
        },
        {
          "key": "int64AsString",
          "kind": "checkbox",
          "label": "64-bit integers as string",
          "default": true
        },
        {
          "key": "oneofAsUnion",
          "kind": "checkbox",
          "label": "Represent oneof as a union type",
          "default": true
        },
        {
          "key": "camelCaseFields",
          "kind": "checkbox",
          "label": "Field names in camelCase",
          "default": true
        },
        {
          "key": "keepComments",
          "kind": "checkbox",
          "label": "Keep comments as doc comments",
          "default": true
        },
        {
          "key": "generateServices",
          "kind": "checkbox",
          "label": "Generate service method types",
          "default": false
        }
      ],
      "keywords": [
        "protobuf to typescript",
        "proto to ts",
        "protocol buffers types",
        ".proto converter",
        "proto3 types",
        "proto2 types",
        "grpc types",
        "protobuf",
        "typescript"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "nginx-to-caddyfile",
      "name": "Nginx config to Caddyfile",
      "description": "Convert an Nginx server configuration to an equivalent Caddyfile.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/nginx-to-caddyfile",
      "embed": "https://textarray.com/embed/nginx-to-caddyfile",
      "mode": "transform",
      "action": "Convert to Caddyfile",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "convertProxy",
          "kind": "checkbox",
          "label": "Convert reverse proxy",
          "default": true
        },
        {
          "key": "convertStatic",
          "kind": "checkbox",
          "label": "Convert static files",
          "default": true
        },
        {
          "key": "convertRedirects",
          "kind": "checkbox",
          "label": "Convert redirects & rewrites",
          "default": true
        },
        {
          "key": "convertTls",
          "kind": "checkbox",
          "label": "Convert TLS settings",
          "default": true
        },
        {
          "key": "convertCompression",
          "kind": "checkbox",
          "label": "Convert compression & caching",
          "default": true
        },
        {
          "key": "convertBodySize",
          "kind": "checkbox",
          "label": "Convert body size limit",
          "default": true
        },
        {
          "key": "showWarnings",
          "kind": "checkbox",
          "label": "Warn about directives with no equivalent",
          "default": true
        }
      ],
      "keywords": [
        "nginx to caddy",
        "caddyfile converter",
        "nginx config converter",
        "reverse proxy config",
        "nginx migration",
        "caddy server",
        "proxy_pass to reverse_proxy",
        "nginx",
        "caddyfile"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "compose-to-kubernetes",
      "name": "docker-compose to Kubernetes manifest",
      "description": "Convert docker-compose services into Kubernetes Deployment and Service manifests.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/compose-to-kubernetes",
      "embed": "https://textarray.com/embed/compose-to-kubernetes",
      "mode": "transform",
      "action": "Convert to Kubernetes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "namespace",
          "kind": "text",
          "label": "Namespace",
          "default": ""
        },
        {
          "key": "commonLabels",
          "kind": "text",
          "label": "Common labels",
          "default": ""
        },
        {
          "key": "replicas",
          "kind": "number",
          "label": "Replicas",
          "default": 2,
          "min": 1,
          "max": 100
        },
        {
          "key": "serviceType",
          "kind": "select",
          "label": "Service type",
          "default": "clusterip",
          "choices": [
            {
              "value": "clusterip",
              "label": "ClusterIP"
            },
            {
              "value": "nodeport",
              "label": "NodePort"
            }
          ]
        },
        {
          "key": "envAs",
          "kind": "select",
          "label": "Environment variables as",
          "default": "configmap",
          "choices": [
            {
              "value": "configmap",
              "label": "ConfigMap"
            },
            {
              "value": "secret",
              "label": "Secret"
            }
          ]
        },
        {
          "key": "volumesAs",
          "kind": "select",
          "label": "Volumes as",
          "default": "pvc",
          "choices": [
            {
              "value": "pvc",
              "label": "PersistentVolumeClaim"
            },
            {
              "value": "emptydir",
              "label": "emptyDir"
            }
          ]
        },
        {
          "key": "probes",
          "kind": "checkbox",
          "label": "Add readiness and liveness probes",
          "default": true
        },
        {
          "key": "ingress",
          "kind": "checkbox",
          "label": "Generate Ingress for exposed ports",
          "default": false
        }
      ],
      "keywords": [
        "docker compose to kubernetes",
        "compose to k8s",
        "kubernetes deployment generator",
        "docker compose converter",
        "k8s manifest generator",
        "compose to deployment and service",
        "yaml",
        "kubernetes",
        "docker-compose",
        "configmap",
        "persistentvolumeclaim",
        "ingress"
      ],
      "updated": "2026-08-21"
    },
    {
      "slug": "fountain-formatter",
      "name": "Fountain screenplay formatter",
      "description": "Format a pasted screenplay into clean Fountain markup, with scene headings, character cues and dialogue.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/fountain-formatter",
      "embed": "https://textarray.com/embed/fountain-formatter",
      "mode": "transform",
      "action": "Format screenplay",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "detectSceneHeadings",
          "kind": "checkbox",
          "label": "Detect scene headings (INT./EXT.)",
          "default": true
        },
        {
          "key": "uppercaseNames",
          "kind": "checkbox",
          "label": "Uppercase character names and transitions",
          "default": true
        },
        {
          "key": "alignDialogue",
          "kind": "checkbox",
          "label": "Align dialogue in preview",
          "default": true
        },
        {
          "key": "numberScenes",
          "kind": "checkbox",
          "label": "Number scenes",
          "default": false
        },
        {
          "key": "outputMode",
          "kind": "select",
          "label": "Output",
          "default": "fountain",
          "choices": [
            {
              "value": "fountain",
              "label": "Clean Fountain"
            },
            {
              "value": "preview",
              "label": "Readable preview"
            }
          ]
        },
        {
          "key": "showCharacterList",
          "kind": "checkbox",
          "label": "List characters and line counts",
          "default": false
        },
        {
          "key": "warnUnclassified",
          "kind": "checkbox",
          "label": "Flag lines that could not be classified",
          "default": true
        }
      ],
      "keywords": [
        "fountain formatter",
        "screenplay formatter",
        "fountain markup",
        "screenwriting",
        "scene heading",
        "script formatting",
        "fountain syntax",
        "character cue"
      ],
      "updated": "2026-08-22"
    },
    {
      "slug": "runic-text",
      "name": "Runic text (Elder Futhark)",
      "description": "Convert text to runic script and back, in three historical alphabets.",
      "category": "stylish-text",
      "categoryName": "Stylish text",
      "url": "https://textarray.com/runic-text",
      "embed": "https://textarray.com/embed/runic-text",
      "mode": "transform",
      "action": "Convert text",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "alphabet",
          "kind": "select",
          "label": "Runic alphabet",
          "default": "elder-futhark",
          "choices": [
            {
              "value": "elder-futhark",
              "label": "Elder Futhark"
            },
            {
              "value": "younger-futhark",
              "label": "Younger Futhark"
            },
            {
              "value": "anglo-saxon-futhorc",
              "label": "Anglo-Saxon Futhorc"
            }
          ]
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "to-runes",
          "choices": [
            {
              "value": "to-runes",
              "label": "To runes"
            },
            {
              "value": "to-latin",
              "label": "To Latin"
            }
          ]
        },
        {
          "key": "unmapped",
          "kind": "select",
          "label": "Letters without a rune",
          "default": "nearest",
          "choices": [
            {
              "value": "nearest",
              "label": "Use nearest rune"
            },
            {
              "value": "omit",
              "label": "Omit"
            },
            {
              "value": "keep",
              "label": "Keep as-is"
            }
          ]
        },
        {
          "key": "wordSeparator",
          "kind": "select",
          "label": "Word separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "dot",
              "label": "Period"
            },
            {
              "value": "colon",
              "label": "Colon"
            }
          ]
        },
        {
          "key": "keepPunctuation",
          "kind": "checkbox",
          "label": "Keep punctuation and numbers",
          "default": true
        },
        {
          "key": "transliterateDiacritics",
          "kind": "checkbox",
          "label": "Transliterate diacritics by sound",
          "default": true
        },
        {
          "key": "showTranscription",
          "kind": "checkbox",
          "label": "Add Latin transcription below",
          "default": false
        }
      ],
      "keywords": [
        "runic text",
        "elder futhark",
        "rune translator",
        "rune generator",
        "viking runes",
        "futhark alphabet",
        "younger futhark",
        "anglo-saxon futhorc",
        "runes translator"
      ],
      "updated": "2026-08-22"
    },
    {
      "slug": "latex-escape",
      "name": "LaTeX escape",
      "description": "Escape or unescape the characters LaTeX reserves for markup, so plain text compiles cleanly.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/latex-escape",
      "embed": "https://textarray.com/embed/latex-escape",
      "mode": "transform",
      "action": "Escape for LaTeX",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "escape",
          "choices": [
            {
              "value": "escape",
              "label": "Escape"
            },
            {
              "value": "unescape",
              "label": "Unescape"
            }
          ]
        },
        {
          "key": "chars",
          "kind": "text",
          "label": "Characters to process",
          "default": "#$%&_{}~^\\"
        },
        {
          "key": "convertQuotes",
          "kind": "checkbox",
          "label": "Convert straight quotes to LaTeX quotes",
          "default": false
        },
        {
          "key": "convertDashes",
          "kind": "checkbox",
          "label": "Convert dashes to -- / ---",
          "default": false
        },
        {
          "key": "preserveMath",
          "kind": "checkbox",
          "label": "Keep math environments untouched",
          "default": true
        },
        {
          "key": "diacritics",
          "kind": "select",
          "label": "Accented letters",
          "default": "utf8",
          "choices": [
            {
              "value": "utf8",
              "label": "Keep as UTF-8"
            },
            {
              "value": "commands",
              "label": "Convert to accent commands"
            }
          ]
        },
        {
          "key": "wrapVerbatim",
          "kind": "checkbox",
          "label": "Wrap result in a verbatim environment",
          "default": false
        },
        {
          "key": "warnBraces",
          "kind": "checkbox",
          "label": "Warn about unmatched braces",
          "default": true
        }
      ],
      "keywords": [
        "latex escape",
        "escape latex characters",
        "latex special characters",
        "unescape latex",
        "tex escape characters",
        "latex reserved characters",
        "latex",
        "overleaf",
        "bibtex"
      ],
      "updated": "2026-08-22"
    },
    {
      "slug": "semaphore-flags",
      "name": "Semaphore flag alphabet",
      "description": "Convert text to the flag semaphore alphabet and back to letters.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/semaphore-flags",
      "embed": "https://textarray.com/embed/semaphore-flags",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Text to semaphore"
            },
            {
              "value": "decode",
              "label": "Semaphore to text"
            }
          ]
        },
        {
          "key": "notation",
          "kind": "select",
          "label": "Flag position notation",
          "default": "compass",
          "choices": [
            {
              "value": "compass",
              "label": "Direction names (N, SW…)"
            },
            {
              "value": "clock",
              "label": "Clock hours (6:00, 7:30…)"
            },
            {
              "value": "arrows",
              "label": "Arrow characters (↓↙…)"
            }
          ]
        },
        {
          "key": "letterSeparator",
          "kind": "select",
          "label": "Letter separator",
          "default": "space",
          "choices": [
            {
              "value": "space",
              "label": "Space"
            },
            {
              "value": "dot",
              "label": "Middle dot"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        },
        {
          "key": "wordSeparator",
          "kind": "select",
          "label": "Word separator",
          "default": "slash",
          "choices": [
            {
              "value": "slash",
              "label": "Slash"
            },
            {
              "value": "doubleSpace",
              "label": "Extra spaces"
            },
            {
              "value": "pipe",
              "label": "Pipe"
            }
          ]
        },
        {
          "key": "digits",
          "kind": "select",
          "label": "Digits",
          "default": "numerals",
          "choices": [
            {
              "value": "numerals",
              "label": "Use the numerals shift"
            },
            {
              "value": "skip",
              "label": "Skip digits"
            }
          ]
        },
        {
          "key": "diacritics",
          "kind": "select",
          "label": "Accented letters",
          "default": "transliterate",
          "choices": [
            {
              "value": "transliterate",
              "label": "Convert to base letter"
            },
            {
              "value": "skip",
              "label": "Skip"
            }
          ]
        },
        {
          "key": "showTranscription",
          "kind": "checkbox",
          "label": "Show plain-letter transcription",
          "default": true
        },
        {
          "key": "showLegend",
          "kind": "checkbox",
          "label": "Show notation legend",
          "default": false
        }
      ],
      "keywords": [
        "semaphore flags",
        "semaphore alphabet",
        "flag semaphore",
        "semaphore code",
        "semaphore translator",
        "semaphore encoder",
        "semaphore decoder",
        "scout semaphore",
        "flag signalling"
      ],
      "updated": "2026-08-22"
    },
    {
      "slug": "rpg-encounter-generator",
      "name": "RPG encounter generator",
      "description": "Generate random tabletop encounters — who shows up, how many, and why.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/rpg-encounter-generator",
      "embed": "https://textarray.com/embed/rpg-encounter-generator",
      "mode": "generate",
      "action": "Generate encounters",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "environment",
          "kind": "select",
          "label": "Environment",
          "default": "forest",
          "choices": [
            {
              "value": "forest",
              "label": "Forest"
            },
            {
              "value": "dungeon",
              "label": "Dungeon"
            },
            {
              "value": "city",
              "label": "City"
            },
            {
              "value": "sea",
              "label": "Sea"
            },
            {
              "value": "desert",
              "label": "Desert"
            }
          ]
        },
        {
          "key": "difficulty",
          "kind": "select",
          "label": "Difficulty",
          "default": "medium",
          "choices": [
            {
              "value": "easy",
              "label": "Easy"
            },
            {
              "value": "medium",
              "label": "Medium"
            },
            {
              "value": "hard",
              "label": "Hard"
            },
            {
              "value": "deadly",
              "label": "Deadly"
            }
          ]
        },
        {
          "key": "partyLevel",
          "kind": "number",
          "label": "Party level",
          "default": 5,
          "min": 1,
          "max": 20,
          "step": 1
        },
        {
          "key": "encounterCount",
          "kind": "number",
          "label": "Encounters",
          "default": 1,
          "min": 1,
          "max": 10,
          "step": 1
        },
        {
          "key": "combatRatio",
          "kind": "range",
          "label": "% combat vs. social",
          "default": 60,
          "min": 0,
          "max": 100
        },
        {
          "key": "includeReason",
          "kind": "checkbox",
          "label": "Include why they are here",
          "default": true
        },
        {
          "key": "includeReward",
          "kind": "checkbox",
          "label": "Include a reward or find",
          "default": true
        },
        {
          "key": "customFoes",
          "kind": "text",
          "label": "Custom foes (comma-separated)",
          "default": ""
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output as",
          "default": "bullets",
          "choices": [
            {
              "value": "bullets",
              "label": "Bullets"
            },
            {
              "value": "paragraph",
              "label": "Paragraph"
            }
          ]
        }
      ],
      "keywords": [
        "rpg encounter generator",
        "random encounter generator",
        "tabletop encounter table",
        "dnd encounter generator",
        "dungeon master tools",
        "random monster generator",
        "ttrpg random encounter",
        "gm random encounters"
      ],
      "updated": "2026-08-22"
    },
    {
      "slug": "crossword-generator",
      "name": "Crossword generator",
      "description": "Turn a list of words and clues into an interlocking crossword puzzle with a numbered legend.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/crossword-generator",
      "embed": "https://textarray.com/embed/crossword-generator",
      "mode": "generate",
      "action": "Generate crossword",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "gridSize",
          "kind": "number",
          "label": "Grid size",
          "default": 15,
          "min": 5,
          "max": 30,
          "step": 1
        },
        {
          "key": "separator",
          "kind": "text",
          "label": "Word/clue separator",
          "default": ":"
        },
        {
          "key": "emptyChar",
          "kind": "text",
          "label": "Empty cell character",
          "default": "·"
        },
        {
          "key": "numbering",
          "kind": "checkbox",
          "label": "Number word starts",
          "default": true
        },
        {
          "key": "showSolution",
          "kind": "checkbox",
          "label": "Show filled solution",
          "default": false
        },
        {
          "key": "preferCompact",
          "kind": "select",
          "label": "Layout strategy",
          "default": "intersections",
          "choices": [
            {
              "value": "intersections",
              "label": "More intersections"
            },
            {
              "value": "compact",
              "label": "Smaller grid"
            }
          ]
        },
        {
          "key": "ignoreDiacritics",
          "kind": "checkbox",
          "label": "Ignore diacritics when composing",
          "default": false
        },
        {
          "key": "showSkipped",
          "kind": "checkbox",
          "label": "List words that couldn't be placed",
          "default": true
        }
      ],
      "keywords": [
        "crossword generator",
        "crossword maker",
        "crossword puzzle creator",
        "word and clue puzzle",
        "printable crossword",
        "crossword from word list",
        "crossword with clues",
        "make a crossword online"
      ],
      "updated": "2026-08-22"
    },
    {
      "slug": "cron-to-systemd-timer",
      "name": "Cron to systemd timer",
      "description": "Turn a cron expression into a ready-to-use systemd .timer and .service unit pair.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/cron-to-systemd-timer",
      "embed": "https://textarray.com/embed/cron-to-systemd-timer",
      "mode": "transform",
      "action": "Convert to systemd timer",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "unitName",
          "kind": "text",
          "label": "Unit name",
          "default": "backup"
        },
        {
          "key": "command",
          "kind": "text",
          "label": "Command to run",
          "default": "/usr/local/bin/backup.sh"
        },
        {
          "key": "user",
          "kind": "text",
          "label": "Run as user",
          "default": ""
        },
        {
          "key": "workDir",
          "kind": "text",
          "label": "Working directory",
          "default": ""
        },
        {
          "key": "randomizedDelay",
          "kind": "number",
          "label": "Randomized delay (seconds)",
          "default": 0,
          "min": 0,
          "max": 3600,
          "step": 30
        },
        {
          "key": "persistent",
          "kind": "checkbox",
          "label": "Catch up a missed run (Persistent)",
          "default": false
        },
        {
          "key": "timezone",
          "kind": "text",
          "label": "Time zone",
          "default": ""
        },
        {
          "key": "describe",
          "kind": "checkbox",
          "label": "Explain each schedule in plain language",
          "default": true
        }
      ],
      "keywords": [
        "cron to systemd timer",
        "systemd timer generator",
        "OnCalendar converter",
        "cron converter",
        "systemd service unit",
        "crontab to systemd",
        "systemd",
        "timer",
        "cron"
      ],
      "updated": "2026-08-23"
    },
    {
      "slug": "webpack-stats-analyzer",
      "name": "Webpack stats analyzer",
      "description": "Find which packages and modules take up the most space in a webpack build.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/webpack-stats-analyzer",
      "embed": "https://textarray.com/embed/webpack-stats-analyzer",
      "mode": "transform",
      "action": "Analyze stats.json",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "limit",
          "kind": "number",
          "label": "Rows to show",
          "default": 20,
          "min": 1,
          "max": 500,
          "step": 1
        },
        {
          "key": "groupBy",
          "kind": "select",
          "label": "Group by",
          "default": "package",
          "choices": [
            {
              "value": "package",
              "label": "node_modules package"
            },
            {
              "value": "folder",
              "label": "Folder"
            },
            {
              "value": "none",
              "label": "Individual module"
            }
          ]
        },
        {
          "key": "entryFilter",
          "kind": "text",
          "label": "Filter by entry point or chunk",
          "default": ""
        },
        {
          "key": "showCompressed",
          "kind": "checkbox",
          "label": "Show compressed size when available",
          "default": false
        },
        {
          "key": "showPercent",
          "kind": "checkbox",
          "label": "Show share of total size",
          "default": true
        },
        {
          "key": "flagDuplicates",
          "kind": "checkbox",
          "label": "Flag packages bundled in multiple versions",
          "default": true
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "webpack stats analyzer",
        "webpack bundle analyzer",
        "stats.json",
        "bundle size",
        "webpack modules",
        "node_modules size",
        "duplicate packages",
        "chunk size",
        "json",
        "csv"
      ],
      "updated": "2026-08-23"
    },
    {
      "slug": "sql-schema-diff",
      "name": "SQL schema diff",
      "description": "Compare two CREATE TABLE schemas and generate the ALTER TABLE migration between them.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sql-schema-diff",
      "embed": "https://textarray.com/embed/sql-schema-diff",
      "mode": "transform",
      "action": "Generate migration",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Target schema (CREATE TABLE)"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "dialect",
          "kind": "select",
          "label": "Database",
          "default": "postgres",
          "choices": [
            {
              "value": "postgres",
              "label": "PostgreSQL"
            },
            {
              "value": "mysql",
              "label": "MySQL"
            },
            {
              "value": "sqlite",
              "label": "SQLite"
            }
          ]
        },
        {
          "key": "includeIndexes",
          "kind": "checkbox",
          "label": "Include index changes",
          "default": true
        },
        {
          "key": "warnDataLoss",
          "kind": "checkbox",
          "label": "Warn about data loss",
          "default": true
        },
        {
          "key": "wrapInTransaction",
          "kind": "checkbox",
          "label": "Wrap in a transaction",
          "default": true
        },
        {
          "key": "reverseMigration",
          "kind": "checkbox",
          "label": "Also generate a rollback migration",
          "default": false
        },
        {
          "key": "comments",
          "kind": "checkbox",
          "label": "Explain each step with comments",
          "default": true
        }
      ],
      "keywords": [
        "sql schema diff",
        "sql migration generator",
        "alter table generator",
        "compare sql schemas",
        "database migration script",
        "schema comparison tool",
        "postgres migration",
        "mysql migration",
        "sqlite migration",
        "sql"
      ],
      "updated": "2026-08-23"
    },
    {
      "slug": "sql-dialect-converter",
      "name": "SQL dialect converter",
      "description": "Rewrite SQL between PostgreSQL, MySQL, SQLite and SQL Server syntax.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sql-dialect-converter",
      "embed": "https://textarray.com/embed/sql-dialect-converter",
      "mode": "transform",
      "action": "Convert SQL",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "from",
          "kind": "select",
          "label": "Source dialect",
          "default": "mysql",
          "choices": [
            {
              "value": "postgresql",
              "label": "PostgreSQL"
            },
            {
              "value": "mysql",
              "label": "MySQL"
            },
            {
              "value": "sqlite",
              "label": "SQLite"
            },
            {
              "value": "sqlserver",
              "label": "SQL Server"
            }
          ]
        },
        {
          "key": "to",
          "kind": "select",
          "label": "Target dialect",
          "default": "postgresql",
          "choices": [
            {
              "value": "postgresql",
              "label": "PostgreSQL"
            },
            {
              "value": "mysql",
              "label": "MySQL"
            },
            {
              "value": "sqlite",
              "label": "SQLite"
            },
            {
              "value": "sqlserver",
              "label": "SQL Server"
            }
          ]
        },
        {
          "key": "quoteIdentifiers",
          "kind": "checkbox",
          "label": "Normalize identifier quoting",
          "default": true
        },
        {
          "key": "convertLimit",
          "kind": "checkbox",
          "label": "Convert row limit clause",
          "default": true
        },
        {
          "key": "convertFunctions",
          "kind": "checkbox",
          "label": "Convert date and string functions",
          "default": true
        },
        {
          "key": "convertConcat",
          "kind": "checkbox",
          "label": "Convert string concatenation",
          "default": true
        },
        {
          "key": "convertTypes",
          "kind": "checkbox",
          "label": "Convert column types",
          "default": true
        },
        {
          "key": "keepComments",
          "kind": "checkbox",
          "label": "Keep comments",
          "default": true
        }
      ],
      "keywords": [
        "sql dialect converter",
        "convert sql",
        "sql syntax converter",
        "sql translator",
        "database migration",
        "postgresql",
        "mysql",
        "sqlite",
        "sql server",
        "tsql"
      ],
      "updated": "2026-08-23"
    },
    {
      "slug": "lockfile-inspector",
      "name": "Lockfile inspector",
      "description": "List every package in a lock file with its exact version and whether it's a direct or transitive dependency.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/lockfile-inspector",
      "embed": "https://textarray.com/embed/lockfile-inspector",
      "mode": "transform",
      "action": "Inspect lock file",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Second lock file (optional, to compare)"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Lock file format",
          "default": "npm",
          "choices": [
            {
              "value": "npm",
              "label": "package-lock.json (npm)"
            },
            {
              "value": "yarn",
              "label": "yarn.lock (Yarn)"
            },
            {
              "value": "pnpm",
              "label": "pnpm-lock.yaml (pnpm)"
            }
          ]
        },
        {
          "key": "sort",
          "kind": "select",
          "label": "Sort",
          "default": "name",
          "choices": [
            {
              "value": "name",
              "label": "Alphabetical"
            },
            {
              "value": "dependents",
              "label": "Most depended-on"
            }
          ]
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output as",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List"
            },
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        },
        {
          "key": "flagDuplicates",
          "kind": "checkbox",
          "label": "Flag packages present in multiple versions",
          "default": true
        },
        {
          "key": "filter",
          "kind": "text",
          "label": "Filter by name or scope",
          "default": ""
        }
      ],
      "keywords": [
        "lockfile inspector",
        "package-lock.json",
        "yarn.lock",
        "pnpm-lock.yaml",
        "list dependencies",
        "direct dependencies",
        "transitive dependencies",
        "duplicate package versions",
        "compare lock files",
        "npm",
        "yarn",
        "pnpm",
        "json",
        "yaml"
      ],
      "updated": "2026-08-23"
    },
    {
      "slug": "question-extractor",
      "name": "Question extractor",
      "description": "Pull every question out of a block of text and list it separately.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/question-extractor",
      "embed": "https://textarray.com/embed/question-extractor",
      "mode": "transform",
      "action": "Extract questions",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "detectByWord",
          "kind": "checkbox",
          "label": "Also detect questions without \"?\"",
          "default": false
        },
        {
          "key": "includeContext",
          "kind": "checkbox",
          "label": "Include the sentence before each question",
          "default": false
        },
        {
          "key": "groupByWord",
          "kind": "checkbox",
          "label": "Group by question word",
          "default": false
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicate questions",
          "default": true
        },
        {
          "key": "numbered",
          "kind": "checkbox",
          "label": "Number the list",
          "default": false
        },
        {
          "key": "order",
          "kind": "select",
          "label": "Order",
          "default": "original",
          "choices": [
            {
              "value": "original",
              "label": "Keep source order"
            },
            {
              "value": "length",
              "label": "Sort by length"
            }
          ]
        },
        {
          "key": "excludeRhetorical",
          "kind": "checkbox",
          "label": "Skip common rhetorical questions",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "Plain list"
            },
            {
              "value": "faq",
              "label": "FAQ section skeleton"
            }
          ]
        }
      ],
      "keywords": [
        "question extractor",
        "extract questions from text",
        "find questions in text",
        "list questions",
        "faq generator",
        "interrogative sentences",
        "question finder"
      ],
      "updated": "2026-08-24"
    },
    {
      "slug": "glossary-extractor",
      "name": "Definition and abbreviation extractor",
      "description": "Build a glossary automatically by finding where your text defines terms and abbreviations.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/glossary-extractor",
      "embed": "https://textarray.com/embed/glossary-extractor",
      "mode": "transform",
      "action": "Extract glossary",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "recognizeAbbreviations",
          "kind": "checkbox",
          "label": "Recognize abbreviations in parentheses",
          "default": true
        },
        {
          "key": "recognizeDefinitions",
          "kind": "checkbox",
          "label": "Recognize definition sentences",
          "default": true
        },
        {
          "key": "sortOrder",
          "kind": "select",
          "label": "Sort by",
          "default": "appearance",
          "choices": [
            {
              "value": "appearance",
              "label": "Order in text"
            },
            {
              "value": "alphabetical",
              "label": "Alphabetical"
            }
          ]
        },
        {
          "key": "showLocation",
          "kind": "checkbox",
          "label": "Show line and paragraph numbers",
          "default": false
        },
        {
          "key": "warnEarlyUse",
          "kind": "checkbox",
          "label": "Warn about abbreviations used before they're introduced",
          "default": true
        },
        {
          "key": "warnConflicts",
          "kind": "checkbox",
          "label": "Warn about abbreviations defined more than once",
          "default": true
        },
        {
          "key": "undefinedOnly",
          "kind": "checkbox",
          "label": "Undefined only",
          "default": false
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output as",
          "default": "glossary",
          "choices": [
            {
              "value": "glossary",
              "label": "Glossary"
            },
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "list",
              "label": "List"
            }
          ]
        }
      ],
      "keywords": [
        "glossary extractor",
        "extract definitions",
        "abbreviation extractor",
        "acronym extractor",
        "glossary generator",
        "definition finder",
        "extract acronyms from text",
        "find abbreviations"
      ],
      "updated": "2026-08-24"
    },
    {
      "slug": "citation-checker",
      "name": "Citation and bibliography checker",
      "description": "Compare the citations used in your text against your reference list and spot what does not line up.",
      "category": "text-manipulation",
      "categoryName": "Text manipulation",
      "url": "https://textarray.com/citation-checker",
      "embed": "https://textarray.com/embed/citation-checker",
      "mode": "transform",
      "action": "Check citations",
      "input": {
        "kind": "text",
        "panels": 2,
        "additionalPanels": [
          "Bibliography"
        ],
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "style",
          "kind": "select",
          "label": "Citation style",
          "default": "author-year",
          "choices": [
            {
              "value": "author-year",
              "label": "Author and year"
            },
            {
              "value": "numbered",
              "label": "Numbered [1]"
            },
            {
              "value": "footnote",
              "label": "Footnote [^1]"
            }
          ]
        },
        {
          "key": "ignoreDiacriticsAndAbbreviations",
          "kind": "checkbox",
          "label": "Ignore diacritics and name abbreviations",
          "default": true
        },
        {
          "key": "warnYearMismatch",
          "kind": "checkbox",
          "label": "Warn about year mismatches",
          "default": true
        },
        {
          "key": "countOccurrences",
          "kind": "checkbox",
          "label": "Count citation occurrences",
          "default": false
        },
        {
          "key": "warnDuplicateEntries",
          "kind": "checkbox",
          "label": "Warn about duplicate list entries",
          "default": true
        },
        {
          "key": "sortByTextOrder",
          "kind": "checkbox",
          "label": "Sort findings by order in text",
          "default": false
        }
      ],
      "keywords": [
        "citation checker",
        "bibliography checker",
        "citation verification",
        "reference checker",
        "check citations against bibliography",
        "missing citations",
        "unused references",
        "in-text citation checker",
        "apa citation checker",
        "reference list checker"
      ],
      "updated": "2026-08-24"
    },
    {
      "slug": "formality-checker",
      "name": "Formality consistency checker",
      "description": "Find places where formal and informal address switch inconsistently in your text.",
      "category": "text-cleaning",
      "categoryName": "Text cleaning",
      "url": "https://textarray.com/formality-checker",
      "embed": "https://textarray.com/embed/formality-checker",
      "mode": "transform",
      "action": "Check formality",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "language",
          "kind": "select",
          "label": "Text language",
          "default": "de",
          "choices": [
            {
              "value": "sk",
              "label": "Slovak"
            },
            {
              "value": "cs",
              "label": "Czech"
            },
            {
              "value": "de",
              "label": "German"
            },
            {
              "value": "pl",
              "label": "Polish"
            },
            {
              "value": "hu",
              "label": "Hungarian"
            },
            {
              "value": "fr",
              "label": "French"
            },
            {
              "value": "es",
              "label": "Spanish"
            }
          ]
        },
        {
          "key": "target",
          "kind": "select",
          "label": "Expected form",
          "default": "formal",
          "choices": [
            {
              "value": "informal",
              "label": "Informal (T)"
            },
            {
              "value": "formal",
              "label": "Formal (V)"
            },
            {
              "value": "neutral",
              "label": "Neither — impersonal"
            }
          ]
        },
        {
          "key": "ignoreQuotes",
          "kind": "checkbox",
          "label": "Ignore quotes and direct speech",
          "default": true
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "List of findings"
            },
            {
              "value": "highlighted",
              "label": "Highlighted text"
            }
          ]
        }
      ],
      "keywords": [
        "formality checker",
        "tykanie vykanie",
        "tu vs vous checker",
        "du vs sie checker",
        "formal informal address",
        "address form consistency",
        "honorific consistency checker",
        "T-V distinction checker"
      ],
      "updated": "2026-08-24"
    },
    {
      "slug": "srt-to-ttml",
      "name": "Subtitles to TTML",
      "description": "Convert SRT and VTT subtitles to TTML (DFXP) for broadcast and streaming platforms, or back again.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/srt-to-ttml",
      "embed": "https://textarray.com/embed/srt-to-ttml",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "to-ttml",
          "choices": [
            {
              "value": "to-ttml",
              "label": "SRT/VTT → TTML"
            },
            {
              "value": "to-srt",
              "label": "TTML → SRT"
            }
          ]
        },
        {
          "key": "profile",
          "kind": "select",
          "label": "TTML profile",
          "default": "dfxp",
          "choices": [
            {
              "value": "dfxp",
              "label": "DFXP (legacy)"
            },
            {
              "value": "imsc1",
              "label": "IMSC1"
            },
            {
              "value": "ebutt",
              "label": "EBU-TT"
            }
          ]
        },
        {
          "key": "timeNotation",
          "kind": "select",
          "label": "Time notation",
          "default": "clock",
          "choices": [
            {
              "value": "clock",
              "label": "Seconds (00:00:01.000)"
            },
            {
              "value": "frames",
              "label": "Hours and frames (00:00:01:00)"
            }
          ]
        },
        {
          "key": "frameRate",
          "kind": "number",
          "label": "Frame rate",
          "default": 25,
          "min": 1,
          "max": 120,
          "step": 0.001
        },
        {
          "key": "styleEncoding",
          "kind": "select",
          "label": "Italic/bold encoding",
          "default": "inline",
          "choices": [
            {
              "value": "inline",
              "label": "Inline attributes"
            },
            {
              "value": "referenced",
              "label": "Named styles"
            }
          ]
        },
        {
          "key": "keepStyles",
          "kind": "checkbox",
          "label": "Keep italic and bold formatting",
          "default": true
        },
        {
          "key": "position",
          "kind": "select",
          "label": "Subtitle position",
          "default": "bottom",
          "choices": [
            {
              "value": "bottom",
              "label": "Bottom of screen"
            },
            {
              "value": "top",
              "label": "Top of screen"
            }
          ]
        },
        {
          "key": "language",
          "kind": "text",
          "label": "Document language",
          "default": "en"
        },
        {
          "key": "warnIssues",
          "kind": "checkbox",
          "label": "Warn about overlaps and invalid times",
          "default": true
        }
      ],
      "keywords": [
        "srt to ttml",
        "ttml converter",
        "dfxp converter",
        "subtitle format converter",
        "ttml to srt",
        "closed caption format",
        "srt",
        "vtt",
        "ttml",
        "dfxp",
        "imsc1",
        "ebu-tt"
      ],
      "updated": "2026-08-24"
    },
    {
      "slug": "terraform-plan-summary",
      "name": "Terraform plan summary",
      "description": "Turn a terraform plan output into a clear summary of what gets created, changed, replaced or destroyed.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/terraform-plan-summary",
      "embed": "https://textarray.com/embed/terraform-plan-summary",
      "mode": "transform",
      "action": "Summarize plan",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "groupBy",
          "kind": "select",
          "label": "Group by",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "type",
              "label": "Resource type"
            },
            {
              "value": "module",
              "label": "Module"
            }
          ]
        },
        {
          "key": "onlyChanged",
          "kind": "checkbox",
          "label": "Show only changed attributes",
          "default": true
        },
        {
          "key": "highlightReplacements",
          "kind": "checkbox",
          "label": "Highlight resources marked for replacement",
          "default": true
        },
        {
          "key": "hideSensitive",
          "kind": "checkbox",
          "label": "Hide sensitive values",
          "default": true
        },
        {
          "key": "filterName",
          "kind": "text",
          "label": "Filter by resource name",
          "default": ""
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "summary",
          "choices": [
            {
              "value": "summary",
              "label": "Summary"
            },
            {
              "value": "markdown",
              "label": "Markdown (PR comment)"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "terraform plan summary",
        "terraform plan",
        "terraform",
        "infrastructure as code",
        "iac",
        "plan output",
        "pull request comment",
        "terraform diff",
        "markdown",
        "csv",
        "devops"
      ],
      "updated": "2026-08-24"
    },
    {
      "slug": "soft-hyphenation",
      "name": "Soft hyphenation",
      "description": "Insert invisible break points into long words so browsers can wrap them cleanly.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/soft-hyphenation",
      "embed": "https://textarray.com/embed/soft-hyphenation",
      "mode": "transform",
      "action": "Insert soft hyphens",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "language",
          "kind": "select",
          "label": "Language rules",
          "default": "en",
          "choices": [
            {
              "value": "en",
              "label": "English"
            },
            {
              "value": "de",
              "label": "German"
            },
            {
              "value": "sk",
              "label": "Slovak"
            },
            {
              "value": "cs",
              "label": "Czech"
            },
            {
              "value": "pl",
              "label": "Polish"
            },
            {
              "value": "hu",
              "label": "Hungarian"
            }
          ]
        },
        {
          "key": "minWordLength",
          "kind": "number",
          "label": "Minimum word length",
          "default": 5,
          "min": 1,
          "max": 20,
          "step": 1
        },
        {
          "key": "minBefore",
          "kind": "number",
          "label": "Minimum characters before break",
          "default": 2,
          "min": 1,
          "max": 6,
          "step": 1
        },
        {
          "key": "minAfter",
          "kind": "number",
          "label": "Minimum characters after break",
          "default": 2,
          "min": 1,
          "max": 6,
          "step": 1
        },
        {
          "key": "hyphenChar",
          "kind": "select",
          "label": "Break character",
          "default": "soft",
          "choices": [
            {
              "value": "soft",
              "label": "Soft hyphen (invisible)"
            },
            {
              "value": "visible",
              "label": "Visible hyphen (-)"
            },
            {
              "value": "bar",
              "label": "Vertical bar (|)"
            }
          ]
        },
        {
          "key": "skipUppercase",
          "kind": "checkbox",
          "label": "Skip ALL CAPS words",
          "default": true
        },
        {
          "key": "skipDigits",
          "kind": "checkbox",
          "label": "Skip words with digits",
          "default": true
        },
        {
          "key": "removeExisting",
          "kind": "checkbox",
          "label": "Remove existing soft hyphens first",
          "default": true
        },
        {
          "key": "breakdownOnly",
          "kind": "checkbox",
          "label": "Show word breakdown only",
          "default": false
        }
      ],
      "keywords": [
        "soft hyphenation",
        "soft hyphen",
        "insert hyphens",
        "discretionary hyphen",
        "word breaking",
        "shy character",
        "hyphenate text",
        "line break hyphenation"
      ],
      "updated": "2026-08-25"
    },
    {
      "slug": "text-to-slides",
      "name": "Text to presentation slides",
      "description": "Split plain text into Markdown slides for Marp or reveal.js.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/text-to-slides",
      "embed": "https://textarray.com/embed/text-to-slides",
      "mode": "transform",
      "action": "Generate slides",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "splitMode",
          "kind": "select",
          "label": "Split by",
          "default": "heading",
          "choices": [
            {
              "value": "heading",
              "label": "Headings"
            },
            {
              "value": "lines",
              "label": "Line count"
            }
          ]
        },
        {
          "key": "headingLevel",
          "kind": "number",
          "label": "Heading level",
          "default": 2,
          "min": 1,
          "max": 6,
          "step": 1
        },
        {
          "key": "linesPerSlide",
          "kind": "number",
          "label": "Lines per slide",
          "default": 6,
          "min": 1,
          "max": 50,
          "step": 1
        },
        {
          "key": "separator",
          "kind": "text",
          "label": "Slide separator",
          "default": "---"
        },
        {
          "key": "bulletsToPoints",
          "kind": "checkbox",
          "label": "Convert bullets to slide points",
          "default": true
        },
        {
          "key": "maxBullets",
          "kind": "number",
          "label": "Max bullets per slide",
          "default": 6,
          "min": 1,
          "max": 20,
          "step": 1
        },
        {
          "key": "speakerNotes",
          "kind": "checkbox",
          "label": "Add speaker notes from paragraphs",
          "default": false
        },
        {
          "key": "titleSlide",
          "kind": "checkbox",
          "label": "Generate title slide",
          "default": true
        },
        {
          "key": "tocSlide",
          "kind": "checkbox",
          "label": "Generate contents slide",
          "default": false
        },
        {
          "key": "numberSlides",
          "kind": "checkbox",
          "label": "Number slides",
          "default": false
        },
        {
          "key": "frontMatter",
          "kind": "checkbox",
          "label": "Add header (Marp front matter)",
          "default": false
        },
        {
          "key": "theme",
          "kind": "select",
          "label": "Theme",
          "default": "default",
          "choices": [
            {
              "value": "default",
              "label": "Default"
            },
            {
              "value": "gaia",
              "label": "Gaia"
            },
            {
              "value": "uncover",
              "label": "Uncover"
            }
          ]
        },
        {
          "key": "warnLongSlides",
          "kind": "checkbox",
          "label": "Warn on slides with too much text",
          "default": true
        }
      ],
      "keywords": [
        "text to slides",
        "markdown slides",
        "presentation generator",
        "marp",
        "reveal.js",
        "slide deck",
        "speaker notes",
        "markdown"
      ],
      "updated": "2026-08-25"
    },
    {
      "slug": "grade-calculator",
      "name": "Grade calculator",
      "description": "Turn a list of students and points into percentages and grades on your own scale.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/grade-calculator",
      "embed": "https://textarray.com/embed/grade-calculator",
      "mode": "transform",
      "action": "Calculate grades",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "maxPoints",
          "kind": "number",
          "label": "Maximum points",
          "default": 100,
          "min": 1,
          "step": 1
        },
        {
          "key": "bonusPoints",
          "kind": "number",
          "label": "Bonus points",
          "default": 0,
          "min": 0,
          "step": 1
        },
        {
          "key": "scaleType",
          "kind": "select",
          "label": "Grading scale",
          "default": "numeric15",
          "choices": [
            {
              "value": "numeric15",
              "label": "Numeric (1 best – 5 worst)"
            },
            {
              "value": "letterAF",
              "label": "Letter (A best – F worst)"
            },
            {
              "value": "passFail",
              "label": "Pass / fail"
            },
            {
              "value": "custom",
              "label": "Custom"
            }
          ]
        },
        {
          "key": "customScale",
          "kind": "text",
          "label": "Custom scale (threshold:grade, …)",
          "default": "90:A,80:B,70:C,60:D,0:F"
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Percent decimals",
          "default": 1,
          "min": 0,
          "max": 2,
          "step": 1
        },
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "points-desc",
          "choices": [
            {
              "value": "points-desc",
              "label": "Points (high to low)"
            },
            {
              "value": "points-asc",
              "label": "Points (low to high)"
            },
            {
              "value": "name",
              "label": "Name"
            }
          ]
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        },
        {
          "key": "includeStats",
          "kind": "checkbox",
          "label": "Show class statistics",
          "default": true
        }
      ],
      "keywords": [
        "grade calculator",
        "points to grade",
        "grading scale calculator",
        "exam grade calculator",
        "percentage to grade",
        "class grade distribution",
        "pass fail calculator",
        "letter grade calculator",
        "csv"
      ],
      "updated": "2026-08-25"
    },
    {
      "slug": "text-calendar-generator",
      "name": "Text calendar generator",
      "description": "Print a month or a full year as a plain-text calendar, aligned into columns.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/text-calendar-generator",
      "embed": "https://textarray.com/embed/text-calendar-generator",
      "mode": "generate",
      "action": "Generate calendar",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "month",
          "kind": "text",
          "label": "Month (1–12)",
          "default": ""
        },
        {
          "key": "year",
          "kind": "text",
          "label": "Year",
          "default": ""
        },
        {
          "key": "monthCount",
          "kind": "number",
          "label": "Number of months",
          "default": 1,
          "min": 1,
          "max": 24,
          "step": 1
        },
        {
          "key": "columns",
          "kind": "number",
          "label": "Months per row",
          "default": 1,
          "min": 1,
          "max": 6,
          "step": 1
        },
        {
          "key": "weekStart",
          "kind": "select",
          "label": "First day of week",
          "default": "monday",
          "choices": [
            {
              "value": "monday",
              "label": "Monday"
            },
            {
              "value": "sunday",
              "label": "Sunday"
            }
          ]
        },
        {
          "key": "language",
          "kind": "select",
          "label": "Names language",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Match page language"
            },
            {
              "value": "en",
              "label": "English"
            },
            {
              "value": "sk",
              "label": "Slovenčina"
            },
            {
              "value": "cs",
              "label": "Čeština"
            },
            {
              "value": "de",
              "label": "Deutsch"
            },
            {
              "value": "pl",
              "label": "Polski"
            },
            {
              "value": "hu",
              "label": "Magyar"
            },
            {
              "value": "es",
              "label": "Español"
            },
            {
              "value": "fr",
              "label": "Français"
            },
            {
              "value": "hr",
              "label": "Hrvatski"
            },
            {
              "value": "it",
              "label": "Italiano"
            },
            {
              "value": "nl",
              "label": "Nederlands"
            },
            {
              "value": "pt",
              "label": "Português"
            },
            {
              "value": "ro",
              "label": "Română"
            },
            {
              "value": "sl",
              "label": "Slovenščina"
            },
            {
              "value": "sv",
              "label": "Svenska"
            },
            {
              "value": "tr",
              "label": "Türkçe"
            },
            {
              "value": "ru",
              "label": "Русский"
            },
            {
              "value": "uk",
              "label": "Українська"
            }
          ]
        },
        {
          "key": "showWeekNumbers",
          "kind": "checkbox",
          "label": "Show week numbers",
          "default": false
        },
        {
          "key": "workdaysOnly",
          "kind": "checkbox",
          "label": "Workdays only",
          "default": false
        },
        {
          "key": "highlight",
          "kind": "text",
          "label": "Highlight dates",
          "default": ""
        },
        {
          "key": "style",
          "kind": "select",
          "label": "Layout",
          "default": "plain",
          "choices": [
            {
              "value": "plain",
              "label": "Spaced"
            },
            {
              "value": "boxed",
              "label": "Boxed"
            }
          ]
        }
      ],
      "keywords": [
        "text calendar generator",
        "ascii calendar",
        "monthly calendar text",
        "printable text calendar",
        "calendar for notes",
        "terminal calendar",
        "calendar with week numbers",
        "plain text calendar maker"
      ],
      "updated": "2026-08-25"
    },
    {
      "slug": "typescript-to-json-schema",
      "name": "TypeScript type to JSON Schema",
      "description": "Convert a TypeScript interface or type alias into JSON Schema.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/typescript-to-json-schema",
      "embed": "https://textarray.com/embed/typescript-to-json-schema",
      "mode": "transform",
      "action": "Convert to JSON Schema",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "schemaVersion",
          "kind": "select",
          "label": "Schema version",
          "default": "2020-12",
          "choices": [
            {
              "value": "draft-07",
              "label": "Draft-07"
            },
            {
              "value": "2020-12",
              "label": "2020-12"
            }
          ]
        },
        {
          "key": "literalUnionAsEnum",
          "kind": "checkbox",
          "label": "String unions as enum",
          "default": true
        },
        {
          "key": "noAdditionalProperties",
          "kind": "checkbox",
          "label": "Disallow additional properties",
          "default": false
        },
        {
          "key": "docCommentsAsDescriptions",
          "kind": "checkbox",
          "label": "Doc comments as descriptions",
          "default": true
        },
        {
          "key": "extractDefs",
          "kind": "checkbox",
          "label": "Extract nested types into definitions",
          "default": true
        }
      ],
      "keywords": [
        "typescript to json schema",
        "ts to json schema",
        "interface to json schema",
        "json schema generator",
        "typescript interface converter",
        "convert typescript type",
        "json schema",
        "typescript",
        "draft-07",
        "2020-12"
      ],
      "updated": "2026-08-25"
    },
    {
      "slug": "wiki-links-to-markdown",
      "name": "Wiki links to Markdown links",
      "description": "Convert [[wiki-style]] links to Markdown links, and back again.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/wiki-links-to-markdown",
      "embed": "https://textarray.com/embed/wiki-links-to-markdown",
      "mode": "transform",
      "action": "Convert links",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "wiki-to-markdown",
          "choices": [
            {
              "value": "wiki-to-markdown",
              "label": "Wiki links → Markdown"
            },
            {
              "value": "markdown-to-wiki",
              "label": "Markdown → Wiki links"
            }
          ]
        },
        {
          "key": "extension",
          "kind": "select",
          "label": "Target file extension",
          "default": "md",
          "choices": [
            {
              "value": "md",
              "label": ".md"
            },
            {
              "value": "html",
              "label": ".html"
            },
            {
              "value": "none",
              "label": "No extension"
            }
          ]
        },
        {
          "key": "spaceStyle",
          "kind": "select",
          "label": "Spaces in path",
          "default": "dash",
          "choices": [
            {
              "value": "dash",
              "label": "Convert to dashes"
            },
            {
              "value": "underscore",
              "label": "Convert to underscores"
            },
            {
              "value": "none",
              "label": "Keep as spaces"
            }
          ]
        },
        {
          "key": "encodeDiacritics",
          "kind": "checkbox",
          "label": "Percent-encode diacritics in the URL",
          "default": false
        },
        {
          "key": "convertEmbeds",
          "kind": "checkbox",
          "label": "Also convert embedded images ![[…]]",
          "default": true
        },
        {
          "key": "folderPrefix",
          "kind": "text",
          "label": "Folder prefix",
          "default": ""
        }
      ],
      "keywords": [
        "wiki links to markdown",
        "wikilink converter",
        "double bracket links",
        "obsidian links to markdown",
        "wiki link syntax",
        "markdown link converter",
        "wiki",
        "markdown"
      ],
      "updated": "2026-08-26"
    },
    {
      "slug": "sepa-qr-payment-generator",
      "name": "SEPA QR payment generator",
      "description": "Turn a name, IBAN and amount into a scannable SEPA (EPC069-12) payment QR code.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/sepa-qr-payment-generator",
      "embed": "https://textarray.com/embed/sepa-qr-payment-generator",
      "mode": "generate",
      "action": "Generate SEPA QR code",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "qr",
      "options": [
        {
          "key": "name",
          "kind": "text",
          "label": "Recipient name",
          "default": ""
        },
        {
          "key": "iban",
          "kind": "text",
          "label": "IBAN",
          "default": ""
        },
        {
          "key": "bic",
          "kind": "text",
          "label": "BIC (optional)",
          "default": ""
        },
        {
          "key": "amount",
          "kind": "number",
          "label": "Amount (EUR)",
          "default": 0,
          "min": 0,
          "max": 999999.99,
          "step": 0.01
        },
        {
          "key": "referenceType",
          "kind": "select",
          "label": "Reference type",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "unstructured",
              "label": "Unstructured (free text)"
            },
            {
              "value": "structured",
              "label": "Structured (creditor reference)"
            }
          ]
        },
        {
          "key": "reference",
          "kind": "text",
          "label": "Reference / variable symbol",
          "default": ""
        },
        {
          "key": "message",
          "kind": "text",
          "label": "Message to payer",
          "default": ""
        },
        {
          "key": "purpose",
          "kind": "text",
          "label": "Purpose code (optional)",
          "default": ""
        },
        {
          "key": "ecLevel",
          "kind": "select",
          "label": "Error correction",
          "default": "M",
          "choices": [
            {
              "value": "L",
              "label": "Low"
            },
            {
              "value": "M",
              "label": "Medium"
            },
            {
              "value": "Q",
              "label": "Quartile"
            },
            {
              "value": "H",
              "label": "High"
            }
          ]
        },
        {
          "key": "size",
          "kind": "select",
          "label": "QR size",
          "default": "medium",
          "choices": [
            {
              "value": "small",
              "label": "Small"
            },
            {
              "value": "medium",
              "label": "Medium"
            },
            {
              "value": "large",
              "label": "Large"
            }
          ]
        }
      ],
      "keywords": [
        "sepa qr code",
        "epc qr code",
        "girocode generator",
        "sepa payment qr",
        "bank transfer qr code",
        "epc069-12",
        "iban qr code",
        "sct qr code"
      ],
      "updated": "2026-08-26"
    },
    {
      "slug": "license-generator",
      "name": "License file generator",
      "description": "Generate the full text of an open-source license with your year and name filled in.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/license-generator",
      "embed": "https://textarray.com/embed/license-generator",
      "mode": "generate",
      "action": "Generate license",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "license",
          "kind": "select",
          "label": "License",
          "default": "mit",
          "choices": [
            {
              "value": "mit",
              "label": "MIT"
            },
            {
              "value": "apache-2.0",
              "label": "Apache License 2.0"
            },
            {
              "value": "gpl-3.0",
              "label": "GNU GPL v3.0"
            },
            {
              "value": "lgpl-3.0",
              "label": "GNU LGPL v3.0"
            },
            {
              "value": "mpl-2.0",
              "label": "Mozilla Public License 2.0"
            },
            {
              "value": "bsd-2-clause",
              "label": "BSD 2-Clause"
            },
            {
              "value": "bsd-3-clause",
              "label": "BSD 3-Clause"
            },
            {
              "value": "isc",
              "label": "ISC"
            },
            {
              "value": "unlicense",
              "label": "The Unlicense"
            },
            {
              "value": "cc0-1.0",
              "label": "CC0 1.0 (public domain)"
            }
          ]
        },
        {
          "key": "year",
          "kind": "text",
          "label": "Year or year range",
          "default": ""
        },
        {
          "key": "holder",
          "kind": "text",
          "label": "Copyright holder",
          "default": ""
        },
        {
          "key": "project",
          "kind": "text",
          "label": "Project name",
          "default": ""
        },
        {
          "key": "includeSpdxHeader",
          "kind": "checkbox",
          "label": "Add SPDX identifier and source-file header",
          "default": false
        },
        {
          "key": "includeSummary",
          "kind": "checkbox",
          "label": "Add a plain-language summary above the license",
          "default": false
        }
      ],
      "keywords": [
        "license generator",
        "open source license generator",
        "license file generator",
        "copyright notice generator",
        "spdx license identifier",
        "license.txt generator",
        "mit license",
        "apache 2.0",
        "gpl-3.0",
        "bsd license"
      ],
      "updated": "2026-08-26"
    },
    {
      "slug": "excel-formula-translator",
      "name": "Excel formula translator",
      "description": "Translate Excel formulas between English and localized function names.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/excel-formula-translator",
      "embed": "https://textarray.com/embed/excel-formula-translator",
      "mode": "transform",
      "action": "Translate formula",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "targetLanguage",
          "kind": "select",
          "label": "Target language",
          "default": "sk",
          "choices": [
            {
              "value": "sk",
              "label": "Slovenčina"
            },
            {
              "value": "cs",
              "label": "Čeština"
            },
            {
              "value": "de",
              "label": "Deutsch"
            },
            {
              "value": "pl",
              "label": "Polski"
            },
            {
              "value": "hu",
              "label": "Magyar"
            }
          ]
        },
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "toLocal",
          "choices": [
            {
              "value": "toLocal",
              "label": "English → local"
            },
            {
              "value": "toEnglish",
              "label": "Local → English"
            }
          ]
        },
        {
          "key": "separator",
          "kind": "select",
          "label": "Argument separator",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto (match direction)"
            },
            {
              "value": "comma",
              "label": "Comma ,"
            },
            {
              "value": "semicolon",
              "label": "Semicolon ;"
            }
          ]
        }
      ],
      "keywords": [
        "excel formula translator",
        "excel function names",
        "vlookup svyhledat",
        "sum suma",
        "if kdyz",
        "translate excel formulas",
        "localized excel functions",
        "excel language converter"
      ],
      "updated": "2026-08-26"
    },
    {
      "slug": "package-manager-converter",
      "name": "npm ⇄ yarn ⇄ pnpm converter",
      "description": "Convert an npm, yarn, pnpm, bun or deno command to the equivalent command in another package manager.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/package-manager-converter",
      "embed": "https://textarray.com/embed/package-manager-converter",
      "mode": "transform",
      "action": "Convert command",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "source",
          "kind": "select",
          "label": "Source manager",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "npm",
              "label": "npm"
            },
            {
              "value": "yarn-classic",
              "label": "Yarn classic"
            },
            {
              "value": "yarn-berry",
              "label": "Yarn berry"
            },
            {
              "value": "pnpm",
              "label": "pnpm"
            },
            {
              "value": "bun",
              "label": "Bun"
            },
            {
              "value": "deno",
              "label": "Deno"
            }
          ]
        },
        {
          "key": "target",
          "kind": "select",
          "label": "Target manager",
          "default": "pnpm",
          "choices": [
            {
              "value": "npm",
              "label": "npm"
            },
            {
              "value": "yarn-classic",
              "label": "Yarn classic"
            },
            {
              "value": "yarn-berry",
              "label": "Yarn berry"
            },
            {
              "value": "pnpm",
              "label": "pnpm"
            },
            {
              "value": "bun",
              "label": "Bun"
            },
            {
              "value": "deno",
              "label": "Deno"
            }
          ]
        },
        {
          "key": "preserveFlags",
          "kind": "checkbox",
          "label": "Preserve flags with no equivalent",
          "default": true
        },
        {
          "key": "warnUnmapped",
          "kind": "checkbox",
          "label": "Warn about flags with no equivalent",
          "default": true
        },
        {
          "key": "batch",
          "kind": "checkbox",
          "label": "Batch mode (convert every line)",
          "default": false
        }
      ],
      "keywords": [
        "npm to yarn",
        "yarn to pnpm",
        "pnpm to npm",
        "package manager converter",
        "npm install to yarn add",
        "bun add",
        "npm to deno",
        "deno add",
        "deno task",
        "npm",
        "yarn",
        "pnpm",
        "bun",
        "deno"
      ],
      "updated": "2026-08-26"
    },
    {
      "slug": "css-clamp-generator",
      "name": "CSS clamp() generator",
      "description": "Generate a fluid CSS clamp() value that scales smoothly between two viewport widths.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/css-clamp-generator",
      "embed": "https://textarray.com/embed/css-clamp-generator",
      "mode": "generate",
      "action": "Generate clamp()",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "minSize",
          "kind": "number",
          "label": "Minimum size",
          "default": 16,
          "min": 1,
          "max": 500,
          "step": 0.5
        },
        {
          "key": "maxSize",
          "kind": "number",
          "label": "Maximum size",
          "default": 32,
          "min": 1,
          "max": 500,
          "step": 0.5
        },
        {
          "key": "minWidth",
          "kind": "number",
          "label": "Minimum viewport width (px)",
          "default": 320,
          "min": 100,
          "max": 3000,
          "step": 10
        },
        {
          "key": "maxWidth",
          "kind": "number",
          "label": "Maximum viewport width (px)",
          "default": 1280,
          "min": 100,
          "max": 3000,
          "step": 10
        },
        {
          "key": "unit",
          "kind": "select",
          "label": "Unit",
          "default": "px",
          "choices": [
            {
              "value": "px",
              "label": "px"
            },
            {
              "value": "rem",
              "label": "rem"
            }
          ]
        },
        {
          "key": "rootFontSize",
          "kind": "number",
          "label": "Root font size (px, for rem)",
          "default": 16,
          "min": 8,
          "max": 32,
          "step": 1
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 2,
          "min": 0,
          "max": 4,
          "step": 1
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "declaration",
          "choices": [
            {
              "value": "declaration",
              "label": "CSS declaration"
            },
            {
              "value": "variable",
              "label": "CSS variable"
            },
            {
              "value": "tailwind",
              "label": "Tailwind class"
            }
          ]
        },
        {
          "key": "a11yCheck",
          "kind": "checkbox",
          "label": "Accessibility check",
          "default": true
        }
      ],
      "keywords": [
        "css clamp generator",
        "fluid typography",
        "responsive font size",
        "clamp() calculator",
        "fluid font size css",
        "vw font size",
        "css",
        "tailwind"
      ],
      "updated": "2026-08-26"
    },
    {
      "slug": "timezone-overlap",
      "name": "Time zone overlap finder",
      "description": "Find the hours when everyone across a list of time zones is in working hours.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/timezone-overlap",
      "embed": "https://textarray.com/embed/timezone-overlap",
      "mode": "transform",
      "action": "Find overlap",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "workStart",
          "kind": "number",
          "label": "Working hours start",
          "default": 9,
          "min": 0,
          "max": 23
        },
        {
          "key": "workEnd",
          "kind": "number",
          "label": "Working hours end",
          "default": 17,
          "min": 1,
          "max": 24
        },
        {
          "key": "windowHours",
          "kind": "number",
          "label": "Minimum overlap length (hours)",
          "default": 1,
          "min": 1,
          "max": 12
        },
        {
          "key": "date",
          "kind": "text",
          "label": "Date (for daylight saving)",
          "default": ""
        },
        {
          "key": "outputMode",
          "kind": "select",
          "label": "Output format",
          "default": "grid",
          "choices": [
            {
              "value": "grid",
              "label": "24-hour grid"
            },
            {
              "value": "list",
              "label": "List of suitable times"
            }
          ]
        },
        {
          "key": "hourFormat",
          "kind": "select",
          "label": "Time format",
          "default": "24",
          "choices": [
            {
              "value": "24",
              "label": "24-hour"
            },
            {
              "value": "12",
              "label": "12-hour"
            }
          ]
        }
      ],
      "keywords": [
        "time zone overlap",
        "meeting time finder",
        "overlapping working hours",
        "schedule across time zones",
        "best time to meet remote team",
        "world clock overlap",
        "timezone overlap calculator",
        "business hours across time zones"
      ],
      "updated": "2026-08-27"
    },
    {
      "slug": "jwt-generator",
      "name": "JWT generator",
      "description": "Build and sign a JSON Web Token with HMAC, right in your browser.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/jwt-generator",
      "embed": "https://textarray.com/embed/jwt-generator",
      "mode": "transform",
      "action": "Generate token",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "algorithm",
          "kind": "select",
          "label": "Algorithm",
          "default": "HS256",
          "choices": [
            {
              "value": "HS256",
              "label": "HS256"
            },
            {
              "value": "HS384",
              "label": "HS384"
            },
            {
              "value": "HS512",
              "label": "HS512"
            }
          ]
        },
        {
          "key": "secret",
          "kind": "text",
          "label": "Secret key",
          "default": "",
          "secret": true
        },
        {
          "key": "addIat",
          "kind": "checkbox",
          "label": "Add iat (issued at)",
          "default": true
        },
        {
          "key": "expiresIn",
          "kind": "select",
          "label": "Expires in",
          "default": "1h",
          "choices": [
            {
              "value": "none",
              "label": "No expiry"
            },
            {
              "value": "15m",
              "label": "15 minutes"
            },
            {
              "value": "1h",
              "label": "1 hour"
            },
            {
              "value": "24h",
              "label": "24 hours"
            },
            {
              "value": "7d",
              "label": "7 days"
            },
            {
              "value": "30d",
              "label": "30 days"
            }
          ]
        },
        {
          "key": "addNbf",
          "kind": "checkbox",
          "label": "Add nbf (not before)",
          "default": false
        },
        {
          "key": "sub",
          "kind": "text",
          "label": "Subject (sub)",
          "default": ""
        },
        {
          "key": "iss",
          "kind": "text",
          "label": "Issuer (iss)",
          "default": ""
        },
        {
          "key": "prettyPayload",
          "kind": "checkbox",
          "label": "Pretty-print payload",
          "default": false
        },
        {
          "key": "verify",
          "kind": "checkbox",
          "label": "Verify signature after signing",
          "default": true
        }
      ],
      "keywords": [
        "jwt generator",
        "generate jwt",
        "create jwt token",
        "json web token generator",
        "hmac jwt",
        "sign jwt",
        "jwt encoder",
        "jwt",
        "hs256",
        "base64",
        "json"
      ],
      "updated": "2026-08-27"
    },
    {
      "slug": "llms-txt-generator",
      "name": "llms.txt generator",
      "description": "Turn a list of pages into an llms.txt file that large language models can read.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/llms-txt-generator",
      "embed": "https://textarray.com/embed/llms-txt-generator",
      "mode": "transform",
      "action": "Generate llms.txt",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "siteName",
          "kind": "text",
          "label": "Site name",
          "default": ""
        },
        {
          "key": "summary",
          "kind": "text",
          "label": "Summary",
          "default": ""
        },
        {
          "key": "section",
          "kind": "select",
          "label": "Default section",
          "default": "docs",
          "choices": [
            {
              "value": "docs",
              "label": "Docs"
            },
            {
              "value": "api",
              "label": "API"
            },
            {
              "value": "blog",
              "label": "Blog"
            },
            {
              "value": "optional",
              "label": "Optional"
            }
          ]
        },
        {
          "key": "includeDescriptions",
          "kind": "checkbox",
          "label": "Include descriptions",
          "default": true
        },
        {
          "key": "urlMode",
          "kind": "select",
          "label": "Links",
          "default": "as-is",
          "choices": [
            {
              "value": "as-is",
              "label": "Keep as-is"
            },
            {
              "value": "absolute",
              "label": "Make absolute"
            },
            {
              "value": "relative",
              "label": "Make relative"
            }
          ]
        },
        {
          "key": "baseUrl",
          "kind": "text",
          "label": "Site URL",
          "default": ""
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Remove duplicate links",
          "default": true
        }
      ],
      "keywords": [
        "llms.txt generator",
        "llms.txt",
        "llms.txt format",
        "ai crawler file",
        "sitemap to llms.txt",
        "markdown link list",
        "create llms.txt",
        "sitemap.xml",
        "markdown"
      ],
      "updated": "2026-08-27"
    },
    {
      "slug": "color-blindness-simulator",
      "name": "Color blindness simulator",
      "description": "See how a color looks to someone with color vision deficiency.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/color-blindness-simulator",
      "embed": "https://textarray.com/embed/color-blindness-simulator",
      "mode": "transform",
      "action": "Simulate",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "type",
          "kind": "select",
          "label": "Deficiency type",
          "default": "deuteranopia",
          "choices": [
            {
              "value": "protanopia",
              "label": "Protanopia (no red)"
            },
            {
              "value": "deuteranopia",
              "label": "Deuteranopia (no green)"
            },
            {
              "value": "tritanopia",
              "label": "Tritanopia (no blue)"
            },
            {
              "value": "protanomaly",
              "label": "Protanomaly (weak red)"
            },
            {
              "value": "deuteranomaly",
              "label": "Deuteranomaly (weak green)"
            },
            {
              "value": "tritanomaly",
              "label": "Tritanomaly (weak blue)"
            },
            {
              "value": "achromatopsia",
              "label": "Achromatopsia (no color)"
            },
            {
              "value": "achromatomaly",
              "label": "Achromatomaly (weak color)"
            }
          ]
        },
        {
          "key": "strength",
          "kind": "range",
          "label": "Simulation strength",
          "default": 100,
          "min": 0,
          "max": 100
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "hex",
          "choices": [
            {
              "value": "hex",
              "label": "HEX"
            },
            {
              "value": "rgb",
              "label": "RGB"
            },
            {
              "value": "hsl",
              "label": "HSL"
            }
          ]
        }
      ],
      "keywords": [
        "color blindness simulator",
        "colour blindness simulator",
        "protanopia",
        "deuteranopia",
        "tritanopia",
        "achromatopsia",
        "color vision deficiency",
        "colorblind checker",
        "hex",
        "rgb",
        "hsl"
      ],
      "updated": "2026-08-27"
    },
    {
      "slug": "dmarc-report-analyzer",
      "name": "DMARC report analyzer",
      "description": "Turn a DMARC aggregate report XML into a readable table of senders, results and policy.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/dmarc-report-analyzer",
      "embed": "https://textarray.com/embed/dmarc-report-analyzer",
      "mode": "transform",
      "action": "Analyze report",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "sortBy",
          "kind": "select",
          "label": "Sort by",
          "default": "count",
          "choices": [
            {
              "value": "count",
              "label": "Message count"
            },
            {
              "value": "ip",
              "label": "Sending IP"
            }
          ]
        },
        {
          "key": "failuresOnly",
          "kind": "checkbox",
          "label": "Show only failures",
          "default": false
        },
        {
          "key": "showSummary",
          "kind": "checkbox",
          "label": "Show pass-rate summary",
          "default": true
        },
        {
          "key": "detectForwarded",
          "kind": "checkbox",
          "label": "Flag likely forwarded mail",
          "default": false
        },
        {
          "key": "groupByDomain",
          "kind": "checkbox",
          "label": "Group by sending domain",
          "default": false
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table"
            },
            {
              "value": "csv",
              "label": "CSV"
            }
          ]
        }
      ],
      "keywords": [
        "dmarc report analyzer",
        "dmarc rua report",
        "dmarc xml parser",
        "dmarc aggregate report",
        "spf dkim report",
        "email authentication report",
        "xml",
        "csv"
      ],
      "updated": "2026-08-27"
    },
    {
      "slug": "sql-to-dbml",
      "name": "SQL schema to DBML",
      "description": "Turn CREATE TABLE statements into a DBML diagram definition.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/sql-to-dbml",
      "embed": "https://textarray.com/embed/sql-to-dbml",
      "mode": "transform",
      "action": "Convert to DBML",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "dialect",
          "kind": "select",
          "label": "Source dialect",
          "default": "postgresql",
          "choices": [
            {
              "value": "postgresql",
              "label": "PostgreSQL"
            },
            {
              "value": "mysql",
              "label": "MySQL"
            },
            {
              "value": "sqlite",
              "label": "SQLite"
            },
            {
              "value": "sqlserver",
              "label": "SQL Server"
            }
          ]
        },
        {
          "key": "mapTypes",
          "kind": "checkbox",
          "label": "Map types to canonical DBML types",
          "default": true
        },
        {
          "key": "keepComments",
          "kind": "checkbox",
          "label": "Keep comments as Note",
          "default": true
        },
        {
          "key": "inferRelationsByNaming",
          "kind": "checkbox",
          "label": "Infer relationships from column names (user_id)",
          "default": false
        },
        {
          "key": "groupByPrefix",
          "kind": "checkbox",
          "label": "Group tables by name prefix",
          "default": false
        }
      ],
      "keywords": [
        "sql to dbml",
        "dbml generator",
        "database diagram",
        "schema visualization",
        "create table to dbml",
        "dbdiagram.io",
        "entity relationship diagram",
        "sql",
        "dbml",
        "mysql",
        "postgresql",
        "sqlite"
      ],
      "updated": "2026-08-27"
    },
    {
      "slug": "markdown-callout-converter",
      "name": "Markdown callout converter",
      "description": "Convert callout and admonition blocks between GitHub, Obsidian, Docusaurus and MkDocs syntax.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/markdown-callout-converter",
      "embed": "https://textarray.com/embed/markdown-callout-converter",
      "mode": "transform",
      "action": "Convert callouts",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "source",
          "kind": "select",
          "label": "Source notation",
          "default": "github",
          "choices": [
            {
              "value": "github",
              "label": "GitHub alerts"
            },
            {
              "value": "obsidian",
              "label": "Obsidian callouts"
            },
            {
              "value": "docusaurus",
              "label": "Docusaurus admonitions"
            },
            {
              "value": "mkdocs",
              "label": "MkDocs admonitions"
            }
          ]
        },
        {
          "key": "target",
          "kind": "select",
          "label": "Target notation",
          "default": "obsidian",
          "choices": [
            {
              "value": "github",
              "label": "GitHub alerts"
            },
            {
              "value": "obsidian",
              "label": "Obsidian callouts"
            },
            {
              "value": "docusaurus",
              "label": "Docusaurus admonitions"
            },
            {
              "value": "mkdocs",
              "label": "MkDocs admonitions"
            }
          ]
        },
        {
          "key": "keepCustomTitle",
          "kind": "checkbox",
          "label": "Keep custom block title",
          "default": true
        },
        {
          "key": "keepFoldable",
          "kind": "checkbox",
          "label": "Keep foldable/collapsible state",
          "default": true
        },
        {
          "key": "normalizeTypes",
          "kind": "checkbox",
          "label": "Normalize block type to note/tip/warning/danger/info",
          "default": false
        }
      ],
      "keywords": [
        "markdown callout converter",
        "admonition converter",
        "github alert syntax",
        "obsidian callout",
        "docusaurus admonition",
        "mkdocs admonition",
        "callout block converter",
        "markdown",
        "github",
        "obsidian",
        "docusaurus",
        "mkdocs"
      ],
      "updated": "2026-08-28"
    },
    {
      "slug": "ssml-generator",
      "name": "SSML markup generator",
      "description": "Wrap plain text in valid SSML tags for text-to-speech: pauses, emphasis, pronunciation and pacing.",
      "category": "text-formatting",
      "categoryName": "Text formatting",
      "url": "https://textarray.com/ssml-generator",
      "embed": "https://textarray.com/embed/ssml-generator",
      "mode": "transform",
      "action": "Generate SSML",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "pauseSentenceMs",
          "kind": "number",
          "label": "Pause between sentences (ms)",
          "default": 500,
          "min": 0,
          "max": 3000,
          "step": 50
        },
        {
          "key": "pauseParagraphMs",
          "kind": "number",
          "label": "Pause between paragraphs (ms)",
          "default": 750,
          "min": 0,
          "max": 5000,
          "step": 50
        },
        {
          "key": "rate",
          "kind": "select",
          "label": "Speaking rate",
          "default": "medium",
          "choices": [
            {
              "value": "x-slow",
              "label": "Extra slow"
            },
            {
              "value": "slow",
              "label": "Slow"
            },
            {
              "value": "medium",
              "label": "Medium"
            },
            {
              "value": "fast",
              "label": "Fast"
            },
            {
              "value": "x-fast",
              "label": "Extra fast"
            }
          ]
        },
        {
          "key": "pitch",
          "kind": "select",
          "label": "Pitch",
          "default": "medium",
          "choices": [
            {
              "value": "x-low",
              "label": "Extra low"
            },
            {
              "value": "low",
              "label": "Low"
            },
            {
              "value": "medium",
              "label": "Medium"
            },
            {
              "value": "high",
              "label": "High"
            },
            {
              "value": "x-high",
              "label": "Extra high"
            }
          ]
        },
        {
          "key": "emphasisMarkers",
          "kind": "checkbox",
          "label": "Emphasize *starred* words",
          "default": true
        },
        {
          "key": "sayAsAcronyms",
          "kind": "checkbox",
          "label": "Spell out ALLCAPS acronyms (say-as)",
          "default": true
        },
        {
          "key": "dictionaryMode",
          "kind": "select",
          "label": "Pronunciation dictionary tag",
          "default": "sub",
          "choices": [
            {
              "value": "sub",
              "label": "Substitution (sub)"
            },
            {
              "value": "phoneme",
              "label": "Phoneme (IPA)"
            }
          ]
        },
        {
          "key": "dictionary",
          "kind": "text",
          "label": "Custom pronunciation dictionary",
          "default": ""
        },
        {
          "key": "platform",
          "kind": "select",
          "label": "Target platform",
          "default": "generic",
          "choices": [
            {
              "value": "generic",
              "label": "Generic SSML"
            },
            {
              "value": "polly",
              "label": "Amazon Polly"
            },
            {
              "value": "google",
              "label": "Google Cloud TTS"
            },
            {
              "value": "azure",
              "label": "Azure Speech"
            }
          ]
        },
        {
          "key": "validateXml",
          "kind": "checkbox",
          "label": "Check XML validity",
          "default": true
        }
      ],
      "keywords": [
        "ssml generator",
        "ssml markup",
        "text to speech markup",
        "speech synthesis markup language",
        "amazon polly ssml",
        "google cloud tts ssml",
        "azure speech ssml",
        "say-as",
        "phoneme",
        "prosody rate pitch"
      ],
      "updated": "2026-08-31"
    },
    {
      "slug": "markdown-to-latex",
      "name": "Markdown to LaTeX",
      "description": "Convert Markdown into LaTeX source ready to compile.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/markdown-to-latex",
      "embed": "https://textarray.com/embed/markdown-to-latex",
      "mode": "transform",
      "action": "Convert to LaTeX",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "documentClass",
          "kind": "select",
          "label": "Document class",
          "default": "article",
          "choices": [
            {
              "value": "article",
              "label": "Article"
            },
            {
              "value": "report",
              "label": "Report"
            },
            {
              "value": "beamer",
              "label": "Beamer"
            },
            {
              "value": "fragment",
              "label": "Fragment (no preamble)"
            }
          ]
        },
        {
          "key": "codePackage",
          "kind": "select",
          "label": "Code package",
          "default": "listings",
          "choices": [
            {
              "value": "verbatim",
              "label": "verbatim"
            },
            {
              "value": "listings",
              "label": "listings"
            },
            {
              "value": "minted",
              "label": "minted"
            }
          ]
        },
        {
          "key": "escapeSpecial",
          "kind": "checkbox",
          "label": "Escape special characters",
          "default": true
        }
      ],
      "keywords": [
        "markdown to latex",
        "md to tex",
        "markdown to tex converter",
        "latex converter",
        "markdown latex",
        "tex source",
        "markdown",
        "latex"
      ],
      "updated": "2026-08-29"
    },
    {
      "slug": "uuencode",
      "name": "UUencode / UUdecode",
      "description": "Convert text or binary data to a uuencoded ASCII block, or decode one back.",
      "category": "encoding",
      "categoryName": "Encoding & conversion",
      "url": "https://textarray.com/uuencode",
      "embed": "https://textarray.com/embed/uuencode",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "mode",
          "kind": "select",
          "label": "Direction",
          "default": "encode",
          "choices": [
            {
              "value": "encode",
              "label": "Encode"
            },
            {
              "value": "decode",
              "label": "Decode"
            }
          ]
        },
        {
          "key": "filename",
          "kind": "text",
          "label": "File name (encode)",
          "default": "file.txt"
        },
        {
          "key": "permissions",
          "kind": "select",
          "label": "File permissions (encode)",
          "default": "644",
          "choices": [
            {
              "value": "644",
              "label": "644 (rw-r--r--)"
            },
            {
              "value": "600",
              "label": "600 (rw-------)"
            },
            {
              "value": "664",
              "label": "664 (rw-rw-r--)"
            },
            {
              "value": "755",
              "label": "755 (rwxr-xr-x)"
            },
            {
              "value": "777",
              "label": "777 (rwxrwxrwx)"
            }
          ]
        },
        {
          "key": "lineLength",
          "kind": "number",
          "label": "Bytes per line (encode)",
          "default": 45,
          "min": 1,
          "max": 45,
          "step": 1
        },
        {
          "key": "xxencode",
          "kind": "checkbox",
          "label": "Use xxencode alphabet",
          "default": false
        },
        {
          "key": "tolerateMissingFooter",
          "kind": "checkbox",
          "label": "Allow missing \"end\" footer (decode)",
          "default": true
        }
      ],
      "keywords": [
        "uuencode",
        "uudecode",
        "xxencode",
        "unix-to-unix encoding",
        "begin end block",
        "ascii text encoding",
        "binary to text",
        "usenet attachment"
      ],
      "updated": "2026-08-28"
    },
    {
      "slug": "video-schema-generator",
      "name": "VideoObject schema generator",
      "description": "Turn video details into a valid schema.org VideoObject JSON-LD block for rich results.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/video-schema-generator",
      "embed": "https://textarray.com/embed/video-schema-generator",
      "mode": "generate",
      "action": "Generate schema",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "name",
          "kind": "text",
          "label": "Video title",
          "default": ""
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "thumbnailUrl",
          "kind": "text",
          "label": "Thumbnail URL(s)",
          "default": ""
        },
        {
          "key": "uploadDate",
          "kind": "text",
          "label": "Upload date",
          "default": ""
        },
        {
          "key": "duration",
          "kind": "text",
          "label": "Duration (ISO 8601)",
          "default": ""
        },
        {
          "key": "contentUrl",
          "kind": "text",
          "label": "Video file URL",
          "default": ""
        },
        {
          "key": "embedUrl",
          "kind": "text",
          "label": "Player URL",
          "default": ""
        },
        {
          "key": "authorType",
          "kind": "select",
          "label": "Author type",
          "default": "Person",
          "choices": [
            {
              "value": "Person",
              "label": "Person"
            },
            {
              "value": "Organization",
              "label": "Organization"
            }
          ]
        },
        {
          "key": "authorName",
          "kind": "text",
          "label": "Author name",
          "default": ""
        },
        {
          "key": "authorUrl",
          "kind": "text",
          "label": "Author URL",
          "default": ""
        },
        {
          "key": "publisherName",
          "kind": "text",
          "label": "Publisher name",
          "default": ""
        },
        {
          "key": "publisherLogoUrl",
          "kind": "text",
          "label": "Publisher logo URL",
          "default": ""
        },
        {
          "key": "transcript",
          "kind": "text",
          "label": "Transcript",
          "default": ""
        },
        {
          "key": "chapters",
          "kind": "text",
          "label": "Chapters",
          "default": ""
        },
        {
          "key": "chapterMode",
          "kind": "select",
          "label": "Chapters as",
          "default": "clip",
          "choices": [
            {
              "value": "clip",
              "label": "Clip list (hasPart)"
            },
            {
              "value": "seek",
              "label": "Jump-to actions (SeekToAction)"
            }
          ]
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print JSON",
          "default": true
        },
        {
          "key": "wrapScript",
          "kind": "checkbox",
          "label": "Wrap in <script> tag",
          "default": true
        }
      ],
      "keywords": [
        "video schema generator",
        "videoobject schema",
        "video structured data",
        "video rich results",
        "schema.org video",
        "json-ld video",
        "video seo markup",
        "json"
      ],
      "updated": "2026-08-29"
    },
    {
      "slug": "job-posting-schema-generator",
      "name": "JobPosting schema generator",
      "description": "Turn job-listing details into valid schema.org JobPosting JSON-LD.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/job-posting-schema-generator",
      "embed": "https://textarray.com/embed/job-posting-schema-generator",
      "mode": "generate",
      "action": "Generate schema",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "title",
          "kind": "text",
          "label": "Job title",
          "default": ""
        },
        {
          "key": "description",
          "kind": "text",
          "label": "Description",
          "default": ""
        },
        {
          "key": "companyName",
          "kind": "text",
          "label": "Employer name",
          "default": ""
        },
        {
          "key": "companyLogo",
          "kind": "text",
          "label": "Employer logo URL",
          "default": ""
        },
        {
          "key": "companyUrl",
          "kind": "text",
          "label": "Employer website URL",
          "default": ""
        },
        {
          "key": "remote",
          "kind": "checkbox",
          "label": "Remote / telecommute job",
          "default": false
        },
        {
          "key": "remoteRegion",
          "kind": "text",
          "label": "Applicants must be based in",
          "default": ""
        },
        {
          "key": "streetAddress",
          "kind": "text",
          "label": "Street address",
          "default": ""
        },
        {
          "key": "addressLocality",
          "kind": "text",
          "label": "City",
          "default": ""
        },
        {
          "key": "addressRegion",
          "kind": "text",
          "label": "State / region",
          "default": ""
        },
        {
          "key": "postalCode",
          "kind": "text",
          "label": "Postal code",
          "default": ""
        },
        {
          "key": "addressCountry",
          "kind": "text",
          "label": "Country code",
          "default": ""
        },
        {
          "key": "employmentType",
          "kind": "select",
          "label": "Employment type",
          "default": "",
          "choices": [
            {
              "value": "",
              "label": "Not specified"
            },
            {
              "value": "FULL_TIME",
              "label": "Full-time"
            },
            {
              "value": "PART_TIME",
              "label": "Part-time"
            },
            {
              "value": "CONTRACTOR",
              "label": "Contractor"
            },
            {
              "value": "TEMPORARY",
              "label": "Temporary"
            },
            {
              "value": "INTERN",
              "label": "Internship"
            },
            {
              "value": "VOLUNTEER",
              "label": "Volunteer"
            },
            {
              "value": "PER_DIEM",
              "label": "Per diem"
            },
            {
              "value": "OTHER",
              "label": "Other"
            }
          ]
        },
        {
          "key": "salaryMin",
          "kind": "number",
          "label": "Salary minimum",
          "default": 0,
          "min": 0
        },
        {
          "key": "salaryMax",
          "kind": "number",
          "label": "Salary maximum",
          "default": 0,
          "min": 0
        },
        {
          "key": "currency",
          "kind": "text",
          "label": "Currency",
          "default": "USD"
        },
        {
          "key": "salaryUnit",
          "kind": "select",
          "label": "Salary unit",
          "default": "YEAR",
          "choices": [
            {
              "value": "HOUR",
              "label": "Per hour"
            },
            {
              "value": "DAY",
              "label": "Per day"
            },
            {
              "value": "WEEK",
              "label": "Per week"
            },
            {
              "value": "MONTH",
              "label": "Per month"
            },
            {
              "value": "YEAR",
              "label": "Per year"
            }
          ]
        },
        {
          "key": "datePosted",
          "kind": "text",
          "label": "Date posted",
          "default": ""
        },
        {
          "key": "validThrough",
          "kind": "text",
          "label": "Valid through",
          "default": ""
        },
        {
          "key": "identifier",
          "kind": "text",
          "label": "Job ID",
          "default": ""
        },
        {
          "key": "wrapScript",
          "kind": "checkbox",
          "label": "Wrap in <script> tag",
          "default": true
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print",
          "default": true
        }
      ],
      "keywords": [
        "jobposting schema generator",
        "job posting schema markup",
        "schema.org jobposting",
        "google jobs structured data",
        "job posting json-ld",
        "rich results for jobs",
        "json-ld",
        "json"
      ],
      "updated": "2026-09-01"
    },
    {
      "slug": "discord-timestamp-generator",
      "name": "Discord timestamp generator",
      "description": "Build Discord’s dynamic <t:...> timestamp markup, shown in each reader’s own time zone.",
      "category": "generators",
      "categoryName": "Random generators",
      "url": "https://textarray.com/discord-timestamp-generator",
      "embed": "https://textarray.com/embed/discord-timestamp-generator",
      "mode": "generate",
      "action": "Generate timestamp",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "dateTime",
          "kind": "text",
          "label": "Date and time (blank = now)",
          "default": ""
        },
        {
          "key": "sourceZone",
          "kind": "text",
          "label": "Source time zone",
          "default": "UTC"
        },
        {
          "key": "format",
          "kind": "select",
          "label": "Format",
          "default": "f",
          "choices": [
            {
              "value": "t",
              "label": "Short time — t (16:20)"
            },
            {
              "value": "T",
              "label": "Long time — T (16:20:30)"
            },
            {
              "value": "d",
              "label": "Short date — d (20/04/2021)"
            },
            {
              "value": "D",
              "label": "Long date — D (20 April 2021)"
            },
            {
              "value": "f",
              "label": "Short date/time — f (20 April 2021 16:20)"
            },
            {
              "value": "F",
              "label": "Long date/time — F (Tuesday, 20 April 2021 16:20)"
            },
            {
              "value": "R",
              "label": "Relative — R (2 months ago)"
            },
            {
              "value": "all",
              "label": "All formats, labelled"
            }
          ]
        },
        {
          "key": "offset",
          "kind": "text",
          "label": "Quick offset",
          "default": ""
        }
      ],
      "keywords": [
        "discord timestamp",
        "discord timestamp generator",
        "discord dynamic timestamp",
        "discord time markup",
        "unix timestamp",
        "discord t: markup",
        "discord relative time",
        "timestamp"
      ],
      "updated": "2026-08-28"
    },
    {
      "slug": "anki-deck-generator",
      "name": "Anki flashcard TSV generator",
      "description": "Turn a list of notes into a tab-separated file ready to import into Anki.",
      "category": "lists",
      "categoryName": "Lists & combinations",
      "url": "https://textarray.com/anki-deck-generator",
      "embed": "https://textarray.com/embed/anki-deck-generator",
      "mode": "transform",
      "action": "Generate deck",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "select",
          "label": "Separator between front and back",
          "default": "dash",
          "choices": [
            {
              "value": "dash",
              "label": "Dash ( - )"
            },
            {
              "value": "colon",
              "label": "Colon ( : )"
            },
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "blank",
              "label": "Blank line (multi-line notes)"
            }
          ]
        },
        {
          "key": "bidirectional",
          "kind": "checkbox",
          "label": "Also add reverse cards (back → front)",
          "default": false
        },
        {
          "key": "markdown",
          "kind": "checkbox",
          "label": "Convert simple Markdown to HTML",
          "default": false
        },
        {
          "key": "dedupe",
          "kind": "checkbox",
          "label": "Skip duplicate fronts",
          "default": false
        },
        {
          "key": "deck",
          "kind": "text",
          "label": "Deck name column (optional)",
          "default": ""
        },
        {
          "key": "tags",
          "kind": "text",
          "label": "Tags column (optional)",
          "default": ""
        }
      ],
      "keywords": [
        "anki deck generator",
        "anki tsv",
        "flashcard generator",
        "flashcard maker",
        "anki import",
        "spaced repetition cards",
        "tsv",
        "anki"
      ],
      "updated": "2026-08-29"
    },
    {
      "slug": "meeting-cost-calculator",
      "name": "Meeting cost calculator",
      "description": "Calculate the true cost of a meeting from attendee count, hourly rates and duration.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/meeting-cost-calculator",
      "embed": "https://textarray.com/embed/meeting-cost-calculator",
      "mode": "transform",
      "action": "Calculate cost",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "rateMode",
          "kind": "select",
          "label": "Rate mode",
          "default": "list",
          "choices": [
            {
              "value": "list",
              "label": "Custom rate per person"
            },
            {
              "value": "uniform",
              "label": "Same rate for everyone"
            }
          ]
        },
        {
          "key": "hourlyRate",
          "kind": "number",
          "label": "Hourly rate (fallback / shared)",
          "default": 50,
          "min": 0,
          "step": 1
        },
        {
          "key": "durationMinutes",
          "kind": "number",
          "label": "Meeting length (minutes)",
          "default": 30,
          "min": 1,
          "max": 1440,
          "step": 5
        },
        {
          "key": "currency",
          "kind": "select",
          "label": "Currency",
          "default": "USD",
          "choices": [
            {
              "value": "USD",
              "label": "USD ($)"
            },
            {
              "value": "EUR",
              "label": "EUR (€)"
            },
            {
              "value": "GBP",
              "label": "GBP (£)"
            },
            {
              "value": "CHF",
              "label": "CHF"
            },
            {
              "value": "JPY",
              "label": "JPY (¥)"
            },
            {
              "value": "CAD",
              "label": "CAD ($)"
            },
            {
              "value": "AUD",
              "label": "AUD ($)"
            },
            {
              "value": "PLN",
              "label": "PLN (zł)"
            },
            {
              "value": "CZK",
              "label": "CZK (Kč)"
            },
            {
              "value": "HUF",
              "label": "HUF (Ft)"
            }
          ]
        },
        {
          "key": "overheadPercent",
          "kind": "number",
          "label": "Overhead surcharge (%)",
          "default": 0,
          "min": 0,
          "max": 200,
          "step": 5
        },
        {
          "key": "recurring",
          "kind": "select",
          "label": "Repeats",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "One-time"
            },
            {
              "value": "weekly",
              "label": "Weekly"
            },
            {
              "value": "biweekly",
              "label": "Every 2 weeks"
            },
            {
              "value": "monthly",
              "label": "Monthly"
            }
          ]
        },
        {
          "key": "altMinutes",
          "kind": "number",
          "label": "Written summary instead (minutes)",
          "default": 5,
          "min": 0,
          "max": 120,
          "step": 1
        }
      ],
      "keywords": [
        "meeting cost calculator",
        "meeting cost",
        "cost of meetings",
        "meeting price calculator",
        "salary cost of meetings",
        "how much does this meeting cost",
        "meeting overhead calculator",
        "meeting ROI"
      ],
      "updated": "2026-08-30"
    },
    {
      "slug": "bic-swift-validator",
      "name": "BIC/SWIFT code validator",
      "description": "Check that a BIC/SWIFT code is well-formed and break it into bank, country, location and branch.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/bic-swift-validator",
      "embed": "https://textarray.com/embed/bic-swift-validator",
      "mode": "transform",
      "action": "Validate BIC/SWIFT codes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "appendXXX",
          "kind": "checkbox",
          "label": "Append XXX for head office",
          "default": true
        },
        {
          "key": "markTestCodes",
          "kind": "checkbox",
          "label": "Flag test codes",
          "default": true
        },
        {
          "key": "showCountryName",
          "kind": "checkbox",
          "label": "Show country name",
          "default": false
        },
        {
          "key": "show",
          "kind": "select",
          "label": "Output",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Table of all codes"
            },
            {
              "value": "errors",
              "label": "Only invalid lines"
            }
          ]
        }
      ],
      "keywords": [
        "bic validator",
        "swift code validator",
        "swift code checker",
        "bic code checker",
        "validate bic",
        "validate swift code",
        "bank identifier code",
        "iso 9362",
        "bic country code"
      ],
      "updated": "2026-09-01"
    },
    {
      "slug": "ascii-bar-chart",
      "name": "ASCII bar chart generator",
      "description": "Turn label/value pairs into a monospace bar chart made of text characters.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/ascii-bar-chart",
      "embed": "https://textarray.com/embed/ascii-bar-chart",
      "mode": "transform",
      "action": "Generate chart",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "separator",
          "kind": "select",
          "label": "Label/value separator",
          "default": "colon",
          "choices": [
            {
              "value": "tab",
              "label": "Tab"
            },
            {
              "value": "comma",
              "label": "Comma"
            },
            {
              "value": "colon",
              "label": "Colon"
            },
            {
              "value": "whitespace",
              "label": "Last whitespace"
            }
          ]
        },
        {
          "key": "width",
          "kind": "number",
          "label": "Chart width (characters)",
          "default": 40,
          "min": 10,
          "max": 100,
          "step": 5
        },
        {
          "key": "barChar",
          "kind": "text",
          "label": "Bar character",
          "default": "█"
        },
        {
          "key": "partialBlocks",
          "kind": "checkbox",
          "label": "Sub-character precision (eighth blocks)",
          "default": true
        },
        {
          "key": "sort",
          "kind": "select",
          "label": "Order",
          "default": "input",
          "choices": [
            {
              "value": "input",
              "label": "Keep input order"
            },
            {
              "value": "value",
              "label": "Sort by value"
            }
          ]
        },
        {
          "key": "showValues",
          "kind": "checkbox",
          "label": "Show value after bar",
          "default": true
        },
        {
          "key": "showPercent",
          "kind": "checkbox",
          "label": "Show percentage of total",
          "default": false
        },
        {
          "key": "alignLabels",
          "kind": "checkbox",
          "label": "Align labels",
          "default": true
        },
        {
          "key": "showTotal",
          "kind": "checkbox",
          "label": "Show totals row",
          "default": false
        },
        {
          "key": "scaleFromZero",
          "kind": "checkbox",
          "label": "Scale from zero",
          "default": true
        }
      ],
      "keywords": [
        "ascii bar chart",
        "bar chart generator",
        "text bar chart",
        "terminal bar chart",
        "unicode bar chart",
        "chart maker",
        "data visualization",
        "csv to chart"
      ],
      "updated": "2026-08-31"
    },
    {
      "slug": "imei-validator",
      "name": "IMEI validator",
      "description": "Check an IMEI's Luhn checksum and split it into TAC, serial number and check digit.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/imei-validator",
      "embed": "https://textarray.com/embed/imei-validator",
      "mode": "transform",
      "action": "Validate IMEIs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "tolerateSeparators",
          "kind": "checkbox",
          "label": "Tolerate spaces, dashes and dots",
          "default": true
        },
        {
          "key": "invalidOnly",
          "kind": "checkbox",
          "label": "Show only invalid rows",
          "default": false
        }
      ],
      "keywords": [
        "imei validator",
        "imei checker",
        "luhn algorithm",
        "imei check digit calculator",
        "imeisv validator",
        "tac serial number",
        "mobile device imei",
        "phone imei check"
      ],
      "updated": "2026-08-30"
    },
    {
      "slug": "isin-validator",
      "name": "ISIN validator",
      "description": "Check whether an ISIN’s country prefix and check digit are valid.",
      "category": "numbers",
      "categoryName": "Numbers",
      "url": "https://textarray.com/isin-validator",
      "embed": "https://textarray.com/embed/isin-validator",
      "mode": "transform",
      "action": "Validate ISINs",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "batch",
          "kind": "checkbox",
          "label": "Batch mode (one code per line)",
          "default": true
        },
        {
          "key": "tolerant",
          "kind": "checkbox",
          "label": "Tolerate spaces and lower case",
          "default": true
        },
        {
          "key": "fullCountryName",
          "kind": "checkbox",
          "label": "Show country by full name",
          "default": false
        },
        {
          "key": "allowSpecialPrefixes",
          "kind": "checkbox",
          "label": "Recognize special XS/EU prefixes",
          "default": true
        },
        {
          "key": "computeMissing",
          "kind": "checkbox",
          "label": "Compute missing check digit (11-character input)",
          "default": false
        },
        {
          "key": "show",
          "kind": "select",
          "label": "Show",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All rows with reason"
            },
            {
              "value": "invalid",
              "label": "Failing rows only"
            }
          ]
        }
      ],
      "keywords": [
        "isin validator",
        "isin checker",
        "international securities identification number",
        "isin check digit",
        "validate isin",
        "securities identifier",
        "nsin",
        "iso 6166"
      ],
      "updated": "2026-08-31"
    },
    {
      "slug": "ads-txt-validator",
      "name": "ads.txt validator",
      "description": "Check an ads.txt file for syntax errors, duplicate entries and missing fields.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ads-txt-validator",
      "embed": "https://textarray.com/embed/ads-txt-validator",
      "mode": "transform",
      "action": "Validate ads.txt",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "checkDuplicates",
          "kind": "checkbox",
          "label": "Check for duplicate entries",
          "default": true
        },
        {
          "key": "warnMissingCertId",
          "kind": "checkbox",
          "label": "Warn on missing certification authority ID",
          "default": true
        },
        {
          "key": "outputMode",
          "kind": "select",
          "label": "Output",
          "default": "errors",
          "choices": [
            {
              "value": "errors",
              "label": "Error list with line numbers"
            },
            {
              "value": "cleaned",
              "label": "Cleaned file"
            }
          ]
        }
      ],
      "keywords": [
        "ads.txt validator",
        "ads.txt checker",
        "authorized digital sellers",
        "programmatic advertising",
        "iab tech lab",
        "direct reseller",
        "ads.txt syntax check"
      ],
      "updated": "2026-08-28"
    },
    {
      "slug": "plist-to-json",
      "name": "Apple plist to JSON",
      "description": "Convert an Apple XML property list to JSON, and JSON back to a plist.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/plist-to-json",
      "embed": "https://textarray.com/embed/plist-to-json",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "plist-to-json",
          "choices": [
            {
              "value": "plist-to-json",
              "label": "plist to JSON"
            },
            {
              "value": "json-to-plist",
              "label": "JSON to plist"
            }
          ]
        },
        {
          "key": "indent",
          "kind": "number",
          "label": "Indent (spaces)",
          "default": 2,
          "min": 0,
          "max": 8,
          "step": 2
        },
        {
          "key": "sortKeys",
          "kind": "checkbox",
          "label": "Sort dictionary keys",
          "default": false
        },
        {
          "key": "dataMode",
          "kind": "select",
          "label": "<data> content",
          "default": "base64",
          "choices": [
            {
              "value": "base64",
              "label": "Keep as base64"
            },
            {
              "value": "text",
              "label": "Decode to text"
            }
          ]
        },
        {
          "key": "iso8601",
          "kind": "checkbox",
          "label": "ISO 8601 dates",
          "default": true
        },
        {
          "key": "tolerateMissingDoctype",
          "kind": "checkbox",
          "label": "Tolerate missing DOCTYPE",
          "default": false
        },
        {
          "key": "reportLine",
          "kind": "checkbox",
          "label": "Report line number on error",
          "default": true
        }
      ],
      "keywords": [
        "plist to json",
        "apple property list",
        "property list converter",
        "plist parser",
        "plist",
        "xml",
        "json",
        "base64",
        "ios config",
        "macos config"
      ],
      "updated": "2026-08-28"
    },
    {
      "slug": "openssl-command-builder",
      "name": "OpenSSL command builder",
      "description": "Assemble a ready-to-paste openssl command line without running anything.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/openssl-command-builder",
      "embed": "https://textarray.com/embed/openssl-command-builder",
      "mode": "generate",
      "action": "Build command",
      "input": {
        "kind": "none",
        "panels": 0
      },
      "output": "text",
      "options": [
        {
          "key": "task",
          "kind": "select",
          "label": "Task",
          "default": "self-signed",
          "choices": [
            {
              "value": "self-signed",
              "label": "Self-signed certificate"
            },
            {
              "value": "csr",
              "label": "Certificate signing request"
            },
            {
              "value": "private-key",
              "label": "Private key"
            },
            {
              "value": "pem-to-der",
              "label": "Convert PEM to DER"
            },
            {
              "value": "pem-to-pkcs12",
              "label": "Convert PEM + key to PKCS#12"
            },
            {
              "value": "inspect",
              "label": "Inspect a certificate"
            },
            {
              "value": "check-pair",
              "label": "Check a key and certificate pair"
            },
            {
              "value": "verify-chain",
              "label": "Verify a certificate chain"
            },
            {
              "value": "test-tls",
              "label": "Test a TLS connection"
            }
          ]
        },
        {
          "key": "keyType",
          "kind": "select",
          "label": "Key type",
          "default": "rsa",
          "choices": [
            {
              "value": "rsa",
              "label": "RSA"
            },
            {
              "value": "ec",
              "label": "EC (elliptic curve)"
            }
          ]
        },
        {
          "key": "rsaBits",
          "kind": "select",
          "label": "RSA key size",
          "default": "2048",
          "choices": [
            {
              "value": "2048",
              "label": "2048 bits"
            },
            {
              "value": "3072",
              "label": "3072 bits"
            },
            {
              "value": "4096",
              "label": "4096 bits"
            }
          ]
        },
        {
          "key": "ecCurve",
          "kind": "select",
          "label": "EC curve",
          "default": "prime256v1",
          "choices": [
            {
              "value": "prime256v1",
              "label": "P-256 (prime256v1)"
            },
            {
              "value": "secp384r1",
              "label": "P-384 (secp384r1)"
            },
            {
              "value": "secp521r1",
              "label": "P-521 (secp521r1)"
            }
          ]
        },
        {
          "key": "commonName",
          "kind": "text",
          "label": "Common name (CN)",
          "default": "example.com"
        },
        {
          "key": "organization",
          "kind": "text",
          "label": "Organization (O)",
          "default": ""
        },
        {
          "key": "country",
          "kind": "text",
          "label": "Country (C)",
          "default": ""
        },
        {
          "key": "subjectAltNames",
          "kind": "text",
          "label": "Subject alternative names",
          "default": ""
        },
        {
          "key": "days",
          "kind": "number",
          "label": "Validity (days)",
          "default": 365,
          "min": 1,
          "max": 3650,
          "step": 1
        },
        {
          "key": "encryptKey",
          "kind": "checkbox",
          "label": "Encrypt the private key with a passphrase",
          "default": false
        },
        {
          "key": "passphrase",
          "kind": "text",
          "label": "Passphrase",
          "default": "",
          "secret": true
        },
        {
          "key": "keyFileName",
          "kind": "text",
          "label": "Private key file name",
          "default": "key.pem"
        },
        {
          "key": "certFileName",
          "kind": "text",
          "label": "Certificate file name",
          "default": "cert.pem"
        },
        {
          "key": "csrFileName",
          "kind": "text",
          "label": "CSR file name",
          "default": "request.csr"
        },
        {
          "key": "inputFileName",
          "kind": "text",
          "label": "Existing certificate file (inspect / convert)",
          "default": "cert.pem"
        },
        {
          "key": "outputFileName",
          "kind": "text",
          "label": "Converted output file name",
          "default": "cert.der"
        },
        {
          "key": "caFileName",
          "kind": "text",
          "label": "CA bundle file (verify chain)",
          "default": "ca-bundle.pem"
        },
        {
          "key": "hostName",
          "kind": "text",
          "label": "Host to test",
          "default": "example.com"
        },
        {
          "key": "port",
          "kind": "number",
          "label": "Port",
          "default": 443,
          "min": 1,
          "max": 65535,
          "step": 1
        }
      ],
      "keywords": [
        "openssl command builder",
        "openssl cheat sheet",
        "generate self-signed certificate",
        "openssl csr command",
        "openssl generate private key",
        "openssl convert pem to der",
        "openssl pkcs12 command",
        "openssl s_client",
        "openssl verify certificate chain",
        "tls",
        "x509",
        "pem",
        "der"
      ],
      "updated": "2026-09-01"
    },
    {
      "slug": "ansi-color-generator",
      "name": "ANSI color code generator",
      "description": "Wrap text in ANSI escape codes to color and style it in a terminal.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/ansi-color-generator",
      "embed": "https://textarray.com/embed/ansi-color-generator",
      "mode": "transform",
      "action": "Generate ANSI codes",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "fgMode",
          "kind": "select",
          "label": "Foreground",
          "default": "basic",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "basic",
              "label": "16 basic colors"
            },
            {
              "value": "256",
              "label": "256-color cube"
            },
            {
              "value": "hex",
              "label": "24-bit hex"
            }
          ]
        },
        {
          "key": "fgValue",
          "kind": "text",
          "label": "Foreground value",
          "default": "green"
        },
        {
          "key": "bgMode",
          "kind": "select",
          "label": "Background",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "None"
            },
            {
              "value": "basic",
              "label": "16 basic colors"
            },
            {
              "value": "256",
              "label": "256-color cube"
            },
            {
              "value": "hex",
              "label": "24-bit hex"
            }
          ]
        },
        {
          "key": "bgValue",
          "kind": "text",
          "label": "Background value",
          "default": ""
        },
        {
          "key": "bold",
          "kind": "checkbox",
          "label": "Bold",
          "default": false
        },
        {
          "key": "dim",
          "kind": "checkbox",
          "label": "Dim",
          "default": false
        },
        {
          "key": "italic",
          "kind": "checkbox",
          "label": "Italic",
          "default": false
        },
        {
          "key": "underline",
          "kind": "checkbox",
          "label": "Underline",
          "default": false
        },
        {
          "key": "blink",
          "kind": "checkbox",
          "label": "Blink",
          "default": false
        },
        {
          "key": "inverse",
          "kind": "checkbox",
          "label": "Inverse",
          "default": false
        },
        {
          "key": "strikethrough",
          "kind": "checkbox",
          "label": "Strikethrough",
          "default": false
        },
        {
          "key": "notation",
          "kind": "select",
          "label": "Escape notation",
          "default": "raw",
          "choices": [
            {
              "value": "raw",
              "label": "Raw (\\u001b)"
            },
            {
              "value": "shell",
              "label": "Shell (\\e)"
            },
            {
              "value": "code",
              "label": "C / Python (\\033)"
            },
            {
              "value": "printf",
              "label": "printf-ready"
            }
          ]
        },
        {
          "key": "resetAtEnd",
          "kind": "checkbox",
          "label": "Reset at end of line",
          "default": true
        },
        {
          "key": "perLine",
          "kind": "checkbox",
          "label": "Rotate a color per line",
          "default": false
        },
        {
          "key": "preview",
          "kind": "checkbox",
          "label": "Show terminal preview",
          "default": false
        }
      ],
      "keywords": [
        "ansi color code generator",
        "ansi escape codes",
        "terminal color codes",
        "cli color codes",
        "console colors",
        "colorize terminal text",
        "shell color codes",
        "256 color codes",
        "bash colors",
        "sgr escape codes"
      ],
      "updated": "2026-08-30"
    },
    {
      "slug": "nmea-parser",
      "name": "NMEA sentence parser",
      "description": "Decode NMEA 0183 GPS sentences into readable, named fields.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/nmea-parser",
      "embed": "https://textarray.com/embed/nmea-parser",
      "mode": "transform",
      "action": "Parse sentences",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "sentenceFilter",
          "kind": "select",
          "label": "Sentence type",
          "default": "all",
          "choices": [
            {
              "value": "all",
              "label": "All types"
            },
            {
              "value": "GGA",
              "label": "GGA — fix data"
            },
            {
              "value": "RMC",
              "label": "RMC — recommended minimum"
            },
            {
              "value": "GLL",
              "label": "GLL — position"
            },
            {
              "value": "GSA",
              "label": "GSA — DOP and satellites"
            },
            {
              "value": "GSV",
              "label": "GSV — satellites in view"
            },
            {
              "value": "VTG",
              "label": "VTG — course and speed"
            }
          ]
        },
        {
          "key": "verifyChecksum",
          "kind": "checkbox",
          "label": "Verify checksum",
          "default": true
        },
        {
          "key": "coordFormat",
          "kind": "select",
          "label": "Coordinate format",
          "default": "decimal",
          "choices": [
            {
              "value": "decimal",
              "label": "Decimal degrees"
            },
            {
              "value": "dms",
              "label": "Degrees, minutes, seconds"
            }
          ]
        },
        {
          "key": "describeStatus",
          "kind": "checkbox",
          "label": "Describe fix quality and satellites",
          "default": true
        },
        {
          "key": "isoTimestamp",
          "kind": "checkbox",
          "label": "Combine date and time into ISO 8601",
          "default": true
        },
        {
          "key": "speedUnit",
          "kind": "select",
          "label": "Speed unit",
          "default": "kmh",
          "choices": [
            {
              "value": "kmh",
              "label": "km/h"
            },
            {
              "value": "knots",
              "label": "Knots"
            }
          ]
        },
        {
          "key": "outputFormat",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Field table"
            },
            {
              "value": "compact",
              "label": "Compact summary"
            },
            {
              "value": "track",
              "label": "Track (lat/lon list)"
            }
          ]
        }
      ],
      "keywords": [
        "nmea parser",
        "nmea 0183",
        "gps sentence decoder",
        "gga rmc gll parser",
        "nmea checksum verifier",
        "decode nmea sentences",
        "gps nmea to decimal degrees",
        "marine gps log parser"
      ],
      "updated": "2026-08-31"
    },
    {
      "slug": "wkt-geojson-converter",
      "name": "WKT to GeoJSON converter",
      "description": "Convert Well-Known Text geometries to GeoJSON, and back, entirely in your browser.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/wkt-geojson-converter",
      "embed": "https://textarray.com/embed/wkt-geojson-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "wktToGeojson",
          "choices": [
            {
              "value": "wktToGeojson",
              "label": "WKT → GeoJSON"
            },
            {
              "value": "geojsonToWkt",
              "label": "GeoJSON → WKT"
            }
          ]
        },
        {
          "key": "wrap",
          "kind": "select",
          "label": "Wrap GeoJSON as",
          "default": "none",
          "choices": [
            {
              "value": "none",
              "label": "Geometry only"
            },
            {
              "value": "feature",
              "label": "Feature"
            },
            {
              "value": "featureCollection",
              "label": "FeatureCollection"
            }
          ]
        },
        {
          "key": "decimals",
          "kind": "number",
          "label": "Decimal places",
          "default": 6,
          "min": 0,
          "max": 15,
          "step": 1
        },
        {
          "key": "closeRings",
          "kind": "checkbox",
          "label": "Close polygon rings automatically",
          "default": true
        },
        {
          "key": "swapCoords",
          "kind": "checkbox",
          "label": "Swap latitude/longitude order",
          "default": false
        },
        {
          "key": "batchMode",
          "kind": "checkbox",
          "label": "Batch mode (one geometry per line)",
          "default": false
        },
        {
          "key": "pretty",
          "kind": "checkbox",
          "label": "Pretty-print JSON",
          "default": true
        }
      ],
      "keywords": [
        "wkt to geojson",
        "geojson to wkt",
        "well-known text converter",
        "wkt converter",
        "geojson converter",
        "wkt parser",
        "geojson",
        "wkt",
        "json",
        "geometry converter",
        "gis"
      ],
      "updated": "2026-09-01"
    },
    {
      "slug": "slack-block-kit-builder",
      "name": "Slack Block Kit builder",
      "description": "Turn a plain text outline into ready-to-send Slack Block Kit JSON.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/slack-block-kit-builder",
      "embed": "https://textarray.com/embed/slack-block-kit-builder",
      "mode": "transform",
      "action": "Build Block Kit JSON",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "bulletMode",
          "kind": "select",
          "label": "Bullet lists",
          "default": "single",
          "choices": [
            {
              "value": "single",
              "label": "One section for the whole list"
            },
            {
              "value": "perItem",
              "label": "One block per item"
            }
          ]
        },
        {
          "key": "payloadMode",
          "kind": "select",
          "label": "Payload for",
          "default": "webhook",
          "choices": [
            {
              "value": "webhook",
              "label": "Incoming webhook"
            },
            {
              "value": "postMessage",
              "label": "chat.postMessage"
            }
          ]
        },
        {
          "key": "channel",
          "kind": "text",
          "label": "Channel (chat.postMessage only)",
          "default": "#general"
        }
      ],
      "keywords": [
        "slack block kit builder",
        "slack block kit generator",
        "slack message builder",
        "slack blocks json",
        "slack webhook payload",
        "chat.postMessage payload",
        "slack section block",
        "slack divider block",
        "slack context block",
        "slack actions block",
        "slack button block",
        "mrkdwn",
        "json",
        "slack",
        "webhook"
      ],
      "updated": "2026-08-30"
    },
    {
      "slug": "dns-zone-generator",
      "name": "DNS zone file generator",
      "description": "Turn a plain list of DNS records into a BIND-style zone file.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/dns-zone-generator",
      "embed": "https://textarray.com/embed/dns-zone-generator",
      "mode": "transform",
      "action": "Generate zone file",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "origin",
          "kind": "text",
          "label": "Origin domain",
          "default": "example.com"
        },
        {
          "key": "ttl",
          "kind": "number",
          "label": "Default TTL (s)",
          "default": 3600,
          "min": 60,
          "max": 604800,
          "step": 60
        },
        {
          "key": "nameFormat",
          "kind": "select",
          "label": "Record names",
          "default": "relative",
          "choices": [
            {
              "value": "relative",
              "label": "Relative"
            },
            {
              "value": "fqdn",
              "label": "Fully qualified"
            }
          ]
        },
        {
          "key": "primaryNs",
          "kind": "text",
          "label": "Primary nameserver",
          "default": "ns1.example.com"
        },
        {
          "key": "adminEmail",
          "kind": "text",
          "label": "Responsible email",
          "default": "admin@example.com"
        },
        {
          "key": "serial",
          "kind": "text",
          "label": "Serial (blank = today)",
          "default": ""
        },
        {
          "key": "refresh",
          "kind": "number",
          "label": "Refresh (s)",
          "default": 3600,
          "min": 60,
          "max": 604800,
          "step": 60
        },
        {
          "key": "retry",
          "kind": "number",
          "label": "Retry (s)",
          "default": 900,
          "min": 60,
          "max": 604800,
          "step": 60
        },
        {
          "key": "expire",
          "kind": "number",
          "label": "Expire (s)",
          "default": 604800,
          "min": 3600,
          "max": 2592000,
          "step": 3600
        },
        {
          "key": "minimum",
          "kind": "number",
          "label": "Minimum TTL (s)",
          "default": 86400,
          "min": 60,
          "max": 604800,
          "step": 60
        }
      ],
      "keywords": [
        "dns zone generator",
        "bind zone file",
        "zone file generator",
        "dns records generator",
        "soa record generator",
        "dns zone file",
        "a record",
        "mx record",
        "txt record",
        "ptr record",
        "srv record",
        "caa record",
        "bind"
      ],
      "updated": "2026-08-29"
    },
    {
      "slug": "whois-parser",
      "name": "WHOIS record parser",
      "description": "Extract registrar, dates, nameservers and status codes from a raw WHOIS response.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/whois-parser",
      "embed": "https://textarray.com/embed/whois-parser",
      "mode": "transform",
      "action": "Parse WHOIS record",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "format",
          "kind": "select",
          "label": "Output format",
          "default": "table",
          "choices": [
            {
              "value": "table",
              "label": "Field table"
            },
            {
              "value": "json",
              "label": "JSON"
            }
          ]
        },
        {
          "key": "explainStatus",
          "kind": "checkbox",
          "label": "Explain status codes",
          "default": true
        },
        {
          "key": "stripBoilerplate",
          "kind": "checkbox",
          "label": "Strip boilerplate and redacted fields",
          "default": true
        },
        {
          "key": "showDaysRemaining",
          "kind": "checkbox",
          "label": "Show days remaining until expiry",
          "default": true
        }
      ],
      "keywords": [
        "whois parser",
        "whois lookup parser",
        "parse whois record",
        "domain registration info",
        "whois to json",
        "epp status codes",
        "domain expiry date",
        "json"
      ],
      "updated": "2026-08-30"
    },
    {
      "slug": "po-file-converter",
      "name": "PO to JSON converter",
      "description": "Convert a gettext .po translation catalogue to JSON, and back again.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/po-file-converter",
      "embed": "https://textarray.com/embed/po-file-converter",
      "mode": "transform",
      "action": "Convert",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "direction",
          "kind": "select",
          "label": "Direction",
          "default": "po-to-json",
          "choices": [
            {
              "value": "po-to-json",
              "label": ".po → JSON"
            },
            {
              "value": "json-to-po",
              "label": "JSON → .po"
            }
          ]
        },
        {
          "key": "nested",
          "kind": "checkbox",
          "label": "Nest keys by dotted msgid",
          "default": false
        },
        {
          "key": "dropEmpty",
          "kind": "checkbox",
          "label": "Drop entries with an empty translation",
          "default": false
        },
        {
          "key": "pluralsAsArray",
          "kind": "checkbox",
          "label": "Plural forms as an array",
          "default": true
        },
        {
          "key": "msgctxtPrefix",
          "kind": "checkbox",
          "label": "Prefix keys with msgctxt",
          "default": true
        },
        {
          "key": "keepComments",
          "kind": "checkbox",
          "label": "Keep comments and source references",
          "default": false
        },
        {
          "key": "keepHeader",
          "kind": "checkbox",
          "label": "Keep the catalogue header",
          "default": true
        }
      ],
      "keywords": [
        "po file converter",
        "po to json",
        "gettext",
        "i18n",
        "l10n",
        "translation catalog",
        "msgid msgstr",
        "json",
        "localization file"
      ],
      "updated": "2026-08-29"
    },
    {
      "slug": "stack-trace-formatter",
      "name": "Stack trace formatter",
      "description": "Clean up and re-indent a pasted stack trace so the frames that matter stand out.",
      "category": "developer-tools",
      "categoryName": "Developer tools",
      "url": "https://textarray.com/stack-trace-formatter",
      "embed": "https://textarray.com/embed/stack-trace-formatter",
      "mode": "transform",
      "action": "Format trace",
      "input": {
        "kind": "text",
        "panels": 1,
        "maxBytes": 10485760
      },
      "output": "text",
      "options": [
        {
          "key": "language",
          "kind": "select",
          "label": "Language",
          "default": "auto",
          "choices": [
            {
              "value": "auto",
              "label": "Auto-detect"
            },
            {
              "value": "java",
              "label": "Java"
            },
            {
              "value": "javascript",
              "label": "JavaScript / Node"
            },
            {
              "value": "python",
              "label": "Python"
            },
            {
              "value": "csharp",
              "label": "C#"
            },
            {
              "value": "go",
              "label": "Go"
            },
            {
              "value": "ruby",
              "label": "Ruby"
            }
          ]
        },
        {
          "key": "collapseVendor",
          "kind": "checkbox",
          "label": "Collapse vendor frames",
          "default": true
        },
        {
          "key": "ownOnly",
          "kind": "checkbox",
          "label": "Keep only my frames",
          "default": false
        },
        {
          "key": "appPath",
          "kind": "text",
          "label": "Your source path",
          "default": ""
        },
        {
          "key": "numberFrames",
          "kind": "checkbox",
          "label": "Number frames",
          "default": true
        },
        {
          "key": "shortenNames",
          "kind": "checkbox",
          "label": "Shorten class names",
          "default": false
        },
        {
          "key": "summary",
          "kind": "checkbox",
          "label": "Show summary line",
          "default": true
        }
      ],
      "keywords": [
        "stack trace formatter",
        "stack trace cleaner",
        "exception formatter",
        "java stack trace parser",
        "stacktrace beautifier",
        "error trace formatter",
        "node.js stack trace",
        "python traceback formatter",
        "c# stack trace",
        "go panic formatter",
        "ruby backtrace formatter"
      ],
      "updated": "2026-09-01"
    }
  ]
}
