Files
2025-08-15 00:19:06 -05:00

142 lines
4.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const express = require('express');
const cors = require('cors');
const app = express();
const PORT = process.env.PORT || 3000;
app.use(cors());
app.use(express.json());
app.use(express.text());
function removeEmDash(text) {
if (!text || typeof text !== 'string') {
return text;
}
function isDateTimeOrPeriod(str) {
const dateTimePatterns = [
/^\d+:\d+/,
/^\d+$/, // number.. could be date, who knows
/^(January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)$/i, // this is dumb
/^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday|Mon|Tue|Wed|Thu|Fri|Sat|Sun)$/i, // days
/^(Spring|Summer|Fall|Autumn|Winter)$/i, // seasons, did you see that, even autumn my zoul!
/^\d{4}$/,
/^Q[1-4]$/i, // quarters for that jerome powell post
];
return dateTimePatterns.some(pattern => pattern.test(str.trim()));
}
let result = text
// 1. parenthetical/interruptive information (word — phrase — word) -> parentheses
.replace(/([a-zA-Z])\s*—\s*([^—]+?)\s*—\s*([a-zA-Z])/g, '$1 ($2) $3')
// 2. date/time ranges (handle early to avoid conflicts)
.replace(/(\d+:\d+\s*[ap]\.?m\.?)\s*—\s*(\d+:\d+\s*[ap]\.?m\.?)/gi, '$1 to $2')
// 3. interrupted speech in dialogue (word—") -> keep as interruption (but clean format)
.replace(/([a-zA-Z])\s*—\s*$/g, '$1 ')
// 4. attribution quotes ("quote" — Author) -> en dash
.replace(/"([^"]+)"\s*—\s*([A-Z][^.!?]*)/g, '"$1" $2')
// 5. dramatic pause/reveal (phrase — Word!) -> ellipsis
.replace(/([a-zA-Z\s]+)\s*—\s*([A-Z][a-zA-Z]*[!.])/g, '$1 ... $2')
// 6. sudden break in thought (clause — but/and/or...) -> comma
.replace(/([a-zA-Z])\s*—\s*(but|and|or|yet|so)\s+/g, '$1, $2 ')
// 7. appositive emphasis (noun — a descriptor) -> comma
.replace(/([a-zA-Z])\s*—\s*(a\s+[a-zA-Z][^.!?]*)/g, '$1, $2')
// 8. summary/amplification at end (items — conclusion.) -> semicolon
.replace(/([a-zA-Z.,\s]*[a-zA-Z.,])\s*—\s*([a-z][^.!?]*\.)/g, '$1 ; $2')
// 9. after sentence punctuation -> space
.replace(/([.!?:;])\s*—\s*([A-Za-z])/g, '$1 $2')
// 10. after comma -> space
.replace(/([,])\s*—\s*([A-Za-z])/g, '$1 $2')
// 11. before closing punctuation -> space
.replace(/([a-zA-Z])\s*—\s*([.,;:!?"'\)\]])/g, '$1 $2')
// 12. after opening punctuation -> space
.replace(/(["'(\[])\s*—\s*([A-Za-z])/g, '$1 $2')
// 13. between letters (simple cases) -> comma
.replace(/([a-zA-Z])\s*—\s*([a-zA-Z])/g, '$1, $2')
// 14. leading em dash -> remove
.replace(/^\s*—\s*/g, '')
// 15. trailing em dash -> remove
.replace(/\s*—\s*$/g, '')
// 16. catch-all remaining -> check if it's a date/time range, otherwise en dash
.replace(/(\S+)\s*—\s*(\S+)/g, (_, left, right) => {
if (isDateTimeOrPeriod(left) && isDateTimeOrPeriod(right)) {
return `${left} ${right}`;
}
return `${left} ${right}`;
});
// sanitation step: clean up spacing issues
result = result
// remove spaces before colons and ellipses
.replace(/\s+\.\.\./g, '...')
.replace(/\s+:/g, ':')
.replace(/\s+;/g, ';')
// clean up multiple spaces
.replace(/\s+/g, ' ')
.trim();
return result;
}
app.post('/emdash', (req, res) => {
try {
const text = typeof req.body === 'string' ? req.body : req.body.text;
if (!text) {
return res.status(400).json({ error: 'Text is required, come on now' });
}
const result = removeEmDash(text);
res.json({
original: text,
result: result
});
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
app.get('/emdash', (req, res) => {
const text = req.query.text;
if (!text) {
return res.status(400).json({ error: 'Text query parameter is required, come on now' });
}
const result = removeEmDash(text);
res.json({
original: text,
result: result
});
});
app.get('/', (req, res) => {
res.json({
message: 'Em Dash API',
description: 'API to linguistically and grammatically replace em dashes.',
endpoints: {
'POST /emdash': 'Send text in body (JSON or plain text)',
'GET /emdash?text=your-text': 'Send text as query parameter'
}
});
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});