Skip to content

Commit

Permalink
Support gzipped files in single file mode
Browse files Browse the repository at this point in the history
  • Loading branch information
curiousdannii committed Dec 10, 2024
1 parent 2eb8db2 commit 747c365
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 74 deletions.
1 change: 1 addition & 0 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ if (projects.includes('ifcomp')) {
projects_to_build.push({
entryPoints: {
bocfel: 'node_modules/emglken/build/bocfel.*',
glkaudio_bg: 'node_modules/glkaudio/glkaudio_bg.wasm',
glulxe: 'node_modules/emglken/build/glulxe.*',
ie: 'src/common/ie.js',
tads: 'node_modules/emglken/build/tads.*',
Expand Down
34 changes: 0 additions & 34 deletions src/common/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,6 @@ https://github.com/curiousdannii/parchment
*/

import {parse_base64, type ProgressCallback, read_response} from '../upstream/asyncglk/src/index-common.js'
import type {ParchmentOptions} from './interface.js'

/** Fetch a VM resource */
export async function fetch_vm_resource(options: ParchmentOptions, path: string, progress_callback?: ProgressCallback) {
// Handle embedded resources in single file mode
if (options.single_file) {
const data = (document.getElementById(path) as HTMLScriptElement).text
if (path.endsWith('.js')) {
return import(`data:text/javascript,${encodeURIComponent(data)}`)
}
if (!path.endsWith('.wasm')) {
throw new Error(`Can't load ${path} in single file mode`)
}
return parse_base64(data)
}

if (path.endsWith('.js')) {
return import(path)
}

// Something else, like a .wasm
// Handle when lib_path is a proper URL (such as import.meta.url), as well as the old style path fragment
let url
try {
url = new URL(path, options.lib_path)
}
catch (_) {
url = options.lib_path + path
}
const response = await fetch(url)
return read_response(response, progress_callback)
}

export async function Uint8Array_to_base64(data: Uint8Array): Promise<string> {
if (typeof Buffer !== 'undefined') {
return Buffer.from(data.buffer).toString('base64')
Expand Down
18 changes: 9 additions & 9 deletions src/common/formats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const formats: Format[] = [
engines: [
{
id: 'scare',
load: ['./scare.js', './scare.wasm'],
load: ['scare.js', 'scare.wasm'],
start: generic_emglken_vm,
},
],
Expand All @@ -63,7 +63,7 @@ export const formats: Format[] = [
engines: [
{
id: 'frankendrift',
load: ['./frankendrift.js'],
load: ['frankendrift.js'],
start: (options, requires) => {
const [file_data, FrankenDrift] = requires
Expand All @@ -86,7 +86,7 @@ export const formats: Format[] = [
engines: [
{
id: 'hugo',
load: ['./hugo.js', './hugo.wasm'],
load: ['hugo.js', 'hugo.wasm'],
start: generic_emglken_vm,
},
],
Expand All @@ -99,7 +99,7 @@ export const formats: Format[] = [
engines: [
/*{
id: 'quixe',
load: ['./quixe.js'],
load: ['quixe.js'],
start: (_story: StoryOptions, options, requires) =>
{
const [file_data, quixe] = requires
Expand All @@ -123,13 +123,13 @@ export const formats: Format[] = [

{
id: 'glulxe',
load: ['./glulxe.js', './glulxe.wasm'],
load: ['glulxe.js', 'glulxe.wasm'],
start: generic_emglken_vm,
},

{
id: 'git',
load: ['./git.js', './git.wasm'],
load: ['git.js', 'git.wasm'],
start: generic_emglken_vm,
},
],
Expand All @@ -141,7 +141,7 @@ export const formats: Format[] = [
engines: [
{
id: 'tads',
load: ['./tads.js', './tads.wasm'],
load: ['tads.js', 'tads.wasm'],
start: generic_emglken_vm,
},
],
Expand All @@ -154,7 +154,7 @@ export const formats: Format[] = [
engines: [
/*{
id: 'zvm',
load: ['./zvm.js'],
load: ['zvm.js'],
start: (_story: StoryOptions, options, requires) =>
{
const [file_data, zvm] = requires
Expand All @@ -172,7 +172,7 @@ export const formats: Format[] = [

{
id: 'bocfel',
load: ['./bocfel.js', './bocfel.wasm'],
load: ['bocfel.js', 'bocfel.wasm'],
start: generic_emglken_vm,
},
],
Expand Down
16 changes: 5 additions & 11 deletions src/common/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ https://github.com/curiousdannii/parchment
*/

import type {BrowserDialog, DownloadOptions, /*GlkApi,*/ GlkOte, GlkOteOptions} from '../upstream/asyncglk/src/index-common.js'

export type ParchmentTruthy = boolean | number
import type {BrowserDialog, /*GlkApi,*/ GlkOte, GlkOteOptions, TruthyOption} from '../upstream/asyncglk/src/index-common.js'

export interface StoryOptions {
/** Size of storyfile in bytes, uncompressed */
Expand All @@ -26,25 +24,21 @@ export interface StoryOptions {
url?: string
}

export interface ParchmentOptions extends DownloadOptions, Partial<GlkOteOptions> {
export interface ParchmentOptions extends Omit<GlkOteOptions, 'accept'> {
// Parchment options

/** Whether or not to automatically launch Parchment */
auto_launch?: ParchmentTruthy,
auto_launch?: TruthyOption,
/** Story path in the array format traditionally used by Parchment for Inform 7 */
default_story?: [string],
/** Path to resources */
lib_path: string,
/** Whether to load embedded resources in single file mode */
single_file?: ParchmentTruthy,
/** Storyfile path or metadata */
story?: string | StoryOptions,
/** Theme name, can be set to 'dark */
theme?: string,
/** Name of theme cookie to check */
theme_cookie: string,
/** Whether to test the AsyncGlk GlkApi library */
use_asyncglk?: ParchmentTruthy,
use_asyncglk?: TruthyOption,

// Modules to pass to other modules

Expand All @@ -58,5 +52,5 @@ export interface ParchmentOptions extends DownloadOptions, Partial<GlkOteOptions
// Common options for VMs

/** Whether or not to load an autosave */
do_vm_autosave?: ParchmentTruthy,
do_vm_autosave?: TruthyOption,
}
6 changes: 2 additions & 4 deletions src/common/launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@ import '../web/web.css'
import Cookies from 'js-cookie'
import prettyBytes from 'pretty-bytes'

import {/*AsyncGlk,*/ Blorb, FileView, type ProgressCallback} from '../upstream/asyncglk/src/index-browser.js'
import {/*AsyncGlk,*/ Blorb, fetch_resource, FileView, type ProgressCallback} from '../upstream/asyncglk/src/index-browser.js'

import {fetch_vm_resource} from './file.js'
import {find_format, identify_blorb_storyfile_format} from './formats.js'
import type {ParchmentOptions, StoryOptions} from './interface.js'
import {get_default_options, get_query_options} from './options.js'


interface ParchmentWindow extends Window {
parchment: ParchmentLauncher
parchment_options?: ParchmentOptions
Expand Down Expand Up @@ -152,7 +150,7 @@ class ParchmentLauncher

const requires = await Promise.all([
story.path || this.options.Dialog.download(story.url!, progress_callback),
...engine.load.map(path => fetch_vm_resource(this.options, path)),
...engine.load.map(path => fetch_resource(this.options, path)),
])
story.path = requires.shift()

Expand Down
26 changes: 18 additions & 8 deletions src/tools/index-processing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ https://github.com/curiousdannii/parchment
*/

import {gzipSync} from 'zlib'

import {escape, truncate} from 'lodash-es'
import prettyBytes from 'pretty-bytes'

import type {TruthyOption} from '../upstream/asyncglk/src/index-common.js'
import {Uint8Array_to_base64} from '../common/file.js'
import type {ParchmentTruthy, ParchmentOptions} from '../common/interface.js'
import type {ParchmentOptions} from '../common/interface.js'

// Is ASCII really okay here?
const utf8decoder = new TextDecoder('ascii', {fatal: true})
Expand All @@ -33,10 +36,11 @@ export interface Story {
}

export interface SingleFileOptions {
date?: ParchmentTruthy
date?: TruthyOption
domain?: string
font?: ParchmentTruthy
single_file?: ParchmentTruthy
font?: TruthyOption
gzip?: TruthyOption
single_file?: TruthyOption
story?: Story
}

Expand Down Expand Up @@ -81,8 +85,11 @@ export async function process_index_html(options: SingleFileOptions, files: Map<
}
}
if (story.data) {
if (options.gzip) {
story.data = gzipSync(story.data, {level: 9})
}
parchment_options.story.url = 'embedded:' + story.filename!
inclusions.push(`<script type="text/plain" id="${story.filename!}">${await Uint8Array_to_base64(story.data)}</script>`)
inclusions.push(`<script type="text/plain${options.gzip ? ';gzip' : ''}" id="${story.filename!}">${await Uint8Array_to_base64(story.data)}</script>`)
}
if (story.filesize) {
parchment_options.story.filesize = story.filesize
Expand All @@ -102,9 +109,12 @@ export async function process_index_html(options: SingleFileOptions, files: Map<

// Process the files
let indexhtml = ''
for (const [filename, data] of files) {
for (let [filename, data] of files) {
if (filename.endsWith('.wasm')) {
inclusions.push(`<script type="text/plain" id="./${filename}">${await Uint8Array_to_base64(data)}</script>`)
if (options.gzip) {
data = gzipSync(data, {level: 9})
}
inclusions.push(`<script type="text/plain${options.gzip ? ';gzip' : ''}" id="${filename}">${await Uint8Array_to_base64(data)}</script>`)
continue
}
else if (filename.endsWith('.gif')) {
Expand Down Expand Up @@ -147,7 +157,7 @@ export async function process_index_html(options: SingleFileOptions, files: Map<
inclusions.push(`<style>${data_as_string}</style>`)
}
else if (filename.endsWith('.js')) {
inclusions.push(`<script type="text/plain" id="./${filename}">${data_as_string}</script>`)
inclusions.push(`<script type="text/plain" id="${filename}">${data_as_string}</script>`)
}
}

Expand Down
16 changes: 9 additions & 7 deletions src/tools/single-file-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const webpath = path.join(rootpath, 'dist/web')
const base_options: Options = {
date: 1,
font: 1,
gzip: 1,
single_file: 1,
terps: [],
}
Expand Down Expand Up @@ -75,15 +76,15 @@ const formats: Record<string, BasicFormat> = {
},
glulx: {
extensions: /\.(gblorb|glb|ulx)/i,
engine: 'quixe',
engine: 'glulxe',
},
tads: {
extensions: /\.(gam|t3)/i,
engine: 'tads',
},
zcode: {
extensions: /\.(zblorb|zlb|z3|z4|z5|z8)/i,
engine: 'zvm',
engine: 'bocfel',
}
}

Expand Down Expand Up @@ -131,18 +132,19 @@ const common_files = [
]
const interpreter_files: Record<string, string[]> = {
bocfel: ['bocfel.wasm', 'bocfel.js'],
git: ['git.wasm', 'git.js'],
glulxe: ['glulxe.wasm', 'glulxe.js'],
git: ['git.wasm', 'git.js', 'glkaudio_bg.wasm'],
glulxe: ['glkaudio_bg.wasm', 'glulxe.wasm', 'glulxe.js'],
hugo: ['hugo.wasm', 'hugo.js'],
quixe: ['quixe.js'],
quixe: ['glkaudio_bg.wasm', 'quixe.js'],
scare: ['scare.wasm', 'scare.js'],
tads: ['tads.wasm', 'tads.js'],
zvm: ['zvm.js'],
}

// Get all the files
// Get all the files, flattened and deduplicated
const filenames = [...new Set(common_files.concat(options.terps.map(terp => interpreter_files[terp]).flat()))]
const files: Map<string, Uint8Array> = new Map()
for (const file of common_files.concat(options.terps.map(terp => interpreter_files[terp]).flat())) {
for (const file of filenames) {
files.set(path.basename(file), await fs.readFile(path.join(webpath, file)))
}

Expand Down

0 comments on commit 747c365

Please sign in to comment.