Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ff2cf84
test: adjust multiline patching test
DecimalTurn Mar 17, 2026
e245616
WIP
DecimalTurn Mar 17, 2026
8a66554
test: add second test for more than one line
DecimalTurn Mar 18, 2026
1e3ff32
fix: generate string for line ending backslash
DecimalTurn Mar 18, 2026
858c39b
fix: use rebuildLeadingNewlineContinuation
DecimalTurn Mar 18, 2026
7bbfb4f
fix: make sure rebuildLeadingNewlineContinuation handles alternative …
DecimalTurn Mar 18, 2026
575fcd9
fix: resolve lint errors in generate.ts and audit script
DecimalTurn Mar 18, 2026
03aa088
feat: switch to per-character greedy wrapping for line-continuation m…
DecimalTurn Apr 10, 2026
467d87e
fix: deal with multiple backslash case
DecimalTurn Apr 10, 2026
3cc381c
fix: preserve multiple consecutive spaces in line-continuation multil…
DecimalTurn Apr 11, 2026
7d1d6c4
fix: preserve whitespace-only lines and blank lines in line-continuat…
DecimalTurn Apr 11, 2026
efa11c0
fix: ensure backslashes in literal multiline strings are not treated …
DecimalTurn Apr 11, 2026
ba7e044
test: add more edge cases for patching line-continuation multiline st…
DecimalTurn Apr 11, 2026
ae7dc43
fix: improve handling of trailing whitespace and backslashes in line …
DecimalTurn Apr 11, 2026
cefd30f
fix: refine backslash handling in line continuation for empty tail pr…
DecimalTurn Apr 11, 2026
eb1b2dd
fix: simplify rebuildLineContinuation parameters by removing delimite…
DecimalTurn Apr 11, 2026
549b22b
fix: improve readability with line breaks
DecimalTurn Apr 11, 2026
decc936
fix: ensure whitespace-only preservation
DecimalTurn Apr 11, 2026
0a80796
feat: add eval modal and buttons for interactive expression evaluatio…
DecimalTurn Apr 11, 2026
ed03f13
fix: leading and trailing whitespace integrity + ensure roundtrip wit…
DecimalTurn Apr 11, 2026
fff97c5
refactor: move to seperate file
DecimalTurn Apr 11, 2026
d2d69c6
refactor: simplify rebuildLineContinuation and add content integrity …
DecimalTurn Apr 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 151 additions & 9 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,80 @@
}
.btn.secondary:hover { border-color: var(--accent); color: var(--accent); }

/* ── Eval button ─────────────────────────── */
.eval-btn {
background: none;
border: 1px solid var(--border);
color: var(--text-dim);
font-family: var(--mono);
font-size: 0.7rem;
padding: 0.1rem 0.45rem;
border-radius: 4px;
cursor: pointer;
transition: color 0.2s, border-color 0.2s;
line-height: 1.4;
}
.eval-btn:hover { color: var(--accent); border-color: var(--accent); }

/* ── Eval modal ───────────────────────────── */
.eval-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.6);
z-index: 100;
align-items: center;
justify-content: center;
}
.eval-overlay.open { display: flex; }
.eval-modal {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 1.25rem;
width: min(640px, 90vw);
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.eval-modal-title {
font-size: 0.8rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-dim);
}
.eval-modal-hint {
color: var(--text-dim);
font-size: 0.82rem;
}
.eval-textarea {
background: var(--bg);
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text);
font-family: var(--mono);
font-size: 0.85rem;
line-height: 1.55;
padding: 0.65rem 0.85rem;
resize: vertical;
min-height: 120px;
width: 100%;
outline: none;
}
.eval-textarea:focus { border-color: var(--accent); }
.eval-error {
color: var(--red);
font-size: 0.82rem;
font-family: var(--mono);
min-height: 1.2em;
}
.eval-modal-actions {
display: flex;
gap: 0.5rem;
justify-content: flex-end;
}

/* ── Error / Status ──────────────────────── */
.status {
margin-top: 0.75rem;
Expand Down Expand Up @@ -271,11 +345,11 @@ <h1>toml-<span>patch</span></h1>
<div class="tab-panel active" id="tab-parse">
<div class="panel-grid">
<div class="panel">
<div class="panel-header">Input <span class="lang">TOML</span></div>
<div class="panel-header"><span>Input <span class="lang">TOML</span></span><button class="eval-btn" onclick="openEvalModal('parse-input')" title="Set value from JS expression">{ }</button></div>
<div id="parse-input" class="cm-host"></div>
</div>
<div class="panel">
<div class="panel-header">Output <span class="lang">JSON</span></div>
<div class="panel-header"><span>Output <span class="lang">JSON</span></span><button class="eval-btn" onclick="copyEditor('parse-output', this)" title="Copy output">Copy</button></div>
<div id="parse-output" class="cm-host"></div>
</div>
</div>
Expand All @@ -290,11 +364,11 @@ <h1>toml-<span>patch</span></h1>
<div class="tab-panel" id="tab-stringify">
<div class="panel-grid">
<div class="panel">
<div class="panel-header">Input <span class="lang">JSON</span></div>
<div class="panel-header"><span>Input <span class="lang">JSON</span></span><button class="eval-btn" onclick="openEvalModal('stringify-input')" title="Set value from JS expression">{ }</button></div>
<div id="stringify-input" class="cm-host"></div>
</div>
<div class="panel">
<div class="panel-header">Output <span class="lang">TOML</span></div>
<div class="panel-header"><span>Output <span class="lang">TOML</span></span><button class="eval-btn" onclick="copyEditor('stringify-output', this)" title="Copy output">Copy</button></div>
<div id="stringify-output" class="cm-host"></div>
</div>
</div>
Expand All @@ -309,15 +383,15 @@ <h1>toml-<span>patch</span></h1>
<div class="tab-panel" id="tab-patch">
<div class="panel-grid triple">
<div class="panel">
<div class="panel-header">Existing Document <span class="lang">TOML</span></div>
<div class="panel-header"><span>Existing Document <span class="lang">TOML</span></span><button class="eval-btn" onclick="openEvalModal('patch-existing')" title="Set value from JS expression">{ }</button></div>
<div id="patch-existing" class="cm-host"></div>
</div>
<div class="panel">
<div class="panel-header">Updated Data <span class="lang">JSON</span></div>
<div class="panel-header"><span>Updated Data <span class="lang">JSON</span></span><button class="eval-btn" onclick="openEvalModal('patch-updated')" title="Set value from JS expression">{ }</button></div>
<div id="patch-updated" class="cm-host"></div>
</div>
<div class="panel">
<div class="panel-header">Patched Result <span class="lang">TOML</span></div>
<div class="panel-header"><span>Patched Result <span class="lang">TOML</span></span><button class="eval-btn" onclick="copyEditor('patch-output', this)" title="Copy output">Copy</button></div>
<div id="patch-output" class="cm-host"></div>
</div>
</div>
Expand Down Expand Up @@ -352,12 +426,15 @@ <h2>Get Started</h2>

<footer>
Built with <a href="https://github.com/DecimalTurn/toml-patch">@decimalturn/toml-patch</a>
· Loaded via <a href="https://unpkg.com/@decimalturn/toml-patch">unpkg</a>
· <!--Loaded via <a href="https://unpkg.com/@decimalturn/toml-patch">unpkg</a>-->
· Loaded from <a href="./dist/toml-patch.js">local build</a>
</footer>

<script type="module">
// ── Load dependencies ────────────────────────────────
import * as TOML from 'https://unpkg.com/@decimalturn/toml-patch';
// import * as TOML from 'https://unpkg.com/@decimalturn/toml-patch';
import * as TOML from './dist/toml-patch.js';

import { EditorView, basicSetup } from 'https://esm.sh/codemirror';
import { EditorState } from 'https://esm.sh/@codemirror/state';
import { json } from 'https://esm.sh/@codemirror/lang-json';
Expand Down Expand Up @@ -594,8 +671,73 @@ <h2>Get Started</h2>
clearStatus('patch-status');
};

// ── Eval Modal ────────────────────────────────────────
let _evalTargetId = null;

window.openEvalModal = function (editorId) {
_evalTargetId = editorId;
document.getElementById('eval-error').textContent = '';
document.getElementById('eval-overlay').classList.add('open');
document.getElementById('eval-textarea').focus();
};

window.closeEvalModal = function () {
document.getElementById('eval-overlay').classList.remove('open');
_evalTargetId = null;
};

window.applyEval = function () {
const expr = document.getElementById('eval-textarea').value;
const errEl = document.getElementById('eval-error');
errEl.textContent = '';
try {
// intentional eval: user-controlled expression in a local demo page
// eslint-disable-next-line no-eval
const result = eval(expr);
if (typeof result !== 'string') {
errEl.textContent = `Expected a string, got ${typeof result}`;
return;
}
setEditorValue(_evalTargetId, result);
closeEvalModal();
} catch (e) {
errEl.textContent = `Error: ${e.message}`;
}
};

document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') closeEvalModal();
});

// ── Copy output ──────────────────────────────────────
window.copyEditor = function (editorId, btn) {
const text = getEditorValue(editorId);
navigator.clipboard.writeText(text).then(() => {
const orig = btn.textContent;
btn.textContent = '✓';
setTimeout(() => { btn.textContent = orig; }, 1500);
}).catch(() => {});
};

</script>

<!-- ── Eval Modal ─────────────────────────────────────── -->
<div class="eval-overlay" id="eval-overlay" onclick="if(event.target===this)closeEvalModal()">
<div class="eval-modal">
<div class="eval-modal-title">JS Expression → Editor</div>
<p class="eval-modal-hint">Enter a JS expression that returns a string. Press <kbd>Ctrl+Enter</kbd> to apply.</p>
<textarea class="eval-textarea" id="eval-textarea"
placeholder="'[section]\nkey = &quot;value&quot;\n'"
spellcheck="false"
onkeydown="if((event.ctrlKey||event.metaKey)&&event.key==='Enter'){event.preventDefault();applyEval();}"
></textarea>
<div class="eval-error" id="eval-error"></div>
<div class="eval-modal-actions">
<button class="btn secondary" onclick="closeEvalModal()">Cancel</button>
<button class="btn" onclick="applyEval()">Apply</button>
</div>
</div>
</div>

</body>
</html>
Loading