# DevLab — Complete Page Index > Free, client-side developer tools. Every tool runs entirely in the browser — no signup, no data leaves the device. Built by Bikram Nath. Site: https://devlab.tools Working tools: 26 Learn guides: 39 Comparisons: 15 ## Tools (fully working) ### Regex - [Regex Tester](https://devlab.tools/tool/regex-tester) A regex tester runs your pattern against sample text in real time and highlights every match, group, and capture as you type. Paste a log line like `2024-01-15 ERROR [db] connection timeout` and a pattern like `(\w+) (\w+) \[(\w+)\]` to instantly see three numbered capture groups light up. Unlike regex101, the matching here uses the JavaScript engine directly, so what you see is exactly what `String.prototype.matchAll()` returns in your browser. Q: Why does my pattern match across lines when I didn't intend it to? A: By default, `.` in JavaScript regex does not match newline characters (`\n`, `\r`). If your matches are spanning lines anyway, you have likely enabled the `s` (dotAll) flag, introduced in ECMAScript 2018, which makes `.` match every character including newlines. Check which flags are active. If you want `.` to stop at line boundaries, remove the `s` flag. If you want `^` and `$` to anchor to each line rather than the whole string, add the `m` (multiline) flag instead. Q: Does this tester support named capture groups? A: Yes. Named capture groups using the `(?...)` syntax were standardized in ECMAScript 2018 and are supported in every major browser engine released after mid-2018. In the match output, named groups appear alongside their numeric index. Use `match.groups.name` to access them in code. One practical note: duplicate group names are not allowed in JavaScript regex, unlike in PCRE where you can reuse a name in alternation branches, so a pattern like `(?\d{4})|(?\d{2})` will throw a `SyntaxError` here. ### CSS - [CSS Gradient Generator](https://devlab.tools/tool/css-gradient-generator) Pick a gradient type, drag color stops across the canvas, set an angle or focal point, and the tool outputs paste-ready CSS immediately. For example, a conic sweep from 0deg through amber to teal produces `background: conic-gradient(from 0deg, #f59e0b, #14b8a6)`, including the `from` keyword that older Firefox versions require. Conic gradient support is what separates this from most dedicated alternatives. Q: Why does my gradient look gray or washed out in the middle? A: That desaturated midpoint is an sRGB interpolation artifact. When two complementary hues sit across the color wheel, the shortest sRGB path between them cuts through a low-chroma zone. CSS Color Level 4 introduced the `in oklch` modifier to fix this: `background: linear-gradient(in oklch, #e63946, #2a9d8f)` routes interpolation through a perceptually uniform space and keeps saturation high across all stops. Chrome 111 and Firefox 113 support it fully; Safari added partial support in 17.2. For older browser floors, inserting a manually chosen saturated midpoint stop is a reliable workaround. Q: How do I create a hard color stop with no fade between colors? A: Set two adjacent stops to the same percentage position. In CSS the result looks like `linear-gradient(to right, #ff0000 50%, #0000ff 50%)`, where both stops share the 50% mark and there is zero blended transition. Most gradient editors let you drag one stop on top of another until their position values match. This is the underlying technique for CSS stripe and checkerboard patterns that avoid background-image entirely and keep the markup clean. ### JSON - [JSON Formatter](https://devlab.tools/tool/json-formatter) Paste minified JSON and get back a syntax-colored, indented version in under a second. Useful when an API response like {"id":1,"items":[{"sku":"A1","qty":3}]} arrives as a single line and you need to read through it quickly. The collapsible tree view lets you fold individual nested objects independently, which flat prettifiers like JSONLint do not offer. Q: Why did my large integer change value after formatting? A: JSON.parse() converts all JSON numbers to IEEE 754 doubles. Any integer beyond 2^53 - 1 (9007199254740991), such as a Twitter snowflake ID or a 64-bit database primary key, loses its least significant bits silently during parsing. The formatter displays what JavaScript actually holds after that conversion, not the original string. To preserve precision, the API producing the data should quote those values as strings: {"tweet_id": "1785346289012345678"}. This is a JavaScript limitation that affects every browser-based JSON tool, including browser DevTools. Q: How large a JSON payload can this handle before the browser struggles? A: V8 imposes a string length limit near 512MB, but the tree renderer becomes unresponsive well before that threshold. Structures with tens of thousands of nodes can freeze the tab at a few megabytes depending on nesting depth. For files above roughly 5MB, jq on the command line (jq '.' input.json) formats without those constraints and handles gigabyte-scale files through its streaming C parser. The browser tool is best suited for payloads you would realistically receive from a single API call. - [JSON Validator](https://devlab.tools/tool/json-validator) Paste any JSON string and the validator pinpoints the exact line and column where parsing fails, telling you whether the problem is a missing comma, an unquoted key, or a trailing comma after the last array element. Feed it a 400-line API response that crashes your fetch handler and you get 'Unexpected token } at line 23, column 4' instead of a generic SyntaxError. Unlike a formatter that silently fixes input, this tool only reports — it never mutates. Q: The validator says my JSON is invalid but JSON.parse() in Node accepts it — why? A: Node's JSON.parse() is spec-compliant and should reject the same input this tool rejects. The most common explanation is that your Node code is not actually calling JSON.parse() on the raw string — it may be using a library like json5 or a YAML parser that accepts a superset of JSON. Another possibility is that you are testing a different string in Node than the one you pasted here, for example one that has already had escape sequences resolved by your shell or terminal before it reached Node. Q: What is the largest JSON input this tool can handle in the browser? A: Chrome and Firefox impose a string length cap that V8 enforces at roughly 512 MB, but the practical browser tab limit is much lower because JSON.parse() needs to allocate the parsed object tree in addition to the raw string. In practice, inputs above 10 to 20 MB will cause the tab to slow noticeably or freeze. For large JSON files, jq on the command line or a streaming parser like stream-json in Node will handle multi-gigabyte input that a browser-based tool cannot. - [JSON Minifier](https://devlab.tools/tool/json-minifier) Strips all whitespace characters (spaces, tabs, and newlines) from JSON to produce the smallest valid representation of the data. Paste a formatted API response like { "id": 1, "name": "Alice" } and get {"id":1,"name":"Alice"} back. Unlike a formatter that also validates structure, this tool focuses purely on compaction without reordering keys or re-encoding numeric values. Q: Does minifying change key order or alter how numbers are encoded? A: Key order is preserved. The browser's JSON.parse followed by JSON.stringify maintains insertion order for string keys as of ECMAScript 2015. Numbers, however, are re-serialized by the JavaScript engine, so 1.0 becomes 1 and 1.000e3 becomes 1000, both mathematically identical but different byte sequences. If exact byte-for-byte preservation of the original number representation matters, that is a sign minification is the wrong step for your use case. Q: My source JSON has // comments and the tool rejects it. Why? A: Standard JSON (ECMA-404) does not allow comments. The tool processes valid JSON only, so C-style // and /* */ comments, which are a JSON5 extension, cause a parse failure before minification begins. This is a spec constraint, not a tool limitation. Strip comments first with a sed command like sed 's|//[^"]*$||g' or run the file through a JSON5-aware parser such as the json5 npm package, then paste the clean output here. - [JSON to TypeScript](https://devlab.tools/tool/json-to-typescript) Paste a raw JSON object and get TypeScript interface declarations back. Nested objects become separate named interfaces, arrays become T[], and any field holding null gets typed as T | null. Useful when a teammate hands you an undocumented API response and you need to type it before wiring it into a service layer. Unlike quicktype, there is no CLI install or schema export step needed for a one-off conversion. Q: What happens when a JSON array contains objects with different shapes? A: The converter typically merges the shapes into a single interface, marking any key absent from at least one object as optional. For example, [{"id":1,"name":"Alice"},{"id":2}] yields an interface where name is string | undefined. If the objects differ so drastically that a merged interface looks wrong, split the array into typed variants manually and use a discriminated union. The single-sample heuristic breaks down most visibly on polymorphic arrays where different items carry entirely different key sets. Q: Why does the output use `number` for fields I know will always be whole integers? A: TypeScript has no integer type at the language level. Both JSON 42 and JSON 3.14 map to number, because the type system makes no distinction between integer and float values. The converter follows the spec faithfully. If downstream code needs integer-only guarantees — for example, a database row ID — add a branded type like type UserId = number & { __brand: 'UserId' } manually after generating the base interface. That constraint cannot be inferred from a JSON sample alone. - [JSONPath Tester](https://devlab.tools/tool/json-path-tester) Test JSONPath expressions against a JSON document and see matching values instantly. Supports dot notation (.key), bracket notation ([0]), and wildcards (.* and [*]). Enter a path like $.store.books[0].title and the matched value appears immediately. All evaluation runs in the browser. Q: What is the difference between $.store.books and $.store.books[*]? A: $.store.books returns the entire books array as a single match — one result which is the array itself. $.store.books[*] applies the wildcard to the array, returning each element as a separate match. This distinction matters when you need to iterate over array elements versus when you want the array itself as a single value. Q: How does the wildcard .* differ from [*]? A: .* (dot-wildcard) returns all property values of an object. [*] (bracket-wildcard) returns all elements of an array. In practice: if the target is an array, use [*]; if it is an object, use .*. Most JSONPath implementations treat [*] as all children regardless of whether the parent is an array or object. - [JSON to Excel / CSV](https://devlab.tools/tool/json-to-excel) The JSON to Excel converter transforms JSON arrays and objects into downloadable .xlsx spreadsheet files directly in your browser. Paste a JSON array of objects — like an API response with user records or product listings — and get a formatted Excel workbook with proper column headers, data types, and multiple sheets for nested structures. No server upload, no file size limits beyond browser memory. Q: What JSON structure works best for conversion to Excel? A: An array of flat objects with consistent keys produces the cleanest spreadsheet — each object becomes a row and each key becomes a column. For example, [{"name":"Alice","age":30},{"name":"Bob","age":25}] creates a two-row, two-column sheet. Nested objects are flattened using dot notation (address.city), and arrays within records are joined into comma-separated strings. Deeply nested or inconsistent structures still convert, but the output may need manual column cleanup. Q: Is there a file size limit? A: There is no hard limit — the conversion runs entirely in your browser using JavaScript. The practical limit is your device's available RAM. Most modern devices handle JSON files up to 50-100 MB without issues. For files larger than that, consider splitting the JSON into chunks or using a server-side tool like pandas in Python. - [OpenAPI Diff Checker](https://devlab.tools/tool/openapi-diff-checker) The OpenAPI Diff Checker compares two OpenAPI (Swagger) specification files and shows exactly what changed between versions — added endpoints, removed parameters, modified response schemas, and breaking changes. Paste two OpenAPI 3.x JSON or YAML specs and get a color-coded diff highlighting additions, removals, and modifications with breaking-change warnings. Runs entirely client-side with no server upload. Q: What OpenAPI versions does it support? A: The checker supports OpenAPI 3.0.x and 3.1.x specifications in both JSON and YAML format. Swagger 2.0 specs are not directly supported — convert them to OpenAPI 3.x first using the official swagger-converter tool or swagger2openapi npm package. The tool validates both specs before diffing and will show parse errors if either spec is malformed. Q: How does it detect breaking changes? A: Breaking changes are identified using standard API compatibility rules: removing an endpoint or HTTP method, adding a required request parameter or header, narrowing a response schema (removing a field clients may depend on), changing a parameter type, or restricting enum values. Each breaking change is flagged with a red warning icon and explanation of why it breaks backward compatibility. - [DB Schema Diff](https://devlab.tools/tool/db-schema-diff) The DB Schema Diff tool compares two database schemas (SQL CREATE TABLE statements) and generates the ALTER TABLE migration needed to transform one into the other. Paste your current schema and target schema as SQL DDL, and get a precise migration script showing added columns, dropped columns, modified types, new indexes, and constraint changes. All processing happens in your browser — no database connection required. Q: What SQL dialects does it support? A: The parser handles PostgreSQL, MySQL, and SQLite CREATE TABLE syntax including data types, constraints (PRIMARY KEY, UNIQUE, NOT NULL, DEFAULT, CHECK, FOREIGN KEY), and CREATE INDEX statements. Dialect-specific features like PostgreSQL arrays, MySQL AUTO_INCREMENT, and SQLite AUTOINCREMENT are recognized. Stored procedures, triggers, and views are not compared — only table and index definitions. Q: Does it generate safe migration scripts? A: The output migration orders operations to avoid dependency errors: new tables are created before foreign keys referencing them, columns are added before constraints using them, and foreign keys are dropped before referenced tables are modified. However, you should always review the output and test it against a staging database before running in production — the tool does not know about your data volume or locking implications. - [CSV to JSON Converter](https://devlab.tools/tool/csv-to-json) Paste CSV data and this tool converts it to a JSON array of objects where keys come from the header row. Handles quoted fields containing commas, bidirectional conversion (CSV to JSON and back), and shows specific errors for malformed input. All processing is client-side — no data is uploaded. Q: How does the tool handle CSV fields that contain commas? A: RFC 4180 specifies that fields containing commas must be enclosed in double quotes. This tool's parser tracks quote state character by character, so a field like "Smith, John" correctly produces one value rather than splitting on the comma inside the quoted field. Double quotes inside a quoted field are represented as two consecutive double quotes, and the parser handles this correctly. Q: What happens if my CSV does not have a header row? A: Uncheck the First row is header option. With this off, each row becomes an array rather than a named object — the output is a JSON array of arrays. This matches the raw structure of headerless CSV and is useful when you plan to label the columns manually in code. - [SQL Formatter](https://devlab.tools/tool/sql-formatter) Paste raw or minified SQL and this tool reformats it with keywords uppercased and each major clause (SELECT, FROM, WHERE, JOIN, ORDER BY, etc.) on its own line. Also minifies SQL to a single line. All processing is client-side — no SQL is sent to a server. Q: Does the formatter handle subqueries and CTEs? A: Basic subqueries are handled — the formatter adds newlines before major keywords inside subqueries as well. CTEs using the WITH clause are recognized. However, deep nesting may not indent perfectly since this is a pattern-based formatter rather than a full SQL AST parser. For complex production queries, tools like pgFormatter or sql-formatter.js with AST parsing produce more precise output. Q: Why does the dialect selector say cosmetic? A: The formatter applies the same keyword uppercasing and clause formatting regardless of which dialect is selected. SQL syntax for SELECT, FROM, WHERE, JOIN, and ORDER BY is nearly identical across PostgreSQL, MySQL, and SQLite, so a single ruleset covers 95% of queries. The selector label is a display hint to remind you which database the query targets. ### Colors - [Color Converter](https://devlab.tools/tool/color-converter) Paste any color in HEX, RGB, HSL, HSB/HSV, or CMYK and all remaining formats update instantly. The typical use is bridging Figma and CSS: input HSL(217, 91%, 60%) and immediately read the HEX (#4A90E2) or RGB equivalent. Unlike single-direction tools, this surfaces all five formats at once, so you can pull a CMYK approximation for print without opening a second tool. Q: Why do different tools return slightly different HSL values for the same HEX input? A: Floating-point rounding is the culprit. Converting HEX to RGB gives integer channel values (0 to 255), and dividing those by 255 produces fractions that get rounded to different decimal places depending on the implementation. A computed hue of 211.3 rounds to 211, but 211.7 might round to 212. Both are faithful representations of the same color. For most UI work this is irrelevant. For programmatic round-tripping where precision matters, use chroma-js, which exposes full floating-point channel values before any rounding occurs. Q: Is HSB the same as HSV, or is there a real difference? A: They are the same color model under two names. HSB (Hue, Saturation, Brightness) is the label Adobe uses in its color pickers. HSV (Hue, Saturation, Value) is the academic and more widely cited term. Both use identical math and produce identical numbers. Neither is the same as HSL, which is what CSS functions like hsl() and color-mix() actually accept. The distinction matters in practice: a fully saturated red is HSB/HSV(0, 100%, 100%) but HSL(0, 100%, 50%), because the third channel means something different in each model. ### Text - [Word Counter](https://devlab.tools/tool/word-counter) Paste or type text and instantly see word count, character count with and without spaces, sentence count, paragraph count, and estimated reading time calculated at 200 words per minute. Paste a 900-word draft and it shows a 4.5-minute read before you publish. Unlike running `wc -w` in a terminal, it also tracks sentence and paragraph boundaries in the same pass without any flags or piping. Q: How does this define a 'word' — does 'full-stack' count as one or two? A: The counter splits on whitespace, so 'full-stack' counts as one word because there is no space inside it. Contractions like 'don't' also count as one word. This matches the behavior of most writing style guides and mirrors what Microsoft Word and Google Docs report. If you need a different definition, the Unix `wc -w` command also splits on whitespace and will give you the same number for hyphenated terms. Q: Why does the character count here differ from what Twitter or Instagram shows? A: Social platforms apply their own counting rules on top of raw character counts. Twitter, for example, normalizes all URLs to 23 characters regardless of actual length and counts certain Unicode characters as two units. Instagram counts grapheme clusters, not code points, so a family emoji composed of multiple code points counts as one character there but may count differently here. This tool reports the raw JavaScript string length in code units, which is useful for most CMS character limits but will not match social platform counters exactly. - [Case Converter](https://devlab.tools/tool/case-converter) Paste any text and get all eight case formats at once: camelCase, PascalCase, snake_case, kebab-case, UPPER_CASE, lowercase, Title Case, and Sentence case, without running separate conversions. Useful when mapping a database column like `user_profile_image` to both a TypeScript property (`userProfileImage`) and a display label (`User Profile Image`) in one step. The all-at-once display is what separates this from single-format transformers. Q: How does the tool detect word boundaries when the input is already camelCase or PascalCase? A: The converter splits on transitions from a lowercase letter to an uppercase letter, so `userProfileImage` yields the tokens `user`, `profile`, `image`. It also handles transitions from a run of uppercase letters back to lowercase, so `HTMLParser` is typically tokenized as `HTML` plus `Parser`. The exact boundary algorithm matters if your identifiers mix acronyms with regular words. Paste a sample first and confirm the output matches your intent before using the result to rename files or variables at scale. Q: What happens to consecutive uppercase sequences like 'getUserID' or 'XMLHttpRequest'? A: Consecutive uppercase runs are the known hard case in any casing library. A heuristic approach treats `ID` and `XML` as single tokens; a strict character-by-character approach splits every capital into its own word. The output you see will tell you which strategy is in use. If the result looks wrong for an acronym-heavy identifier, manually space the input (`get User ID` or `XML Http Request`) so the tokenizer has unambiguous boundaries to work from before converting. - [Text Diff Checker](https://devlab.tools/tool/text-diff-checker) Paste two text blocks side-by-side to instantly see every added, removed, or changed character highlighted in color. Useful when you need to spot whether a config file changed between two deploys — paste the old and new versions, and the diff highlights the exact lines that shifted, down to individual characters. Unlike line-only differ tools, this operates at character granularity, so a single changed word inside a long sentence is isolated rather than flagging the entire line as different. Q: Why does character-level diff flag my entire file as changed when only one line is different? A: This almost always means the two inputs have different line endings. CRLF (Windows) versus LF (Unix) differences are invisible to the eye but are real characters, so every single line ends with an extra \r that the other side lacks. The diff algorithm sees each line as distinct. Fix it by normalizing line endings before pasting: in most editors, 'Convert to Unix line endings' or a regex replace of \r\n to \n will collapse the noise down to the one line you actually care about. Q: How does this differ from running 'diff' or 'git diff' in the terminal? A: The Unix diff command and git diff operate on files and output a patch format that is text-based and context-aware but not visually highlighted unless you pipe through a colorizer like delta or diff-so-fancy. They also require both versions to exist as files on disk. This tool accepts raw pasted text with no file system access required, and the character-level highlighting within a changed line is something standard diff does not produce by default. For files already tracked in git, git diff is strictly better because it carries commit metadata and can produce patch files. For ad-hoc text comparison without a repo, this is faster. - [Markdown Previewer](https://devlab.tools/tool/markdown-previewer) A markdown previewer renders your raw .md source into formatted HTML in real time as you type, letting you catch broken table alignment, missing blank lines before lists, or stray asterisks before they hit a PR. Paste a README with a pipe-delimited table on the left and watch the rendered columns appear on the right instantly. Unlike a static file viewer, edits reflect immediately without a save-reload cycle. Q: Does this render GitHub Flavored Markdown or CommonMark, and does it matter for my README? A: The distinction matters specifically for tables, task lists, and auto-linked URLs. CommonMark does not include those features; GFM adds them as extensions. If you write '- [ ] item' expecting a checkbox, a CommonMark renderer will show it as plain text. For README files destined for GitHub, the most reliable check is GitHub itself. This tool is most useful for catching issues that exist in both flavors: missing blank lines before headings, unclosed bold markers, or code fences using an unrecognized language identifier. Q: Why does raw HTML embedded in my Markdown not render, or get stripped entirely? A: Most Markdown parsers pass inline HTML through to the output, but browser-based previewers typically sanitize the result using a library like DOMPurify to prevent XSS. Tags like script, iframe, and style get stripped before the HTML hits the DOM. A div or span with a class attribute usually survives; a script tag will not. If exact HTML passthrough is critical, a local pandoc conversion is more predictable than any browser-based previewer, because pandoc applies no sanitization by default. ### Encoding - [Base64 Encoder / Decoder](https://devlab.tools/tool/base64-encoder-decoder) Base64 encoding converts binary or text data into a 64-character ASCII alphabet so it can travel safely through systems that only handle plain text. A common case: pasting a small PNG into CSS as `background-image: url('data:image/png;base64,iVBORw0K...')` avoids an extra HTTP request. Unlike most online converters, this tool supports URL-safe Base64 (replacing `+` and `/` with `-` and `_`) and handles binary file encoding, not just strings. Q: Why does the Base64 output always end with one or two equals signs? A: Base64 encodes in groups of three input bytes at a time. When the input length isn't a multiple of three, the last group is padded with zero bits to complete it, and `=` characters mark that padding in the output so a decoder knows how many real bytes were in the final group. One `=` means one padding byte was added; `==` means two. Some systems (JWT, for instance) strip padding entirely and rely on the decoder to infer it from output length. If you paste a padded string into a JWT library and get an error, try removing the trailing `=` signs. Q: What is URL-safe Base64 and when do I need it? A: Standard Base64 uses `+` and `/` as its 62nd and 63rd characters. Both are meaningful in URLs: `+` decodes as a space in query strings and `/` separates path segments. URL-safe Base64 (RFC 4648 §5) swaps them for `-` and `_`, which are URL-unreserved. JWTs, many OAuth tokens, and Google Cloud signed URLs all use URL-safe Base64 without padding. If you paste a standard-Base64 string into a URL and the server returns a 400, switching to URL-safe mode is usually the fix. - [URL Encoder / Decoder](https://devlab.tools/tool/url-encoder-decoder) Paste a raw query string like `name=John Doe&city=São Paulo` and get back `name=John%20Doe&city=S%C3%A3o%20Paulo`, percent-encoded and safe to append to any endpoint. Unlike running encodeURIComponent() in a browser console, this tool exposes the distinction between full URL encoding and component-level encoding separately, which is the detail that trips up integrations when a parameter value itself contains reserved characters like & or =. Q: What is the difference between encoding a full URL and encoding a URL component? A: Encoding a full URL preserves the structural characters that give the URL its meaning: /, ?, &, =, #, and : are left untouched because they delimit the scheme, host, path, and query. Encoding a component assumes the input is a single value inside the URL, so those same characters get percent-encoded too. If a query parameter value contains a literal &, component encoding is required, or that & will be misread as a parameter separator by any server or router that parses the URL. Q: Why does my URL contain both %20 and + for spaces? A: Two different encoding standards are in play. RFC 3986, which governs URLs in general, requires spaces to become %20. The application/x-www-form-urlencoded specification, used by HTML form submissions and many older REST APIs, uses + to represent a space. Copy a URL from a browser address bar after submitting a search form and you will often see + in the query string. Most server-side frameworks decode both, but when constructing URLs manually or programmatically, %20 is unambiguous across all parsers. - [JWT Decoder](https://devlab.tools/tool/jwt-decoder) Paste a JWT and it splits the token at the two dots, base64url-decodes each segment, and renders the header, payload, and signature as formatted JSON. Useful when you have a token like `eyJhbGciOiJSUzI1NiJ9...` from an Authorization header and need to confirm the `exp` claim without spinning up a debugger or curl. Unlike jwt.io, nothing leaves your browser tab. Q: Why does the decoded payload show correct JSON but the signature segment looks like random bytes? A: The signature segment is intentional binary output from an HMAC or RSA operation, then base64url-encoded. Decoding it back to bytes gives you the raw cryptographic signature, not readable text. This tool renders those bytes as a hex or binary string depending on implementation, but there is nothing to read there — the signature's purpose is machine verification, not human inspection. If you want to verify it, you need the signing secret (HMAC-SHA256) or the issuer's public key (RS256/ES256), neither of which belongs in a browser tool. Q: My token has a period inside the payload after decoding. Did it get corrupted? A: No. JWTs are split on exactly two dots that separate header, payload, and signature. Dots that appear inside any of those three segments after base64url-decoding are part of the JSON content, not structural delimiters. The decoder splits on the first and second dot only, so nested dots in claim values like an email address in a `sub` field (`user@example.com` does not contain dots, but `client_id` values sometimes do) come through intact in the JSON output. - [Hash Generator](https://devlab.tools/tool/hash-generator) Paste any string and get its MD5, SHA-1, SHA-256, and SHA-512 digests simultaneously as lowercase hex. Practical example: copy the contents of a downloaded config snippet, paste it here, and compare the SHA-256 output against a publisher's documented checksum — no terminal needed. The side-by-side display of all four algorithms in a single step is what separates this from running openssl dgst separately per algorithm. Q: Why is the SHA-256 output always exactly 64 characters no matter how long my input is? A: Hash functions produce a fixed-length output regardless of input size — that is by design. SHA-256 always produces a 256-bit digest, which is 32 bytes, and each byte is represented as two hex characters, giving 64 characters. SHA-512 is 512 bits (64 bytes, 128 hex chars), SHA-1 is 160 bits (40 hex chars), and MD5 is 128 bits (32 hex chars). This fixed-length property is exactly what makes hashes useful as fingerprints: a short API key and a multi-paragraph changelog both produce a 64-character SHA-256 digest. Q: Is MD5 still safe enough to verify a file download in 2026? A: For pure corruption detection — confirming bytes were not mangled in transit — MD5 still works mechanically. The real problem is that MD5 is cryptographically broken: collision attacks that craft two different inputs sharing the same hash are computationally feasible. A motivated attacker could substitute a malicious file with a matching MD5. For any new integrity workflow, use SHA-256 at minimum. Most package registries and Linux distributions have already migrated their checksums to SHA-256 or SHA-512 for exactly this reason. - [UUID Generator](https://devlab.tools/tool/uuid-generator) This tool generates UUID v4 identifiers in your browser using the Web Crypto API's crypto.randomUUID(). Generate 1, 5, 10, 25, or 100 UUIDs at once. Each UUID is a 128-bit random value in the standard 8-4-4-4-12 hex format. No server calls, no data sent anywhere. Q: Is UUID v4 safe to use as a primary key in PostgreSQL? A: Yes for most workloads. PostgreSQL's uuid type stores UUIDs as 16 bytes and supports UUID-indexed columns efficiently. The concern is index fragmentation: v4 UUIDs insert randomly into the B-tree, causing more page splits than sequential integers. At under 10 million rows this is negligible; above that, consider UUID v7 (time-ordered) or gen_random_uuid() with a separate created_at index for range scans. Never store UUIDs as VARCHAR(36) — the uuid type is 2x more space-efficient. Q: What is the difference between UUID v4 and ULID? A: Both are 128-bit unique identifiers, but ULID encodes a 48-bit millisecond timestamp in the first 10 characters, followed by 80 random bits, encoded in Crockford Base32. This makes ULIDs sortable by creation time and more database-friendly for indexed inserts. UUID v4 is purely random with no timestamp component. If you need sortable IDs in a modern system, ULID or UUID v7 are better choices than v4. ### Time - [Unix Timestamp Converter](https://devlab.tools/tool/unix-timestamp-converter) Paste a Unix timestamp like 1716076800 and get the equivalent UTC and local date-time strings instantly; type a date and get the epoch integer back. The live counter showing the current timestamp refreshes every second, which makes it useful for checking whether a JWT or OAuth token's exp field has already passed before making another API call. Q: Why does the converted date show a time that's several hours off from what I expected? A: The tool renders timestamps in UTC by default. If your log file or API records events in UTC, that output is correct. If you expected local time, the difference equals your UTC offset. A timestamp of 1716076800 displays as 2024-05-19 00:00:00 UTC but as 2024-05-19 05:30:00 in IST (UTC+5:30). Confusion multiplies when the system that generated the timestamp stored local time instead of UTC, which violates the convention that Unix timestamps are always UTC-relative. Check the source system's timezone setting before assuming the converter is wrong. Q: My timestamp is 13 digits. Why does the converted date land in the wrong year? A: JavaScript's Date constructor takes milliseconds, not seconds. A 13-digit value like 1716076800000 is in milliseconds and converts to 2024-05-19. Feed that number to a tool expecting seconds and it reads the value as roughly 54,000 years in the future. The reverse mistake is equally common: a 10-digit seconds value like 1716076800 passed to Date() without multiplying by 1000 gives a date in January 1970, because Date() treats it as 1.7 billion milliseconds. Stripe and most server-side APIs use seconds; browser APIs like Date.now() use milliseconds. Count the digits before converting. - [Cron Expression Generator](https://devlab.tools/tool/cron-expression-generator) Build a cron expression using the visual field builder (minute, hour, day, month, weekday) and get the human-readable description instantly. Shows the next 5 execution times as absolute dates so you can verify the schedule before deploying. Choose from 8 common presets or enter custom values. Q: What does */15 mean in the minute field? A: The */n syntax means every n units starting from the minimum. So */15 in the minute field means at minutes 0, 15, 30, and 45 of every hour — four times per hour. This syntax works in all five fields: */2 in the hour field means every 2 hours, 12 times per day. Q: How does the day-of-month and day-of-week interaction work? A: When both day-of-month and day-of-week are specified (neither is *), most cron implementations use OR semantics: the job runs when EITHER condition is met. So 0 0 1 * 1 runs at midnight on the 1st of every month AND at midnight every Monday, not only on Mondays that happen to be the 1st. ### Numbers - [Number Base Converter](https://devlab.tools/tool/number-base-converter) Paste any integer in binary, octal, decimal, or hex and instantly see all four representations side by side. Useful when reading ARM disassembly where operands are hex but your bitmask logic is in binary: entering 0xFF immediately shows 11111111, 377, and 255 at once. Showing all four bases simultaneously without switching modes is what separates this from single-direction converters. Q: Why does entering a large hex value like 0xFFFFFFFF give a negative decimal on some converters but a positive one here? A: The difference is signed versus unsigned interpretation. 0xFFFFFFFF is 4294967295 as an unsigned 32-bit integer, but JavaScript's bitwise operators coerce numbers to signed 32-bit integers internally, making it appear as -1 when you use operations like `>>> 0` in the console. A converter that pipes your input through bitwise ops will show -1; one that uses `parseInt('FFFFFFFF', 16)` directly preserves the unsigned value 4294967295. Always check which interpretation a tool uses when you are working with 32-bit hardware registers or IPv4 addresses. Q: What is the largest integer this will convert accurately? A: JavaScript's Number type uses IEEE 754 double-precision floating-point, which represents integers exactly only up to 2^53 - 1, or 9007199254740991 (Number.MAX_SAFE_INTEGER). Beyond that threshold, integer precision is lost and conversions will silently round. If you need to convert 64-bit integers — common when working with database row IDs, cryptographic keys, or 64-bit register values — you would need a tool backed by BigInt arithmetic. For those cases, a Python one-liner using bin()/hex() on an actual int is more reliable than any browser-based converter that has not explicitly opted into BigInt. ### HTML - [HTML Beautifier](https://devlab.tools/tool/html-beautifier) Paste minified or messy HTML and get back properly indented, nested markup in one click. Useful when a CMS export hands you a wall of tags with no whitespace — for example, a 4KB single-line Mailchimp template becomes scannable, attributed markup with configurable 2- or 4-space indentation. Unlike a general code editor's format-on-save, this runs entirely on the page with no install required. Q: Will the beautifier change anything other than whitespace? A: In normal operation, no — it only adjusts indentation and line breaks. Attribute order, attribute quoting style, tag casing, and content are left untouched. If you paste `` you'll get back `` with corrected indentation, not ``. Some formatters normalize these things, but this tool's scope is whitespace only. If you need attribute sorting or quote normalization, a full Prettier run with the HTML plugin is the right tool. Q: Why does the formatted output look wrong for inline elements like `` inside `

`? A: Inline elements — ``, ``, ``, `` — are treated as block-level for indentation purposes by most text-based HTML formatters, including this one. That means you may see a `` on its own indented line even though it sits inline in the rendered page. This is a known trade-off of text-based formatting versus DOM-aware formatting. The output is still semantically correct HTML; it just won't match what Prettier's HTML plugin produces with its inline-element-aware line-wrapping logic. ## Learn Guides - [Regex Basics: A Complete Beginner's Guide](https://devlab.tools/learn/regex-basics): Learn regular expressions from scratch. Understand patterns, metacharacters, and how to write your first regex. - [Regex Special Characters: Complete Reference](https://devlab.tools/learn/regex-special-chars): Master every regex metacharacter and special character with examples and interactive tests. - [Regex Groups and Captures Explained](https://devlab.tools/learn/regex-groups): Learn how to use capturing groups, non-capturing groups, and named groups to extract data with regex. - [Regex Quantifiers: Complete Guide](https://devlab.tools/learn/regex-quantifiers): Master greedy, lazy, and possessive quantifiers in regular expressions with practical examples. - [CSS Selectors: The Complete Guide](https://devlab.tools/learn/css-selectors): Learn every type of CSS selector — from basic to advanced — with examples and specificity explanations. - [CSS Specificity: Why Your Styles Aren't Applying](https://devlab.tools/learn/css-specificity): Understand how CSS specificity works, how to calculate it, and how to avoid the !important trap. - [JSONPath Syntax: Query JSON Like XPath](https://devlab.tools/learn/json-path-syntax): Learn JSONPath syntax to query, filter, and extract data from nested JSON structures. - [Unix Timestamps Explained](https://devlab.tools/learn/unix-timestamps-explained): Everything you need to know about Unix time — what it is, how it works, and common pitfalls. - [Base64 Encoding Explained](https://devlab.tools/learn/base64-explained): Understand what Base64 is, how it works, when to use it, and when not to. - [JWT Structure and How It Works](https://devlab.tools/learn/jwt-structure): Understand JSON Web Tokens: their structure, how to decode them, and when to use (and not use) them. - [JWT vs Session Tokens: Which Should You Use?](https://devlab.tools/learn/jwt-vs-session-tokens): Understand the fundamental differences between stateless JWT authentication and stateful session tokens, with concrete guidance on which fits your use case. - [JWT Refresh Tokens Explained](https://devlab.tools/learn/jwt-refresh-tokens): Learn how refresh tokens extend JWT authentication sessions securely, without requiring users to log in again every 15 minutes. - [Hash Functions Explained: MD5, SHA-256, and When to Use Each](https://devlab.tools/learn/hash-functions-explained): Learn what hash functions do, why cryptographic hashes are one-way, and which algorithm to use for passwords, checksums, and data integrity. - [URL Encoding Explained: What %20 Actually Means](https://devlab.tools/learn/url-encoding-explained): Understand percent-encoding, why spaces become %20, when to use encodeURI vs encodeURIComponent, and how to decode URLs correctly. - [JSON Schema Explained: Validate Your JSON Data](https://devlab.tools/learn/json-schema-explained): Learn how JSON Schema works, how to write validation rules for objects and arrays, and how to use it for API request validation and OpenAPI documentation. - [JSON vs YAML: Which Should You Use?](https://devlab.tools/learn/json-vs-yaml): Compare JSON and YAML for configuration files, API responses, and data interchange — with concrete rules for when each format is the right choice. - [JSON.stringify and JSON.parse: Edge Cases You Should Know](https://devlab.tools/learn/json-stringify-parse): Master JavaScript JSON serialization — what stringify drops, how to handle dates and undefined, the replacer and reviver functions, and circular reference errors. - [Regex Lookahead and Lookbehind: Match Without Consuming](https://devlab.tools/learn/regex-lookahead-lookbehind): Understand zero-width assertions in regex — how lookahead and lookbehind let you match based on surrounding context without including that context in the result. - [Regex for Email Validation: The Right Approach](https://devlab.tools/learn/regex-email-validation): Learn why perfect email regex is impossible, what a practical validation pattern looks like, and when to use client-side vs server-side validation. - [The CSS Box Model: margin, padding, border, and content](https://devlab.tools/learn/css-box-model): Understand how every HTML element is rendered as a rectangular box, how margin and padding differ, and how box-sizing:border-box changes layout forever. - [Flexbox vs CSS Grid: When to Use Each](https://devlab.tools/learn/css-flexbox-vs-grid): Learn the fundamental difference between one-dimensional Flexbox and two-dimensional Grid, with practical examples for navbars, galleries, and page layouts. - [CSS Custom Properties (Variables) Explained](https://devlab.tools/learn/css-variables-explained): Learn how CSS custom properties work, how they differ from preprocessor variables, and how to use them for theming, dark mode, and dynamic styling. - [ISO 8601 Explained: The Right Way to Format Dates](https://devlab.tools/learn/iso-8601-explained): Learn the ISO 8601 date and datetime standard, why 2026-06-13T10:30:00Z is unambiguous, and how to use it correctly in APIs and databases. - [Unix Timestamps vs ISO 8601: Which to Use in Your API?](https://devlab.tools/learn/unix-timestamp-vs-iso): Compare Unix epoch timestamps with ISO 8601 strings for API design, database storage, and JavaScript date handling — with a clear recommendation. - [UTF-8 Explained: How Computers Store Text](https://devlab.tools/learn/utf8-explained): Understand how UTF-8 encodes every writing system into bytes, why it became the universal standard, and how encoding bugs appear in real applications. - [CORS Explained: Why Your API Call is Blocked](https://devlab.tools/learn/cors-explained): Understand why browsers enforce the Same-Origin Policy, how CORS headers unlock cross-origin requests, and how to configure CORS correctly on your server. - [HTTP Status Codes: A Practical Developer Guide](https://devlab.tools/learn/http-status-codes-guide): Learn what each HTTP status code range means, which codes to use in your REST API, and how to avoid the most common status code mistakes. - [Named Capture Groups in Regex: Clean Extractions](https://devlab.tools/learn/regex-named-capture-groups): Learn how named capture groups make regex results readable, how to access them in JavaScript, and why they beat numbered groups for complex patterns. - [Color Spaces Explained: RGB, HSL, HEX, and Beyond](https://devlab.tools/learn/color-spaces-explained): Understand how computers represent color. Learn the differences between RGB, HSL, HEX, HSV, and OKLCH — and when to use each one. - [Color Contrast for Developers: WCAG Rules and How to Check](https://devlab.tools/learn/css-color-contrast): Learn the WCAG contrast requirements for text, icons, and interactive elements — and how to test contrast ratios in your projects. - [Number Bases Explained: Binary, Octal, Decimal, and Hex](https://devlab.tools/learn/number-bases-explained): Understand how number systems work — from binary and octal to decimal and hexadecimal — with practical examples for developers. - [Bitwise Operations for Web Developers](https://devlab.tools/learn/bitwise-operations-guide): A practical guide to AND, OR, XOR, NOT, and bit shifting — with real use cases like feature flags, permissions, and colour manipulation. - [HTML Semantic Elements: A Complete Reference](https://devlab.tools/learn/html-semantic-elements): Learn which HTML elements to use for headers, navigation, articles, sections, and more — and why semantics matter for SEO and accessibility. - [Text Encoding for Developers: ASCII, UTF-8, and Unicode](https://devlab.tools/learn/text-encoding-utf8-ascii): How computers store text — from ASCII to Unicode to UTF-8. Understand encoding errors, BOM, and why mojibake happens. - [What is Regex? Complete Guide for Developers](https://devlab.tools/learn/regex-explained): Master regular expressions from patterns and flags to groups, lookahead, named captures, and common mistakes across JavaScript, Python, and other languages. - [JSON Format Explained: Structure, Syntax, and Common Errors](https://devlab.tools/learn/json-explained): Understand JSON syntax, valid vs invalid values, parsing in JavaScript and other languages, the difference from JSON5, and how to validate JSON with schemas. - [How JWT Works: Header, Payload, Signature Decoded](https://devlab.tools/learn/jwt-explained): Understand JWT structure, how HS256 and RS256 signing work, when to use JWT over sessions, and the security mistakes that get apps breached. - [How to Convert Any Website to Markdown (for LLMs, RAG & Docs)](https://devlab.tools/learn/convert-website-to-markdown): Compare every way to turn a web page into Markdown — pandoc, Turndown, browser tools, and hosted crawlers — and learn when each one breaks down. - [Preparing Website Content for RAG: Clean Markdown Pipelines](https://devlab.tools/learn/website-to-markdown-for-rag): Why clean Markdown beats raw HTML for RAG, how to strip boilerplate and crawl sitemaps, and how to build the pipeline with or without your own infrastructure. ## Comparisons - [Regex vs. String Methods](https://devlab.tools/compare/regex-vs-string-methods): When should you use regular expressions, and when are string methods like indexOf, split, and replace enough? Verdict: Use string methods for simple, known patterns. Reach for regex when you need to match variable content, validate formats, or extract multiple pieces of data from text. For critical validation (like emails), consider a battle-tested library. - [JSON vs. YAML](https://devlab.tools/compare/json-vs-yaml): A practical comparison of JSON and YAML for configuration files, data interchange, and developer experience. Verdict: Use JSON for machine-to-machine communication and APIs. Use YAML for human-maintained configuration files, especially in DevOps tooling where readability and comments matter. - [Base64 vs. Hex Encoding](https://devlab.tools/compare/base64-vs-hex): Understanding when to use Base64 versus hexadecimal encoding for binary data. Verdict: Use Base64 when transmitting binary data through text channels (APIs, headers, URLs). Use Hex when working with cryptographic values, debugging binary data, or when byte-level readability matters. - [MD5 vs. SHA-256](https://devlab.tools/compare/md5-vs-sha256): When to use MD5 versus SHA-256 for checksums and hashing. Verdict: Never use MD5 for security purposes. For checksums where security is irrelevant, MD5 is fine. For anything security-related, use SHA-256 or higher. For passwords, use bcrypt or Argon2 — neither MD5 nor SHA-256 is appropriate. - [CSS Flexbox vs. Grid](https://devlab.tools/compare/flexbox-vs-grid): The definitive guide on when to use CSS Flexbox versus CSS Grid for your layouts. Verdict: Flexbox is for components (one direction). Grid is for layouts (two directions). They are complementary — use Grid for the overall page structure and Flexbox for components within those areas. - [RGB vs. HSL Colors](https://devlab.tools/compare/rgb-vs-hsl): Understanding RGB and HSL color models and when to use each in CSS and design. Verdict: Use RGB/HEX for exact colors from designs. Use HSL in CSS for building design systems, creating color variants, and theming — it's much easier to reason about "10% lighter" in HSL than in RGB. - [Unix Timestamp vs. ISO 8601](https://devlab.tools/compare/unix-time-vs-iso8601): When to use Unix timestamps versus ISO 8601 date strings for storing and transmitting time. Verdict: Store as Unix timestamp in databases for efficiency. Use ISO 8601 in user-facing APIs, logs, and configuration files for readability. Always normalize to UTC before storage regardless of format. - [JWT vs. Session Tokens](https://devlab.tools/compare/jwt-vs-session-tokens): A practical security comparison of JWTs and server-side session tokens for authentication. Verdict: For most web apps with a single backend, session tokens are simpler and more secure. Use JWTs for microservices, mobile apps, or when stateless auth is architecturally required — but use short expiry times and a token refresh strategy. - [Markdown vs. HTML](https://devlab.tools/compare/markdown-vs-html): When to write content in Markdown versus raw HTML, and the tradeoffs of each format. Verdict: Use Markdown for content that humans write and read. Use HTML for web pages and layouts requiring full control. Most modern projects use Markdown for content and convert it to HTML at build time. - [Cron Jobs vs. Webhooks](https://devlab.tools/compare/cron-vs-webhook): Should you use scheduled cron jobs or event-driven webhooks for your automation? Here's how to decide. Verdict: Use webhooks for real-time reactions to events — they're more efficient and lower latency. Use cron for periodic tasks that run on a schedule regardless of external events. Many production systems use both: cron for reliability, webhooks for immediacy. - [TypeScript vs. JavaScript](https://devlab.tools/compare/typescript-vs-javascript): When does adding TypeScript pay off, and when is vanilla JavaScript the better choice? Verdict: Use TypeScript for any project that will live beyond a prototype or involve more than one developer. The compile-time safety and tooling improvements pay for the build-step cost many times over. Use plain JavaScript for throwaway scripts, quick experiments, and environments where a build step is impractical. - [REST vs. GraphQL](https://devlab.tools/compare/rest-vs-graphql): Two dominant API paradigms compared — when REST's simplicity wins and when GraphQL's flexibility matters. Verdict: Use REST when your API has clear resources, needs HTTP caching, or is consumed by many external clients. Use GraphQL when clients have diverse data needs, you want a strongly typed contract, or you are building a dashboard that pulls from many data sources. Many teams use both: REST for simple CRUD, GraphQL for complex queries. - [npm vs. pnpm vs. Yarn](https://devlab.tools/compare/npm-vs-pnpm-vs-yarn): Comparing the three major JavaScript package managers on speed, disk usage, and developer experience. Verdict: Use npm if you want zero setup and maximum compatibility. Use pnpm for monorepos, disk savings, and strict dependency resolution. Yarn (Berry) is a strong choice if you want Plug'n'Play or already use it — but for new projects in 2026, pnpm offers the best balance of speed, correctness, and ecosystem support. - [UTF-8 vs. UTF-16](https://devlab.tools/compare/utf8-vs-utf16): Two Unicode encodings compared — why the web chose UTF-8 and when UTF-16 still makes sense. Verdict: Use UTF-8 for storage, transmission, and interchange — it is the universal standard and is more compact for most content. UTF-16 is an implementation detail of JavaScript, Java, and Windows internals — you rarely choose it directly. When you encounter UTF-16 (e.g. reading a Windows-generated CSV), convert to UTF-8 at the boundary. - [Sass Variables vs. CSS Custom Properties](https://devlab.tools/compare/sass-vs-css-variables): Should you use Sass $variables or native CSS custom properties (--vars)? The answer depends on when you need the values resolved. Verdict: Use CSS custom properties for anything that needs to change at runtime — themes, user preferences, component variants. Use Sass variables for build-time constants like breakpoints, colour math, and generating utility classes. Most modern projects use both: Sass variables compile down to CSS custom properties, giving you the best of both worlds. ## Categories - [Regex Tools](https://devlab.tools/category/regex): Test, debug, and learn regular expressions with interactive tools and references. - [CSS Tools](https://devlab.tools/category/css): Generate CSS gradients, shadows, grids, animations, and more with visual editors. - [JSON Tools](https://devlab.tools/category/json): Format, validate, minify, convert, and query JSON data with ease. - [Colors Tools](https://devlab.tools/category/colors): Convert color formats, check contrast, and generate palettes. - [Text Tools](https://devlab.tools/category/text): Count words, convert case, diff text, and generate placeholder content. - [Encoding Tools](https://devlab.tools/category/encoding): Encode and decode Base64, URLs, HTML entities, JWT, and hashes. - [Time Tools](https://devlab.tools/category/time): Convert timestamps, timezones, dates, and build cron expressions. - [Numbers Tools](https://devlab.tools/category/numbers): Convert number bases, calculate bits/bytes, percentages, and Roman numerals. - [HTML Tools](https://devlab.tools/category/html): Beautify, minify, and convert HTML to other formats. - [Crypto Tools](https://devlab.tools/category/crypto): Generate cryptographic hashes and work with encoding schemes. ## Site Pages - [Home](https://devlab.tools): Main page with tool search and popular tools. - [All Tools](https://devlab.tools/tools): Full index of working DevLab tools. - [Categories](https://devlab.tools/categories): Tools grouped by category. - [Learn](https://devlab.tools/learn): Educational guides on regex, CSS, JSON, encoding, and more. - [Comparisons](https://devlab.tools/comparisons): Side-by-side comparisons of developer approaches. - [About](https://devlab.tools/about): Who builds DevLab and how it works. - [Contact](https://devlab.tools/contact): Get in touch. ## In development (not yet live) - Regex Cheatsheet (regex) - Regex to String Generator (regex) - Common Regex Patterns (regex) - Regex Explainer (regex) - Regex Flags Explained (regex) - Lookahead & Lookbehind Guide (regex) - Named Capture Groups (regex) - CSS Box Shadow Generator (css) - CSS Border Radius Generator (css) - CSS Flexbox Generator (css) - CSS Grid Generator (css) - CSS Animation Generator (css) - CSS Filter Generator (css) - CSS Clip Path Generator (css) - CSS Variables Cheatsheet (css) - CSS Specificity Calculator (css) - Color Contrast Checker (colors) - Color Palette Generator (colors) - Color Shades Generator (colors) - Gradient Color Picker (colors) - Lorem Ipsum Generator (text) - Slug Generator (text) - HTML Entity Encoder (encoding) - Timezone Converter (time) - Date Duration Calculator (time) - Bit & Byte Calculator (numbers) - Percentage Calculator (numbers) - Roman Numeral Converter (numbers) - HTML Minifier (html) - HTML to Markdown (html)