快速自建 Parchment

Parchment 是什么

IFWiki

项目地址

Parchment 是一个纯前端的互动小说播放器,支持 Zcode,Glulx,TADS,Hugo 在内的几乎所有主流格式。

iplayif 使用的就是 Parchment,Inform 7 的发布功能也是 Parchment。

展示成果

构建,修改 Index

Parchment 也提供了单文件版,但我们想修改 index.html ,所以肯定还是要手动构建。

官方构建指南

修改后的 index.html 如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Parchment</title>
    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0">
    <script src="dist/web/jquery.min.js"></script>
    <script src="dist/web/ie.js" nomodule></script>
    <script src="dist/web/web.js" type="module"></script>
    <link rel="stylesheet" href="dist/web/web.css">
    <style>
      #about { max-height: 100%; overflow-y: auto; }
      #games-list { list-style: none; padding: 0; }
      #games-list li { margin: 1em 0; }
      #games-list .meta { opacity: 0.7; font-size: 0.9em; }
    </style>
  </head>
  <body>
    <div id="gameport">
      <div id="about">
        <h1>Lots of Games</h1>
        <p>Powered by <a href="https://github.com/curiousdannii/parchment">parchment</a>.</p>
        <p>Find stories to play at the <a href="https://ifdb.org/">Interactive Fiction Database</a>.</p>
        <p id="play-url">
          <input id="play-url-input" placeholder="Enter a URL of a story file" type="url">
          <button id="play-url-button">Go</button>
        </p>
        <p id="play-url-error"></p>
        <label id="custom-file-upload" for="file-upload" tabindex="0" role="button">
          <p>Or, click here to play a story file on your device</p>
        </label>
        <input id="file-upload" type="file" style="display: none"/>
        <ul id="games-list"></ul>
        <noscript><p>Parchment requires Javascript. Please enable it in your browser.</p></noscript>
      </div>
      <div id="windowport"></div>
      <div id="loadingpane" style="display:none;">
        <img src="dist/web/waiting.gif" alt="LOADING"><br>
        <em>&nbsp;&nbsp;&nbsp;Loading...</em>
      </div>
      <div id="errorpane" style="display:none;"><div id="errorcontent">...</div></div>
    </div>
    <script>
      fetch('games.json')
    .then(res => {
        if (!res.ok) throw new Error()
        return res.json()
    })
    .then(games => {
        const list = document.getElementById('games-list')
        for (const game of games) {
            const li = document.createElement('li')
            const link = document.createElement('a')
            link.href = '?story=' + encodeURIComponent(game.file)
            const title = document.createElement('strong')
            title.textContent = game.title
            link.appendChild(title)
            const meta = document.createElement('span')
            meta.className = 'meta'
            meta.textContent = [game.author, game.released].filter(Boolean).join(' · ')
            li.append(link, document.createElement('br'), meta)
            list.appendChild(li)
        }
    })
    .catch(() => {
        document.getElementById('games-list').remove()
    })
    </script>
  </body>
</html>

中间这段脚本会利用 games.json 的数据为 stories/ 下的游戏们生成链接。

添加本地游戏

新建一个 stories 目录,将下载的游戏文件放进去。

再新建一个格式如下的 games.json

[
  {
    "title": "Photopia",
    "author": "Adam Cadre (as Opal O'Donnell)",
    "released": "1998-10-01",
    "file": "stories/photopia.z5"
  },
  {
    "title": "Varicella",
    "author": "Adam Cadre",
    "released": "1999-08-19",
    "file": "stories/varicella.z8"
  },
  {
    "title": "9:05",
    "author": "Adam Cadre",
    "released": "2000-01-03",
    "file": "stories/905.z5"
  }
]

然后就可以愉快地玩游戏了。

Date: 2026-08-24 Mon 18:08