{"id":2390,"date":"2026-04-08T17:45:53","date_gmt":"2026-04-08T17:45:53","guid":{"rendered":"https:\/\/primetoolhub.com\/?page_id=2390"},"modified":"2026-08-08T14:19:55","modified_gmt":"2026-08-08T14:19:55","slug":"lorem-ipsum-and-json-dummy-data-generator-pro","status":"publish","type":"page","link":"https:\/\/schoolict.net\/tools\/lorem-ipsum-and-json-dummy-data-generator-pro\/","title":{"rendered":"Free Lorem Ipsum and JSON Dummy Data Generator Pro"},"content":{"rendered":"<div class=\"pth-hero-section\">\n<div class=\"pth-hero-content\">\n<h2><b data-path-to-node=\"3,2,0\" data-index-in-node=\"0\">Stop Writing Sample Data by Hand<\/b> \u2014 Build mock JSON payloads and flexible text placeholders effortlessly.<\/h2>\n<p>Instantly generate custom Lorem Ipsum text, rich HTML placeholders, and realistic JSON dummy user profiles 100% offline. Perfect for UI\/UX and frontend developers. Now use Lorem Ipsum &amp; JSON Dummy Data Generator Pro<\/p>\n<div id=\"pth-toc-placeholder\">\u00a0<\/div>\n<\/div>\n<div class=\"pth-hero-image\"><img decoding=\"async\" src=\"https:\/\/schoolict.net\/tools\/wp-content\/uploads\/2026\/04\/Lorem-Ipsum-Dummy-Data-Generator-1024x572.jpeg\" alt=\"Lorem Ipsum &amp; Dummy Data Generator\" width=\"450\" height=\"253\" data-no-lazy=\"1\" \/><\/div>\n<\/div>\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Table of Contents<\/h2><nav><ul><li><a href=\"#\ud83d\udd34-why-a-seed-turns-sample-data-into-a-test-fixture\">\ud83d\udd34\u00a0Why a Seed Turns Sample Data Into a Test Fixture<\/a><\/li><li><a href=\"#\ud83d\udfe1-building-a-schema-that-matches-your-real-api\">\ud83d\udfe1\u00a0Building a Schema That Matches Your Real API<\/a><ul><li><a href=\"#\ud83d\udfe2-records-that-make-internal-sense\">\ud83d\udfe2\u00a0Records That Make Internal Sense<\/a><\/li><\/ul><\/li><li><a href=\"#\ud83d\udd34-awkward-names-and-empty-values-are-the-point\">\ud83d\udd34\u00a0Awkward Names and Empty Values Are the Point<\/a><\/li><li><a href=\"#\ud83d\udfe1-picking-the-right-export-format\">\ud83d\udfe1\u00a0Picking the Right Export Format<\/a><\/li><li><a href=\"#\ud83d\udfe2-nested-records-for-realistic-api-mocking\">\ud83d\udfe2\u00a0Nested Records for Realistic API Mocking<\/a><\/li><\/ul><\/nav><\/div>\n\n\n<!-- LSCACHE_DISABLE -->\r\n<style>\r\n#pth-mds-wrapper{font-family:'Inter',system-ui,-apple-system,sans-serif;color:#1e293b;line-height:1.6;max-width:1400px;margin:0 auto;box-sizing:border-box;background:#f8fafc;padding:20px;border-radius:16px}\r\n#pth-mds-wrapper *{box-sizing:border-box;min-width:0}\r\n#pth-mds-wrapper .mds-card{background:#fff;border:1px solid #e2e8f0;border-radius:12px;padding:22px;margin-bottom:20px;box-shadow:0 4px 6px -1px rgba(0,0,0,.04)}\r\n#pth-mds-wrapper h2.mds-title{font-size:1.5rem;font-weight:800;color:#1d4ed8;margin:0 0 6px}\r\n#pth-mds-wrapper .mds-sub{color:#334155;margin:0 0 12px;font-weight:500;font-size:.9rem}\r\n#pth-mds-wrapper .mds-meta{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:14px}\r\n#pth-mds-wrapper .mds-badge{font-size:.7rem;font-weight:800;padding:3px 10px;border-radius:20px}\r\n#pth-mds-wrapper .mds-b-blue{background:#eff6ff;color:#1d4ed8;border:1px solid #bfdbfe}\r\n#pth-mds-wrapper .mds-b-green{background:#f0fdf4;color:#047857;border:1px solid #bbf7d0}\r\n#pth-mds-wrapper .mds-b-purple{background:#f5f3ff;color:#5b21b6;border:1px solid #ddd6fe}\r\n#pth-mds-wrapper .mds-toolbar{display:flex;gap:8px;flex-wrap:wrap}\r\n#pth-mds-wrapper .mds-btn{border:none;padding:9px 18px;border-radius:8px;font-weight:700;cursor:pointer;font-size:.85rem;display:inline-flex;align-items:center;gap:6px;font-family:inherit;transition:.15s}\r\n#pth-mds-wrapper .mds-btn-primary{background:#2563eb;color:#fff}\r\n#pth-mds-wrapper .mds-btn-primary:hover{background:#1d4ed8}\r\n#pth-mds-wrapper .mds-btn-sec{background:#f1f5f9;color:#334155;border:1px solid #cbd5e1}\r\n#pth-mds-wrapper .mds-btn-sec:hover{background:#e2e8f0}\r\n#pth-mds-wrapper .mds-btn-purple{background:#f5f3ff;color:#5b21b6;border:1px solid #ddd6fe}\r\n#pth-mds-wrapper .mds-btn-danger{background:#fef2f2;color:#991b1b;border:1px solid #fecaca}\r\n#pth-mds-wrapper .mds-btn-sm{padding:6px 12px;font-size:.78rem}\r\n#pth-mds-wrapper .mds-grid{display:grid;grid-template-columns:1.85fr 1fr;gap:20px;align-items:start}\r\n#pth-mds-wrapper .mds-grid.mds-fw{grid-template-columns:1fr}\r\n#pth-mds-wrapper .mds-grid.mds-fw .mds-side{display:none}\r\n#pth-mds-wrapper .mds-main{background:#fff;border:1px solid #e2e8f0;border-radius:12px;padding:22px;box-shadow:0 4px 6px -1px rgba(0,0,0,.04)}\r\n#pth-mds-wrapper .mds-side{background:#fff;border:1px solid #e2e8f0;border-radius:12px;padding:22px}\r\n#pth-mds-wrapper .mds-tabs{display:flex;flex-wrap:wrap;border-bottom:2px solid #e2e8f0;margin-bottom:20px;gap:2px}\r\n#pth-mds-wrapper .mds-tab{background:transparent;border:none;padding:10px 14px;font-size:.85rem;font-weight:700;color:#334155;cursor:pointer;border-bottom:3px solid transparent;margin-bottom:-2px;border-radius:8px 8px 0 0;font-family:inherit;transition:.15s;white-space:nowrap}\r\n#pth-mds-wrapper .mds-tab:hover{color:#1d4ed8;background:#f1f5f9}\r\n#pth-mds-wrapper .mds-tab.mds-active{color:#1d4ed8;border-bottom-color:#2563eb;background:#eff6ff}\r\n#pth-mds-wrapper .mds-panel{display:none}\r\n#pth-mds-wrapper .mds-panel.mds-active{display:block}\r\n#pth-mds-wrapper .mds-fld{margin-bottom:14px}\r\n#pth-mds-wrapper .mds-fld label{display:block;font-size:.8rem;font-weight:700;margin-bottom:6px;color:#334155}\r\n#pth-mds-wrapper .mds-inp{width:100%;padding:10px 13px;font-size:.9rem;border:2px solid #cbd5e1;border-radius:8px;font-family:inherit;font-weight:600;color:#0f172a;outline:none;background:#fff}\r\n#pth-mds-wrapper .mds-inp:focus{border-color:#2563eb;box-shadow:0 0 0 3px rgba(37,99,235,.1)}\r\n#pth-mds-wrapper input.mds-inp[type=number]{font-family:'Courier New',monospace;font-weight:700}\r\n#pth-mds-wrapper .mds-row2{display:grid;grid-template-columns:1fr 1fr;gap:14px}\r\n#pth-mds-wrapper .mds-row3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px}\r\n#pth-mds-wrapper .mds-sec{font-size:.75rem;font-weight:800;color:#334155;text-transform:uppercase;letter-spacing:.4px;margin:18px 0 10px;border-bottom:2px solid #f1f5f9;padding-bottom:6px}\r\n#pth-mds-wrapper .mds-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:14px}\r\n#pth-mds-wrapper .mds-chip{background:#f8fafc;border:1px solid #cbd5e1;border-radius:20px;padding:6px 13px;font-size:.78rem;font-weight:700;color:#334155;cursor:pointer;font-family:inherit;transition:.15s}\r\n#pth-mds-wrapper .mds-chip:hover{border-color:#2563eb;color:#1d4ed8;background:#eff6ff}\r\n#pth-mds-wrapper .mds-chip.mds-on{background:#2563eb;color:#fff;border-color:#2563eb}\r\n#pth-mds-wrapper .mds-frow{display:grid;grid-template-columns:1.1fr 1.4fr auto auto auto;gap:7px;margin-bottom:7px;align-items:center}\r\n#pth-mds-wrapper .mds-frow .mds-inp{padding:8px 10px;font-size:.83rem}\r\n#pth-mds-wrapper .mds-mini{background:#f1f5f9;color:#334155;border:1px solid #cbd5e1;border-radius:7px;width:32px;height:34px;cursor:pointer;font-weight:800;font-family:inherit;font-size:.9rem;line-height:1;flex-shrink:0;padding:0}\r\n#pth-mds-wrapper .mds-mini:hover{background:#e2e8f0;color:#1d4ed8}\r\n#pth-mds-wrapper .mds-mini.mds-del{background:#fef2f2;color:#991b1b;border-color:#fecaca}\r\n#pth-mds-wrapper .mds-mini.mds-del:hover{background:#fee2e2}\r\n#pth-mds-wrapper .mds-outbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:12px;margin-bottom:12px}\r\n#pth-mds-wrapper .mds-outbar select{padding:8px 11px;border:2px solid #cbd5e1;border-radius:8px;font-family:inherit;font-weight:700;font-size:.83rem;color:#0f172a;background:#fff;outline:none}\r\n#pth-mds-wrapper .mds-outbar select:focus{border-color:#2563eb}\r\n#pth-mds-wrapper .mds-out{width:100%;min-height:280px;padding:14px;font-family:'Courier New',monospace;font-size:.83rem;line-height:1.6;border:2px solid #cbd5e1;border-radius:10px;background:#f8fafc;color:#0f172a;resize:vertical;outline:none;white-space:pre;overflow-wrap:normal;overflow-x:auto}\r\n#pth-mds-wrapper .mds-out:focus{border-color:#2563eb}\r\n#pth-mds-wrapper .mds-stats{display:flex;gap:14px;flex-wrap:wrap;font-size:.75rem;color:#334155;font-weight:700;margin-top:8px;justify-content:flex-end}\r\n#pth-mds-wrapper .mds-note{background:#fffbeb;border:1px solid #fde68a;border-radius:8px;padding:12px 14px;font-size:.82rem;color:#92400e;font-weight:500;margin-bottom:14px;line-height:1.5}\r\n#pth-mds-wrapper .mds-info{background:#eff6ff;border:1px solid #bfdbfe;border-radius:8px;padding:12px 14px;font-size:.82rem;color:#1e293b;font-weight:500;margin-bottom:14px;line-height:1.5}\r\n#pth-mds-wrapper .mds-info code,#pth-mds-wrapper .mds-note code{background:#fff;color:#1d4ed8;padding:1px 5px;border-radius:4px;font-weight:800;font-size:.78rem}\r\n#pth-mds-wrapper .mds-check{display:flex;align-items:flex-start;gap:8px;font-size:.84rem;font-weight:600;color:#334155;margin-bottom:9px;cursor:pointer;line-height:1.45}\r\n#pth-mds-wrapper .mds-check input{width:auto;margin:3px 0 0;flex-shrink:0;cursor:pointer}\r\n#pth-mds-wrapper .mds-side h3{font-size:.95rem;font-weight:800;color:#0f172a;margin:0 0 10px}\r\n#pth-mds-wrapper .mds-side h3.mds-mt{margin-top:22px}\r\n#pth-mds-wrapper .mds-side p{font-size:.82rem;color:#1e293b;font-weight:500;margin:0 0 10px}\r\n#pth-mds-wrapper .mds-tbl{width:100%;border-collapse:collapse;background:#fff;border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;margin-bottom:14px}\r\n#pth-mds-wrapper .mds-tbl th{background:#f8fafc;padding:9px;font-size:.72rem;font-weight:800;color:#0f172a;text-align:left;border-bottom:1px solid #e2e8f0;text-transform:uppercase;letter-spacing:.3px}\r\n#pth-mds-wrapper .mds-tbl td{padding:8px 9px;font-size:.82rem;color:#1e293b;border-bottom:1px solid #f1f5f9;font-weight:500}\r\n#pth-mds-wrapper .mds-tbl tr:last-child td{border-bottom:none}\r\n#pth-mds-wrapper .mds-tbl .mds-mono{font-family:monospace;font-weight:700;color:#1d4ed8}\r\n#pth-mds-wrapper .mds-xlink{background:#f5f3ff;border:1px solid #ddd6fe;border-radius:8px;padding:12px 14px;font-size:.82rem;color:#1e293b;font-weight:500;margin-top:14px}\r\n#pth-mds-wrapper .mds-xlink a{color:#5b21b6;font-weight:800;text-decoration:none;display:block;margin-top:4px}\r\n#pth-mds-wrapper .mds-xlink a:hover{text-decoration:underline}\r\n#pth-mds-wrapper .mds-toast{visibility:hidden;min-width:220px;background:#0f172a;color:#fff;text-align:center;border-radius:8px;padding:12px 18px;position:fixed;z-index:99999;left:50%;bottom:30px;transform:translateX(-50%);font-size:.85rem;font-weight:700;opacity:0;transition:.3s;pointer-events:none}\r\n#pth-mds-wrapper .mds-toast.mds-show{visibility:visible;opacity:1;bottom:50px}\r\n#pth-mds-wrapper .mds-toast.mds-ok{background:#047857}\r\n#pth-mds-wrapper .mds-toast.mds-err{background:#991b1b}\r\n@media(max-width:900px){#pth-mds-wrapper .mds-grid{grid-template-columns:1fr}#pth-mds-wrapper .mds-row2,#pth-mds-wrapper .mds-row3{grid-template-columns:1fr}#pth-mds-wrapper .mds-frow{grid-template-columns:1fr 1fr auto auto auto}}\r\n<\/style>\r\n\r\n<div id=\"pth-mds-wrapper\">\r\n<div id=\"mds-toast\" class=\"mds-toast\" role=\"status\" aria-live=\"polite\"><\/div>\r\n\r\n<div class=\"mds-card\">\r\n  <h2 class=\"mds-title\">Mock Data Studio<\/h2>\r\n  <p class=\"mds-sub\">Generate Lorem Ipsum and realistic test records from a schema you define. Seeded for reproducible fixtures, four locale packs, nested relations, and export to JSON, CSV, TSV, XML, SQL or Markdown. 100% offline.<\/p>\r\n  <div class=\"mds-meta\">\r\n    <span class=\"mds-badge mds-b-blue\">v2.1<\/span>\r\n    <span class=\"mds-badge mds-b-green\">100% Offline<\/span>\r\n    <span class=\"mds-badge mds-b-purple\">Seeded &amp; Reproducible<\/span>\r\n  <\/div>\r\n  <div class=\"mds-toolbar\">\r\n    <button type=\"button\" class=\"mds-btn mds-btn-purple\" id=\"mds-sample\">Load Sample<\/button>\r\n    <button type=\"button\" class=\"mds-btn mds-btn-sec\" id=\"mds-fw\">Full Width<\/button>\r\n    <button type=\"button\" class=\"mds-btn mds-btn-danger\" id=\"mds-reset\">Reset All<\/button>\r\n  <\/div>\r\n<\/div>\r\n\r\n<div class=\"mds-grid\" id=\"mds-grid\">\r\n<div class=\"mds-main\">\r\n\r\n<div class=\"mds-tabs\" role=\"tablist\" aria-label=\"Mock Data Studio sections\">\r\n  <button type=\"button\" class=\"mds-tab mds-active\" data-tab=\"schema\">Schema Builder<\/button>\r\n  <button type=\"button\" class=\"mds-tab\" data-tab=\"nested\">Nested &amp; Relations<\/button>\r\n  <button type=\"button\" class=\"mds-tab\" data-tab=\"realism\">Realism &amp; Seed<\/button>\r\n  <button type=\"button\" class=\"mds-tab\" data-tab=\"lorem\">Lorem Text<\/button>\r\n  <button type=\"button\" class=\"mds-tab\" data-tab=\"exportopt\">Export Options<\/button>\r\n<\/div>\r\n\r\n<!-- SCHEMA BUILDER -->\r\n<div id=\"mds-p-schema\" class=\"mds-panel mds-active\">\r\n  <div class=\"mds-sec\">Schema Presets<\/div>\r\n  <div class=\"mds-chips\" id=\"mds-presets\"><\/div>\r\n\r\n  <div class=\"mds-row2\">\r\n    <div class=\"mds-fld\"><label for=\"mds-count\">Number of Records<\/label>\r\n      <input type=\"number\" id=\"mds-count\" class=\"mds-inp\" value=\"10\" min=\"1\" max=\"5000\"><\/div>\r\n    <div class=\"mds-fld\"><label for=\"mds-addtype\">Add a Field<\/label>\r\n      <select id=\"mds-addtype\" class=\"mds-inp\"><\/select><\/div>\r\n  <\/div>\r\n  <button type=\"button\" class=\"mds-btn mds-btn-sec mds-btn-sm\" id=\"mds-addfield\" style=\"margin-bottom:16px;\">+ Add Field to Schema<\/button>\r\n\r\n  <div class=\"mds-sec\">Your Schema <span style=\"text-transform:none;letter-spacing:0;font-weight:600;color:#334155;\">&mdash; rename any field, reorder with the arrows<\/span><\/div>\r\n  <div id=\"mds-schema-rows\"><\/div>\r\n  <div class=\"mds-info\" style=\"margin-top:12px;\">Field <strong>names<\/strong> become your JSON keys, CSV headers and SQL columns &mdash; rename them to match your real API. Field <strong>types<\/strong> decide what kind of value is generated. The two are independent, so a field named <code>author<\/code> can hold a <code>fullName<\/code> value.<\/div>\r\n<\/div>\r\n\r\n<!-- NESTED -->\r\n<div id=\"mds-p-nested\" class=\"mds-panel\">\r\n  <label class=\"mds-check\"><input type=\"checkbox\" id=\"mds-nest-on\"> <span><strong>Enable nested child records<\/strong> &mdash; give every parent record an array of children, the way a real API returns a user with their orders.<\/span><\/label>\r\n  <div id=\"mds-nest-cfg\" style=\"display:none;\">\r\n    <div class=\"mds-row3\">\r\n      <div class=\"mds-fld\"><label for=\"mds-nest-key\">Array Key Name<\/label>\r\n        <input type=\"text\" id=\"mds-nest-key\" class=\"mds-inp\" value=\"orders\"><\/div>\r\n      <div class=\"mds-fld\"><label for=\"mds-nest-min\">Min per Parent<\/label>\r\n        <input type=\"number\" id=\"mds-nest-min\" class=\"mds-inp\" value=\"1\" min=\"0\" max=\"50\"><\/div>\r\n      <div class=\"mds-fld\"><label for=\"mds-nest-max\">Max per Parent<\/label>\r\n        <input type=\"number\" id=\"mds-nest-max\" class=\"mds-inp\" value=\"3\" min=\"0\" max=\"50\"><\/div>\r\n    <\/div>\r\n    <label class=\"mds-check\"><input type=\"checkbox\" id=\"mds-nest-fk\" checked> <span>Add a foreign key on each child pointing back to its parent's <code>id<\/code><\/span><\/label>\r\n    <div class=\"mds-fld\" style=\"margin-top:10px;\"><label for=\"mds-nest-addtype\">Add a Child Field<\/label>\r\n      <select id=\"mds-nest-addtype\" class=\"mds-inp\"><\/select><\/div>\r\n    <button type=\"button\" class=\"mds-btn mds-btn-sec mds-btn-sm\" id=\"mds-nest-addfield\" style=\"margin-bottom:16px;\">+ Add Field to Child Schema<\/button>\r\n    <div class=\"mds-sec\">Child Schema<\/div>\r\n    <div id=\"mds-nest-rows\"><\/div>\r\n    <div class=\"mds-note\" style=\"margin-top:14px;\"><strong>Flat formats cannot hold arrays.<\/strong> CSV, TSV and SQL are tabular, so a nested array is written into a single column as compact JSON text. For genuinely nested output use JSON or XML.<\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- REALISM -->\r\n<div id=\"mds-p-realism\" class=\"mds-panel\">\r\n  <div class=\"mds-sec\">Reproducibility<\/div>\r\n  <div class=\"mds-row2\">\r\n    <div class=\"mds-fld\"><label for=\"mds-seed\">Seed (any text or number)<\/label>\r\n      <input type=\"text\" id=\"mds-seed\" class=\"mds-inp\" value=\"primetoolhub\" placeholder=\"e.g. 42 or my-project\"><\/div>\r\n    <div class=\"mds-fld\"><label>&nbsp;<\/label>\r\n      <button type=\"button\" class=\"mds-btn mds-btn-sec\" id=\"mds-randseed\" style=\"width:100%;justify-content:center;\">Random New Seed<\/button><\/div>\r\n  <\/div>\r\n  <label class=\"mds-check\"><input type=\"checkbox\" id=\"mds-seed-on\" checked> <span><strong>Use the seed<\/strong> &mdash; the same seed always produces byte-identical data, so you can commit a fixture and regenerate it exactly. Uncheck for fresh random data every time.<\/span><\/label>\r\n\r\n  <div class=\"mds-sec\">Locale<\/div>\r\n  <div class=\"mds-fld\"><label for=\"mds-locale\">Name, city and phone style<\/label>\r\n    <select id=\"mds-locale\" class=\"mds-inp\">\r\n      <option value=\"us\" selected>United States<\/option>\r\n      <option value=\"uk\">United Kingdom<\/option>\r\n      <option value=\"in\">India<\/option>\r\n      <option value=\"lk\">Sri Lanka<\/option>\r\n    <\/select><\/div>\r\n\r\n  <div class=\"mds-sec\">Data Quality &amp; Edge Cases<\/div>\r\n  <div class=\"mds-fld\"><label for=\"mds-null\">Inject empty or null values (%)<\/label>\r\n    <input type=\"number\" id=\"mds-null\" class=\"mds-inp\" value=\"0\" min=\"0\" max=\"90\"><\/div>\r\n  <label class=\"mds-check\"><input type=\"checkbox\" id=\"mds-awkward\"> <span><strong>Include awkward but realistic names<\/strong> &mdash; apostrophes, hyphens and accents (O'Brien, Nguy&#7877;n, Al-Rashid). These are the values that break naive form validation, which is exactly why your test data should contain them.<\/span><\/label>\r\n  <label class=\"mds-check\"><input type=\"checkbox\" id=\"mds-unique\" checked> <span>Force <code>id<\/code>, <code>email<\/code> and <code>username<\/code> to be unique across the set<\/span><\/label>\r\n\r\n  <div class=\"mds-sec\">Date Range<\/div>\r\n  <div class=\"mds-row2\">\r\n    <div class=\"mds-fld\"><label for=\"mds-date-from\">From<\/label>\r\n      <input type=\"date\" id=\"mds-date-from\" class=\"mds-inp\" value=\"2023-01-01\"><\/div>\r\n    <div class=\"mds-fld\"><label for=\"mds-date-to\">To<\/label>\r\n      <input type=\"date\" id=\"mds-date-to\" class=\"mds-inp\" value=\"2026-12-31\"><\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- LOREM -->\r\n<div id=\"mds-p-lorem\" class=\"mds-panel\">\r\n  <div class=\"mds-info\">This tab produces placeholder <em>text<\/em> rather than records. Click Generate while this tab is open and the output below switches to Lorem Ipsum.<\/div>\r\n  <div class=\"mds-row3\">\r\n    <div class=\"mds-fld\"><label for=\"mds-lorem-amount\">Amount<\/label>\r\n      <input type=\"number\" id=\"mds-lorem-amount\" class=\"mds-inp\" value=\"3\" min=\"1\" max=\"500\"><\/div>\r\n    <div class=\"mds-fld\"><label for=\"mds-lorem-unit\">Unit<\/label>\r\n      <select id=\"mds-lorem-unit\" class=\"mds-inp\">\r\n        <option value=\"paragraphs\" selected>Paragraphs<\/option>\r\n        <option value=\"sentences\">Sentences<\/option>\r\n        <option value=\"words\">Words<\/option>\r\n      <\/select><\/div>\r\n    <div class=\"mds-fld\"><label for=\"mds-lorem-wrap\">HTML Wrapping<\/label>\r\n      <select id=\"mds-lorem-wrap\" class=\"mds-inp\">\r\n        <option value=\"plain\" selected>Plain text<\/option>\r\n        <option value=\"p\">Paragraph &lt;p&gt;<\/option>\r\n        <option value=\"li\">List items &lt;li&gt;<\/option>\r\n        <option value=\"h2\">Headings &lt;h2&gt;<\/option>\r\n        <option value=\"blockquote\">Blockquote<\/option>\r\n      <\/select><\/div>\r\n  <\/div>\r\n  <label class=\"mds-check\"><input type=\"checkbox\" id=\"mds-lorem-classic\" checked> <span>Begin with the classic opening <code>Lorem ipsum dolor sit amet<\/code><\/span><\/label>\r\n  <div class=\"mds-row2\">\r\n    <div class=\"mds-fld\"><label for=\"mds-lorem-min\">Min words per sentence<\/label>\r\n      <input type=\"number\" id=\"mds-lorem-min\" class=\"mds-inp\" value=\"6\" min=\"2\" max=\"40\"><\/div>\r\n    <div class=\"mds-fld\"><label for=\"mds-lorem-max\">Max words per sentence<\/label>\r\n      <input type=\"number\" id=\"mds-lorem-max\" class=\"mds-inp\" value=\"16\" min=\"3\" max=\"60\"><\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- EXPORT OPTIONS -->\r\n<div id=\"mds-p-exportopt\" class=\"mds-panel\">\r\n  <div class=\"mds-info\">Format-specific settings. Pick the actual output format in the bar below the tabs.<\/div>\r\n  <div class=\"mds-sec\">JSON<\/div>\r\n  <label class=\"mds-check\"><input type=\"checkbox\" id=\"mds-json-pretty\" checked> <span>Pretty-print with indentation (uncheck for minified single-line output)<\/span><\/label>\r\n\r\n  <div class=\"mds-sec\">CSV \/ TSV<\/div>\r\n  <label class=\"mds-check\"><input type=\"checkbox\" id=\"mds-csv-header\" checked> <span>Include a header row of field names<\/span><\/label>\r\n  <div class=\"mds-fld\"><label for=\"mds-csv-delim\">CSV delimiter<\/label>\r\n    <select id=\"mds-csv-delim\" class=\"mds-inp\">\r\n      <option value=\",\" selected>Comma ( , )<\/option>\r\n      <option value=\";\">Semicolon ( ; ) &mdash; common in European Excel<\/option>\r\n      <option value=\"|\">Pipe ( | )<\/option>\r\n    <\/select><\/div>\r\n\r\n  <div class=\"mds-sec\">SQL<\/div>\r\n  <div class=\"mds-row2\">\r\n    <div class=\"mds-fld\"><label for=\"mds-sql-table\">Table name<\/label>\r\n      <input type=\"text\" id=\"mds-sql-table\" class=\"mds-inp\" value=\"users\"><\/div>\r\n    <div class=\"mds-fld\"><label for=\"mds-sql-mode\">Statement style<\/label>\r\n      <select id=\"mds-sql-mode\" class=\"mds-inp\">\r\n        <option value=\"multi\" selected>One multi-row INSERT<\/option>\r\n        <option value=\"single\">One INSERT per record<\/option>\r\n      <\/select><\/div>\r\n  <\/div>\r\n  <div class=\"mds-xlink\">Already have a CSV file you need turned into SQL?\r\n    <a href=\"\/free-csv-to-sql-query-converter\/\" target=\"_blank\" rel=\"noopener\">CSV to SQL Query Converter<\/a><\/div>\r\n\r\n  <div class=\"mds-sec\">XML<\/div>\r\n  <div class=\"mds-row2\">\r\n    <div class=\"mds-fld\"><label for=\"mds-xml-root\">Root element<\/label>\r\n      <input type=\"text\" id=\"mds-xml-root\" class=\"mds-inp\" value=\"records\"><\/div>\r\n    <div class=\"mds-fld\"><label for=\"mds-xml-row\">Row element<\/label>\r\n      <input type=\"text\" id=\"mds-xml-row\" class=\"mds-inp\" value=\"record\"><\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- OUTPUT BAR -->\r\n<div class=\"mds-outbar\">\r\n  <button type=\"button\" class=\"mds-btn mds-btn-primary\" id=\"mds-generate\">Generate<\/button>\r\n  <label for=\"mds-format\" style=\"font-size:.8rem;font-weight:800;color:#334155;\">Format<\/label>\r\n  <select id=\"mds-format\" aria-label=\"Output format\">\r\n    <option value=\"json\" selected>JSON<\/option>\r\n    <option value=\"csv\">CSV<\/option>\r\n    <option value=\"tsv\">TSV<\/option>\r\n    <option value=\"xml\">XML<\/option>\r\n    <option value=\"sql\">SQL INSERT<\/option>\r\n    <option value=\"md\">Markdown table<\/option>\r\n    <option value=\"js\">JS array<\/option>\r\n  <\/select>\r\n  <button type=\"button\" class=\"mds-btn mds-btn-sec mds-btn-sm\" id=\"mds-copy\">Copy<\/button>\r\n  <button type=\"button\" class=\"mds-btn mds-btn-sec mds-btn-sm\" id=\"mds-download\">Download<\/button>\r\n  <button type=\"button\" class=\"mds-btn mds-btn-danger mds-btn-sm\" id=\"mds-clear\">Clear<\/button>\r\n<\/div>\r\n\r\n<textarea id=\"mds-out\" class=\"mds-out\" readonly spellcheck=\"false\" aria-label=\"Generated output\"><\/textarea>\r\n<div class=\"mds-stats\">\r\n  <span id=\"mds-stat-records\">0 records<\/span>\r\n  <span id=\"mds-stat-chars\">0 chars<\/span>\r\n  <span id=\"mds-stat-size\">0 KB<\/span>\r\n  <span id=\"mds-stat-seed\">seed: &mdash;<\/span>\r\n<\/div>\r\n\r\n<\/div>\r\n\r\n<div class=\"mds-side\">\r\n  <h3>Why Seeding Matters<\/h3>\r\n  <p>Most generators use plain randomness, so you can never produce the same dataset twice. With a seed, the output is deterministic: <code>seed=42<\/code> today gives byte-identical records to <code>seed=42<\/code> next month.<\/p>\r\n  <p>That is what turns throwaway sample data into a real test fixture &mdash; one you can commit to a repository and have every developer and CI run reproduce exactly.<\/p>\r\n\r\n  <h3 class=\"mds-mt\">Format Cheat Sheet<\/h3>\r\n  <table class=\"mds-tbl\">\r\n    <thead><tr><th>Format<\/th><th>Best for<\/th><\/tr><\/thead>\r\n    <tbody>\r\n      <tr><td class=\"mds-mono\">JSON<\/td><td>APIs, JS fixtures<\/td><\/tr>\r\n      <tr><td class=\"mds-mono\">CSV<\/td><td>Excel, bulk import<\/td><\/tr>\r\n      <tr><td class=\"mds-mono\">TSV<\/td><td>Pasting into Sheets<\/td><\/tr>\r\n      <tr><td class=\"mds-mono\">XML<\/td><td>Legacy and SOAP systems<\/td><\/tr>\r\n      <tr><td class=\"mds-mono\">SQL<\/td><td>Seeding a database<\/td><\/tr>\r\n      <tr><td class=\"mds-mono\">Markdown<\/td><td>Docs and README tables<\/td><\/tr>\r\n    <\/tbody>\r\n  <\/table>\r\n\r\n  <h3 class=\"mds-mt\">Honest Limits<\/h3>\r\n  <p>This data is <strong>plausible, not real<\/strong>. Addresses are assembled from parts, so a street and city may not genuinely coexist. Emails use reserved test domains and cannot receive mail.<\/p>\r\n  <p>Use it to exercise layouts, validation and imports &mdash; never as a stand-in for real statistics or for anything that must reflect an actual place or person.<\/p>\r\n\r\n  <div class=\"mds-xlink\">Need identifiers or a JSON tidy-up instead?\r\n    <a href=\"\/free-offline-uuid-guid-generator-validator-tool\/\" target=\"_blank\" rel=\"noopener\">UUID \/ GUID Generator<\/a>\r\n    <a href=\"\/free-json-formatter-validator-data-converter\/\" target=\"_blank\" rel=\"noopener\">JSON Formatter &amp; Validator<\/a>\r\n  <\/div>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n\r\n<script data-no-optimize=\"1\" data-no-minify=\"1\" data-cfasync=\"false\">\r\n(function(){\r\n'use strict';\r\nif(window.pthMockDataApp){return;}\r\n\r\n\/* Angle\/quote\/backtick helpers from char codes, so no raw tag substring, bare\r\n   angle\/quote-regex, or literal backtick sits in this inline script. WordPress\/\r\n   LiteSpeed mangles those inside inline scripts and kills the whole block\r\n   (every button dies). Runtime output is byte-identical. *\/\r\nvar LT=String.fromCharCode(60);\/* < *\/\r\nvar GT=String.fromCharCode(62);\/* > *\/\r\nvar QT=String.fromCharCode(34);\/* \" *\/\r\nvar SQ=String.fromCharCode(39);\/* ' *\/\r\nvar BT=String.fromCharCode(96);\/* backtick *\/\r\n\r\n\/* ===== SEEDED PRNG: xorshift32 (pure ES5, no Math.imul) ===== *\/\r\nfunction makeRng(seed){\r\nvar s=seed>>>0;\r\nif(s===0){s=0x9E3779B9;}\r\nreturn function(){\r\ns^=(s<<13);s>>>=0;\r\ns^=(s>>>17);\r\ns^=(s<<5);s>>>=0;\r\nreturn s\/4294967296;\r\n};\r\n}\r\n\/* FNV-1a style string hash so a seed can be any text *\/\r\nfunction hashString(str){\r\nvar h=2166136261>>>0,i;\r\nstr=String(str);\r\nfor(i=0;i<str.length;i++){\r\nh^=str.charCodeAt(i);\r\nh=(h+((h<<1)+(h<<4)+(h<<7)+(h<<8)+(h<<24)))>>>0;\r\n}\r\nreturn h>>>0;\r\n}\r\n\r\n\/* ===== LOCALE PACKS ===== *\/\r\nvar LOCALES={\r\nus:{\r\nlabel:'United States',\r\nfirst:['James','Mary','John','Patricia','Robert','Jennifer','Michael','Linda','William','Elizabeth','David','Barbara','Richard','Susan','Joseph','Jessica','Thomas','Sarah','Daniel','Karen','Matthew','Nancy','Anthony','Lisa','Mark','Betty'],\r\nlast:['Smith','Johnson','Williams','Brown','Jones','Garcia','Miller','Davis','Rodriguez','Martinez','Wilson','Anderson','Taylor','Moore','Jackson','Martin','Lee','Perez','Thompson','White','Harris','Clark','Lewis','Walker'],\r\ncities:['New York','Los Angeles','Chicago','Houston','Phoenix','Philadelphia','San Antonio','San Diego','Dallas','Austin','Seattle','Denver','Boston','Portland'],\r\nregions:['California','Texas','Florida','New York','Illinois','Ohio','Georgia','Arizona','Washington','Colorado'],\r\nstreets:['Main','Oak','Pine','Maple','Cedar','Elm','Washington','Lake','Hill','Park','Sunset','Highland'],\r\nstypes:['Street','Avenue','Road','Lane','Drive','Boulevard','Court','Way'],\r\ncountry:'United States',\r\nphone:function(r){return '(' + (200+Math.floor(r()*700)) + ') ' + (200+Math.floor(r()*700)) + '-' + String(1000+Math.floor(r()*9000));},\r\npostal:function(r){return String(10000+Math.floor(r()*89999));}\r\n},\r\nuk:{\r\nlabel:'United Kingdom',\r\nfirst:['Oliver','Amelia','George','Olivia','Harry','Isla','Jack','Ava','Charlie','Emily','Thomas','Sophie','Oscar','Grace','William','Poppy','James','Freya','Henry','Charlotte'],\r\nlast:['Smith','Jones','Taylor','Brown','Williams','Wilson','Johnson','Davies','Patel','Robinson','Wright','Thompson','Evans','Walker','White','Roberts','Green','Hall'],\r\ncities:['London','Manchester','Birmingham','Leeds','Glasgow','Liverpool','Bristol','Sheffield','Edinburgh','Cardiff','Leicester','Nottingham','Newcastle','Brighton'],\r\nregions:['Greater London','West Midlands','Greater Manchester','West Yorkshire','Merseyside','Kent','Essex','Surrey','Hampshire','Lancashire'],\r\nstreets:['High','Church','Station','Victoria','Mill','Green','Kings','Queens','Park','Bridge','York','Windsor'],\r\nstypes:['Street','Road','Lane','Avenue','Close','Way','Gardens','Place'],\r\ncountry:'United Kingdom',\r\nphone:function(r){return '+44 7' + String(100+Math.floor(r()*900)) + ' ' + String(100000+Math.floor(r()*900000));},\r\npostal:function(r){\r\nvar a='ABCDEFGHKLMNOPRSTUWXY',b='ABDEFGHJLNPQRSTUWXYZ';\r\nreturn a.charAt(Math.floor(r()*a.length))+a.charAt(Math.floor(r()*a.length))+String(1+Math.floor(r()*99))+' '+String(1+Math.floor(r()*9))+b.charAt(Math.floor(r()*b.length))+b.charAt(Math.floor(r()*b.length));\r\n}\r\n},\r\n\"in\":{\r\nlabel:'India',\r\nfirst:['Aarav','Ananya','Vivaan','Diya','Aditya','Saanvi','Arjun','Aadhya','Reyansh','Anika','Krishna','Ishita','Rohan','Kavya','Aryan','Priya','Karthik','Meera','Rahul','Neha'],\r\nlast:['Sharma','Verma','Patel','Gupta','Singh','Kumar','Reddy','Nair','Iyer','Joshi','Mehta','Desai','Chopra','Malhotra','Rao','Banerjee','Das','Pillai'],\r\ncities:['Mumbai','Delhi','Bengaluru','Hyderabad','Chennai','Kolkata','Pune','Ahmedabad','Jaipur','Kochi','Lucknow','Chandigarh','Indore','Coimbatore'],\r\nregions:['Maharashtra','Karnataka','Tamil Nadu','Delhi','Telangana','West Bengal','Gujarat','Rajasthan','Kerala','Punjab'],\r\nstreets:['MG','Gandhi','Nehru','Station','Temple','Market','Church','Lake','Ring','Bazaar','Civil Lines','Mall'],\r\nstypes:['Road','Street','Marg','Lane','Nagar','Colony','Avenue','Cross'],\r\ncountry:'India',\r\nphone:function(r){return '+91 ' + String(70+Math.floor(r()*30)) + String(10000000+Math.floor(r()*89999999));},\r\npostal:function(r){return String(110000+Math.floor(r()*789999));}\r\n},\r\nlk:{\r\nlabel:'Sri Lanka',\r\nfirst:['Nimal','Kamala','Sunil','Chamari','Ruwan','Dilani','Kasun','Sanduni','Pradeep','Ishara','Tharindu','Nadeesha','Chaminda','Hasini','Lahiru','Amali','Rajitha','Shanika','Dinesh','Malsha','Arun','Kavitha','Suresh','Priyanka'],\r\nlast:['Perera','Fernando','Silva','De Silva','Jayawardena','Bandara','Rathnayake','Wickramasinghe','Gunasekara','Dissanayake','Senanayake','Ekanayake','Herath','Kumara','Mendis','Peiris','Rajapaksa','Weerasinghe','Samarasinghe','Amarasinghe'],\r\ncities:['Colombo','Kandy','Galle','Jaffna','Negombo','Kurunegala','Anuradhapura','Ratnapura','Batticaloa','Matara','Badulla','Trincomalee','Gampaha','Nuwara Eliya'],\r\nregions:['Western','Central','Southern','Northern','Eastern','North Western','North Central','Uva','Sabaragamuwa'],\r\nstreets:['Galle','Kandy','Temple','Station','Main','Lake','Hospital','School','Market','Beach','Hill','Peradeniya'],\r\nstypes:['Road','Street','Lane','Mawatha','Place','Avenue'],\r\ncountry:'Sri Lanka',\r\nphone:function(r){\r\nvar pfx=['70','71','72','74','75','76','77','78'];\r\nreturn '+94 ' + pfx[Math.floor(r()*pfx.length)] + ' ' + String(100+Math.floor(r()*900)) + ' ' + String(1000+Math.floor(r()*9000));\r\n},\r\npostal:function(r){return String(10000+Math.floor(r()*70000));}\r\n}\r\n};\r\n\r\nvar AWKWARD_FIRST=['Jos\\u00E9','Ren\\u00E9e','Zo\\u00EB','Fran\\u00E7ois','Nguy\\u1EC5n','Bj\\u00F6rn','\\u00C5sa','Se\\u00E1n'];\r\nvar AWKWARD_LAST=[\"O'Brien\",\"D'Angelo\",\"van der Berg\",\"Al-Rashid\",\"Smith-Jones\",\"O'Connor\",'M\\u00FCller','Garc\\u00EDa'];\r\n\r\nvar LOREM=['lorem','ipsum','dolor','sit','amet','consectetur','adipiscing','elit','sed','do','eiusmod','tempor','incididunt','ut','labore','et','dolore','magna','aliqua','enim','ad','minim','veniam','quis','nostrud','exercitation','ullamco','laboris','nisi','aliquip','ex','ea','commodo','consequat','duis','aute','irure','reprehenderit','in','voluptate','velit','esse','cillum','fugiat','nulla','pariatur','excepteur','sint','occaecat','cupidatat','non','proident','sunt','culpa','qui','officia','deserunt','mollit','anim','id','est','laborum'];\r\n\r\nvar COMPANIES=['TechCorp','GlobalNet','InnoVision','AlphaSys','NexusData','QuantumWorks','CloudSync','FutureDev','ApexSolutions','OmniTech','DataFlow','BlueSky','CoreLogic','BrightPath'];\r\nvar SUFFIX=['Ltd','Inc','LLC','Group','Holdings','Systems','Labs','Partners'];\r\nvar JOBS=['Software Engineer','Product Manager','Data Analyst','Marketing Manager','Graphic Designer','Sales Executive','HR Specialist','Financial Analyst','Content Strategist','UX Designer','Project Manager','Accountant','DevOps Engineer','System Administrator','QA Engineer','Business Analyst'];\r\nvar DEPTS=['Engineering','Marketing','Sales','Human Resources','Finance','Operations','Support','Design','Legal','Research'];\r\nvar PRODUCTS=['Wireless Mouse','Mechanical Keyboard','USB-C Hub','Laptop Stand','Noise-Cancelling Headphones','Webcam','Monitor Arm','Desk Lamp','External SSD','Docking Station','Ergonomic Chair','Cable Organiser'];\r\nvar CATEGORIES=['Electronics','Accessories','Furniture','Peripherals','Storage','Audio','Networking','Office'];\r\nvar COLORS=['Red','Blue','Green','Black','White','Silver','Navy','Charcoal','Teal','Amber'];\r\nvar STATUSES=['active','pending','completed','cancelled','archived'];\r\nvar CURRENCIES=['USD','EUR','GBP','INR','LKR','AUD','JPY'];\r\nvar TESTDOMAINS=['example.com','example.org','example.net','test.invalid'];\r\n\r\n\/* Field type catalogue: key -> {label, group, defName} *\/\r\nvar FIELD_TYPES=[\r\n{k:'idSeq',n:'ID (sequential)',d:'id'},\r\n{k:'uuid',n:'UUID v4 style',d:'uuid'},\r\n{k:'firstName',n:'First name',d:'firstName'},\r\n{k:'lastName',n:'Last name',d:'lastName'},\r\n{k:'fullName',n:'Full name',d:'name'},\r\n{k:'username',n:'Username',d:'username'},\r\n{k:'email',n:'Email (test domain)',d:'email'},\r\n{k:'phone',n:'Phone (locale)',d:'phone'},\r\n{k:'jobTitle',n:'Job title',d:'jobTitle'},\r\n{k:'department',n:'Department',d:'department'},\r\n{k:'company',n:'Company name',d:'company'},\r\n{k:'street',n:'Street address',d:'street'},\r\n{k:'city',n:'City (locale)',d:'city'},\r\n{k:'region',n:'State \/ province',d:'state'},\r\n{k:'postal',n:'Postal \/ ZIP code',d:'zip'},\r\n{k:'country',n:'Country (locale)',d:'country'},\r\n{k:'website',n:'Website URL',d:'website'},\r\n{k:'ipv4',n:'IPv4 address',d:'ip'},\r\n{k:'macAddr',n:'MAC address',d:'mac'},\r\n{k:'datePast',n:'Date (in range)',d:'createdAt'},\r\n{k:'dateTime',n:'Date and time (ISO)',d:'timestamp'},\r\n{k:'birthDate',n:'Birth date',d:'birthDate'},\r\n{k:'age',n:'Age (18-75)',d:'age'},\r\n{k:'gender',n:'Gender',d:'gender'},\r\n{k:'bool',n:'Boolean',d:'isActive'},\r\n{k:'productName',n:'Product name',d:'product'},\r\n{k:'category',n:'Category',d:'category'},\r\n{k:'sku',n:'SKU code',d:'sku'},\r\n{k:'price',n:'Price (decimal)',d:'price'},\r\n{k:'quantity',n:'Quantity (integer)',d:'quantity'},\r\n{k:'currency',n:'Currency code',d:'currency'},\r\n{k:'status',n:'Status (enum)',d:'status'},\r\n{k:'rating',n:'Rating 1-5',d:'rating'},\r\n{k:'percent',n:'Percentage 0-100',d:'percent'},\r\n{k:'color',n:'Colour name',d:'color'},\r\n{k:'hexColor',n:'Hex colour',d:'hex'},\r\n{k:'latitude',n:'Latitude',d:'lat'},\r\n{k:'longitude',n:'Longitude',d:'lng'},\r\n{k:'sentence',n:'Lorem sentence',d:'title'},\r\n{k:'paragraph',n:'Lorem paragraph',d:'description'}\r\n];\r\n\r\nvar PRESETS={\r\nuser:{label:'User',fields:['idSeq','fullName','email','username','phone','city','country','datePast','bool']},\r\nproduct:{label:'Product',fields:['idSeq','productName','sku','category','price','quantity','currency','rating','bool']},\r\norder:{label:'Order',fields:['idSeq','fullName','email','price','currency','quantity','status','dateTime']},\r\nemployee:{label:'Employee',fields:['idSeq','fullName','email','jobTitle','department','phone','city','datePast']},\r\npost:{label:'Blog Post',fields:['idSeq','sentence','paragraph','fullName','datePast','category','bool']},\r\ngeo:{label:'Location',fields:['idSeq','city','region','country','postal','latitude','longitude']}\r\n};\r\n\r\nwindow.pthMockDataApp={\r\ninitialized:false,\r\nschema:[],\r\nchildSchema:[],\r\nlastRecords:null,\r\nlastMode:'records',\r\ntoastTimer:null,\r\n\r\nel:function(id){return document.getElementById(id);},\r\n\r\ntoast:function(msg,type){\r\nvar t=this.el('mds-toast');\r\nif(!t){return;}\r\nt.textContent=msg;\r\nt.className='mds-toast mds-show'+(type==='err'?' mds-err':' mds-ok');\r\nvar self=this;\r\nclearTimeout(self.toastTimer);\r\nself.toastTimer=setTimeout(function(){t.className='mds-toast';},3000);\r\n},\r\n\r\nesc:function(s){\r\nreturn String(s).replace(\/&\/g,'&amp;').replace(new RegExp(LT,'g'),'&lt;').replace(new RegExp(GT,'g'),'&gt;').replace(new RegExp(QT,'g'),'&quot;');\r\n},\r\n\r\nswitchTab:function(id){\r\nvar w=this.el('pth-mds-wrapper');\r\nif(!w){return;}\r\nvar i,tabs=w.querySelectorAll('.mds-tab'),panels=w.querySelectorAll('.mds-panel');\r\nfor(i=0;i<tabs.length;i++){tabs[i].classList.remove('mds-active');}\r\nfor(i=0;i<panels.length;i++){panels[i].classList.remove('mds-active');}\r\nvar b=w.querySelector('.mds-tab[data-tab=\"'+id+'\"]'),p=this.el('mds-p-'+id);\r\nif(b){b.classList.add('mds-active');}\r\nif(p){p.classList.add('mds-active');}\r\n},\r\n\r\ntypeByKey:function(k){\r\nvar i;\r\nfor(i=0;i<FIELD_TYPES.length;i++){if(FIELD_TYPES[i].k===k){return FIELD_TYPES[i];}}\r\nreturn null;\r\n},\r\n\r\n\/* ---------- VALUE GENERATION ---------- *\/\r\npick:function(r,arr){return arr[Math.floor(r()*arr.length)];},\r\nrint:function(r,min,max){return min+Math.floor(r()*(max-min+1));},\r\n\r\nslug:function(s){\r\nreturn String(s).toLowerCase().split(SQ).join('').replace(\/\\u2019\/g,'').replace(\/[^a-z0-9]+\/g,'.').replace(\/^\\.+|\\.+$\/g,'');\r\n},\r\n\r\nmakeValue:function(type,idx,ctx){\r\nvar r=ctx.rng,loc=ctx.loc,self=this;\r\nswitch(type){\r\ncase 'idSeq': return idx+1;\r\ncase 'uuid': return this.uuidLike(r);\r\ncase 'firstName': return this.personFirst(ctx);\r\ncase 'lastName': return this.personLast(ctx);\r\ncase 'fullName': return this.personFirst(ctx)+' '+this.personLast(ctx);\r\ncase 'username': return this.slug(this.personFirst(ctx))+'.'+this.slug(this.personLast(ctx)).charAt(0)+(ctx.unique?String(idx+1):String(this.rint(r,10,999)));\r\ncase 'email': return this.slug(this.personFirst(ctx))+'.'+this.slug(this.personLast(ctx))+(ctx.unique?String(idx+1):'')+'@'+this.pick(r,TESTDOMAINS);\r\ncase 'phone': return loc.phone(r);\r\ncase 'jobTitle': return this.pick(r,JOBS);\r\ncase 'department': return this.pick(r,DEPTS);\r\ncase 'company': return this.pick(r,COMPANIES)+' '+this.pick(r,SUFFIX);\r\ncase 'street': return this.rint(r,1,999)+' '+this.pick(r,loc.streets)+' '+this.pick(r,loc.stypes);\r\ncase 'city': return this.pick(r,loc.cities);\r\ncase 'region': return this.pick(r,loc.regions);\r\ncase 'postal': return loc.postal(r);\r\ncase 'country': return loc.country;\r\ncase 'website': return 'https:\/\/www.'+this.pick(r,TESTDOMAINS);\r\ncase 'ipv4': return this.rint(r,1,223)+'.'+this.rint(r,0,255)+'.'+this.rint(r,0,255)+'.'+this.rint(r,1,254);\r\ncase 'macAddr': return this.macAddr(r);\r\ncase 'datePast': return this.dateInRange(r,ctx).slice(0,10);\r\ncase 'dateTime': return this.dateInRange(r,ctx);\r\ncase 'birthDate': return this.birthDate(r);\r\ncase 'age': return this.rint(r,18,75);\r\ncase 'gender': return this.pick(r,['Male','Female','Non-binary','Prefer not to say']);\r\ncase 'bool': return r()<0.5;\r\ncase 'productName': return this.pick(r,PRODUCTS);\r\ncase 'category': return this.pick(r,CATEGORIES);\r\ncase 'sku': return 'SKU-'+String.fromCharCode(65+Math.floor(r()*26))+String.fromCharCode(65+Math.floor(r()*26))+'-'+this.rint(r,1000,9999);\r\ncase 'price': return Math.round((5+r()*995)*100)\/100;\r\ncase 'quantity': return this.rint(r,1,250);\r\ncase 'currency': return this.pick(r,CURRENCIES);\r\ncase 'status': return this.pick(r,STATUSES);\r\ncase 'rating': return this.rint(r,1,5);\r\ncase 'percent': return this.rint(r,0,100);\r\ncase 'color': return this.pick(r,COLORS);\r\ncase 'hexColor': return this.hexColor(r);\r\ncase 'latitude': return Math.round((r()*180-90)*1e6)\/1e6;\r\ncase 'longitude': return Math.round((r()*360-180)*1e6)\/1e6;\r\ncase 'sentence': return this.loremSentence(r,5,11,false);\r\ncase 'paragraph': return this.loremParagraph(r,3,5,6,16,false);\r\ndefault: return null;\r\n}\r\n},\r\n\r\n\/* One coherent identity per record, so email and username match the name *\/\r\npersonFirst:function(ctx){\r\nif(ctx.rec.first===undefined){\r\nctx.rec.first=(ctx.awkward&&ctx.rng()<0.25)?this.pick(ctx.rng,AWKWARD_FIRST):this.pick(ctx.rng,ctx.loc.first);\r\n}\r\nreturn ctx.rec.first;\r\n},\r\n\r\npersonLast:function(ctx){\r\nif(ctx.rec.last===undefined){\r\nctx.rec.last=(ctx.awkward&&ctx.rng()<0.25)?this.pick(ctx.rng,AWKWARD_LAST):this.pick(ctx.rng,ctx.loc.last);\r\n}\r\nreturn ctx.rec.last;\r\n},\r\n\r\nuuidLike:function(r){\r\nvar hex='0123456789abcdef',out='',i;\r\nfor(i=0;i<36;i++){\r\nif(i===8||i===13||i===18||i===23){out+='-';}\r\nelse if(i===14){out+='4';}\r\nelse if(i===19){out+=hex.charAt(8+Math.floor(r()*4));}\r\nelse{out+=hex.charAt(Math.floor(r()*16));}\r\n}\r\nreturn out;\r\n},\r\n\r\nmacAddr:function(r){\r\nvar hex='0123456789ABCDEF',parts=[],i,j,p;\r\nfor(i=0;i<6;i++){\r\np='';\r\nfor(j=0;j<2;j++){p+=hex.charAt(Math.floor(r()*16));}\r\nparts.push(p);\r\n}\r\nreturn parts.join(':');\r\n},\r\n\r\nhexColor:function(r){\r\nvar hex='0123456789abcdef',out='#',i;\r\nfor(i=0;i<6;i++){out+=hex.charAt(Math.floor(r()*16));}\r\nreturn out;\r\n},\r\n\r\ndateInRange:function(r,ctx){\r\nvar span=ctx.dateTo-ctx.dateFrom;\r\nif(!(span>0)){span=0;}\r\nvar d=new Date(ctx.dateFrom+Math.floor(r()*(span+1)));\r\nreturn d.toISOString().slice(0,19)+'Z';\r\n},\r\n\r\nbirthDate:function(r){\r\nvar year=new Date().getFullYear()-this.rint(r,18,75);\r\nvar month=this.rint(r,1,12);\r\nvar day=this.rint(r,1,28);\r\nreturn year+'-'+(month<10?'0':'')+month+'-'+(day<10?'0':'')+day;\r\n},\r\n\r\nloremSentence:function(r,minW,maxW,classic){\r\nvar n=this.rint(r,minW,maxW),words=[],i;\r\nif(classic){\r\nwords=['lorem','ipsum','dolor','sit','amet','consectetur','adipiscing','elit'];\r\nfor(i=words.length;i<n;i++){words.push(this.pick(r,LOREM));}\r\n}else{\r\nfor(i=0;i<n;i++){words.push(this.pick(r,LOREM));}\r\n}\r\nvar s=words.join(' ');\r\nreturn s.charAt(0).toUpperCase()+s.slice(1)+'.';\r\n},\r\n\r\nloremParagraph:function(r,minS,maxS,minW,maxW,classic){\r\nvar n=this.rint(r,minS,maxS),out=[],i;\r\nfor(i=0;i<n;i++){out.push(this.loremSentence(r,minW,maxW,classic&&i===0));}\r\nreturn out.join(' ');\r\n},\r\n\r\n\/* ---------- CONTEXT ---------- *\/\r\nbuildCtx:function(){\r\nvar seedOn=this.el('mds-seed-on').checked;\r\nvar seedRaw=this.el('mds-seed').value;\r\nvar seedNum=seedOn?hashString(seedRaw||'0'):(Math.floor(Math.random()*4294967295)>>>0);\r\nvar from=Date.parse(this.el('mds-date-from').value+'T00:00:00Z');\r\nvar to=Date.parse(this.el('mds-date-to').value+'T23:59:59Z');\r\nif(isNaN(from)){from=Date.parse('2023-01-01T00:00:00Z');}\r\nif(isNaN(to)||to<from){to=from+86400000;}\r\nreturn {\r\nrng:makeRng(seedNum),\r\nloc:LOCALES[this.el('mds-locale').value]||LOCALES.us,\r\nnullPct:Math.max(0,Math.min(90,parseFloat(this.el('mds-null').value)||0)),\r\nawkward:this.el('mds-awkward').checked,\r\nunique:this.el('mds-unique').checked,\r\ndateFrom:from,\r\ndateTo:to,\r\nrec:{},\r\nseedLabel:seedOn?(seedRaw||'0'):'random',\r\nseedNum:seedNum\r\n};\r\n},\r\n\r\nbuildRecord:function(schema,idx,ctx){\r\nvar obj={},i,f,v;\r\nctx.rec={};\r\nfor(i=0;i<schema.length;i++){\r\nf=schema[i];\r\nv=this.makeValue(f.type,idx,ctx);\r\n\/* null injection, but never on a field forced unique *\/\r\nvar protectedField=(ctx.unique&&(f.type==='idSeq'||f.type==='email'||f.type==='username'));\r\nif(!protectedField&&ctx.nullPct>0&&ctx.rng()*100<ctx.nullPct){\r\nv=(ctx.rng()<0.5)?null:'';\r\n}\r\nobj[f.name]=v;\r\n}\r\nreturn obj;\r\n},\r\n\r\ngenerateRecords:function(){\r\nvar ctx=this.buildCtx();\r\nvar count=Math.max(1,Math.min(5000,parseInt(this.el('mds-count').value,10)||10));\r\nif(!this.schema.length){\r\nthis.toast('Add at least one field to the schema','err');\r\nreturn null;\r\n}\r\nvar nest=this.el('mds-nest-on').checked&&this.childSchema.length>0;\r\nvar key=(this.el('mds-nest-key').value||'items').replace(\/[^A-Za-z0-9_$]\/g,'')||'items';\r\nvar nmin=Math.max(0,parseInt(this.el('mds-nest-min').value,10)||0);\r\nvar nmax=Math.max(nmin,parseInt(this.el('mds-nest-max').value,10)||nmin);\r\nvar fk=this.el('mds-nest-fk').checked;\r\nvar out=[],i,j,rec,kids,kid,cnt;\r\nfor(i=0;i<count;i++){\r\nrec=this.buildRecord(this.schema,i,ctx);\r\nif(nest){\r\nkids=[];\r\ncnt=this.rint(ctx.rng,nmin,nmax);\r\nfor(j=0;j<cnt;j++){\r\nkid=this.buildRecord(this.childSchema,j,ctx);\r\nif(fk){kid.parentId=(rec.id!==undefined?rec.id:i+1);}\r\nkids.push(kid);\r\n}\r\nrec[key]=kids;\r\n}\r\nout.push(rec);\r\n}\r\nthis.lastSeedLabel=ctx.seedLabel;\r\nreturn out;\r\n},\r\n\r\ngenerateLorem:function(){\r\nvar ctx=this.buildCtx();\r\nvar amount=Math.max(1,Math.min(500,parseInt(this.el('mds-lorem-amount').value,10)||3));\r\nvar unit=this.el('mds-lorem-unit').value;\r\nvar wrap=this.el('mds-lorem-wrap').value;\r\nvar classic=this.el('mds-lorem-classic').checked;\r\nvar minW=Math.max(2,parseInt(this.el('mds-lorem-min').value,10)||6);\r\nvar maxW=Math.max(minW,parseInt(this.el('mds-lorem-max').value,10)||16);\r\nvar parts=[],i;\r\nif(unit==='words'){\r\nvar words=[];\r\nif(classic){words=['lorem','ipsum','dolor','sit','amet'];}\r\nfor(i=words.length;i<amount;i++){words.push(this.pick(ctx.rng,LOREM));}\r\nparts.push(words.slice(0,amount).join(' '));\r\n}else if(unit==='sentences'){\r\nfor(i=0;i<amount;i++){parts.push(this.loremSentence(ctx.rng,minW,maxW,classic&&i===0));}\r\n}else{\r\nfor(i=0;i<amount;i++){parts.push(this.loremParagraph(ctx.rng,3,6,minW,maxW,classic&&i===0));}\r\n}\r\nthis.lastSeedLabel=ctx.seedLabel;\r\nvar joiner='\\n\\n',open='',close='';\r\nif(wrap==='p'){open='' + LT + 'p>';close='' + LT + '\/p>';joiner='\\n';}\r\nelse if(wrap==='li'){open='  ' + LT + 'li>';close='' + LT + '\/li>';joiner='\\n';}\r\nelse if(wrap==='h2'){open='' + LT + 'h2>';close='' + LT + '\/h2>';joiner='\\n';}\r\nelse if(wrap==='blockquote'){open='' + LT + 'blockquote>';close='' + LT + '\/blockquote>';joiner='\\n';}\r\nif(wrap==='plain'){return parts.join(joiner);}\r\nvar wrapped=[];\r\nfor(i=0;i<parts.length;i++){wrapped.push(open+parts[i]+close);}\r\nvar body=wrapped.join(joiner);\r\nif(wrap==='li'){body='' + LT + 'ul>\\n'+body+'\\n' + LT + '\/ul>';}\r\nreturn body;\r\n},\r\n\r\n\/* ---------- EXPORTERS ---------- *\/\r\nflatValue:function(v){\r\nif(v===null||v===undefined){return '';}\r\nif(typeof v==='object'){return JSON.stringify(v);}\r\nreturn String(v);\r\n},\r\n\r\nallKeys:function(recs){\r\nvar keys=[],seen={},i,k;\r\nfor(i=0;i<recs.length;i++){\r\nfor(k in recs[i]){\r\nif(recs[i].hasOwnProperty(k)&&!seen[k]){seen[k]=1;keys.push(k);}\r\n}\r\n}\r\nreturn keys;\r\n},\r\n\r\ntoCSV:function(recs,delim){\r\nvar keys=this.allKeys(recs),lines=[],i,j,row,cell;\r\nvar self=this;\r\nfunction q(s){\r\ns=self.flatValue(s);\r\nif(s.indexOf(delim)>=0||s.indexOf('\"')>=0||s.indexOf('\\n')>=0||s.indexOf('\\r')>=0){\r\nreturn '\"'+s.replace(new RegExp(QT,'g'),'\"\"')+'\"';\r\n}\r\nreturn s;\r\n}\r\nif(this.el('mds-csv-header').checked){\r\nrow=[];\r\nfor(j=0;j<keys.length;j++){row.push(q(keys[j]));}\r\nlines.push(row.join(delim));\r\n}\r\nfor(i=0;i<recs.length;i++){\r\nrow=[];\r\nfor(j=0;j<keys.length;j++){\r\ncell=recs[i][keys[j]];\r\nrow.push(q(cell===undefined?'':cell));\r\n}\r\nlines.push(row.join(delim));\r\n}\r\nreturn lines.join('\\n');\r\n},\r\n\r\ntoXML:function(recs){\r\nvar root=(this.el('mds-xml-root').value||'records').replace(\/[^A-Za-z0-9_\\-]\/g,'')||'records';\r\nvar rowEl=(this.el('mds-xml-row').value||'record').replace(\/[^A-Za-z0-9_\\-]\/g,'')||'record';\r\nvar self=this;\r\nfunction xesc(s){\r\nreturn String(s).replace(\/&\/g,'&amp;').replace(new RegExp(LT,'g'),'&lt;').replace(new RegExp(GT,'g'),'&gt;').replace(new RegExp(QT,'g'),'&quot;').replace(new RegExp(SQ,'g'),'&apos;');\r\n}\r\nfunction tagName(k){\r\nvar t=String(k).replace(\/[^A-Za-z0-9_\\-]\/g,'_');\r\nif(\/^[0-9\\-]\/.test(t)){t='_'+t;}\r\nreturn t||'field';\r\n}\r\nfunction nodeFor(val,name,indent){\r\nvar pad=new Array(indent+1).join('  '),out='',i,k;\r\nif(val===null||val===undefined){return pad+'' + LT + ''+name+'\/>\\n';}\r\nif(Object.prototype.toString.call(val)==='[object Array]'){\r\nout+=pad+'' + LT + ''+name+'>\\n';\r\nfor(i=0;i<val.length;i++){out+=nodeFor(val[i],'item',indent+1);}\r\nout+=pad+'' + LT + '\/'+name+'>\\n';\r\nreturn out;\r\n}\r\nif(typeof val==='object'){\r\nout+=pad+'' + LT + ''+name+'>\\n';\r\nfor(k in val){if(val.hasOwnProperty(k)){out+=nodeFor(val[k],tagName(k),indent+1);}}\r\nout+=pad+'' + LT + '\/'+name+'>\\n';\r\nreturn out;\r\n}\r\nreturn pad+'' + LT + ''+name+'>'+xesc(val)+'' + LT + '\/'+name+'>\\n';\r\n}\r\nvar out='' + LT + '?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n' + LT + ''+root+'>\\n',i;\r\nfor(i=0;i<recs.length;i++){out+=nodeFor(recs[i],rowEl,1);}\r\nout+='' + LT + '\/'+root+'>\\n';\r\nreturn out;\r\n},\r\n\r\ntoSQL:function(recs){\r\nvar table=(this.el('mds-sql-table').value||'users').replace(\/[^A-Za-z0-9_]\/g,'')||'users';\r\nvar mode=this.el('mds-sql-mode').value;\r\nvar keys=this.allKeys(recs),self=this;\r\nfunction ident(k){return BT+String(k).replace(\/[^A-Za-z0-9_]\/g,'_')+BT;}\r\nfunction lit(v){\r\nif(v===null||v===undefined){return 'NULL';}\r\nif(typeof v==='boolean'){return v?'1':'0';}\r\nif(typeof v==='number'&&isFinite(v)){return String(v);}\r\nvar s=(typeof v==='object')?JSON.stringify(v):String(v);\r\nreturn \"'\"+s.replace(\/\\\\\/g,'\\\\\\\\').replace(new RegExp(SQ,'g'),\"''\")+\"'\";\r\n}\r\nvar cols=[],i,j,vals,rows=[];\r\nfor(j=0;j<keys.length;j++){cols.push(ident(keys[j]));}\r\nvar head='INSERT INTO '+ident(table)+' ('+cols.join(', ')+') VALUES';\r\nfor(i=0;i<recs.length;i++){\r\nvals=[];\r\nfor(j=0;j<keys.length;j++){vals.push(lit(recs[i][keys[j]]));}\r\nrows.push('('+vals.join(', ')+')');\r\n}\r\nif(!rows.length){return '-- no rows';}\r\nif(mode==='single'){\r\nvar out=[];\r\nfor(i=0;i<rows.length;i++){out.push(head+'\\n  '+rows[i]+';');}\r\nreturn out.join('\\n');\r\n}\r\nreturn head+'\\n  '+rows.join(',\\n  ')+';';\r\n},\r\n\r\ntoMarkdown:function(recs){\r\nvar keys=this.allKeys(recs),self=this,i,j,row,cell;\r\nfunction md(s){return self.flatValue(s).replace(\/\\|\/g,'\\\\|').replace(\/\\n\/g,' ');}\r\nvar lines=[],sep=[];\r\nrow=[];\r\nfor(j=0;j<keys.length;j++){row.push(md(keys[j]));sep.push('---');}\r\nlines.push('| '+row.join(' | ')+' |');\r\nlines.push('| '+sep.join(' | ')+' |');\r\nfor(i=0;i<recs.length;i++){\r\nrow=[];\r\nfor(j=0;j<keys.length;j++){\r\ncell=recs[i][keys[j]];\r\nrow.push(md(cell===undefined?'':cell));\r\n}\r\nlines.push('| '+row.join(' | ')+' |');\r\n}\r\nreturn lines.join('\\n');\r\n},\r\n\r\nformat:function(recs){\r\nvar f=this.el('mds-format').value;\r\nif(f==='json'){return JSON.stringify(recs,null,this.el('mds-json-pretty').checked?2:0);}\r\nif(f==='js'){return 'var mockData = '+JSON.stringify(recs,null,2)+';';}\r\nif(f==='csv'){return this.toCSV(recs,this.el('mds-csv-delim').value||',');}\r\nif(f==='tsv'){return this.toCSV(recs,'\\t');}\r\nif(f==='xml'){return this.toXML(recs);}\r\nif(f==='sql'){return this.toSQL(recs);}\r\nif(f==='md'){return this.toMarkdown(recs);}\r\nreturn JSON.stringify(recs,null,2);\r\n},\r\n\r\n\/* ---------- OUTPUT ---------- *\/\r\ngenerate:function(){\r\nvar w=this.el('pth-mds-wrapper');\r\nvar active=w.querySelector('.mds-tab.mds-active');\r\nvar tab=active?active.getAttribute('data-tab'):'schema';\r\nif(tab==='lorem'){\r\nvar text=this.generateLorem();\r\nthis.lastRecords=null;\r\nthis.lastMode='lorem';\r\nthis.el('mds-out').value=text;\r\nthis.updateStats(0);\r\nthis.toast('Lorem text generated','ok');\r\nreturn;\r\n}\r\nvar recs=this.generateRecords();\r\nif(!recs){return;}\r\nthis.lastRecords=recs;\r\nthis.lastMode='records';\r\nthis.el('mds-out').value=this.format(recs);\r\nthis.updateStats(recs.length);\r\nthis.toast(recs.length+' records generated','ok');\r\n},\r\n\r\nreformat:function(){\r\nif(this.lastMode!=='records'||!this.lastRecords){return;}\r\nthis.el('mds-out').value=this.format(this.lastRecords);\r\nthis.updateStats(this.lastRecords.length);\r\n},\r\n\r\nupdateStats:function(n){\r\nvar v=this.el('mds-out').value;\r\nvar bytes;\r\ntry{bytes=unescape(encodeURIComponent(v)).length;}catch(e){bytes=v.length;}\r\nthis.el('mds-stat-records').textContent=(this.lastMode==='lorem')?'lorem text':(n+' records');\r\nthis.el('mds-stat-chars').textContent=v.length.toLocaleString('en-US')+' chars';\r\nthis.el('mds-stat-size').textContent=(bytes<1024?bytes+' B':(bytes\/1024).toFixed(1)+' KB');\r\nthis.el('mds-stat-seed').textContent='seed: '+(this.lastSeedLabel||'\\u2014');\r\n},\r\n\r\ncopyOut:function(){\r\nvar ta=this.el('mds-out');\r\nif(!ta.value){this.toast('Nothing to copy','err');return;}\r\nta.removeAttribute('readonly');\r\nta.select();\r\ntry{document.execCommand('copy');this.toast('Copied to clipboard','ok');}\r\ncatch(e){this.toast('Copy failed','err');}\r\nta.setAttribute('readonly','readonly');\r\nwindow.getSelection().removeAllRanges();\r\n},\r\n\r\ndownload:function(){\r\nvar v=this.el('mds-out').value;\r\nif(!v){this.toast('Generate something first','err');return;}\r\nvar f=this.el('mds-format').value;\r\nvar ext='txt',mime='text\/plain';\r\nif(this.lastMode==='lorem'){\r\nvar wrap=this.el('mds-lorem-wrap').value;\r\next=(wrap==='plain')?'txt':'html';\r\nmime=(wrap==='plain')?'text\/plain':'text\/html';\r\n}else{\r\nif(f==='json'){ext='json';mime='application\/json';}\r\nelse if(f==='js'){ext='js';mime='text\/javascript';}\r\nelse if(f==='csv'){ext='csv';mime='text\/csv';}\r\nelse if(f==='tsv'){ext='tsv';mime='text\/tab-separated-values';}\r\nelse if(f==='xml'){ext='xml';mime='application\/xml';}\r\nelse if(f==='sql'){ext='sql';mime='text\/plain';}\r\nelse if(f==='md'){ext='md';mime='text\/markdown';}\r\n}\r\nvar blob=new Blob([v],{type:mime});\r\nvar url=URL.createObjectURL(blob);\r\nvar a=document.createElement('a');\r\na.href=url;a.download='mock-data.'+ext;\r\ndocument.body.appendChild(a);a.click();document.body.removeChild(a);\r\nsetTimeout(function(){URL.revokeObjectURL(url);},2000);\r\nthis.toast('Downloaded mock-data.'+ext,'ok');\r\n},\r\n\r\n\/* ---------- SCHEMA UI ---------- *\/\r\nuniqueName:function(list,base){\r\nvar names={},i;\r\nfor(i=0;i<list.length;i++){names[list[i].name]=1;}\r\nif(!names[base]){return base;}\r\nvar n=2;\r\nwhile(names[base+n]){n++;}\r\nreturn base+n;\r\n},\r\n\r\nrenderSchema:function(which){\r\nvar isChild=(which==='child');\r\nvar list=isChild?this.childSchema:this.schema;\r\nvar box=this.el(isChild?'mds-nest-rows':'mds-schema-rows');\r\nif(!box){return;}\r\nif(!list.length){\r\nbox.innerHTML='' + LT + 'div style=\"text-align:center;color:#334155;padding:18px;font-weight:600;font-size:.86rem;\">No fields yet. Pick a preset above or add a field.' + LT + '\/div>';\r\nreturn;\r\n}\r\nvar html='',i,t,j,opts;\r\nfor(i=0;i<list.length;i++){\r\nt=this.typeByKey(list[i].type);\r\nopts='';\r\nfor(j=0;j<FIELD_TYPES.length;j++){\r\nopts+='' + LT + 'option value=\"'+FIELD_TYPES[j].k+'\"'+(FIELD_TYPES[j].k===list[i].type?' selected':'')+'>'+this.esc(FIELD_TYPES[j].n)+'' + LT + '\/option>';\r\n}\r\nhtml+='' + LT + 'div class=\"mds-frow\">';\r\nhtml+='' + LT + 'input type=\"text\" class=\"mds-inp mds-fname\" data-i=\"'+i+'\" value=\"'+this.esc(list[i].name)+'\" aria-label=\"Field name\">';\r\nhtml+='' + LT + 'select class=\"mds-inp mds-ftype\" data-i=\"'+i+'\" aria-label=\"Field type\">'+opts+'' + LT + '\/select>';\r\nhtml+='' + LT + 'button type=\"button\" class=\"mds-mini mds-up\" data-i=\"'+i+'\" aria-label=\"Move up\">&uarr;' + LT + '\/button>';\r\nhtml+='' + LT + 'button type=\"button\" class=\"mds-mini mds-down\" data-i=\"'+i+'\" aria-label=\"Move down\">&darr;' + LT + '\/button>';\r\nhtml+='' + LT + 'button type=\"button\" class=\"mds-mini mds-del mds-rm\" data-i=\"'+i+'\" aria-label=\"Remove field\">&times;' + LT + '\/button>';\r\nhtml+='' + LT + '\/div>';\r\n}\r\nbox.innerHTML=html;\r\nvar self=this;\r\nfunction idx(el){return parseInt(el.getAttribute('data-i'),10);}\r\nvar names=box.querySelectorAll('.mds-fname');\r\nfor(i=0;i<names.length;i++){\r\nnames[i].addEventListener('input',function(){list[idx(this)].name=this.value;});\r\n}\r\nvar types=box.querySelectorAll('.mds-ftype');\r\nfor(i=0;i<types.length;i++){\r\ntypes[i].addEventListener('change',function(){list[idx(this)].type=this.value;});\r\n}\r\nvar ups=box.querySelectorAll('.mds-up');\r\nfor(i=0;i<ups.length;i++){\r\nups[i].addEventListener('click',function(){\r\nvar k=idx(this);\r\nif(k>0){var tmp=list[k-1];list[k-1]=list[k];list[k]=tmp;self.renderSchema(which);}\r\n});\r\n}\r\nvar downs=box.querySelectorAll('.mds-down');\r\nfor(i=0;i<downs.length;i++){\r\ndowns[i].addEventListener('click',function(){\r\nvar k=idx(this);\r\nif(k<list.length-1){var tmp=list[k+1];list[k+1]=list[k];list[k]=tmp;self.renderSchema(which);}\r\n});\r\n}\r\nvar rms=box.querySelectorAll('.mds-rm');\r\nfor(i=0;i<rms.length;i++){\r\nrms[i].addEventListener('click',function(){\r\nlist.splice(idx(this),1);\r\nself.renderSchema(which);\r\n});\r\n}\r\n},\r\n\r\naddField:function(which,typeKey){\r\nvar isChild=(which==='child');\r\nvar list=isChild?this.childSchema:this.schema;\r\nvar t=this.typeByKey(typeKey);\r\nif(!t){return;}\r\nlist.push({name:this.uniqueName(list,t.d),type:t.k});\r\nthis.renderSchema(which);\r\n},\r\n\r\napplyPreset:function(key){\r\nvar p=PRESETS[key];\r\nif(!p){return;}\r\nthis.schema=[];\r\nvar i,t;\r\nfor(i=0;i<p.fields.length;i++){\r\nt=this.typeByKey(p.fields[i]);\r\nif(t){this.schema.push({name:this.uniqueName(this.schema,t.d),type:t.k});}\r\n}\r\nthis.renderSchema('parent');\r\nvar w=this.el('pth-mds-wrapper');\r\nvar chips=w.querySelectorAll('#mds-presets .mds-chip'),j;\r\nfor(j=0;j<chips.length;j++){\r\nchips[j].classList.toggle('mds-on',chips[j].getAttribute('data-preset')===key);\r\n}\r\nif(key==='product'){this.el('mds-sql-table').value='products';}\r\nelse if(key==='order'){this.el('mds-sql-table').value='orders';}\r\nelse if(key==='employee'){this.el('mds-sql-table').value='employees';}\r\nelse if(key==='post'){this.el('mds-sql-table').value='posts';}\r\nelse{this.el('mds-sql-table').value='users';}\r\n},\r\n\r\nbuildTypeSelects:function(){\r\nvar opts='',i;\r\nfor(i=0;i<FIELD_TYPES.length;i++){\r\nopts+='' + LT + 'option value=\"'+FIELD_TYPES[i].k+'\">'+this.esc(FIELD_TYPES[i].n)+'' + LT + '\/option>';\r\n}\r\nthis.el('mds-addtype').innerHTML=opts;\r\nthis.el('mds-nest-addtype').innerHTML=opts;\r\nthis.el('mds-addtype').value='fullName';\r\nthis.el('mds-nest-addtype').value='productName';\r\n},\r\n\r\nbuildPresetChips:function(){\r\nvar box=this.el('mds-presets'),html='',k;\r\nfor(k in PRESETS){\r\nif(PRESETS.hasOwnProperty(k)){\r\nhtml+='' + LT + 'button type=\"button\" class=\"mds-chip\" data-preset=\"'+k+'\">'+this.esc(PRESETS[k].label)+'' + LT + '\/button>';\r\n}\r\n}\r\nbox.innerHTML=html;\r\nvar self=this,chips=box.querySelectorAll('.mds-chip'),i;\r\nfor(i=0;i<chips.length;i++){\r\nchips[i].addEventListener('click',function(){self.applyPreset(this.getAttribute('data-preset'));});\r\n}\r\n},\r\n\r\nloadSample:function(){\r\nthis.applyPreset('user');\r\nthis.el('mds-count').value=8;\r\nthis.el('mds-locale').value='lk';\r\nthis.el('mds-seed').value='primetoolhub';\r\nthis.el('mds-seed-on').checked=true;\r\nthis.el('mds-null').value=0;\r\nthis.el('mds-awkward').checked=false;\r\nthis.el('mds-nest-on').checked=false;\r\nthis.el('mds-nest-cfg').style.display='none';\r\nthis.el('mds-format').value='json';\r\nthis.switchTab('schema');\r\nthis.generate();\r\nthis.toast('Sample loaded: 8 Sri Lanka users, seeded','ok');\r\n},\r\n\r\nresetAll:function(){\r\nthis.applyPreset('user');\r\nthis.childSchema=[\r\n{name:'orderId',type:'idSeq'},\r\n{name:'product',type:'productName'},\r\n{name:'price',type:'price'}\r\n];\r\nthis.renderSchema('child');\r\nthis.el('mds-count').value=10;\r\nthis.el('mds-locale').value='us';\r\nthis.el('mds-seed').value='primetoolhub';\r\nthis.el('mds-seed-on').checked=true;\r\nthis.el('mds-null').value=0;\r\nthis.el('mds-awkward').checked=false;\r\nthis.el('mds-unique').checked=true;\r\nthis.el('mds-nest-on').checked=false;\r\nthis.el('mds-nest-cfg').style.display='none';\r\nthis.el('mds-nest-key').value='orders';\r\nthis.el('mds-nest-min').value=1;\r\nthis.el('mds-nest-max').value=3;\r\nthis.el('mds-nest-fk').checked=true;\r\nthis.el('mds-date-from').value='2023-01-01';\r\nthis.el('mds-date-to').value='2026-12-31';\r\nthis.el('mds-lorem-amount').value=3;\r\nthis.el('mds-lorem-unit').value='paragraphs';\r\nthis.el('mds-lorem-wrap').value='plain';\r\nthis.el('mds-lorem-classic').checked=true;\r\nthis.el('mds-lorem-min').value=6;\r\nthis.el('mds-lorem-max').value=16;\r\nthis.el('mds-format').value='json';\r\nthis.el('mds-json-pretty').checked=true;\r\nthis.el('mds-csv-header').checked=true;\r\nthis.el('mds-csv-delim').value=',';\r\nthis.el('mds-sql-table').value='users';\r\nthis.el('mds-sql-mode').value='multi';\r\nthis.el('mds-xml-root').value='records';\r\nthis.el('mds-xml-row').value='record';\r\nthis.el('mds-out').value='';\r\nthis.lastRecords=null;\r\nthis.lastSeedLabel=null;\r\nthis.updateStats(0);\r\nthis.toast('Reset to defaults','ok');\r\n},\r\n\r\nbindEvents:function(){\r\nvar self=this;\r\nvar w=this.el('pth-mds-wrapper');\r\nif(!w||w.getAttribute('data-bound')==='1'){return;}\r\nw.setAttribute('data-bound','1');\r\n\r\nvar i,tabs=w.querySelectorAll('.mds-tab');\r\nfor(i=0;i<tabs.length;i++){\r\ntabs[i].addEventListener('click',function(){self.switchTab(this.getAttribute('data-tab'));});\r\n}\r\nthis.el('mds-addfield').addEventListener('click',function(){\r\nself.addField('parent',self.el('mds-addtype').value);\r\n});\r\nthis.el('mds-nest-addfield').addEventListener('click',function(){\r\nself.addField('child',self.el('mds-nest-addtype').value);\r\n});\r\nthis.el('mds-nest-on').addEventListener('change',function(){\r\nself.el('mds-nest-cfg').style.display=this.checked?'block':'none';\r\n});\r\nthis.el('mds-randseed').addEventListener('click',function(){\r\nself.el('mds-seed').value=String(Math.floor(Math.random()*1000000));\r\nself.el('mds-seed-on').checked=true;\r\n});\r\nthis.el('mds-generate').addEventListener('click',function(){self.generate();});\r\nthis.el('mds-format').addEventListener('change',function(){self.reformat();});\r\nthis.el('mds-copy').addEventListener('click',function(){self.copyOut();});\r\nthis.el('mds-download').addEventListener('click',function(){self.download();});\r\nthis.el('mds-clear').addEventListener('click',function(){\r\nself.el('mds-out').value='';\r\nself.lastRecords=null;\r\nself.updateStats(0);\r\n});\r\nthis.el('mds-sample').addEventListener('click',function(){self.loadSample();});\r\nthis.el('mds-reset').addEventListener('click',function(){self.resetAll();});\r\nthis.el('mds-fw').addEventListener('click',function(){\r\nvar g=self.el('mds-grid');\r\ng.classList.toggle('mds-fw');\r\nthis.textContent=g.classList.contains('mds-fw')?'Restore Sidebar':'Full Width';\r\n});\r\nvar reformatIds=['mds-json-pretty','mds-csv-header','mds-csv-delim','mds-sql-table','mds-sql-mode','mds-xml-root','mds-xml-row'];\r\nfor(i=0;i<reformatIds.length;i++){\r\nvar elx=this.el(reformatIds[i]);\r\nif(elx){\r\nelx.addEventListener('change',function(){self.reformat();});\r\nelx.addEventListener('input',function(){self.reformat();});\r\n}\r\n}\r\n},\r\n\r\ninit:function(){\r\nthis.bindEvents();\r\nthis.buildTypeSelects();\r\nthis.buildPresetChips();\r\nthis.applyPreset('user');\r\nthis.childSchema=[\r\n{name:'orderId',type:'idSeq'},\r\n{name:'product',type:'productName'},\r\n{name:'price',type:'price'}\r\n];\r\nthis.renderSchema('child');\r\nthis.generate();\r\n}\r\n};\r\n\r\nfunction pthMDSInit(){\r\nif(!window.pthMockDataApp.initialized&&document.getElementById('pth-mds-wrapper')){\r\nwindow.pthMockDataApp.initialized=true;\r\nwindow.pthMockDataApp.init();\r\n}\r\n}\r\npthMDSInit();\r\nif(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',pthMDSInit);}\r\nwindow.addEventListener('load',function(){setTimeout(pthMDSInit,50);});\r\nif(!window.pthMockDataApp.initialized&&typeof MutationObserver!=='undefined'){\r\nvar mdsObs=new MutationObserver(function(){\r\nif(document.getElementById('pth-mds-wrapper')){mdsObs.disconnect();pthMDSInit();}\r\n});\r\nmdsObs.observe(document.body||document.documentElement,{childList:true,subtree:true});\r\nsetTimeout(function(){mdsObs.disconnect();},10000);\r\n}\r\n})();\r\n<\/script>\n\n\n\n<style>\n.pth-feature-wrap{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:20px;margin-bottom:40px}\n.pth-feat-box{border:1px solid #e2e8f0;background:#fff;padding:24px;border-radius:12px;box-shadow:0 4px 6px -1px rgba(0,0,0,0.02);transition:all .3s ease}\n.pth-feat-box:hover{border-color:#bfdbfe;transform:translateY(-3px);box-shadow:0 10px 15px -3px rgba(0,0,0,0.05)}\n.pth-feat-title{font-size:1.05rem;font-weight:800;color:#0f172a;margin:0 0 10px;display:flex;align-items:center;gap:10px}\n.pth-feat-text{font-size:.9rem;color:#1e293b;line-height:1.6;margin:0;font-weight:500}\n.pth-steps-wrap{border:1px solid #e2e8f0;background:#fff;padding:40px 30px;border-radius:16px;text-align:center;box-shadow:0 4px 6px -1px rgba(0,0,0,0.02);margin-bottom:40px;width:100%;box-sizing:border-box}\n.pth-steps-title{font-size:1.2rem;font-weight:800;color:#0f172a;text-transform:uppercase;margin:0 0 35px;letter-spacing:1px}\n.pth-steps-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:30px}\n.pth-step-item{display:flex;flex-direction:column;align-items:center}\n.pth-step-num{width:45px;height:45px;background:#2563eb;color:#fff;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:1.2rem;margin-bottom:15px;box-shadow:0 4px 10px rgba(37,99,235,.3)}\n.pth-step-name{font-weight:800;color:#0f172a;margin:0 0 8px;font-size:1rem}\n.pth-step-desc{font-size:.9rem;color:#1e293b;line-height:1.5;margin:0;font-weight:500}\n<\/style>\n<div class=\"pth-feature-wrap\">\n  <div class=\"pth-feat-box\">\n    <p class=\"pth-feat-title\"><span aria-hidden=\"true\">\ud83d\udfe2<\/span> Seeded &mdash; The Same Data, Every Time<\/p>\n    <p class=\"pth-feat-text\">Nearly every free generator uses plain randomness, so you can never produce the same dataset twice. Type a seed here and the output becomes deterministic: the same seed always yields byte-identical records. That is what turns throwaway sample data into a real <strong>test fixture<\/strong> you can commit to a repository and have every teammate and CI run reproduce exactly.<\/p>\n  <\/div>\n  <div class=\"pth-feat-box\">\n    <p class=\"pth-feat-title\"><span aria-hidden=\"true\">\ud83d\udd35<\/span> Your Schema, Not a Fixed List<\/p>\n    <p class=\"pth-feat-text\">Build the record shape you actually need from <strong>40 field types<\/strong> &mdash; names, emails, prices, coordinates, timestamps, SKUs and more. Rename any field so the JSON keys match your real API, reorder with the arrows, and start from one of six presets: User, Product, Order, Employee, Blog Post or Location.<\/p>\n  <\/div>\n  <div class=\"pth-feat-box\">\n    <p class=\"pth-feat-title\"><span aria-hidden=\"true\">\ud83d\udfe3<\/span> Seven Formats, Four Locales<\/p>\n    <p class=\"pth-feat-text\">Export the same records as JSON, CSV, TSV, XML, SQL <code>INSERT<\/code>, a Markdown table, or a ready-to-paste JS array &mdash; switching format never regenerates the data. Names, cities and phone formats follow the locale you pick: United States, United Kingdom, India, or <strong>Sri Lanka<\/strong>, with 14 real cities, all 9 provinces and correct <code>+94 7X<\/code> mobile formatting.<\/p>\n  <\/div>\n<\/div>\n \n<div class=\"pth-steps-wrap\">\n  <p class=\"pth-steps-title\">How to Use Mock Data Studio<\/p>\n  <div class=\"pth-steps-grid\">\n    <div class=\"pth-step-item\">\n      <div class=\"pth-step-num\" aria-hidden=\"true\">1<\/div>\n      <p class=\"pth-step-name\">Start From a Preset<\/p>\n      <p class=\"pth-step-desc\">Click User, Product, Order, Employee, Blog Post or Location to load a sensible schema, then set how many records you want. Load Sample fills everything in if you just want to see it work.<\/p>\n    <\/div>\n    <div class=\"pth-step-item\">\n      <div class=\"pth-step-num\" aria-hidden=\"true\">2<\/div>\n      <p class=\"pth-step-name\">Shape the Schema<\/p>\n      <p class=\"pth-step-desc\">Add fields, rename them to match your API, reorder them, or delete what you do not need. Field names and field types are independent, so a field called <code>author<\/code> can hold a full-name value.<\/p>\n    <\/div>\n    <div class=\"pth-step-item\">\n      <div class=\"pth-step-num\" aria-hidden=\"true\">3<\/div>\n      <p class=\"pth-step-name\">Set Realism and Seed<\/p>\n      <p class=\"pth-step-desc\">Pick a locale, choose a seed so the output is reproducible, and optionally inject a percentage of empty values or enable awkward-but-real names to stress-test your validation.<\/p>\n    <\/div>\n    <div class=\"pth-step-item\">\n      <div class=\"pth-step-num\" aria-hidden=\"true\">4<\/div>\n      <p class=\"pth-step-name\">Generate and Export<\/p>\n      <p class=\"pth-step-desc\">Hit Generate, then switch format in the bar to see the same records as JSON, CSV, SQL and the rest. Copy to clipboard or download with the correct file extension.<\/p>\n    <\/div>\n  <\/div>\n<\/div>\n\n\n<div id=\"start-seo-article\"><\/div>\n\n\n<p class=\"wp-block-paragraph\">Last updated: August 2026<\/p>\n\n\n\n<h2 id=\"\ud83d\udd34-why-a-seed-turns-sample-data-into-a-test-fixture\" class=\"wp-block-heading\">\ud83d\udd34&nbsp;<strong>Why a Seed Turns Sample Data Into a Test Fixture<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here is a problem every developer hits eventually. You generate a hundred mock users, build a page against them, and something breaks on record 63 \u2014 a name too long for the column, an empty field your template did not expect. You regenerate to investigate, and the data is completely different. Record 63 is now someone else. The bug is gone, unreproducible, and you have learned nothing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That happens because ordinary randomness is not repeatable. JavaScript&#8217;s built-in random number generator cannot be seeded \u2014 there is no way to ask it to produce the same sequence twice. So every generator built on it produces throwaway data by definition.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This tool uses a&nbsp;<strong>seeded<\/strong>&nbsp;generator instead. Give it a seed \u2014 any text or number,&nbsp;<code>42<\/code>&nbsp;or&nbsp;<code>my-project<\/code>&nbsp;\u2014 and the entire dataset becomes a pure function of that seed. Generate now, generate next month on a different machine, and you get byte-identical records. Suddenly your mock data has the property that matters: it is&nbsp;<em>reproducible<\/em>. You can note the seed in a bug report, commit the fixture to your repository, and have every teammate and every CI run see exactly the same hundred users, including the one that broke.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Untick&nbsp;<strong>Use the seed<\/strong>&nbsp;when you want fresh data on every click \u2014 useful for eyeballing variety. Tick it when the data needs to stay put.<\/p>\n\n\n\n<h2 id=\"\ud83d\udfe1-building-a-schema-that-matches-your-real-api\" class=\"wp-block-heading\">\ud83d\udfe1&nbsp;<strong>Building a Schema That Matches Your Real API<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Mock data is only useful if its shape matches what your application actually expects. A generator with a fixed set of fields forces you to rewrite your code around the mock, which is exactly backwards.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Schema Builder separates two things that are usually conflated: the&nbsp;<strong>field name<\/strong>, which becomes your JSON key, CSV header and SQL column, and the&nbsp;<strong>field type<\/strong>, which decides what kind of value gets generated. They are independent. If your API returns&nbsp;<code>customer_email<\/code>, name the field that and give it the email type. If it returns&nbsp;<code>author<\/code>&nbsp;holding a person&#8217;s name, name it&nbsp;<code>author<\/code>&nbsp;and give it the full-name type. The generated data then drops into your code without any adaptation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The six presets are starting points, not constraints \u2014 load User, then rename and reorder until it matches your schema. The arrows matter more than they look: field order determines column order in CSV and SQL output, which matters when you are importing into a table that already exists.<\/p>\n\n\n\n<h3 id=\"\ud83d\udfe2-records-that-make-internal-sense\" class=\"wp-block-heading\">\ud83d\udfe2&nbsp;<strong>Records That Make Internal Sense<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">One detail worth calling out because it is the thing most generators get wrong: within a single record, the person-related fields agree with each other. If a record has both a name and an email, you get&nbsp;<code>Kasun Wickramasinghe<\/code>&nbsp;paired with&nbsp;<code>kasun.wickramasinghe1@example.com<\/code>, not a name from one draw and an unrelated email from another. Usernames derive from the same identity too. It sounds like a small thing, but incoherent records look obviously fake the moment anyone glances at a table of them \u2014 and they make it impossible to eyeball whether your join logic is working.<\/p>\n\n\n\n<h2 id=\"\ud83d\udd34-awkward-names-and-empty-values-are-the-point\" class=\"wp-block-heading\">\ud83d\udd34&nbsp;<strong>Awkward Names and Empty Values Are the Point<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Clean test data is comfortable and nearly useless. Every record complete, every name a tidy seven letters of ASCII \u2014 your interface looks perfect, and then real users arrive and it falls apart.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Two options in the Realism tab exist specifically to break that comfort.&nbsp;<strong>Inject empty or null values<\/strong>&nbsp;sprinkles a percentage of blanks through the data, which is how you find out that your template prints the word &#8220;null&#8221; on screen, or that a sort function throws when a field is missing. Set it to 20 or 30 percent and watch what happens; most interfaces have at least one place that assumes every field is populated.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Include awkward but realistic names<\/strong>&nbsp;mixes in the ones that break naive validation: apostrophes (<code>O'Brien<\/code>), hyphens (<code>Smith-Jones<\/code>), accents (<code>Jos\u00e9<\/code>,&nbsp;<code>Garc\u00eda<\/code>), particles (<code>van der Berg<\/code>) and non-Latin characters. These are not exotic edge cases \u2014 they are ordinary names belonging to enormous numbers of real people, and they routinely get rejected by regular expressions written by someone who assumed names contain only letters A to Z. If your form rejects&nbsp;<code>O'Brien<\/code>, better to discover that from mock data than from an angry customer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note that fields set to be unique \u2014&nbsp;<code>id<\/code>,&nbsp;<code>email<\/code>,&nbsp;<code>username<\/code>&nbsp;\u2014 are never blanked even at a high null percentage, because a null primary key is a different class of problem and would just mask the ones you are actually testing for.<\/p>\n\n\n\n<h2 id=\"\ud83d\udfe1-picking-the-right-export-format\" class=\"wp-block-heading\">\ud83d\udfe1&nbsp;<strong>Picking the Right Export Format<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The same generated records can leave as seven different formats, and switching format does not regenerate the data \u2014 you are looking at one dataset rendered different ways.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud83d\udd35\u00a0<strong>JSON<\/strong>\u00a0for API mocking and JavaScript fixtures.\u00a0<strong>JS array<\/strong>\u00a0is the same thing wrapped in a variable declaration for pasting straight into a file.<\/li>\n\n\n\n<li>\ud83d\udfe0\u00a0<strong>CSV and TSV<\/strong>\u00a0for spreadsheets and bulk import. Values containing commas, quotes or line breaks are properly quoted and escaped, so they survive a round trip through Excel or a strict parser. Pick the semicolon delimiter if your Excel is set to a European locale.<\/li>\n\n\n\n<li>\ud83d\udfe3\u00a0<strong>SQL INSERT<\/strong>\u00a0for seeding a database directly. Apostrophes are escaped correctly (<code>O''Brien<\/code>), nulls are written as unquoted\u00a0<code>NULL<\/code>, numbers stay unquoted and booleans become 1 or 0. Choose one multi-row insert for speed, or one statement per record if you need to run them selectively.<\/li>\n\n\n\n<li>\ud83d\udd35\u00a0<strong>XML<\/strong>\u00a0for legacy and SOAP systems, with proper entity escaping.\u00a0<strong>Markdown table<\/strong>\u00a0for dropping sample output into documentation or a README.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">One honest constraint: CSV, TSV and SQL are&nbsp;<em>flat<\/em>&nbsp;formats. If you have enabled nested child records, an array cannot fit in a single cell, so it is written into one column as compact JSON text. That is the only sensible option, but it means nested data really wants JSON or XML. Already have a CSV file that needs turning into SQL? That is a different job, handled by the dedicated&nbsp;<a href=\"https:\/\/schoolict.net\/tools\/free-csv-to-sql-query-converter\/\">CSV to SQL Query Converter<\/a>&nbsp;[confirm slug].<\/p>\n\n\n\n<h2 id=\"\ud83d\udfe2-nested-records-for-realistic-api-mocking\" class=\"wp-block-heading\">\ud83d\udfe2&nbsp;<strong>Nested Records for Realistic API Mocking<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Real APIs rarely return flat lists. A user endpoint returns a user&nbsp;<em>with<\/em>&nbsp;their orders; a post returns comments. The Nested &amp; Relations tab builds that shape: define a child schema, name the array key, set how many children each parent gets, and every parent record arrives with its own populated array. With the foreign-key option enabled, each child also carries a&nbsp;<code>parentId<\/code>&nbsp;pointing back at its parent&#8217;s&nbsp;<code>id<\/code>&nbsp;\u2014 so you can test the join logic you would use against the real database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Everything here runs in your browser with no network requests, which is worth knowing because mock data often mirrors the structure of a real, confidential schema. Pasting your table layout into a random online generator tells that site&#8217;s operator quite a lot about your system. For the wider argument on keeping this kind of work local, see the&nbsp;<a href=\"https:\/\/schoolict.net\/tools\/secure-offline-web-development-utilities-guide\/\">guide to secure offline development utilities<\/a>, and if you need to tidy or validate the JSON afterwards, the&nbsp;<a href=\"https:\/\/schoolict.net\/tools\/free-offline-json-formatter-validator-article\/\">JSON formatter and validator guide<\/a>&nbsp;covers that side. The rest of the toolkit is indexed under&nbsp;<a href=\"https:\/\/schoolict.net\/tools\/free-web-tools-by-category\/\">free web tools by category<\/a>.<\/p>\n\n\n\n\n<style>\n.pth-faq-section{margin-top:50px;margin-bottom:40px;font-family:inherit}\n.pth-faq-header{font-size:1.8rem;font-weight:800;color:#0f172a;margin-bottom:25px;border-bottom:2px solid #e2e8f0;padding-bottom:10px;display:flex;align-items:center;gap:10px}\n.pth-faq-grid{display:grid;grid-template-columns:100%;gap:20px}\n@media(min-width:768px){.pth-faq-grid{grid-template-columns:repeat(2,1fr)}}\n@media(min-width:1024px){.pth-faq-grid{grid-template-columns:repeat(3,1fr)}}\n.pth-faq-card{background:#f8fafc;padding:24px;border-radius:12px;border:1px solid #e2e8f0;transition:transform .2s ease;break-inside:avoid}\n.pth-faq-card:hover{transform:translateY(-3px);box-shadow:0 4px 12px rgba(0,0,0,.05)}\n.pth-faq-q{color:#0f172a;font-size:1rem;font-weight:700;margin:0 0 12px;line-height:1.4}\n.pth-faq-a{margin:0;font-size:.95rem;color:#1e293b;line-height:1.6;font-weight:500}\n<\/style>\n<div class=\"pth-faq-section\">\n  <div class=\"pth-faq-header\"><span aria-hidden=\"true\">\u2753<\/span> Frequently Asked Questions<\/div>\n  <div class=\"pth-faq-grid\">\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">What does the seed actually do?<\/p>\n      <p class=\"pth-faq-a\">It makes generation deterministic. The same seed always produces byte-identical records, so you can commit the output as a test fixture and have every teammate and CI run reproduce it exactly. Untick it for fresh random data on every click.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Is any of this data real?<\/p>\n      <p class=\"pth-faq-a\">No. It is plausible but entirely fabricated. Addresses are assembled from parts, so a street and city may not genuinely coexist. Emails use reserved test domains and cannot receive mail. Never treat it as real statistics or a real place or person.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Are the email addresses safe to use?<\/p>\n      <p class=\"pth-faq-a\">Yes. They use <code>example.com<\/code>, <code>example.org<\/code>, <code>example.net<\/code> and <code>.invalid<\/code> &mdash; domains reserved by standards bodies precisely so test data cannot accidentally deliver mail to a real inbox.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Why do the names and emails match each other?<\/p>\n      <p class=\"pth-faq-a\">Because incoherent records look obviously fake and make it impossible to eyeball whether your join or display logic works. Within one record, the name, email and username all derive from the same generated identity.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Does switching export format regenerate the data?<\/p>\n      <p class=\"pth-faq-a\">No. The records are generated once and rendered into whichever format you pick, so you can compare the same dataset as JSON, CSV and SQL without anything changing underneath you.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Why does my nested array appear as text in the CSV?<\/p>\n      <p class=\"pth-faq-a\">Because CSV, TSV and SQL are flat table formats with no way to represent an array inside a cell. The array is written as compact JSON in a single column. For genuinely nested output, use JSON or XML.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">What is the awkward names option for?<\/p>\n      <p class=\"pth-faq-a\">It mixes in apostrophes, hyphens, accents and particles &mdash; O&#8217;Brien, Garc&iacute;a, van der Berg. These are ordinary real names that frequently get rejected by validation written for plain A&ndash;Z text. Better to find that in testing.<\/p>\n    <\/div>\n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Is anything uploaded?<\/p>\n      <p class=\"pth-faq-a\">No. Everything runs as JavaScript in your browser with no network requests after the page loads. That matters here, because a mock schema often mirrors the structure of a real, confidential database.<\/p>\n    <\/div>\n  <\/div>\n<\/div>\n \n","protected":false},"excerpt":{"rendered":"<p>Stop Writing Sample Data by Hand \u2014 Build mock JSON payloads and flexible text placeholders effortlessly. Instantly generate custom Lorem Ipsum text, rich HTML placeholders, and realistic JSON dummy user profiles 100% offline. Perfect for UI\/UX and frontend developers. Now use Lorem Ipsum &amp; JSON Dummy Data Generator Pro \u00a0 \ud83d\udfe2 Seeded &mdash; The Same &#8230; <a title=\"Free Lorem Ipsum and JSON Dummy Data Generator Pro\" class=\"read-more\" href=\"https:\/\/schoolict.net\/tools\/lorem-ipsum-and-json-dummy-data-generator-pro\/\" aria-label=\"Read more about Free Lorem Ipsum and JSON Dummy Data Generator Pro\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":2392,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-2390","page","type-page","status-publish","has-post-thumbnail"],"_links":{"self":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/2390","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/comments?post=2390"}],"version-history":[{"count":2,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/2390\/revisions"}],"predecessor-version":[{"id":6994,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/2390\/revisions\/6994"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/media\/2392"}],"wp:attachment":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/media?parent=2390"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}