Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion scripts/smoke.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { Personalizer, collectThemes, normalizeTheme } from '../src/personalize.js';
import { SearchIndex, tokenize, snippet } from '../src/search.js';
import { asMovements, monthByNumber, movementOf, mirrorOf, currentMonth, neighbors } from '../src/journey.js';
import { asMovements, monthByNumber, monthsOfMovement, movementOf, mirrorOf, currentMonth, neighbors } from '../src/journey.js';

const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const { articles } = JSON.parse(
Expand Down Expand Up @@ -145,6 +145,16 @@ check('snippet falls back to the start of the text when nothing matches', () =>
assert.ok(s.startsWith('Gratitude'));
});

check('snippet does not cut mid-word at the trailing window edge', () => {
// The half-window (30 chars for contextChars=60) ends inside a word without the fix.
const body = 'target ' + 'filler '.repeat(20);
const s = snippet({ body }, ['target'], { contextChars: 60 });
assert.ok(s.endsWith(' …'), 'long text should produce a trailing ellipsis');
const beforeMark = s.slice(0, s.lastIndexOf(' …'));
const lastWord = beforeMark.split(/\s+/).pop();
assert.equal(lastWord, 'filler');
});

check('search matches an author name', () => {
const idx = new SearchIndex().build([
{ title: 'On stillness', themes: ['Silence'], author: 'Nirodbaran', summary: 'x', body: 'y' },
Expand All @@ -154,4 +164,15 @@ check('search matches an author name', () => {
assert.ok(hits[0].matched.includes('nirodbaran'));
});

console.log('journey.js (more)');

check("monthsOfMovement returns a movement's months in calendar order", () => {
const months = monthsOfMovement(arc, 'ground');
assert.deepEqual(months.map((m) => m.number), [1, 2, 3, 4, 5]);
});

check('mirrorOf returns null for months with no mirror partner', () => {
assert.equal(mirrorOf(arc, 6), null);
});

console.log(`\n${passed} checks passed.`);
7 changes: 6 additions & 1 deletion src/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,12 @@ export function snippet(article, terms = [], { contextChars = 120 } = {}) {
}
if (idx === -1) continue;
const start = Math.max(0, idx - half);
const end = Math.min(text.length, idx + half);
let end = Math.min(text.length, idx + half);
// Avoid cutting mid-word at the trailing edge of the window.
if (end < text.length && /\S/.test(text[end])) {
const nextSpace = text.indexOf(' ', end);
end = nextSpace !== -1 ? nextSpace : text.length;
}
let s = text.slice(start, end).trim();
if (start > 0) s = `… ${s}`;
if (end < text.length) s = `${s} …`;
Expand Down
Loading