-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFancyLineWrapper.html
More file actions
174 lines (166 loc) · 6.84 KB
/
Copy pathFancyLineWrapper.html
File metadata and controls
174 lines (166 loc) · 6.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Fancy Line Wrapper</title>
<link rel="stylesheet" href="styles.css"/>
<!-- Icon from https://icons8.com/icon/q-7YCXE1jTFn/word-wrap with -->
<!-- background=#395B64 (copyOutputButton background) and color=#333 (body background) -->
<link rel="icon" type="image/x-icon" href="icons8-word-wrap-96.png">
<script src="jquery-3.6.3.min.js"></script>
<script>
$(document).ready(function() {
// Loads previous data on refresh
if (localStorage["inputTextAreaData"]) {
$("#inputTextArea").val(localStorage["inputTextAreaData"]);
}
if (localStorage["lineLength"]) {
$("#lineLengthField").val(localStorage["lineLength"]);
}
syncOutputTextArea()
// Copies text to clipboard
$('#copyOutputButton').on('click', (e) => {
e.preventDefault(); // prevent "submitting" the form which would clear and reload the page
navigator.clipboard.writeText($("#outputTextArea").val());
$("#copiedMessage").fadeIn(200).delay(1000).fadeOut(500);
});
// When the user types or pastes something into the inputTextArea, sync it to the outputTextArea
$("#inputTextArea").on("input", () => syncOutputTextArea());
// Show the settings modal when the settings button is clicked
$('#settingsButton').on('click', () => {
$("#settingsModal").show();
});
// Hide the settings modal when the close button is clicked
$('#settingsCloseButton').on('click', () => {
$("#settingsModal").hide();
});
// When the user types or pastes something into the lineLengthField, sync the line length and update
$("#lineLengthField").on("input", () => {
localStorage["lineLength"] = $("#lineLengthField").val();
syncOutputTextArea()
});
});
function syncOutputTextArea() {
localStorage["inputTextAreaData"] = $("#inputTextArea").val();
var lineLength = getLineLength();
var output = "";
var lines = $("#inputTextArea").val().split('\n')
var inCodeBlock = false;
lines.forEach(function(nextLine) {
if (nextLine.trim().startsWith("```")) {
inCodeBlock = !inCodeBlock;
output += nextLine + '\n';
return;
}
if (inCodeBlock) {
output += nextLine + '\n';
return;
}
nextLine = cleanLine(nextLine);
var listIndentLevel = determineListIndentLevel(nextLine);
var leadingSpaces = nextLine.search(/\S/);
if (leadingSpaces === -1) leadingSpaces = 0;
nextLine = nextLine.trim();
if (nextLine === "") {
output += '\n';
return;
}
var currentOutputLine = ""
if (listIndentLevel !== -1) {
currentOutputLine += " ".repeat(leadingSpaces);
}
var words = nextLine.split(/\s+/);
words.forEach(function(nextWord) {
if (currentOutputLine.length + nextWord.length > lineLength) {
currentOutputLine = removeLastCharIfNeeded(currentOutputLine);
if (currentOutputLine.trim() !== "") {
output += currentOutputLine + '\n';
currentOutputLine = "";
if (listIndentLevel !== -1) {
currentOutputLine += " ".repeat(listIndentLevel);
}
}
}
currentOutputLine += nextWord + ' ';
})
currentOutputLine = removeLastCharIfNeeded(currentOutputLine)
output += currentOutputLine + '\n';
})
output = removeLastCharIfNeeded(output);
$("#outputTextArea").val(output);
// Set the line length of the text areas
$("#inputTextArea").attr('cols', lineLength);
$("#outputTextArea").attr('cols', lineLength);
}
function removeLastCharIfNeeded(str) {
if (str.endsWith(' ') || str.endsWith('\n')) {
return str.substring(0, str.length - 1);
}
return str;
}
function cleanLine(line) {
// Replace "fancy" quotes with plain ones
line = line.replaceAll("“", "\"");
line = line.replaceAll("”", "\"");
line = line.replaceAll("‘", "'");
line = line.replaceAll("’", "'");
// Replace "fancy" dashes and ellipsis with plain ones
line = line.replaceAll("–", "-");
line = line.replaceAll("—", "--");
line = line.replaceAll("…", "...");
// Replace other common annoying characters
line = line.replaceAll("\u00A0", " "); // non-breaking space
line = line.replaceAll("\r", ""); // carriage return
return line;
}
function determineListIndentLevel(line) {
// Support for:
// - Bullets: - , * , +
// - Numbers: 1. , 1) , (1)
// - Letters: a. , a) , (a)
// - Roman: i. , i) , (i) , iii. , (iii)
const pattern = /^( *)([-*+] |\d+[.)] |[a-zA-Z][.)] |[ivxIVX]+[.)] |\(\d+\) |\([a-zA-Z]\) |\([ivxIVX]+\) )/;
var match = line.match(pattern);
if (match != null) {
return match[0].length;
}
return -1;
}
function getLineLength() {
var lineLength = parseInt(localStorage["lineLength"]);
if (isNaN(lineLength)) {
lineLength = 80;
}
return lineLength;
}
</script>
</head>
<body>
<h1>Fancy Line Wrapper</h1>
<textarea id="inputTextArea" class="inputTextArea" placeholder="Enter text here" cols="80" rows="15" autofocus></textarea>
<!-- We put these in a form to help align the copyOutputButton with the outputTextArea -->
<form id="outputForm" class="outputForm">
<textarea id="outputTextArea" class="outputTextArea" placeholder="Get text here" cols="80" rows="15" readonly></textarea>
<button id="copyOutputButton" type="button" class="copyOutputButton">
<!-- Icon from https://clipground.com/images/copy-4.png -->
<img src="copy-4.png" title="Click to Copy" class="copyOutputButtonImage">
<div id="copiedMessage" class="copiedMessage">Copied!</div>
</button>
</form>
<br/>
<button id="settingsButton" class="settingsButton">Settings</button>
<!-- The Modal -->
<div id="settingsModal" class="settingsModal">
<!-- Modal content -->
<div class="settingsModalContent">
<span id="settingsCloseButton" class="settingsCloseButton">×</span>
<h3>Settings</h3>
<label for="lineLengthField">Line Length:</label>
<input id="lineLengthField" type="number" class="inputTextArea" value="80" min="1">
</div>
</div>
<br/>
<br/>
<a href="README.md" target="_blank">README</a>
</body>
</html>