需求:临时需要创建一个 build.sh 脚本,给它一个图片目录做为参数,生成 index.html 网页中展示所有目录图片。方便搜索查看。

build.sh

#!/bin/bash

if [[ -z "$@" ]]; then
  echo "Usage: $0 image_dir1 [image_dir2 ...]"
  exit 1
fi

cmd="find"
for folder in "$@";
do
  cmd="${cmd} '$folder'"
done
cmd="$cmd -type f"

renderFileList() {
  eval $cmd | egrep '(.svg|.jpg|.jpeg|.gif|.png)$' | while read -r file;
  do
    echo "        list.push(\"${file}\");"
  done
}

render() {
  cat <<EOF
<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>Images Search</title>
    <style>
      body {
        background-color: #00000020;
      }

      .search-input {
        position: sticky;
        top: 0.5rem;
        left: 0;
      }

      table td {
        border-bottom: 1px solid rgba(0, 0, 0, 0.2);
      }

      .icon-image {
        width: 35px;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div>
        <input class="search-input" type="search" placeholder="Type In Image Name" />
        <span><strong class="num-of-results"><!-- num of results --></strong> results.</span>
      </div>
      <table class="icon-list">
        <tr>
          <td><!-- module --></td>
          <td><!-- name.ext --></td>
          <td>
            <img
              class="icon-image"
              src="my/logo.png"
            />
          </td>
        </tr>
      </table>
    </div>

    <script>
      const initialState = {
        kw: "",
        iconData: getIconFilenameArr(),
        get allIcons() {
          return this.iconData.map((filename) => {
            const [_, module, name, ext] = filename.match(/^(.*)\/(.*)\.(.*)\$/);
            return {
              filename,
              module,
              name,
              ext,
            };
          });
        },
        get icons() {
          return this.allIcons.filter((item) => {
            if (this.kw)
              return item.filename.match(new RegExp(this.kw, "i")) !== null;
            return true;
          });
        },
      };
      const state = new Proxy(initialState, {
        set: (o, p, v) => {
          if (o[p] === v) {
            return true;
          }

          const res = Reflect.set(o, p, v);
          render();
          return res;
        },
      });

      const App = {
        searchInput: document.querySelector(".search-input"),
        numOfResults: document.querySelector(".num-of-results"),
        table: document.querySelector(".icon-list"),
        tableRows: {},
        imgTpl: document
          .querySelector(".icon-list")
          .querySelectorAll("tr")[0]
          .cloneNode(true),
      };

      (function App__didMount() {
        function debounce(fn, timeout = 300) {
          let token = null;

          console.assert(typeof fn === "function");

          return (...args) => {
            if (token) {
              clearTimeout(token);
              token = null;
            }

            token = setTimeout(() => fn(...args), timeout);
          };
        }

        let onInputKeyup = debounce(function (e) {
          state.kw = e.target.value;
        });

        App.searchInput.addEventListener("keyup", onInputKeyup);
        App.searchInput.addEventListener("search", onInputKeyup);
      })();

      function render() {
        // render num of results
        App.numOfResults.innerText = state.icons.length;

        // render table
        App.table.innerHTML = "";

        // render icon list
        state.icons.forEach((icon) => {
          const imgTr = App.imgTpl.cloneNode(true);
          const td1 = imgTr.querySelector("td:nth-child(1)");
          const td2 = imgTr.querySelector("td:nth-child(2)");
          const img = imgTr.querySelector("img");
          td1.innerText = icon.module;
          td2.innerText = icon.name + '.' + icon.ext;
          img.src = icon.filename;
          App.table.appendChild(imgTr);
        });
      }

      function getIconFilenameArr() {
        const list = [];
$(renderFileList)
        return list;
      }

      render();
    </script>
  </body>
</html>
EOF

}


render > index.html
open index.html

用法:

Usage: ./build.sh image_dir1 [image_dir2 ...]

例子:

./build.sh assets/images/ assets/icons/