initial commit

This commit is contained in:
Mo Elzubeir
2025-08-15 00:19:06 -05:00
commit 0b362bed4b
5 changed files with 360 additions and 0 deletions
+142
View File
@@ -0,0 +1,142 @@
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}`);
});