mirror of
https://github.com/0x5eal/luau-unzip.git
synced 2025-04-10 17:20:53 +01:00
chore: add a markdown docs generation script for moonwave comments (#2)
This commit is contained in:
commit
25b87de27e
10 changed files with 693 additions and 6 deletions
56
.github/workflows/doc.yml
vendored
Normal file
56
.github/workflows/doc.yml
vendored
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
name: Update API reference docs
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- 'lib/init.luau'
|
||||||
|
- '.lune/docsgen/**/*.luau'
|
||||||
|
- '**/.nix'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-ref:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install nix
|
||||||
|
uses: nixbuild/nix-quick-install-action@v29
|
||||||
|
|
||||||
|
- name: Restore and cache Nix store
|
||||||
|
uses: nix-community/cache-nix-action@v5
|
||||||
|
with:
|
||||||
|
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix') }}
|
||||||
|
restore-prefixes-first-match: nix-${{ runner.os }}-
|
||||||
|
gc-max-store-size-linux: 5368709000
|
||||||
|
purge: true
|
||||||
|
purge-prefixes: cache-${{ runner.os }}-
|
||||||
|
purge-created: 0
|
||||||
|
purge-primary-key: never
|
||||||
|
|
||||||
|
- name: Cache pesde data
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.pesde
|
||||||
|
key: pesde-${{ runner.os }}-${{ hashFiles('pesde.toml') }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: nix develop -c pesde install --locked
|
||||||
|
|
||||||
|
- name: Update markdown API reference docs
|
||||||
|
run: nix develop -c lune run docsgen
|
||||||
|
|
||||||
|
- name: Commit & push
|
||||||
|
run: |
|
||||||
|
git config --global user.name "github-actions[bot]"
|
||||||
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
git add -A
|
||||||
|
git commit -m "docs: update refs for https://github.com/0x5eal/luau-unzip/commit/${{ github.event.client_payload.sha }}" && \
|
||||||
|
git push || echo "warn: no changes to commit"
|
34
.lune/docsgen/init.luau
Normal file
34
.lune/docsgen/init.luau
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
--> Generate markdown documentation from moonwave comments
|
||||||
|
|
||||||
|
local process = require("@lune/process")
|
||||||
|
local serde = require("@lune/serde")
|
||||||
|
|
||||||
|
local moonwave = require("./moonwave")
|
||||||
|
local logger = require("./log")
|
||||||
|
local writeMarkdown = require("./markdown")
|
||||||
|
|
||||||
|
local function extract(input: string): (number, { moonwave.Item }?)
|
||||||
|
local res = process.spawn("moonwave-extractor", { "extract", input }, {
|
||||||
|
stdio = {
|
||||||
|
stderr = "forward"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if not res.ok then
|
||||||
|
print()
|
||||||
|
logger.log("error", "`moonwave-extractor` failed with exit code", res.code)
|
||||||
|
return res.code, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, items: { moonwave.Item } = pcall(serde.decode, "json" :: "json", res.stdout)
|
||||||
|
if not ok then
|
||||||
|
return 1, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0, items
|
||||||
|
end
|
||||||
|
|
||||||
|
local code, items = extract("lib/init.luau")
|
||||||
|
writeMarkdown("./docs/index.md", items :: { moonwave.Item })
|
||||||
|
|
||||||
|
process.exit(code)
|
24
.lune/docsgen/log.luau
Normal file
24
.lune/docsgen/log.luau
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
local stdio = require("@lune/stdio")
|
||||||
|
|
||||||
|
local base = stdio.style("bold")
|
||||||
|
|
||||||
|
local STYLE_INFO = base .. `{stdio.color("green")}info{stdio.color("reset")}:`
|
||||||
|
local STYLE_WARN = base .. `{stdio.color("yellow")}warn{stdio.color("reset")}:`
|
||||||
|
local STYLE_ERROR = base .. `{stdio.color("red")}error{stdio.color("reset")}:`
|
||||||
|
|
||||||
|
export type LogType = "info" | "warn" | "error"
|
||||||
|
local styleMappings: { [LogType]: string } = {
|
||||||
|
info = STYLE_INFO,
|
||||||
|
warn = STYLE_WARN,
|
||||||
|
error = STYLE_ERROR,
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
styles = styleMappings,
|
||||||
|
log = function<T...>(type: LogType, ...: T...): ()
|
||||||
|
local writer: (string) -> () = if type == "info" then stdio.write else stdio.ewrite
|
||||||
|
local fmtMsg = stdio.format(styleMappings[type], ...)
|
||||||
|
|
||||||
|
return writer(fmtMsg .. "\n")
|
||||||
|
end
|
||||||
|
}
|
177
.lune/docsgen/markdown.luau
Normal file
177
.lune/docsgen/markdown.luau
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
local fs = require("@lune/fs")
|
||||||
|
|
||||||
|
local moonwave = require("./moonwave")
|
||||||
|
local logger = require("./log")
|
||||||
|
|
||||||
|
local function writeSectionHeader(buf: string, title: string)
|
||||||
|
buf ..= `## {title}\n`
|
||||||
|
return buf
|
||||||
|
end
|
||||||
|
|
||||||
|
local function writeRef(buf: string, name: string, fragment: string?)
|
||||||
|
buf ..= `\n[{name}]: #{fragment or name}\n`
|
||||||
|
return buf
|
||||||
|
end
|
||||||
|
|
||||||
|
local function writeClass(buf: string, name: string, desc: string)
|
||||||
|
buf ..= `# \`{name}\`\n`
|
||||||
|
buf ..= desc
|
||||||
|
buf ..= `\n\n`
|
||||||
|
return buf
|
||||||
|
end
|
||||||
|
|
||||||
|
local function writeDeclaration(buf: string, name: string, fields: { moonwave.Property })
|
||||||
|
buf ..= `\`\`\`luau\n`
|
||||||
|
buf ..= `export type {name} = \{\n`
|
||||||
|
for _, field in fields do
|
||||||
|
buf ..= `\t{field.name}: {field.lua_type},\n`
|
||||||
|
end
|
||||||
|
buf ..= "}\n"
|
||||||
|
buf ..= `\`\`\`\n`
|
||||||
|
return buf
|
||||||
|
end
|
||||||
|
|
||||||
|
local function writeProperty(buf: string, name: string, desc: string, type: string)
|
||||||
|
-- buf ..= `- **\`{name}: {type}\`** - {desc}\n`
|
||||||
|
buf ..= `- **{name}** - {desc}\n`
|
||||||
|
return buf
|
||||||
|
end
|
||||||
|
|
||||||
|
local function writeFunction(
|
||||||
|
buf: string,
|
||||||
|
class: string,
|
||||||
|
type: string,
|
||||||
|
name: string,
|
||||||
|
desc: string,
|
||||||
|
params: { moonwave.FunctionParam },
|
||||||
|
returns: { moonwave.FunctionReturn },
|
||||||
|
private: boolean
|
||||||
|
)
|
||||||
|
local sep = if type == "method" then ":" else "."
|
||||||
|
local declaredSignature = `{class}{sep}{name}`
|
||||||
|
buf ..= `### \`{name}\`\n`
|
||||||
|
|
||||||
|
if private then
|
||||||
|
buf ..= `> [!IMPORTANT]\n`
|
||||||
|
buf ..= `> This is a private API. It may be exported publically, but try to avoid\n`
|
||||||
|
buf ..= `> using this API, since it can have breaking changes at any time without\n`
|
||||||
|
buf ..= `> warning.\n\n`
|
||||||
|
end
|
||||||
|
|
||||||
|
buf ..= `{desc}\n`
|
||||||
|
buf ..= `\`\`\`luau\n`
|
||||||
|
buf ..= `{declaredSignature}(`
|
||||||
|
if #params > 0 then
|
||||||
|
buf ..= "\n"
|
||||||
|
for _, param in params do
|
||||||
|
buf ..= `\t{param.name}: {param.lua_type}, -- {param.desc}\n`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
buf ..= `)`
|
||||||
|
|
||||||
|
if #returns > 0 then
|
||||||
|
if #returns == 1 then
|
||||||
|
buf ..= `: {returns[1].lua_type}\n`
|
||||||
|
else
|
||||||
|
for pos, ret in returns do
|
||||||
|
buf ..= `({ret.lua_type}`
|
||||||
|
if pos ~= #returns then
|
||||||
|
buf ..= `, `
|
||||||
|
end
|
||||||
|
end
|
||||||
|
buf ..= `)`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
buf ..= `\n\`\`\`\n`
|
||||||
|
buf = writeRef(buf, declaredSignature, name)
|
||||||
|
return buf
|
||||||
|
end
|
||||||
|
|
||||||
|
local function writeType(buf: string, name: string, desc: string, type: string)
|
||||||
|
buf ..= `\`\`\`luau\n`
|
||||||
|
buf ..= `export type {name} = {type}\n`
|
||||||
|
buf ..= `\`\`\`\n`
|
||||||
|
return buf
|
||||||
|
end
|
||||||
|
|
||||||
|
local function writeMarkdown(path: string, items: { moonwave.Item })
|
||||||
|
local start = os.clock()
|
||||||
|
local buf = ""
|
||||||
|
for _, item in items do
|
||||||
|
logger.log("info", "Generating docs for", item.name)
|
||||||
|
buf = writeClass(buf, item.name, item.desc)
|
||||||
|
|
||||||
|
local props: { moonwave.Property } = {}
|
||||||
|
for pos, type in item.types do
|
||||||
|
if type.name == item.name then
|
||||||
|
table.remove(item.types, pos)
|
||||||
|
props = type.fields
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
buf = writeDeclaration(buf, item.name, props)
|
||||||
|
buf = writeSectionHeader(buf, "Properties")
|
||||||
|
for _, prop in props do
|
||||||
|
if prop.ignore then
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
|
buf = writeProperty(buf, prop.name, prop.desc, prop.lua_type)
|
||||||
|
end
|
||||||
|
buf ..= "\n"
|
||||||
|
|
||||||
|
buf = writeSectionHeader(buf, "API")
|
||||||
|
for _, func in item.functions do
|
||||||
|
if func.ignore then
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
|
buf = writeFunction(
|
||||||
|
buf,
|
||||||
|
item.name,
|
||||||
|
func.function_type,
|
||||||
|
func.name,
|
||||||
|
func.desc,
|
||||||
|
func.params,
|
||||||
|
func.returns,
|
||||||
|
func.private
|
||||||
|
)
|
||||||
|
end
|
||||||
|
buf ..= "\n"
|
||||||
|
|
||||||
|
buf = writeSectionHeader(buf, "Types")
|
||||||
|
for _, type in item.types do
|
||||||
|
if type.ignore then
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
|
buf ..= `### \`{type.name}\`\n`
|
||||||
|
if type.private then
|
||||||
|
buf ..= `> [!IMPORTANT]\n`
|
||||||
|
buf ..= `> This is a private type. It may be exported publically, but try to avoid\n`
|
||||||
|
buf ..= `> using it, since its definition can have a breaking change at any time\n`
|
||||||
|
buf ..= `> without warning.\n\n`
|
||||||
|
end
|
||||||
|
buf ..= `{type.desc}\n`
|
||||||
|
if type.lua_type ~= nil then
|
||||||
|
buf = writeType(buf, type.name, type.desc, type.lua_type)
|
||||||
|
else
|
||||||
|
local fields: { moonwave.Property } = type.fields or {}
|
||||||
|
buf = writeDeclaration(buf, type.name, fields)
|
||||||
|
for _, field in fields do
|
||||||
|
buf = writeProperty(buf, field.name, field.desc, field.lua_type)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
buf = writeRef(buf, type.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
buf = writeRef(buf, item.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
logger.log("info", string.format("Generated docs in %.2fms", (os.clock() - start) * 1000))
|
||||||
|
logger.log("info", "Writing to", path)
|
||||||
|
fs.writeFile(path, buf)
|
||||||
|
end
|
||||||
|
|
||||||
|
return writeMarkdown
|
59
.lune/docsgen/moonwave.luau
Normal file
59
.lune/docsgen/moonwave.luau
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
--> Copied from https://github.com/lune-org/docs/blob/0a1e5a/.lune/moonwave.luau
|
||||||
|
|
||||||
|
export type Source = {
|
||||||
|
path: string,
|
||||||
|
line: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FunctionParam = {
|
||||||
|
name: string,
|
||||||
|
desc: string,
|
||||||
|
lua_type: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FunctionReturn = {
|
||||||
|
desc: string,
|
||||||
|
lua_type: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Function = {
|
||||||
|
name: string,
|
||||||
|
desc: string,
|
||||||
|
params: { FunctionParam },
|
||||||
|
returns: { FunctionReturn },
|
||||||
|
function_type: string,
|
||||||
|
tags: { string }?,
|
||||||
|
ignore: boolean,
|
||||||
|
private: boolean,
|
||||||
|
source: Source,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Property = {
|
||||||
|
name: string,
|
||||||
|
desc: string,
|
||||||
|
lua_type: string,
|
||||||
|
tags: { string }?,
|
||||||
|
ignore: boolean,
|
||||||
|
source: Source,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Type = {
|
||||||
|
name: string,
|
||||||
|
desc: string,
|
||||||
|
lua_type: string,
|
||||||
|
ignore: boolean,
|
||||||
|
private: boolean,
|
||||||
|
fields: { Property },
|
||||||
|
source: Source,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Item = {
|
||||||
|
name: string,
|
||||||
|
desc: string,
|
||||||
|
functions: { Function },
|
||||||
|
properties: { Property },
|
||||||
|
types: { Type },
|
||||||
|
source: Source,
|
||||||
|
}
|
||||||
|
|
||||||
|
return {}
|
|
@ -6,7 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
- Documentation comments powered by [moonwave](https://github.com/evaera/moonwave)
|
- Added doc comments powered by [moonwave](https://github.com/evaera/moonwave)
|
||||||
|
- Added markdown doc generator lune script and configured pesde docs
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed incorrect type signatures for some functions
|
- Fixed incorrect type signatures for some functions
|
||||||
### Changed
|
### Changed
|
||||||
|
|
7
dev.nix
7
dev.nix
|
@ -111,6 +111,13 @@ pkgs.mkShell {
|
||||||
artifactName = "pesde-0.6.0-rc.8-linux-x86_64.zip";
|
artifactName = "pesde-0.6.0-rc.8-linux-x86_64.zip";
|
||||||
sha256 = "xjY8yPTAD32xeQokHDSWBOiGALLxPOU89Xlxi2Jdnno=";
|
sha256 = "xjY8yPTAD32xeQokHDSWBOiGALLxPOU89Xlxi2Jdnno=";
|
||||||
})
|
})
|
||||||
|
(fromGithubRelease {
|
||||||
|
name = "evaera/moonwave";
|
||||||
|
exeName = "moonwave-extractor";
|
||||||
|
version = "v1.2.1";
|
||||||
|
artifactName = "moonwave-extractor-v1.2.1-linux.zip";
|
||||||
|
sha256 = "UPZ5ZIazNNBcqny7srFIkHqX0t09r0F1M9q4KyjLNgQ=";
|
||||||
|
})
|
||||||
(fromPesdeManifest {
|
(fromPesdeManifest {
|
||||||
name = "JohnnyMorganz/luau-lsp";
|
name = "JohnnyMorganz/luau-lsp";
|
||||||
exeName = "luau-lsp";
|
exeName = "luau-lsp";
|
||||||
|
|
321
docs/index.md
Normal file
321
docs/index.md
Normal file
|
@ -0,0 +1,321 @@
|
||||||
|
# `ZipEntry`
|
||||||
|
A single entry (a file or a directory) in a ZIP file, and its properties.
|
||||||
|
|
||||||
|
```luau
|
||||||
|
export type ZipEntry = {
|
||||||
|
name: string,
|
||||||
|
versionMadeBy: { software: string, os: MadeByOS },
|
||||||
|
compressedSize: number,
|
||||||
|
size: number,
|
||||||
|
offset: number,
|
||||||
|
timestamp: number,
|
||||||
|
method: CompressionMethod,
|
||||||
|
crc: number,
|
||||||
|
isDirectory: boolean,
|
||||||
|
isText: boolean,
|
||||||
|
attributes: number,
|
||||||
|
parent: ZipEntry?,
|
||||||
|
children: { ZipEntry },
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Properties
|
||||||
|
- **name** - File path within ZIP, '/' suffix indicates directory
|
||||||
|
- **versionMadeBy** - Version of software and OS that created the ZIP
|
||||||
|
- **compressedSize** - Compressed size in bytes
|
||||||
|
- **size** - Uncompressed size in bytes
|
||||||
|
- **offset** - Absolute position of local header in ZIP
|
||||||
|
- **timestamp** - MS-DOS format timestamp
|
||||||
|
- **method** - Method used to compress the file
|
||||||
|
- **crc** - CRC32 checksum of the uncompressed data
|
||||||
|
- **isDirectory** - Whether the entry is a directory or not
|
||||||
|
- **isText** - Whether the entry is plain ASCII text or binary
|
||||||
|
- **attributes** - File attributes
|
||||||
|
- **parent** - Parent directory entry, `nil` if entry is root
|
||||||
|
- **children** - Children of the entry, if it was a directory, empty array for files
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `new`
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> This is a private API. It may be exported publically, but try to avoid
|
||||||
|
> using this API, since it can have breaking changes at any time without
|
||||||
|
> warning.
|
||||||
|
|
||||||
|
|
||||||
|
```luau
|
||||||
|
ZipEntry.new(
|
||||||
|
offset: number, -- Offset of the entry in the ZIP file
|
||||||
|
name: string, -- File path within ZIP, '/' suffix indicates directory
|
||||||
|
properties: ZipEntryProperties, -- Properties of the entry
|
||||||
|
): ZipEntry
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipEntry.new]: #new
|
||||||
|
### `isSymlink`
|
||||||
|
Returns whether the entry is a symlink.
|
||||||
|
```luau
|
||||||
|
ZipEntry:isSymlink(): boolean
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipEntry:isSymlink]: #isSymlink
|
||||||
|
### `getPath`
|
||||||
|
Resolves the path of the entry based on its relationship with other entries. It is recommended to use this
|
||||||
|
method instead of accessing the `name` property directly, although they should be equivalent.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Never use this method when extracting files from the ZIP, since it can contain absolute paths
|
||||||
|
> (say `/etc/passwd`) referencing directories outside the current directory (say `/tmp/extracted`),
|
||||||
|
> causing unintended overwrites of files.
|
||||||
|
```luau
|
||||||
|
ZipEntry:getPath(): string
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipEntry:getPath]: #getPath
|
||||||
|
### `getSafePath`
|
||||||
|
Resolves the path of the entry based on its relationship with other entries and returns it
|
||||||
|
only if it is safe to use for extraction, otherwise returns `nil`.
|
||||||
|
```luau
|
||||||
|
ZipEntry:getSafePath(): string?
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipEntry:getSafePath]: #getSafePath
|
||||||
|
### `sanitizePath`
|
||||||
|
Sanitizes the path of the entry, potentially losing information, but ensuring the path is
|
||||||
|
safe to use for extraction.
|
||||||
|
```luau
|
||||||
|
ZipEntry:sanitizePath(): string
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipEntry:sanitizePath]: #sanitizePath
|
||||||
|
### `compressionEfficiency`
|
||||||
|
Calculates the compression efficiency of the entry, or `nil` if the entry is a directory.
|
||||||
|
|
||||||
|
Uses the formula: `round((1 - compressedSize / size) * 100)` and outputs a percentage.
|
||||||
|
```luau
|
||||||
|
ZipEntry:compressionEfficiency(): number?
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipEntry:compressionEfficiency]: #compressionEfficiency
|
||||||
|
### `isFile`
|
||||||
|
Returns whether the entry is a file, i.e., not a directory or symlink.
|
||||||
|
```luau
|
||||||
|
ZipEntry:isFile(): boolean
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipEntry:isFile]: #isFile
|
||||||
|
### `unixMode`
|
||||||
|
Parses the entry's attributes to extract a UNIX mode, represented as a [UnixMode].
|
||||||
|
```luau
|
||||||
|
ZipEntry:unixMode(): UnixMode?
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipEntry:unixMode]: #unixMode
|
||||||
|
|
||||||
|
## Types
|
||||||
|
### `MadeByOS`
|
||||||
|
The OS that created the ZIP.
|
||||||
|
```luau
|
||||||
|
export type MadeByOS = "FAT" | "AMIGA" | "VMS" | "UNIX" | "VM/CMS" | "Atari ST" | "OS/2" | "MAC" | "Z-System" | "CP/M" | "NTFS" | "MVS" | "VSE" | "Acorn RISCOS" | "VFAT" | "Alternate MVS" | "BeOS" | "TANDEM" | "OS/400" | "OS/X" | "Unknown"
|
||||||
|
```
|
||||||
|
|
||||||
|
[MadeByOS]: #MadeByOS
|
||||||
|
### `CompressionMethod`
|
||||||
|
The method used to compress the file:
|
||||||
|
- `STORE` - No compression
|
||||||
|
- `DEFLATE` - Compressed raw deflate chunks
|
||||||
|
```luau
|
||||||
|
export type CompressionMethod = "STORE" | "DEFLATE"
|
||||||
|
```
|
||||||
|
|
||||||
|
[CompressionMethod]: #CompressionMethod
|
||||||
|
### `ZipEntryProperties`
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> This is a private type. It may be exported publically, but try to avoid
|
||||||
|
> using it, since its definition can have a breaking change at any time
|
||||||
|
> without warning.
|
||||||
|
|
||||||
|
A set of properties that describe a ZIP entry. Used internally for construction of
|
||||||
|
[ZipEntry] objects.
|
||||||
|
```luau
|
||||||
|
export type ZipEntryProperties = {
|
||||||
|
versionMadeBy: number,
|
||||||
|
compressedSize: number,
|
||||||
|
size: number,
|
||||||
|
attributes: number,
|
||||||
|
timestamp: number,
|
||||||
|
method: CompressionMethod?,
|
||||||
|
crc: number,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **versionMadeBy** - Version of software and OS that created the ZIP
|
||||||
|
- **compressedSize** - Compressed size in bytes
|
||||||
|
- **size** - Uncompressed size in bytes
|
||||||
|
- **attributes** - File attributes
|
||||||
|
- **timestamp** - MS-DOS format timestamp
|
||||||
|
- **method** - Method used
|
||||||
|
- **crc** - CRC32 checksum of the uncompressed data
|
||||||
|
|
||||||
|
[ZipEntryProperties]: #ZipEntryProperties
|
||||||
|
### `UnixMode`
|
||||||
|
A object representation of the UNIX mode.
|
||||||
|
```luau
|
||||||
|
export type UnixMode = {
|
||||||
|
perms: string,
|
||||||
|
typeFlags: string,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **perms** - The permission octal
|
||||||
|
- **typeFlags** - The type flags octal
|
||||||
|
|
||||||
|
[UnixMode]: #UnixMode
|
||||||
|
|
||||||
|
[ZipEntry]: #ZipEntry
|
||||||
|
# `ZipReader`
|
||||||
|
The main class which represents a decoded state of a ZIP file, holding references
|
||||||
|
to its entries. This is the primary point of interaction with the ZIP file's contents.
|
||||||
|
|
||||||
|
```luau
|
||||||
|
export type ZipReader = {
|
||||||
|
data: buffer,
|
||||||
|
comment: string,
|
||||||
|
entries: { ZipEntry },
|
||||||
|
directories: { [string]: ZipEntry },
|
||||||
|
root: ZipEntry,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Properties
|
||||||
|
- **data** - The buffer containing the raw bytes of the ZIP
|
||||||
|
- **comment** - Comment associated with the ZIP
|
||||||
|
- **entries** - The decoded entries present
|
||||||
|
- **directories** - The directories and their respective entries
|
||||||
|
- **root** - The entry of the root directory
|
||||||
|
|
||||||
|
## API
|
||||||
|
### `new`
|
||||||
|
Creates a new ZipReader instance from the raw bytes of a ZIP file.
|
||||||
|
|
||||||
|
**Errors if the ZIP file is invalid.**
|
||||||
|
```luau
|
||||||
|
ZipReader.new(
|
||||||
|
data: buffer, -- The buffer containing the raw bytes of the ZIP
|
||||||
|
): ZipReader
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipReader.new]: #new
|
||||||
|
### `parseCentralDirectory`
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> This is a private API. It may be exported publically, but try to avoid
|
||||||
|
> using this API, since it can have breaking changes at any time without
|
||||||
|
> warning.
|
||||||
|
|
||||||
|
Parses the central directory of the ZIP file and populates the `entries` and `directories`
|
||||||
|
fields. Used internally during initialization of the [ZipReader].
|
||||||
|
|
||||||
|
**Errors if the ZIP file is invalid.**
|
||||||
|
```luau
|
||||||
|
ZipReader:parseCentralDirectory()
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipReader:parseCentralDirectory]: #parseCentralDirectory
|
||||||
|
### `buildDirectoryTree`
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> This is a private API. It may be exported publically, but try to avoid
|
||||||
|
> using this API, since it can have breaking changes at any time without
|
||||||
|
> warning.
|
||||||
|
|
||||||
|
Builds the directory tree from the entries. Used internally during initialization of the
|
||||||
|
[ZipReader].
|
||||||
|
```luau
|
||||||
|
ZipReader:buildDirectoryTree()
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipReader:buildDirectoryTree]: #buildDirectoryTree
|
||||||
|
### `findEntry`
|
||||||
|
Finds a [ZipEntry] by its path in the ZIP archive.
|
||||||
|
```luau
|
||||||
|
ZipReader:findEntry(
|
||||||
|
path: string, -- Path to the entry to find
|
||||||
|
): ZipEntry?
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipReader:findEntry]: #findEntry
|
||||||
|
### `extract`
|
||||||
|
Extracts the specified [ZipEntry] from the ZIP archive. See [ZipReader:extractDirectory] for
|
||||||
|
extracting directories.
|
||||||
|
```luau
|
||||||
|
ZipReader:extract(
|
||||||
|
entry: ZipEntry, -- The entry to extract
|
||||||
|
options: ExtractionOptions?, -- Options for the extraction
|
||||||
|
): buffer | string
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipReader:extract]: #extract
|
||||||
|
### `extractDirectory`
|
||||||
|
Extracts all the files in a specified directory, skipping any directory entries.
|
||||||
|
|
||||||
|
**Errors if [ZipReader:extract] errors on an entry in the directory.**
|
||||||
|
```luau
|
||||||
|
ZipReader:extractDirectory(
|
||||||
|
path: string, -- The path to the directory to extract
|
||||||
|
options: ExtractionOptions?, -- Options for the extraction
|
||||||
|
): { [string]: buffer } | { [string]: string }
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipReader:extractDirectory]: #extractDirectory
|
||||||
|
### `listDirectory`
|
||||||
|
Lists the entries within a specified directory path.
|
||||||
|
```luau
|
||||||
|
ZipReader:listDirectory(
|
||||||
|
path: string, -- The path to the directory to list
|
||||||
|
): { ZipEntry }
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipReader:listDirectory]: #listDirectory
|
||||||
|
### `walk`
|
||||||
|
Recursively walks through the ZIP file, calling the provided callback for each entry
|
||||||
|
with the current entry and its depth.
|
||||||
|
```luau
|
||||||
|
ZipReader:walk(
|
||||||
|
callback: (entry: ZipEntry, depth: number) -> (), -- The function to call for each entry
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipReader:walk]: #walk
|
||||||
|
### `getStats`
|
||||||
|
Retrieves statistics about the ZIP file.
|
||||||
|
```luau
|
||||||
|
ZipReader:getStats(): ZipStatistics
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[ZipReader:getStats]: #getStats
|
||||||
|
|
||||||
|
## Types
|
||||||
|
### `ZipStatistics`
|
||||||
|
|
||||||
|
```luau
|
||||||
|
export type ZipStatistics = {
|
||||||
|
fileCount: number,
|
||||||
|
dirCount: number,
|
||||||
|
totalSize: number,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **fileCount** - The number of files in the ZIP
|
||||||
|
- **dirCount** - The number of directories in the ZIP
|
||||||
|
- **totalSize** - The total size of all files in the ZIP
|
||||||
|
|
||||||
|
[ZipStatistics]: #ZipStatistics
|
||||||
|
|
||||||
|
[ZipReader]: #ZipReader
|
|
@ -168,6 +168,14 @@ export type CompressionMethod = "STORE" | "DEFLATE"
|
||||||
|
|
||||||
A set of properties that describe a ZIP entry. Used internally for construction of
|
A set of properties that describe a ZIP entry. Used internally for construction of
|
||||||
[ZipEntry] objects.
|
[ZipEntry] objects.
|
||||||
|
|
||||||
|
@field versionMadeBy number -- Version of software and OS that created the ZIP
|
||||||
|
@field compressedSize number -- Compressed size in bytes
|
||||||
|
@field size number -- Uncompressed size in bytes
|
||||||
|
@field attributes number -- File attributes
|
||||||
|
@field timestamp number -- MS-DOS format timestamp
|
||||||
|
@field method CompressionMethod? -- Method used
|
||||||
|
@field crc number -- CRC32 checksum of the uncompressed data
|
||||||
]=]
|
]=]
|
||||||
type ZipEntryProperties = {
|
type ZipEntryProperties = {
|
||||||
versionMadeBy: number,
|
versionMadeBy: number,
|
||||||
|
@ -234,11 +242,10 @@ end
|
||||||
Resolves the path of the entry based on its relationship with other entries. It is recommended to use this
|
Resolves the path of the entry based on its relationship with other entries. It is recommended to use this
|
||||||
method instead of accessing the `name` property directly, although they should be equivalent.
|
method instead of accessing the `name` property directly, although they should be equivalent.
|
||||||
|
|
||||||
:::warning
|
> [!WARNING]
|
||||||
Never use this method when extracting files from the ZIP, since it can contain absolute paths
|
> Never use this method when extracting files from the ZIP, since it can contain absolute paths
|
||||||
(say `/etc/passwd`) referencing directories outside the current directory (say `/tmp/extracted`),
|
> (say `/etc/passwd`) referencing directories outside the current directory (say `/tmp/extracted`),
|
||||||
causing unintended overwrites of files.
|
> causing unintended overwrites of files.
|
||||||
:::
|
|
||||||
|
|
||||||
@return string -- The path of the entry
|
@return string -- The path of the entry
|
||||||
]=]
|
]=]
|
||||||
|
|
|
@ -10,6 +10,7 @@ includes = [
|
||||||
"pesde.toml",
|
"pesde.toml",
|
||||||
"lib/**/*.luau",
|
"lib/**/*.luau",
|
||||||
"!tests/**/*",
|
"!tests/**/*",
|
||||||
|
"docs/**/*.md"
|
||||||
]
|
]
|
||||||
|
|
||||||
[engines]
|
[engines]
|
||||||
|
|
Loading…
Add table
Reference in a new issue