البحث
جزء من قسم أساسيات Node.js في رحلة Node.js على Coddy. الدرس 23 من 24.
مع بضع عشرات من الملاحظات، يتوقف التمرير عبر list عن العمل: تحتاج إلى البحث.
حوّل كلا الطرفين إلى أحرف صغيرة قبل المقارنة، لكي تتطابق Milk وmilk وMILK جميعها، ثم اختبر باستخدام includes. كرّر على القائمة كاملة واحتفظ بكل فهرس، لكي تعرض المطابقة الرقم نفسه كما في list، وهو الرقم الذي يتوقعه كل من done وremind.
const songs = ['Blue Moon', 'Moonlight', 'Sunny'];
const query = 'MOON'.toLowerCase();
songs.forEach((title, i) => {
if (title.toLowerCase().includes(query)) {
console.log(`${i + 1}. ${title}`);
}
});التحدي
سهل- يعرض
search <word>كل ملاحظة تحتوي على الكلمة، بصرف النظر عن حالة الأحرف، مع ترقيمها كما فيlist. - عندما لا يطابق أي شيء، يعرض
No notes match <word>.
شغّل node notes.js search milk، ثم search MILK، ثم كلمة لم تكتبها من قبل.
جرّب بنفسك
// تبدأ أداة ملاحظاتك من هنا.
import { rmSync } from 'node:fs';
import path from 'node:path';
import { formatNote } from './format.js';
import stats from './legacy/stats.cjs';
import pkg from './package.json' with { type: 'json' };
import store from './store.js';
const [command, ...words] = process.argv.slice(2);
const text = words.join(' ');
store.on('added', (note, n) => {
console.log(`Saved note ${n}.`);
});
const noteNumber = (word) => {
const n = Number(word);
if (!Number.isInteger(n) || n < 1 || n > store.notes.length) {
console.error(`No note ${word}`);
process.exit(1);
}
return n;
};
if (command === 'add') {
await store.add(text);
} else if (command === 'list') {
const owner = process.env.NOTES_OWNER ?? 'you';
console.log(`Notes for ${owner}`);
if (store.notes.length === 0) {
console.log('No notes yet');
}
const lines = store.notes.map((note, i) => formatNote(i + 1, note));
if (store.settings.sort === 'newest') {
lines.reverse();
}
lines.forEach((line) => console.log(line));
} else if (command === 'where') {
const file = path.join(process.cwd(), 'notes.json');
console.log(file);
console.log(path.basename(file));
} else if (command === 'stats') {
console.log(`${store.notes.length} notes, ${stats.countWords(store.notes)} words`);
} else if (command === 'done') {
const removed = await store.remove(noteNumber(words[0]));
console.log(`Done: ${removed}`);
} else if (command === 'remind') {
const note = store.notes[noteNumber(words[0]) - 1];
let count = 3;
const timer = setInterval(() => {
if (count > 0) {
console.log(count);
count -= 1;
} else {
console.log(note);
clearInterval(timer);
}
}, 200);
} else if (command === 'import') {
let input = '';
for await (const chunk of process.stdin) {
input += chunk;
}
const lines = input
.split('\n')
.map((line) => line.trim())
.filter((line) => line !== '');
for (const line of lines) {
await store.add(line);
}
console.log(`Imported ${lines.length} notes.`);
} else if (command === 'version') {
console.log(`${pkg.name} ${pkg.version}`);
} else if (command === 'clear') {
rmSync('notes.json', { force: true });
console.log('Deleted notes.json');
} else {
if (command) {
console.error(`Unknown command: ${command}`);
}
console.error('Usage: node notes.js <command> [words]');
process.exit(1);
}