Lompat ke konten
dokumentasi.id
Commit 3ce63fd
v3
Star5,3 rb

Kamu membaca versi lama. Halaman ini hanya bisa dibaca.

7

Helper Berkas dan Filter Blacklist

src/utils/index.ts adalah modul kecil berisi empat export: resolve, getLanguage, getFiles, dan isBlacklisted. Modul itu juga mengimpor src/data/blacklist.json di baris ketiga, sehingga daftar kata terlarang ikut termuat setiap kali modul ini dipakai. src/utils/index.ts:1-3 Pemakainya hanya dua skrip: src/build.ts mengimpor keempat helper, sedangkan src/check.ts hanya mengambil getFiles dan isBlacklisted. src/build.ts:5 src/check.ts:4

Empat helper itu berbeda tugas: resolve dan getLanguage murni menghitung string, getFiles satu-satunya yang membaca direktori data/, dan isBlacklisted satu-satunya yang menyentuh daftar kata terlarang.

ExportSignatureHasilPemanggil
resolve(...fileName: string[]) => stringpath absolut di bawah data/src/build.ts src/utils/index.ts:5-7
getLanguage(filePath: string) => stringbasename tanpa ekstensisrc/build.ts src/utils/index.ts:9-11
getFiles(dirPath = resolve(), fileList = []) => Promise<string[]>daftar path berkas .jsonsrc/build.ts, src/check.ts src/utils/index.ts:13-33
isBlacklisted(html: string) => booleantrue bila body memuat kata terlarangsrc/build.ts, src/check.ts src/utils/index.ts:35-37

Peta ketergantungan helper

graph TD
  Build["src/build.ts"]
  Check["src/check.ts"]
  Resolve["resolve()"]
  GetFiles["getFiles()"]
  GetLanguage["getLanguage()"]
  IsBlacklisted["isBlacklisted()"]
  Blacklist["src/data/blacklist.json"]
  Data["data/**/*.json"]

  Build --> GetFiles
  Build --> GetLanguage
  Build --> IsBlacklisted
  Build --> Resolve
  Check --> GetFiles
  Check --> IsBlacklisted
  GetFiles -->|"dirPath default"| Resolve
  GetFiles -->|"rekursi direktori"| GetFiles
  GetFiles -->|"readdir + stat"| Data
  Resolve -->|"path.resolve"| Data
  IsBlacklisted -->|"blacklist.some"| Blacklist

  style Data fill:#336791,color:#fff
  style Blacklist fill:#336791,color:#fff
  style GetFiles fill:#8b5cf6,color:#fff
  style GetLanguage fill:#8b5cf6,color:#fff
  style Resolve fill:#8b5cf6,color:#fff
  style IsBlacklisted fill:#f59e0b,color:#000
  style Build fill:#2d7d46,color:#fff
  style Check fill:#2d7d46,color:#fff
%% fig: Ketergantungan helper ke data dan blacklist
%% desc: Dua skrip pemanggil memakai empat helper di src/utils/index.ts; hanya getFiles yang membaca direktori data dan hanya isBlacklisted yang membaca blacklist.json.
Fig. 1: Ketergantungan helper ke data dan blacklistDua skrip pemanggil memakai empat helper di src/utils/index.ts; hanya getFiles yang membaca direktori data dan hanya isBlacklisted yang membaca blacklist.json.

resolve dan letak direktori data/

resolve menggabungkan import.meta.dir milik modul (src/utils) dengan '..', '..', 'data', lalu menyambung sisa argumen. src/utils/index.ts:5-7 Karena itu resolve() tanpa argumen menunjuk ke direktori data/ di akar repository, dan resolve('books', 'id.json') menunjuk ke berkas kategori di dalamnya.

src/build.ts memakai helper yang sama untuk tujuan berbeda. Ia menyusun nama berkas dari ['README', language === 'id' ? null : language, 'md'] yang nilai null-nya dibuang oleh filter, lalu meneruskan import.meta.dir sebagai argumen pertama ke resolve. src/build.ts:87-91 Karena path.resolve memulai ulang perhitungan begitu menemukan path absolut, hasil akhirnya berada di akar repository (README.md atau README.en.md), bukan di dalam data/. src/build.ts:5

getFiles menelusuri data/ secara rekursif

getFiles menerima dirPath (default resolve()) dan fileList (default []), membaca isi direktori dengan fsPromises.readdir, lalu memeriksa setiap entri memakai fsPromises.stat. src/utils/index.ts:13-33 Entri yang berupa berkas dan berakhiran .json didorong ke fileList; entri yang berupa direktori ditelusuri dengan panggilan getFiles rekursif yang membawa fileList yang sama. src/utils/index.ts:24-28

Pengisian fileList terjadi di dalam callback Promise.all, sehingga urutannya mengikuti selesainya masing-masing stat, bukan urutan readdir. src/utils/index.ts:19-30 Kedua skrip pemanggil cukup menulis await getFiles() tanpa argumen dan menerima seluruh berkas JSON kategori. src/build.ts:13 src/check.ts:9

getLanguage sebagai kunci pengelompokan

getLanguage memanggil path.basename(filePath, path.extname(filePath)), jadi ekstensi dibuang dan .../books/id.json menjadi id. src/utils/index.ts:9-11 Hasilnya dipakai src/build.ts sebagai kunci peta data per bahasa. src/build.ts:14 src/build.ts:79-83 Pemetaan itu yang kemudian menentukan pasangan kategori dan berkas README; pembahasannya ada di Dukungan Multi-Bahasa dan Pipeline Build Markdown.

isBlacklisted dan isi blacklist

isBlacklisted mengembalikan blacklist.some((item) => html.includes(item)). src/utils/index.ts:35-37 Artinya pencocokan berupa substring peka huruf besar-kecil atas seluruh body halaman, bukan pencocokan kata utuh. src/data/blacklist.json berisi tiga entri: "nfsw", "porn", dan "hentai". src/data/blacklist.json:1

⚠️ Entri pertama ditulis nfsw, bukan nsfw. Karena pencocokan memakai includes, ejaan itu hanya cocok bila body memuat harfiah nfsw; pesan galat di check.ts sendiri tetap menyebut "NSFW". src/data/blacklist.json:1 src/check.ts:52-55

⚠️ Karena pencocokan substring, satu kata terlarang yang muncul di sembarang tempat dalam body sudah cukup untuk menandai halaman. Kata porn di dalam kata lain yang lebih panjang juga terhitung. src/utils/index.ts:35-37

Dua pemanggil, dua akibat berbeda

src/check.ts memeriksa setiap URL yang belum ada di array crawled. Bila isBlacklisted(body) bernilai true, skrip mencetak Sorry, the NSFW API is not allowed here :) lalu memanggil process.exit(1), sehingga seluruh pemeriksaan berhenti pada URL pertama yang terdeteksi. src/check.ts:52-55

src/build.ts memakai fungsi yang sama dengan akibat yang lebih ringan: URL hanya didorong ke array crawledx, dan API yang URL-nya ada di crawledx dibuang dari json.apis lewat splice. src/build.ts:52-54 src/build.ts:64-73

graph LR
  Body["response.text()"]
  IsB["isBlacklisted(body)"]
  Exit["process.exit(1)"]
  Crawledx["crawledx.push(url)"]
  Splice["json.apis.splice(i, 1)"]
  Keep["status = response.status !== 404"]

  Body --> IsB
  IsB -->|"true di check.ts"| Exit
  IsB -->|"true di build.ts"| Crawledx
  Crawledx --> Splice
  IsB -->|"false"| Keep

  style Body fill:#8b5cf6,color:#fff
  style IsB fill:#f59e0b,color:#000
  style Exit fill:#dc2626,color:#fff
  style Splice fill:#dc2626,color:#fff
  style Crawledx fill:#f59e0b,color:#000
  style Keep fill:#2d7d46,color:#fff
%% fig: Akibat isBlacklisted di dua pemanggil
%% desc: Body halaman yang sama dinilai isBlacklisted; check.ts langsung menghentikan proses, sedangkan build.ts menandai URL untuk dibuang dari daftar API.
Fig. 2: Akibat isBlacklisted di dua pemanggilBody halaman yang sama dinilai isBlacklisted; check.ts langsung menghentikan proses, sedangkan build.ts menandai URL untuk dibuang dari daftar API.
Berkas pemanggilBarisKapan berjalanAkibat bila isBlacklisted bernilai true
src/build.ts52-54hanya di dalam cabang --rewriteURL masuk crawledx, lalu API dibuang dari json.apis src/build.ts:64-73
src/check.ts52-55setiap URL yang belum ada di crawledcetak Sorry, the NSFW API is not allowed here :), lalu process.exit(1) src/check.ts:52-55

⚠️ Pemeriksaan di build.ts hanya berjalan ketika argumen --rewrite diberikan. Tanpa flag itu isBlacklisted tidak pernah dipanggil saat build, sehingga body halaman tidak diperiksa sama sekali. src/build.ts:20 Rincian cabang tersebut ada di Mode Rewrite dan Status API.

Jalur ke CI

Pemeriksaan check.ts dijalankan sebagai skrip check yang memanggil bun run src/check.ts. package.json:39-40 Workflow NSFW Check menjalankan bun check pada pull request yang dibuka atau dibuka ulang, sehingga process.exit(1) di isBlacklisted itulah yang menggagalkan job. .github/workflows/nsfw-check.yml:25-27 Pemicu workflow dan pemeriksaan data lain dibahas di Otomasi GitHub Actions dan Validator Data lewat check.ts.