Overview
What Sort Unique Lines does
Handles standard and rich-text line breaks, trims a list, removes exact duplicate lines, and sorts the remaining entries case-insensitively with a deterministic tie-breaker.
| Category | Text Editing & Formatting |
|---|---|
| Action type | JavaScript |
| Default result | Replace selected text by default |
| Internet | Not required |
Example
Action and outcome
| Action | Outcome |
|---|---|
| Sort Unique LinesSelected text: Mango Apple Pear Apple | Apple Mango Pear |
Workflow
Use Sort Unique Lines
Follow these steps to remove duplicate lines and sort the remaining text with ActionClip.
- Select the text you want to use.
- Choose Sort Unique Lines from ActionClip.
- In editable text, ActionClip replaces the selection immediately. In read-only text, it opens the result for review and copying.
Before you add it
Requirements and privacy
- Before you start: No setup required.
- Your selected text: Runs locally in ActionClip’s JavaScript sandbox. Selected text does not leave your Mac.
Inspect before installing
Action script
The script below is included so you can inspect how the action works before downloading it.
JavaScript definition
function run(selected_text) {
const lines = selected_text
.split(/\r\n|[\n\r\u000B\u000C\u0085\u2028\u2029]/)
.map((line) => line.trim())
.filter(Boolean);
function naturalCompare(a, b) {
const chunksA = a.match(/\d+|\D+/g) || [];
const chunksB = b.match(/\d+|\D+/g) || [];
const count = Math.max(chunksA.length, chunksB.length);
for (let index = 0; index < count; index += 1) {
if (chunksA[index] === undefined) return -1;
if (chunksB[index] === undefined) return 1;
const partA = chunksA[index];
const partB = chunksB[index];
const numericA = /^\d+$/.test(partA);
const numericB = /^\d+$/.test(partB);
if (numericA && numericB) {
const valueA = partA.replace(/^0+(?=\d)/, "");
const valueB = partB.replace(/^0+(?=\d)/, "");
if (valueA.length !== valueB.length) return valueA.length - valueB.length;
if (valueA !== valueB) return valueA < valueB ? -1 : 1;
if (partA.length !== partB.length) return partA.length - partB.length;
} else {
const foldedA = partA.toLocaleLowerCase();
const foldedB = partB.toLocaleLowerCase();
if (foldedA !== foldedB) return foldedA < foldedB ? -1 : 1;
}
}
return a < b ? -1 : a > b ? 1 : 0;
}
return [...new Set(lines)].sort(naturalCompare).join("\n");
}