電子冒険:エピソード23:ファイルに関する表示情報


ファイルマネージャを改良しましょう.私たちが表示したい情報がたくさんあります.ちょっと始めましょう
  • ファイルサイズ
  • 最終更新時刻
  • シンボリックリンクに関しては、どこに
  • プリロード。js


    この小さな変更は既にノードの情報を得るためにコードを再構築する必要があります.
    let { readdir } = require("fs/promises")
    
    let directoryContents = async (path) => {
      let results = await readdir(path, {withFileTypes: true})
      return await Promise.all(results.map(entry => fileInfo(path, entry)))
    }
    
    ノードが実際にどのように実行しているかよくわかりません.ほとんどすべての他の言語が一度に1つのシステムコールを実行するので、我々はできるreturn results.map(entry => await fileInfo(path, entry)) , しかし、これは実際に並列に実行される可能性のあるオフの上で私は最初に大きなリストを構築しているし、全体を待っている.
    今、次の部分は少しぎこちない取得します.いくつかの線の機能を持つpreload.js いいですが、これは大きくなっています.フロントエンドテストの複雑さなしでテストすることができるいくつかのバックエンドコードに、我々はむしろそれを置きます.私たちはすぐにそれを取得します.
    let { stat, readlink } = require("fs/promises")
    
    let fileInfo = async (basePath, entry) => {
      let {name} = entry
      let fullPath = path.join(basePath, name)
      let linkTarget = null
      let fileStat
    
      if (entry.isSymbolicLink()) {
        linkTarget = await readlink(fullPath)
      }
    
      // This most commonly happens with broken symlinks
      // but could also happen if the file is deleted
      // while we're checking it as race condition
      try {
        fileStat = await stat(fullPath)
      } catch {
        return {
          name,
          type: "broken",
          linkTarget,
        }
      }
    
      let {size, mtime} = fileStat
    
      if (fileStat.isDirectory()) {
        return {
          name,
          type: "directory",
          mtime,
          linkTarget,
        }
      } else if (fileStat.isFile()) {
        return {
          name,
          linkTarget,
          type: "file",
          size,
          mtime,
          linkTarget,
        }
      } else {
        return {
          name,
          type: "special",
        }
      }
    }
    
    これは以下のような多くのケースをカバーしなければなりません.
  • ファイル
  • ファイルへのシンボリックリンク
  • ディレクトリ
  • ディレクトリへのシンボリックリンク
  • エラー(チェック中に削除されたファイル)
  • エラーへのシンボリックリンク(シンボリックリンクは、存在しないファイルを指します.
  • 特殊ファイル( socket , fifo , deviceなど)
  • 特殊ファイルへのシンボリックリンク
  • 我々はユニットテストする必要があります何かのような音?我々は絶対に、まだではない!

    インデックス.HTML


    私が忘れた1つのもの.ちょうどどんなウェブサーバからでもHTMLを提供しているとき、それはHTTPヘッダーでUTF 8であることをブラウザに言います.私たちがrawファイルをロードしているように、ブラウザはデフォルトのブラウザーのデフォルトは誰も前のY 2 K以来見られないエンコードし、電子さえその狂ったことを行う.それで、私たちは、それがutf 8であると言う必要があります.そうする多くの方法の一つです
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8">
      </head>
      <body>
        <link rel="stylesheet" href="/build/bundle.css">
        <script src="/build/bundle.js"></script>
      </body>
    </html>
    

    アプリ。スベルト


    そして、グリッド形式でその情報を表示するためのいくつかの非常に単純なコンポーネントです.私たちはもっと良いことをすることができます.
    <script>
      let directory = window.api.currentDirectory()
      $: filesPromise = window.api.directoryContents(directory)
      $: isRoot = (directory === "/")
    
      function navigate(path) {
        if (directory === "/") {
          directory = "/" + path
        } else {
          directory += "/" + path
        }
      }
      function navigateUp() {
        directory = directory.split("/").slice(0, -1).join("/") || "/"
      }
      function formatDate(d) {
        return d ? d.toDateString() : ""
      }
      function formatName(entry) {
        if (entry.linkTarget) {
          return `${entry.name}${entry.linkTarget}`
        } else {
          return entry.name
        }
      }
    </script>
    
    <h1>{directory}</h1>
    
    {#await filesPromise}
    {:then files}
      <div class="file-list">
        {#if !isRoot}
          <div><button on:click={() => navigateUp()}>..</button></div>
          <div></div>
          <div></div>
          <div></div>
        {/if}
        {#each files as entry}
          <div>
            {#if entry.type === "directory"}
              <button on:click={() => navigate(entry.name)}>
                {formatName(entry)}
              </button>
            {:else}
              {formatName(entry)}
            {/if}
          </div>
          <div>
            {entry.type}
            {entry.linkTarget ? " link" : ""}
          </div>
          <div>{entry.size ? entry.size : ""}</div>
          <div>{formatDate(entry.mtime)}</div>
        {/each}
      </div>
    {/await}
    
    <style>
      :global(body) {
        background-color: #444;
        color: #ccc;
      }
      .file-list {
        display: grid;
        grid-template-columns: 3fr 1fr 1fr 1fr;
      }
    </style>
    

    結果


    以下に結果を示します.node_modules :


    次のエピソードでは、バックエンドコードの一部をテストすることができます.
    いつものように.all the code for the episode is here .