{"id":474179,"date":"2025-09-07T15:00:58","date_gmt":"2025-09-07T15:00:58","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=474179"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=474179","title":{"rendered":"<span>\u041f\u0435\u0442-\u043f\u0440\u043e\u0435\u043a\u0442 \u0441 AI-\u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u043e\u043c: \u043c\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043e\u043f\u044b\u0442 \u0432\u0430\u0439\u0431\u043a\u043e\u0434\u0438\u043d\u0433\u0430<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041a\u0430\u043a \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438, \u044f \u0434\u0430\u0432\u043d\u043e \u043c\u0435\u0447\u0442\u0430\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 pet\u2011\u043f\u0440\u043e\u0435\u043a\u0442\u00a0\u2014 \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0447\u0443\u0432\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u044f \u00ab\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u043c\u00bb \u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0442\u044c \u0431\u043e\u044f\u0442\u044c\u0441\u044f \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439. \u0412\u00a0\u0438\u0442\u043e\u0433\u0435 \u0440\u0435\u0448\u0438\u043b\u0441\u044f: \u0431\u0443\u0434\u0443 \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0435\u0431\u2011\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f\u00a0\u043b\u0438\u0447\u043d\u044b\u0445 \u0437\u0430\u043c\u0435\u0442\u043e\u043a.<\/p>\n<p>\u041d\u0430\u00a0\u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u044f \u043d\u0435\u00a0\u0441\u043e\u0432\u0441\u0435\u043c \u043d\u043e\u0432\u0438\u0447\u043e\u043a. \u0420\u0430\u043d\u044c\u0448\u0435 \u0443\u00a0\u043c\u0435\u043d\u044f \u0443\u0436\u0435\u00a0\u0431\u044b\u043b\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u043e\u0441\u0432\u043e\u0438\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u044f\u0437\u044b\u043a\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043d\u043e\u00a0\u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u0430\u0440\u044b \u0441\u0442\u0440\u043e\u0447\u0435\u043a \u043a\u043e\u0434\u0430 \u0434\u0435\u043b\u043e \u0440\u0435\u0434\u043a\u043e \u0437\u0430\u0445\u043e\u0434\u0438\u043b\u043e. \u0423\u043c\u0435\u043d\u0438\u0435 \u00ab\u0433\u0443\u0433\u043b\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u00bb \u0438 \u0438\u0441\u043a\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442\u044b \u043d\u0430\u00a0StackOverflow \u043f\u043e\u043a\u0430 \u0434\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u0442\u044f\u0436\u0435\u043b\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0432\u0435\u0441\u0442\u0438 \u0447\u0442\u043e\u2011\u0442\u043e \u0434\u043e\u00a0\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u00a0\u0431\u044b\u043b\u043e \u0441\u043b\u043e\u0436\u043d\u043e.<\/p>\n<p>\u0412\u00a0\u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0439\u0442\u0438 \u043f\u043e\u00a0\u0442\u0440\u0435\u043d\u0434\u0430\u043c \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432\u00a0\u043f\u0440\u043e\u0446\u0435\u0441\u0441 AI. \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0425\u0430\u0431\u0440\u0443, \u0447\u0442\u043e\u00a0\u0432\u00a0\u043d\u0443\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u0434\u043a\u0438\u043d\u0443\u043b <a href=\"https:\/\/habr.com\/ru\/companies\/koda\/articles\/936906\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u044e \u043f\u0440\u043e\u00a0Koda<\/a>. \u0421\u00a0Koda \u0438 \u043d\u0430\u0447\u0430\u043b\u0441\u044f \u043c\u043e\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442. \u0410\u00a0\u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0445\u043e\u0447\u0443 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0440\u0435\u0441\u043f\u0435\u043a\u0442 \u0437\u0430\u00a0\u0442\u043e, \u0447\u0442\u043e\u00a0\u0432\u0441\u0451 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e.<\/p>\n<h2>\u0427\u0442\u043e \u044f \u0445\u043e\u0442\u0435\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c<\/h2>\n<p>\u0418\u0434\u0435\u044f\u00a0\u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0439: \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f\u00a0\u0437\u0430\u043c\u0435\u0442\u043e\u043a, \u0433\u0434\u0435 \u0442\u0435\u043a\u0441\u0442 \u043c\u043e\u0436\u043d\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043d\u0430\u00a0UI. \u0414\u043b\u044f\u00a0\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u044b\u0431\u0440\u0430\u043b TypeScript: \u0441\u00a0\u0435\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c \u044f \u0443\u0436\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u043a\u043e\u043c.<\/p>\n<h3>\u041a\u0430\u043a AI \u043f\u043e\u043c\u043e\u0433\u0430\u043b<\/h3>\n<p>\u041e\u043f\u044b\u0442 \u0441\u00a0Koda \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c, \u0445\u043e\u0442\u044f \u0438 \u043d\u0435\u00a0\u0431\u0435\u0437\u00a0\u043d\u044e\u0430\u043d\u0441\u043e\u0432.<\/p>\n<h4>\u041f\u0435\u0440\u0432\u044b\u0435 \u0448\u0430\u0433\u0438<\/h4>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044f \u0441\u043f\u0440\u043e\u0441\u0438\u043b \u0443\u00a0AI, \u043a\u0430\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f\u00a0\u0441\u0442\u0430\u0440\u0442\u0430. \u041e\u043d \u0441\u0440\u0430\u0437\u0443 \u0432\u044b\u0434\u0430\u043b \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439, \u0438 \u043f\u0440\u0438\u044f\u0442\u043d\u043e \u0443\u0434\u0438\u0432\u0438\u043b\u043e, \u0447\u0442\u043e\u00a0\u0432\u0441\u0451 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e\u00a0\u0431\u044b\u043b\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u044f\u043c\u043e \u0432\u00a0\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435, \u043d\u0435\u00a0\u043a\u043e\u043f\u0430\u044f\u0441\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4e8\/f86\/d94\/4e8f86d94c39a00e291d2b5543d717b8.png\" width=\"1600\" height=\"1014\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/4e8\/f86\/d94\/4e8f86d94c39a00e291d2b5543d717b8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4e8\/f86\/d94\/4e8f86d94c39a00e291d2b5543d717b8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u043e\u0442\u043e\u043c \u044f \u0443\u0442\u043e\u0447\u043d\u0438\u043b: \u00ab\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?\u00bb\u00a0\u2014 \u0438 Koda \u043d\u0430\u0433\u0435\u043d\u0435\u0440\u0438\u043b \u043c\u043e\u0434\u0435\u043b\u044c, \u0441\u0435\u0440\u0432\u0438\u0441 \u0438 \u0444\u0430\u0439\u043b \u0434\u043b\u044f\u00a0\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438. \u0418, \u043a\u00a0\u043c\u043e\u0435\u043c\u0443 \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u044e, \u0432\u0441\u0451 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0441\u00a0\u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0440\u0430\u0437\u0430, \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a, \u043a\u0430\u043a\u00a0\u044f \u043e\u0436\u0438\u0434\u0430\u043b.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/40f\/2e5\/da4\/40f2e5da48f2603f8fa207d3aba5f055.png\" width=\"1600\" height=\"962\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/40f\/2e5\/da4\/40f2e5da48f2603f8fa207d3aba5f055.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/40f\/2e5\/da4\/40f2e5da48f2603f8fa207d3aba5f055.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dd0\/e6d\/9c2\/dd0e6d9c2b24992c09ff29d3d9cc6b61.png\" width=\"1600\" height=\"962\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/dd0\/e6d\/9c2\/dd0e6d9c2b24992c09ff29d3d9cc6b61.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dd0\/e6d\/9c2\/dd0e6d9c2b24992c09ff29d3d9cc6b61.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<details class=\"spoiler\">\n<summary>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b<\/summary>\n<div class=\"spoiler__content\">\n<p><code>tsconfig.json<\/code><\/p>\n<pre><code class=\"json\">{   \"compilerOptions\": {     \"target\": \"ES2020\",     \"module\": \"commonjs\",     \"outDir\": \".\/dist\",     \"rootDir\": \".\/src\",     \"strict\": true,     \"esModuleInterop\": true,     \"skipLibCheck\": true,     \"forceConsistentCasingInFileNames\": true   } }<\/code><\/pre>\n<p><code>Note.ts<\/code><\/p>\n<pre><code class=\"typescript\">export interface Note {   id: string;   title: string;   content: string;   createdAt: Date;   updatedAt: Date; }<\/code><\/pre>\n<p><code>NoteService.ts<\/code><\/p>\n<pre><code class=\"typescript\">import { Note } from '..\/models\/Note';  export class NoteService {   private notes: Note[] = [];    getAllNotes(): Note[] {     return this.notes;   }    getNoteById(id: string): Note | undefined {     return this.notes.find(note =&gt; note.id === id);   }    createNote(note: Omit&lt;Note, 'id' | 'createdAt' | 'updatedAt'&gt;): Note {     const newNote: Note = {       ...note,       id: Date.now().toString(),       createdAt: new Date(),       updatedAt: new Date()     };          this.notes.push(newNote);     return newNote;   }    updateNote(id: string, updatedNote: Partial&lt;Omit&lt;Note, 'id' | 'createdAt'&gt;&gt;): Note | null {     const noteIndex = this.notes.findIndex(note =&gt; note.id === id);          if (noteIndex === -1) {       return null;     }          this.notes[noteIndex] = {       ...this.notes[noteIndex],       ...updatedNote,       updatedAt: new Date()     };          return this.notes[noteIndex];   }    deleteNote(id: string): boolean {     const initialLength = this.notes.length;     this.notes = this.notes.filter(note =&gt; note.id !== id);     return this.notes.length !== initialLength;   } }<\/code><\/pre>\n<p><code>index.ts<\/code><\/p>\n<pre><code class=\"typescript\">import { NoteService } from '.\/services\/NoteService';  const noteService = new NoteService();  \/\/ \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0437\u0430\u043c\u0435\u0442\u043a\u0430\u043c\u0438 function main() {   \/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438   const newNote = noteService.createNote({     title: '\u041f\u0435\u0440\u0432\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430',     content: '\u042d\u0442\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043c\u043e\u0435\u0439 \u043f\u0435\u0440\u0432\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438'   });   console.log('\u0421\u043e\u0437\u0434\u0430\u043d\u0430 \u0437\u0430\u043c\u0435\u0442\u043a\u0430:', newNote);    \/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0435\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438   const secondNote = noteService.createNote({     title: '\u0412\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430',     content: '\u0422\u0435\u043a\u0441\u0442 \u0432\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438'   });    \/\/ \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0437\u0430\u043c\u0435\u0442\u043e\u043a   console.log('\u0412\u0441\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438:', noteService.getAllNotes());    \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438   const updatedNote = noteService.updateNote(newNote.id, {     content: '\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0435\u0440\u0432\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438'   });   console.log('\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430:', updatedNote);    \/\/ \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438   const isDeleted = noteService.deleteNote(secondNote.id);   console.log('\u0412\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0430:', isDeleted);   console.log('\u041e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0438:', noteService.getAllNotes()); }  main();<\/code><\/pre>\n<\/div>\n<\/details>\n<h3>\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0441 UI<\/h3>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c\u00a0\u0431\u044b\u043b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u042f \u0441\u043d\u043e\u0432\u0430 \u043e\u0431\u0440\u0430\u0442\u0438\u043b\u0441\u044f \u043a\u00a0AI\u00a0\u2014 \u0438 \u0432\u043e\u0442 \u0442\u0443\u0442 \u043d\u0430\u0447\u0430\u043b\u0438\u0441\u044c \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8f5\/743\/2ea\/8f57432ead6db0791c816cf4ad81be4f.png\" width=\"995\" height=\"1600\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/8f5\/743\/2ea\/8f57432ead6db0791c816cf4ad81be4f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8f5\/743\/2ea\/8f57432ead6db0791c816cf4ad81be4f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u0435\u0440\u0432\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043a\u043e\u0434\u0430 \u043d\u0435\u00a0\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5aa\/9ac\/e26\/5aa9ace26af526f36209ed330789bfdc.png\" width=\"1600\" height=\"802\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/5aa\/9ac\/e26\/5aa9ace26af526f36209ed330789bfdc.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5aa\/9ac\/e26\/5aa9ace26af526f36209ed330789bfdc.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0430\u0440\u044b \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439 UI \u0432\u0441\u0451\u00a0\u0436\u0435 \u0437\u0430\u0432\u0451\u043b\u0441\u044f&#8230;<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c78\/961\/f08\/c78961f08443689670520096b4b9bfdb.png\" width=\"1600\" height=\"962\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c78\/961\/f08\/c78961f08443689670520096b4b9bfdb.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c78\/961\/f08\/c78961f08443689670520096b4b9bfdb.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u043d\u043e\u00a0\u0440\u0430\u0434\u043e\u0441\u0442\u044c\u00a0\u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043c\u0435\u043d\u0438\u043b\u0430\u0441\u044c \u0440\u0430\u0437\u043e\u0447\u0430\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c: \u043a\u043d\u043e\u043f\u043a\u0430 \u00ab\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043c\u0435\u0442\u043a\u0443\u00bb \u043d\u0435\u00a0\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430.<\/p>\n<p>\u0422\u0443\u0442 \u0438 \u043d\u0430\u0447\u0430\u043b\u0441\u044f \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0432\u0430\u0439\u0431\u043a\u043e\u0434\u0438\u043d\u0433: \u043c\u043d\u043e\u0433\u043e \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043a\u00a0AI, \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0432\u0438\u0441\u0430\u043d\u0438\u0439 \u00ab\u0430\u0433\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0440\u0435\u0436\u0438\u043c\u0430\u00bb \u0438 \u0434\u0430\u0436\u0435 \u043f\u0430\u0440\u0430 \u043b\u043e\u0436\u043d\u044b\u0445 \u0434\u043e\u0433\u0430\u0434\u043e\u043a \u043e\u0442\u00a0\u0441\u0430\u043c\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438. \u0412\u00a0\u0447\u0430\u0442\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u0430\u043b\u0438, \u0447\u0442\u043e\u00a0\u0447\u0430\u0441\u0442\u044c \u0438\u0437\u00a0\u044d\u0442\u043e\u0433\u043e\u00a0\u2014 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u0431\u0430\u0433\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043a\u043e\u0440\u043e \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c34\/ca6\/fc9\/c34ca6fc9c17447b39f59cb4401c8586.png\" width=\"1122\" height=\"940\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c34\/ca6\/fc9\/c34ca6fc9c17447b39f59cb4401c8586.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c34\/ca6\/fc9\/c34ca6fc9c17447b39f59cb4401c8586.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<details class=\"spoiler\">\n<summary>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b<\/summary>\n<div class=\"spoiler__content\">\n<p><code>ui.ts<\/code><\/p>\n<pre><code class=\"typescript\">import { NoteService } from '.\/services\/NoteService.js'; import { Note } from '.\/models\/Note.js';  export class NotesApp {   private noteService: NoteService;   private noteTitleInput!: HTMLInputElement;   private noteContentInput!: HTMLTextAreaElement;   private addNoteButton!: HTMLButtonElement;   private notesList!: HTMLDivElement;    constructor() {     this.noteService = new NoteService();     this.initializeElements();     this.attachEventListeners();     this.renderNotes();   }    private initializeElements() {     this.noteTitleInput = document.getElementById('noteTitle') as HTMLInputElement;     this.noteContentInput = document.getElementById('noteContent') as HTMLTextAreaElement;     this.addNoteButton = document.getElementById('addNoteBtn') as HTMLButtonElement;     this.notesList = document.getElementById('notesList') as HTMLDivElement;   }    private attachEventListeners() {     this.addNoteButton.addEventListener('click', () =&gt; this.addNote());   }    private addNote() {     const title = this.noteTitleInput.value.trim();     const content = this.noteContentInput.value.trim();      if (!title || !content) {       alert('\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0432\u0441\u0435 \u043f\u043e\u043b\u044f');       return;     }          this.noteService.createNote({ title, content });     this.noteTitleInput.value = '';     this.noteContentInput.value = '';     this.renderNotes();   }    private deleteNote(id: string) {     this.noteService.deleteNote(id);     this.renderNotes();   }    private formatDate(date: Date): string {     return new Date(date).toLocaleString('ru-RU');   }    private renderNotes() {     const notes = this.noteService.getAllNotes();     this.notesList.innerHTML = '';          if (notes.length === 0) {       this.notesList.innerHTML = '&lt;p&gt;\u0417\u0430\u043c\u0435\u0442\u043e\u043a \u043d\u0435\u0442&lt;\/p&gt;';       return;     }          notes.forEach(note =&gt; {       const noteElement = document.createElement('div');       noteElement.className = 'note';       noteElement.innerHTML = `         &lt;h3&gt;${this.escapeHtml(note.title)}&lt;\/h3&gt;         &lt;p&gt;${this.escapeHtml(note.content)}&lt;\/p&gt;         &lt;small&gt;\u0421\u043e\u0437\u0434\u0430\u043d\u043e: ${this.formatDate(note.createdAt)} | \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043e: ${this.formatDate(note.updatedAt)}&lt;\/small&gt;         &lt;button class=\"delete-btn\" data-id=\"${note.id}\"&gt;\u0423\u0434\u0430\u043b\u0438\u0442\u044c&lt;\/button&gt;       `;       this.notesList.appendChild(noteElement);     });      \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043e\u043a \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f     document.querySelectorAll('.delete-btn').forEach(button =&gt; {       button.addEventListener('click', (e) =&gt; {         const id = (e.target as HTMLButtonElement).getAttribute('data-id');         if (id) this.deleteNote(id);       });     });   }    \/\/ \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f HTML, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c XSS-\u0430\u0442\u0430\u043a\u0438   private escapeHtml(text: string): string {     const map: Record&lt;string, string&gt; = {       '&amp;': '&amp;amp;',       '&lt;': '&amp;lt;',       '&gt;': '&amp;gt;',       '\"': '&amp;quot;',       \"'\": '&amp;#039;'     };          return text.replace(\/[&amp;&lt;&gt;\"']\/g, (m) =&gt; map[m]);   } }  \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 DOM document.addEventListener('DOMContentLoaded', () =&gt; {   new NotesApp(); });<\/code><\/pre>\n<p><code>index.html<\/code><\/p>\n<pre><code class=\"css\">&lt;!DOCTYPE html&gt; &lt;html lang=\"ru\"&gt; &lt;head&gt;   &lt;meta charset=\"UTF-8\"&gt;   &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;   &lt;title&gt;\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043c\u0435\u0442\u043e\u043a&lt;\/title&gt;   &lt;link rel=\"stylesheet\" href=\"styles.css\"&gt; &lt;\/head&gt; &lt;body&gt;   &lt;div class=\"container\"&gt;     &lt;h1&gt;\u041c\u043e\u0438 \u0437\u0430\u043c\u0435\u0442\u043a\u0438&lt;\/h1&gt;          &lt;div class=\"form-container\"&gt;       &lt;h2&gt;\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043c\u0435\u0442\u043a\u0443&lt;\/h2&gt;       &lt;div class=\"form-group\"&gt;         &lt;label for=\"noteTitle\"&gt;\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a:&lt;\/label&gt;         &lt;input type=\"text\" id=\"noteTitle\" placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a\"&gt;       &lt;\/div&gt;       &lt;div class=\"form-group\"&gt;         &lt;label for=\"noteContent\"&gt;\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435:&lt;\/label&gt;         &lt;textarea id=\"noteContent\" placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438\"&gt;&lt;\/textarea&gt;       &lt;\/div&gt;       &lt;button id=\"addNoteBtn\"&gt;\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043c\u0435\u0442\u043a\u0443&lt;\/button&gt;     &lt;\/div&gt;          &lt;div class=\"notes-container\"&gt;       &lt;h2&gt;\u0421\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043c\u0435\u0442\u043e\u043a&lt;\/h2&gt;       &lt;div id=\"notesList\"&gt;&lt;\/div&gt;     &lt;\/div&gt;   &lt;\/div&gt;      &lt;script type=\"module\" src=\"dist\/ui.js\"&gt;&lt;\/script&gt; &lt;\/body&gt; &lt;\/html&gt;<\/code><\/pre>\n<p><code>styles.css<\/code><\/p>\n<pre><code class=\"css\">body {   font-family: Arial, sans-serif;   line-height: 1.6;   margin: 0;   padding: 20px;   background-color: #f5f5f5;   color: #333; }  .container {   max-width: 800px;   margin: 0 auto;   background-color: #fff;   padding: 20px;   border-radius: 8px;   box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); }  h1, h2 {   color: #2c3e50; }  .form-container {   margin-bottom: 30px;   padding: 15px;   background-color: #f9f9f9;   border-radius: 5px; }  .form-group {   margin-bottom: 15px; }  label {   display: block;   margin-bottom: 5px;   font-weight: bold; }  input[type=\"text\"], textarea {   width: 100%;   padding: 8px;   border: 1px solid #ddd;   border-radius: 4px;   font-size: 14px; }  textarea {   height: 100px; }  button {   background-color: #3498db;   color: white;   border: none;   padding: 10px 15px;   border-radius: 4px;   cursor: pointer;   font-size: 14px; }  button:hover {   background-color: #2980b9; }  .note-item {   border: 1px solid #eee;   padding: 15px;   margin-bottom: 15px;   border-radius: 5px;   position: relative; }  .note-title {   font-size: 18px;   font-weight: bold;   margin-bottom: 10px; }  .note-content {   margin-bottom: 15px; }  .note-date {   font-size: 12px;   color: #777; }  .delete-btn {   position: absolute;   top: 10px;   right: 10px;   background-color: #e74c3c; }  .delete-btn:hover {   background-color: #c0392b; }<\/code><\/pre>\n<\/div>\n<\/details>\n<h3>\u0418\u0441\u0442\u0438\u043d\u043d\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430<\/h3>\n<p>\u0412\u00a0\u0438\u0442\u043e\u0433\u0435 \u043e\u0448\u0438\u0431\u043a\u0430 \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043d\u0435\u00a0\u0432\u00a0\u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430\u00a0\u0432\u00a0\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<p>\u0411\u044b\u043b\u043e:<\/p>\n<pre><code class=\"json\">{ \u00a0\u00a0\"compilerOptions\": { \u00a0\u00a0\u00a0\u00a0\"target\": \"ES2020\", \u00a0\u00a0\u00a0\u00a0\"module\": \"commonjs\", \u00a0\u00a0\u00a0\u00a0\"outDir\": \".\/dist\", \u00a0\u00a0\u00a0\u00a0\"rootDir\": \".\/src\", \u00a0\u00a0\u00a0\u00a0\"strict\": true, \u00a0\u00a0\u00a0\u00a0\"esModuleInterop\": true, \u00a0\u00a0\u00a0\u00a0\"skipLibCheck\": true, \u00a0\u00a0\u00a0\u00a0\"forceConsistentCasingInFileNames\": true \u00a0\u00a0} }<\/code><\/pre>\n<p>\u0421\u0442\u0430\u043b\u043e:<\/p>\n<pre><code class=\"json\">{ \u00a0\u00a0\"compilerOptions\": { \u00a0\u00a0\u00a0\u00a0\"target\": \"ES2020\", \u00a0\u00a0\u00a0\u00a0\"module\": \"ES2020\", \u00a0\u00a0\u00a0\u00a0\"outDir\": \".\/dist\", \u00a0\u00a0\u00a0\u00a0\"rootDir\": \".\/src\", \u00a0\u00a0\u00a0\u00a0\"strict\": true, \u00a0\u00a0\u00a0\u00a0\"esModuleInterop\": true, \u00a0\u00a0\u00a0\u00a0\"skipLibCheck\": true, \u00a0\u00a0\u00a0\u00a0\"forceConsistentCasingInFileNames\": true \u00a0\u00a0} }<\/code><\/pre>\n<p>\u041a\u0430\u043a\u00a0\u043e\u0431\u044a\u044f\u0441\u043d\u0438\u043b AI, CommonJS \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u00a0Node.js \u0438 \u0433\u0440\u0443\u0437\u0438\u0442 \u043c\u043e\u0434\u0443\u043b\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u0447\u0435\u0440\u0435\u0437 require, \u0430\u00a0ES2020\u00a0\u2014 \u044d\u0442\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0434\u043b\u044f\u00a0\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0430\u044f top\u2011level await. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0439 \u043f\u0440\u0430\u0432\u043a\u0438 \u0432\u0441\u0451 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1f\/767\/2b5\/c1f7672b56174790f68a366a07b1db34.png\" width=\"1600\" height=\"962\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c1f\/767\/2b5\/c1f7672b56174790f68a366a07b1db34.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1f\/767\/2b5\/c1f7672b56174790f68a366a07b1db34.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043d\u043e\u043f\u043a\u0438 \u00ab\u0423\u0434\u0430\u043b\u0438\u0442\u044c\u00bb \u0438 \u0435\u0451 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u043e\u0442\u0440\u044f\u0441\u0430\u044e\u0449\u0435\u0435 \ud83d\ude42 \u041d\u043e\u00a0\u0443\u0436 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u044f \u0435\u0451 \u043d\u0435\u00a0\u0431\u0443\u0434\u0443. \u041f\u043e\u00a0\u043a\u0440\u0430\u0439\u043d\u0435 \u043c\u0435\u0440\u0435 \u043d\u0435\u00a0\u0432\u00a0\u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<h3>\u0418\u0442\u043e\u0433\u0438 \u0432\u0430\u0439\u0431\u043a\u043e\u0434\u0438\u043d\u0433\u0430<\/h3>\n<ol>\n<li>\n<p>\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f\u00a0\u043f\u043e\u043c\u043e\u0449\u0438 \u0432\u00a0\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0435\u0441\u0442\u044c \u0443\u0436\u0435 \u0441\u0435\u0439\u0447\u0430\u0441<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0434\u0430 \u0441\u043a\u043e\u0440\u0435\u0435 \u0440\u0430\u0434\u0443\u0435\u0442, \u0447\u0435\u043c \u0440\u0430\u0437\u043e\u0447\u0430\u0440\u043e\u0432\u044b\u0432\u0430\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u041d\u043e\u00a0\u0432\u043e\u0442 \u043f\u043e\u0438\u0441\u043a \u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043e\u043a \u00ab\u043d\u0435 \u0432\u00a0\u043a\u043e\u0434\u0435, \u0430\u00a0\u0440\u044f\u0434\u043e\u043c \u0441\u00a0\u043d\u0438\u043c\u00bb \u0443\u00a0AI \u043f\u043e\u043a\u0430 \u0447\u0442\u043e\u00a0\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043e\u0442\u0432\u0430\u043b \u0431\u0430\u0448\u043a\u0438<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u00a0AI\u2011\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0432\u00a0\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445, \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \ud83d\ude42<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/944734\/\"> https:\/\/habr.com\/ru\/articles\/944734\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041a\u0430\u043a \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438, \u044f \u0434\u0430\u0432\u043d\u043e \u043c\u0435\u0447\u0442\u0430\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 pet\u2011\u043f\u0440\u043e\u0435\u043a\u0442\u00a0\u2014 \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0447\u0443\u0432\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u044f \u00ab\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u043c\u00bb \u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0442\u044c \u0431\u043e\u044f\u0442\u044c\u0441\u044f \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439. \u0412\u00a0\u0438\u0442\u043e\u0433\u0435 \u0440\u0435\u0448\u0438\u043b\u0441\u044f: \u0431\u0443\u0434\u0443 \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0435\u0431\u2011\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f\u00a0\u043b\u0438\u0447\u043d\u044b\u0445 \u0437\u0430\u043c\u0435\u0442\u043e\u043a.<\/p>\n<p>\u041d\u0430\u00a0\u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u044f \u043d\u0435\u00a0\u0441\u043e\u0432\u0441\u0435\u043c \u043d\u043e\u0432\u0438\u0447\u043e\u043a. \u0420\u0430\u043d\u044c\u0448\u0435 \u0443\u00a0\u043c\u0435\u043d\u044f \u0443\u0436\u0435\u00a0\u0431\u044b\u043b\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u043e\u0441\u0432\u043e\u0438\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u044f\u0437\u044b\u043a\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043d\u043e\u00a0\u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u0430\u0440\u044b \u0441\u0442\u0440\u043e\u0447\u0435\u043a \u043a\u043e\u0434\u0430 \u0434\u0435\u043b\u043e \u0440\u0435\u0434\u043a\u043e \u0437\u0430\u0445\u043e\u0434\u0438\u043b\u043e. \u0423\u043c\u0435\u043d\u0438\u0435 \u00ab\u0433\u0443\u0433\u043b\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u00bb \u0438 \u0438\u0441\u043a\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442\u044b \u043d\u0430\u00a0StackOverflow \u043f\u043e\u043a\u0430 \u0434\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u0442\u044f\u0436\u0435\u043b\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0432\u0435\u0441\u0442\u0438 \u0447\u0442\u043e\u2011\u0442\u043e \u0434\u043e\u00a0\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u00a0\u0431\u044b\u043b\u043e \u0441\u043b\u043e\u0436\u043d\u043e.<\/p>\n<p>\u0412\u00a0\u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0439\u0442\u0438 \u043f\u043e\u00a0\u0442\u0440\u0435\u043d\u0434\u0430\u043c \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432\u00a0\u043f\u0440\u043e\u0446\u0435\u0441\u0441 AI. \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0425\u0430\u0431\u0440\u0443, \u0447\u0442\u043e\u00a0\u0432\u00a0\u043d\u0443\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u0434\u043a\u0438\u043d\u0443\u043b <a href=\"https:\/\/habr.com\/ru\/companies\/koda\/articles\/936906\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u044e \u043f\u0440\u043e\u00a0Koda<\/a>. \u0421\u00a0Koda \u0438 \u043d\u0430\u0447\u0430\u043b\u0441\u044f \u043c\u043e\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442. \u0410\u00a0\u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0445\u043e\u0447\u0443 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0440\u0435\u0441\u043f\u0435\u043a\u0442 \u0437\u0430\u00a0\u0442\u043e, \u0447\u0442\u043e\u00a0\u0432\u0441\u0451 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e.<\/p>\n<h2>\u0427\u0442\u043e \u044f \u0445\u043e\u0442\u0435\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c<\/h2>\n<p>\u0418\u0434\u0435\u044f\u00a0\u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0439: \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f\u00a0\u0437\u0430\u043c\u0435\u0442\u043e\u043a, \u0433\u0434\u0435 \u0442\u0435\u043a\u0441\u0442 \u043c\u043e\u0436\u043d\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043d\u0430\u00a0UI. \u0414\u043b\u044f\u00a0\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u044b\u0431\u0440\u0430\u043b TypeScript: \u0441\u00a0\u0435\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c \u044f \u0443\u0436\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u043a\u043e\u043c.<\/p>\n<h3>\u041a\u0430\u043a AI \u043f\u043e\u043c\u043e\u0433\u0430\u043b<\/h3>\n<p>\u041e\u043f\u044b\u0442 \u0441\u00a0Koda \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c, \u0445\u043e\u0442\u044f \u0438 \u043d\u0435\u00a0\u0431\u0435\u0437\u00a0\u043d\u044e\u0430\u043d\u0441\u043e\u0432.<\/p>\n<h4>\u041f\u0435\u0440\u0432\u044b\u0435 \u0448\u0430\u0433\u0438<\/h4>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044f \u0441\u043f\u0440\u043e\u0441\u0438\u043b \u0443\u00a0AI, \u043a\u0430\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f\u00a0\u0441\u0442\u0430\u0440\u0442\u0430. \u041e\u043d \u0441\u0440\u0430\u0437\u0443 \u0432\u044b\u0434\u0430\u043b \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439, \u0438 \u043f\u0440\u0438\u044f\u0442\u043d\u043e \u0443\u0434\u0438\u0432\u0438\u043b\u043e, \u0447\u0442\u043e\u00a0\u0432\u0441\u0451 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e\u00a0\u0431\u044b\u043b\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u044f\u043c\u043e \u0432\u00a0\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435, \u043d\u0435\u00a0\u043a\u043e\u043f\u0430\u044f\u0441\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u043e\u0442\u043e\u043c \u044f \u0443\u0442\u043e\u0447\u043d\u0438\u043b: \u00ab\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?\u00bb\u00a0\u2014 \u0438 Koda \u043d\u0430\u0433\u0435\u043d\u0435\u0440\u0438\u043b \u043c\u043e\u0434\u0435\u043b\u044c, \u0441\u0435\u0440\u0432\u0438\u0441 \u0438 \u0444\u0430\u0439\u043b \u0434\u043b\u044f\u00a0\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438. \u0418, \u043a\u00a0\u043c\u043e\u0435\u043c\u0443 \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u044e, \u0432\u0441\u0451 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0441\u00a0\u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0440\u0430\u0437\u0430, \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a, \u043a\u0430\u043a\u00a0\u044f \u043e\u0436\u0438\u0434\u0430\u043b.<\/p>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<details class=\"spoiler\">\n<summary>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b<\/summary>\n<div class=\"spoiler__content\">\n<p><code>tsconfig.json<\/code><\/p>\n<pre><code class=\"json\">{   \"compilerOptions\": {     \"target\": \"ES2020\",     \"module\": \"commonjs\",     \"outDir\": \".\/dist\",     \"rootDir\": \".\/src\",     \"strict\": true,     \"esModuleInterop\": true,     \"skipLibCheck\": true,     \"forceConsistentCasingInFileNames\": true   } }<\/code><\/pre>\n<p><code>Note.ts<\/code><\/p>\n<pre><code class=\"typescript\">export interface Note {   id: string;   title: string;   content: string;   createdAt: Date;   updatedAt: Date; }<\/code><\/pre>\n<p><code>NoteService.ts<\/code><\/p>\n<pre><code class=\"typescript\">import { Note } from '..\/models\/Note';  export class NoteService {   private notes: Note[] = [];    getAllNotes(): Note[] {     return this.notes;   }    getNoteById(id: string): Note | undefined {     return this.notes.find(note =&gt; note.id === id);   }    createNote(note: Omit&lt;Note, 'id' | 'createdAt' | 'updatedAt'&gt;): Note {     const newNote: Note = {       ...note,       id: Date.now().toString(),       createdAt: new Date(),       updatedAt: new Date()     };          this.notes.push(newNote);     return newNote;   }    updateNote(id: string, updatedNote: Partial&lt;Omit&lt;Note, 'id' | 'createdAt'&gt;&gt;): Note | null {     const noteIndex = this.notes.findIndex(note =&gt; note.id === id);          if (noteIndex === -1) {       return null;     }          this.notes[noteIndex] = {       ...this.notes[noteIndex],       ...updatedNote,       updatedAt: new Date()     };          return this.notes[noteIndex];   }    deleteNote(id: string): boolean {     const initialLength = this.notes.length;     this.notes = this.notes.filter(note =&gt; note.id !== id);     return this.notes.length !== initialLength;   } }<\/code><\/pre>\n<p><code>index.ts<\/code><\/p>\n<pre><code class=\"typescript\">import { NoteService } from '.\/services\/NoteService';  const noteService = new NoteService();  \/\/ \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0437\u0430\u043c\u0435\u0442\u043a\u0430\u043c\u0438 function main() {   \/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438   const newNote = noteService.createNote({     title: '\u041f\u0435\u0440\u0432\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430',     content: '\u042d\u0442\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043c\u043e\u0435\u0439 \u043f\u0435\u0440\u0432\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438'   });   console.log('\u0421\u043e\u0437\u0434\u0430\u043d\u0430 \u0437\u0430\u043c\u0435\u0442\u043a\u0430:', newNote);    \/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0435\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438   const secondNote = noteService.createNote({     title: '\u0412\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430',     content: '\u0422\u0435\u043a\u0441\u0442 \u0432\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438'   });    \/\/ \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0437\u0430\u043c\u0435\u0442\u043e\u043a   console.log('\u0412\u0441\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438:', noteService.getAllNotes());    \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438   const updatedNote = noteService.updateNote(newNote.id, {     content: '\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0435\u0440\u0432\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438'   });   console.log('\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430:', updatedNote);    \/\/ \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438   const isDeleted = noteService.deleteNote(secondNote.id);   console.log('\u0412\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0430:', isDeleted);   console.log('\u041e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0438:', noteService.getAllNotes()); }  main();<\/code><\/pre>\n<\/div>\n<\/details>\n<h3>\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0441 UI<\/h3>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c\u00a0\u0431\u044b\u043b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u042f \u0441\u043d\u043e\u0432\u0430 \u043e\u0431\u0440\u0430\u0442\u0438\u043b\u0441\u044f \u043a\u00a0AI\u00a0\u2014 \u0438 \u0432\u043e\u0442 \u0442\u0443\u0442 \u043d\u0430\u0447\u0430\u043b\u0438\u0441\u044c \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. <\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u0435\u0440\u0432\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043a\u043e\u0434\u0430 \u043d\u0435\u00a0\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0430\u0440\u044b \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439 UI \u0432\u0441\u0451\u00a0\u0436\u0435 \u0437\u0430\u0432\u0451\u043b\u0441\u044f&#8230;<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u043d\u043e\u00a0\u0440\u0430\u0434\u043e\u0441\u0442\u044c\u00a0\u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043c\u0435\u043d\u0438\u043b\u0430\u0441\u044c \u0440\u0430\u0437\u043e\u0447\u0430\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c: \u043a\u043d\u043e\u043f\u043a\u0430 \u00ab\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043c\u0435\u0442\u043a\u0443\u00bb \u043d\u0435\u00a0\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430.<\/p>\n<p>\u0422\u0443\u0442 \u0438 \u043d\u0430\u0447\u0430\u043b\u0441\u044f \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0432\u0430\u0439\u0431\u043a\u043e\u0434\u0438\u043d\u0433: \u043c\u043d\u043e\u0433\u043e \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043a\u00a0AI, \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0432\u0438\u0441\u0430\u043d\u0438\u0439 \u00ab\u0430\u0433\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0440\u0435\u0436\u0438\u043c\u0430\u00bb \u0438 \u0434\u0430\u0436\u0435 \u043f\u0430\u0440\u0430 \u043b\u043e\u0436\u043d\u044b\u0445 \u0434\u043e\u0433\u0430\u0434\u043e\u043a \u043e\u0442\u00a0\u0441\u0430\u043c\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438. \u0412\u00a0\u0447\u0430\u0442\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u0430\u043b\u0438, \u0447\u0442\u043e\u00a0\u0447\u0430\u0441\u0442\u044c \u0438\u0437\u00a0\u044d\u0442\u043e\u0433\u043e\u00a0\u2014 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u0431\u0430\u0433\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043a\u043e\u0440\u043e \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c.<\/p>\n<figure class=\"full-width\"><\/figure>\n<details class=\"spoiler\">\n<summary>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b<\/summary>\n<div class=\"spoiler__content\">\n<p><code>ui.ts<\/code><\/p>\n<pre><code class=\"typescript\">import { NoteService } from '.\/services\/NoteService.js'; import { Note } from '.\/models\/Note.js';  export class NotesApp {   private noteService: NoteService;   private noteTitleInput!: HTMLInputElement;   private noteContentInput!: HTMLTextAreaElement;   private addNoteButton!: HTMLButtonElement;   private notesList!: HTMLDivElement;    constructor() {     this.noteService = new NoteService();     this.initializeElements();     this.attachEventListeners();     this.renderNotes();   }    private initializeElements() {     this.noteTitleInput = document.getElementById('noteTitle') as HTMLInputElement;     this.noteContentInput = document.getElementById('noteContent') as HTMLTextAreaElement;     this.addNoteButton = document.getElementById('addNoteBtn') as HTMLButtonElement;     this.notesList = document.getElementById('notesList') as HTMLDivElement;   }    private attachEventListeners() {     this.addNoteButton.addEventListener('click', () =&gt; this.addNote());   }    private addNote() {     const title = this.noteTitleInput.value.trim();     const content = this.noteContentInput.value.trim();      if (!title || !content) {       alert('\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0432\u0441\u0435 \u043f\u043e\u043b\u044f');       return;     }          this.noteService.createNote({ title, content });     this.noteTitleInput.value = '';     this.noteContentInput.value = '';     this.renderNotes();   }    private deleteNote(id: string) {     this.noteService.deleteNote(id);     this.renderNotes();   }    private formatDate(date: Date): string {     return new Date(date).toLocaleString('ru-RU');   }    private renderNotes() {     const notes = this.noteService.getAllNotes();     this.notesList.innerHTML = '';          if (notes.length === 0) {       this.notesList.innerHTML = '&lt;p&gt;\u0417\u0430\u043c\u0435\u0442\u043e\u043a \u043d\u0435\u0442&lt;\/p&gt;';       return;     }          notes.forEach(note =&gt; {       const noteElement = document.createElement('div');       noteElement.className = 'note';       noteElement.innerHTML = `         &lt;h3&gt;${this.escapeHtml(note.title)}&lt;\/h3&gt;         &lt;p&gt;${this.escapeHtml(note.content)}&lt;\/p&gt;         &lt;small&gt;\u0421\u043e\u0437\u0434\u0430\u043d\u043e: ${this.formatDate(note.createdAt)} | \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043e: ${this.formatDate(note.updatedAt)}&lt;\/small&gt;         &lt;button class=\"delete-btn\" data-id=\"${note.id}\"&gt;\u0423\u0434\u0430\u043b\u0438\u0442\u044c&lt;\/button&gt;       `;       this.notesList.appendChild(noteElement);     });      \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043e\u043a \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f     document.querySelectorAll('.delete-btn').forEach(button =&gt; {       button.addEventListener('click', (e) =&gt; {         const id = (e.target as HTMLButtonElement).getAttribute('data-id');         if (id) this.deleteNote(id);       });     });   }    \/\/ \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f HTML, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c XSS-\u0430\u0442\u0430\u043a\u0438   private escapeHtml(text: string): string {     const map: Record&lt;string, string&gt; = {       '&amp;': '&amp;amp;',       '&lt;': '&amp;lt;',       '&gt;': '&amp;gt;',       '\"': '&amp;quot;',       \"'\": '&amp;#039;'     };          return text.replace(\/[&amp;&lt;&gt;\"']\/g, (m) =&gt; map[m]);   } }  \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 DOM document.addEventListener('DOMContentLoaded', () =&gt; {   new NotesApp(); });<\/code><\/pre>\n<p><code>index.html<\/code><\/p>\n<pre><code class=\"css\">&lt;!DOCTYPE html&gt; &lt;html lang=\"ru\"&gt; &lt;head&gt;   &lt;meta charset=\"UTF-8\"&gt;   &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;   &lt;title&gt;\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043c\u0435\u0442\u043e\u043a&lt;\/title&gt;   &lt;link rel=\"stylesheet\" href=\"styles.css\"&gt; &lt;\/head&gt; &lt;body&gt;   &lt;div class=\"container\"&gt;     &lt;h1&gt;\u041c\u043e\u0438 \u0437\u0430\u043c\u0435\u0442\u043a\u0438&lt;\/h1&gt;          &lt;div class=\"form-container\"&gt;       &lt;h2&gt;\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043c\u0435\u0442\u043a\u0443&lt;\/h2&gt;       &lt;div class=\"form-group\"&gt;         &lt;label for=\"noteTitle\"&gt;\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a:&lt;\/label&gt;         &lt;input type=\"text\" id=\"noteTitle\" placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a\"&gt;       &lt;\/div&gt;       &lt;div class=\"form-group\"&gt;         &lt;label for=\"noteContent\"&gt;\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435:&lt;\/label&gt;         &lt;textarea id=\"noteContent\" placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438\"&gt;&lt;\/textarea&gt;       &lt;\/div&gt;       &lt;button id=\"addNoteBtn\"&gt;\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043c\u0435\u0442\u043a\u0443&lt;\/button&gt;     &lt;\/div&gt;          &lt;div class=\"notes-container\"&gt;       &lt;h2&gt;\u0421\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043c\u0435\u0442\u043e\u043a&lt;\/h2&gt;       &lt;div id=\"notesList\"&gt;&lt;\/div&gt;     &lt;\/div&gt;   &lt;\/div&gt;      &lt;script type=\"module\" src=\"dist\/ui.js\"&gt;&lt;\/script&gt; &lt;\/body&gt; &lt;\/html&gt;<\/code><\/pre>\n<p><code>styles.css<\/code><\/p>\n<pre><code class=\"css\">body {   font-family: Arial, sans-serif;   line-height: 1.6;   margin: 0;   padding: 20px;   background-color: #f5f5f5;   color: #333; }  .container {   max-width: 800px;   margin: 0 auto;   background-color: #fff;   padding: 20px;   border-radius: 8px;   box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); }  h1, h2 {   color: #2c3e50; }  .form-container {   margin-bottom: 30px;   padding: 15px;   background-color: #f9f9f9;   border-radius: 5px; }  .form-group {   margin-bottom: 15px; }  label {   display: block;   margin-bottom: 5px;   font-weight: bold; }  input[type=\"text\"], textarea {   width: 100%;   padding: 8px;   border: 1px solid #ddd;   border-radius: 4px;   font-size: 14px; }  textarea {   height: 100px; }  button {   background-color: #3498db;   color: white;   border: none;   padding: 10px 15px;   border-radius: 4px;   cursor: pointer;   font-size: 14px; }  button:hover {   background-color: #2980b9; }  .note-item {   border: 1px solid #eee;   padding: 15px;   margin-bottom: 15px;   border-radius: 5px;   position: relative; }  .note-title {   font-size: 18px;   font-weight: bold;   margin-bottom: 10px; }  .note-content {   margin-bottom: 15px; }  .note-date {   font-size: 12px;   color: #777; }  .delete-btn {   position: absolute;   top: 10px;   right: 10px;   background-color: #e74c3c; }  .delete-btn:hover {   background-color: #c0392b; }<\/code><\/pre>\n<\/div>\n<\/details>\n<h3>\u0418\u0441\u0442\u0438\u043d\u043d\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430<\/h3>\n<p>\u0412\u00a0\u0438\u0442\u043e\u0433\u0435 \u043e\u0448\u0438\u0431\u043a\u0430 \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043d\u0435\u00a0\u0432\u00a0\u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430\u00a0\u0432\u00a0\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<p>\u0411\u044b\u043b\u043e:<\/p>\n<pre><code class=\"json\">{ \u00a0\u00a0\"compilerOptions\": { \u00a0\u00a0\u00a0\u00a0\"target\": \"ES2020\", <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-474179","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/474179","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=474179"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/474179\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=474179"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=474179"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=474179"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}