Programmatic text comparison
Define a Local Text-Comparison API in JavaScript
Build a JavaScript comparison interface with explicit string inputs, optional Unicode and newline normalization, and distinct exact and normalized results.
A text-comparison API needs a precise contract before it needs an HTTP endpoint. Define the accepted inputs, the equality rule and how errors are reported. The function below is a local JavaScript interface you can call from your own Node.js code; it is not a claim that this site exposes a public remote comparison service.
Define explicit request fields
The request contains left and right strings. Two optional booleans control Unicode NFC normalization and newline normalization. Both default to false, so an ordinary request performs exact string comparison without silently trimming spaces or ignoring letter case.
The response includes exactEqual and equalUnderOptions separately. Keeping both answers prevents a normalized match from being mistaken for unchanged original text. The options are returned with the result so that a caller can record the rule that produced it.
Save the function as compare-text.cjs
function compareText(request) {
if (!request || typeof request !== "object" || Array.isArray(request))
throw new TypeError("Request must be an object");
const allowed = new Set(["left", "right", "normalizeNFC", "normalizeNewlines"]);
if (Object.keys(request).some(key => !allowed.has(key)))
throw new TypeError("Unknown request field");
const { left, right, normalizeNFC = false, normalizeNewlines = false } = request;
if (typeof left !== "string" || typeof right !== "string")
throw new TypeError("left and right must be strings");
if (typeof normalizeNFC !== "boolean" || typeof normalizeNewlines !== "boolean")
throw new TypeError("Normalization options must be booleans");
if (left.length > 200000 || right.length > 200000)
throw new RangeError("Each input is limited to 200000 UTF-16 code units");
function prepare(text) {
if (normalizeNewlines) text = text.replace(/\r\n?/g, "\n");
return normalizeNFC ? text.normalize("NFC") : text;
}
const a = prepare(left), b = prepare(right);
return {
exactEqual: left === right,
equalUnderOptions: a === b,
options: { normalizeNFC, normalizeNewlines },
utf16Units: { left: left.length, right: right.length }
};
}
module.exports = { compareText };
Load it with const { compareText } = require("./compare-text.cjs"), then call compareText({ left: "alpha", right: "alpha" }). Both equality fields are true. Replacing right with "beta" makes both false. No network request or file write occurs.
Make normalization a visible choice
For left equal to A followed by CRLF and B, and right equal to A followed by LF and B, exactEqual is false. Setting normalizeNewlines to true makes equalUnderOptions true because CRLF and lone CR are mapped to LF. It does not remove a final newline or collapse spaces.
For café in precomposed and decomposed accent forms, normalizeNFC can make the comparison match while exactEqual remains false. MDN’s normalize documentation explains the Unicode normalization forms. NFC is not transliteration, spelling correction or a semantic similarity calculation.
Reject ambiguous calls
The function rejects missing string fields, arrays used as the request, unknown field names and nonboolean options. It also rejects either input above two hundred thousand UTF-16 code units. An empty string is valid, and two empty strings compare equal.
These failures throw exceptions rather than returning equal: false. A caller should distinguish invalid input from a valid comparison that found a difference. Otherwise, an omitted field or a misspelled option can be reported as though two real texts were compared.
Keep the length unit accurate
The reported lengths are JavaScript string lengths, measured in UTF-16 code units. An emoji can occupy more than one such unit, and a joined visible character can contain several components. The limit and output labels use the same unit intentionally.
Do not relabel those figures as bytes, words or visible characters. If a surrounding API enforces a transport-byte limit, measure the encoded request separately. A text-length limit and a JSON request-size limit answer different resource questions.
Add transport only when the application needs it
A web service would need its own request parsing, authentication decisions, size limits, error mapping and deployment configuration. Those are separate from the comparison function shown here. Avoid inventing an endpoint URL or assuming that a browser tool’s page URL accepts JSON POST requests.
For an interactive comparison, use Text Compare and inspect the supplied passages directly. For a programmatic workflow, call the local function with controlled inputs and preserve its options with the result. Neither exact equality nor normalized equality establishes plagiarism, shared authorship or equivalent meaning.


