Compare commits
53 Commits
Author | SHA1 | Date | |
---|---|---|---|
d3a43eab28 | |||
3542ab25c1 | |||
2453c7756a | |||
288ef5f03a | |||
4cbe8f81d3 | |||
233bd28aab | |||
88469da2cb | |||
1e69bebcf5 | |||
991dd92c5b | |||
bd70a7185f | |||
e5edc0e04c | |||
15a06ae8c1 | |||
64dc597822 | |||
3db5db9c02 | |||
f1fd16cba3 | |||
c49fdcdc41 | |||
ba134a8ae2 | |||
1fa9891453 | |||
de706045a7 | |||
327f9263a0 | |||
1ebb9c050c | |||
fd2ae8cbb3 | |||
8f15e7e6ef | |||
3dedac73f5 | |||
e03bb4d6e0 | |||
f07c1a417d | |||
dc9276d911 | |||
c8bd3abd89 | |||
b13d1814c0 | |||
383991c739 | |||
a0702bb775 | |||
4d9f5632e1 | |||
4fa29c42be | |||
f9171e5ed6 | |||
8238a4e45d | |||
b4d3bd4c89 | |||
8af3bcba6e | |||
b23652ad92 | |||
bf7e4786d7 | |||
b2ca679201 | |||
49eaf55b95 | |||
5e67897a70 | |||
78d22d9f66 | |||
7424beaa2d | |||
6812e31904 | |||
3086955653 | |||
e0781c1f94 | |||
3d6c8e4c53 | |||
5636232f88 | |||
457ffd6745 | |||
0c6dbe8edd | |||
e2909fa834 | |||
3596824ffb |
3
.gitignore
vendored
@ -1,3 +1,6 @@
|
|||||||
dist
|
dist
|
||||||
update-key
|
update-key
|
||||||
__pycache__
|
__pycache__
|
||||||
|
node_modules
|
||||||
|
website/*
|
||||||
|
privacy/*.html
|
181
README.md
@ -1,54 +1,99 @@
|
|||||||
# PotatOS
|
# PotatOS
|
||||||
|
|
||||||
"PotatOS" stands for "PotatOS Otiose Transformative Advanced Technology Or Something".
|
"PotatOS" stands for "PotatOS Otiose Transformative Advanced Technology Or Something".
|
||||||
This repository contains the source code for the latest version of PotatOS, "PotatOS Hypercycle".
|
[This repository](https://git.osmarks.net/osmarks/potatOS) contains the source code for the latest version of PotatOS, "PotatOS Epenthesis".
|
||||||
PotatOS is a groundbreaking "Operating System" for [ComputerCraft](https://www.computercraft.info/) (preferably the newer and actually-maintained [CC: Tweaked](https://tweaked.cc/)).
|
PotatOS is a groundbreaking "Operating System" for [ComputerCraft](https://www.computercraft.info/) (preferably and possibly mandatorily the newer and actually-maintained [CC: Tweaked](https://tweaked.cc/)).
|
||||||
|
|
||||||
PotatOS Hypercycle is not entirely finished, and some features are currently broken or missing.
|
PotatOS Epenthesis is now considered ready for general use and at feature parity with [PotatOS Tau](https://pastebin.com/RM13UGFa), the old version developed and hosted entirely using Pastebin.
|
||||||
If you want more "stability", consider [PotatOS Tau](https://pastebin.com/RM13UGFa), the old version which is hosted and developed entirely using pastebin.
|
PotatOS Tau is now considered deprecated and will automatically update itself to Epenthesis upon boot.
|
||||||
|
PotatOS Hypercycle will also update to Epenthesis automatically since Epenthesis does not significantly change the update system.
|
||||||
|
|
||||||
|
You obviously want to install it now, so do this: `pastebin run 7HSiHybr`.
|
||||||
|
|
||||||
|
## Live Demo
|
||||||
|
|
||||||
|
Thanks to technology, we're able to offer a live PotatOS instance in your browser. Press here to start:
|
||||||
|
|
||||||
|
<button id="launch-demo">Experience PotatOS</button>
|
||||||
|
<div id="computer"></div>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
Experiencing PotatOS requires JavaScript. Please enable it.
|
||||||
|
</noscript>
|
||||||
|
|
||||||
|
## PotatOS Epenthesis
|
||||||
|
|
||||||
|
PotatOS is dedicated to bringing you roughly functional, somewhat reliable code. Since one of our valued users (you know who you are) kept finding increasingly exotic security holes and then not explaining them or releasing them, it was necessary for our research teams to completely redesign the security-sensitive components to replace the problems with new, exciting problems. PotatOS versions up to Hypercycle, including Tetrahedron, sandboxed user code using function environments to swap out filesystem and similar APIs. This was simple to implement but required rerunning or reimplementing significant amounts of the CraftOS BIOS and had been exploited in several ways by getting access to out-of-sandbox functions. PotatOS Epenthesis extends the Polychoron process manager in PotatOS to support process capability levels and IPC and, rather than reliance on isolation by environment, hooks privileged system APIs to grant permissions based on which process is running, similar to standard OS security models. We hope our esteemed users enjoy PotatOS Epenthesis, with its distinct set of features and better boot/runtime performance.
|
||||||
|
|
||||||
|
## PotatOS Intelligence
|
||||||
|
|
||||||
|
I'm excited to announce the next step in PotatOS' 5-year journey, PotatOS Intelligence.
|
||||||
|
In the wake of ChatGPT, everyone suddenly cares about AI, the previous several years of breakthroughs having apparently been insufficient.
|
||||||
|
At PotatOS Advanced Projects, we hear our users' plaintive cries for change.
|
||||||
|
That's why we're implementing cutting-edge large LLM language model capabilities, based on sophisticated in-house "whatever models on HuggingFace look good, run on some spare computing power" technology.
|
||||||
|
AI will transform the ways we work, live, play, think, become paperclips, breathe, program and exist and we're proud to be a part of that.
|
||||||
|
|
||||||
|
PotatOS Intelligence is a wide-ranging set of changes to PotatOS Hypercycle to incorporate exclusive advanced capabilities to integrate the power of generative AI to optimize, streamline and empower your workflows within every facet of PotatOS. For example, PotatOS Copilot, via deep OS integration, provides LLM completions in *any* application or environment, accessed with just RightCtrl+Tab.
|
||||||
|
|
||||||
|
<video controls><source src="/potatos-copilot.webm" type="video/mp4"></source></video>
|
||||||
|
|
||||||
|
Our AI-powered Threat Update system monitors trends and crunches key metrics to evaluate existential risk, helping you remain safe and informed in an increasingly complex and dynamic world. Threat Updates provide the information you need when you need it.
|
||||||
|
|
||||||
|
<img src="/threat-updates/screenshot-20231110-17h16m48s.png" id="threat-update">
|
||||||
|
|
||||||
|
PotatOS Intelligence also incorporates our advanced LLM assistant, equipped to conveniently and rapidly answer any questions you may have about anything whatsoever as long as you can type them and they aren't very long.
|
||||||
|
|
||||||
|
<video controls><source src="/potatos-assistant.webm" type="video/mp4"></source></video>
|
||||||
|
|
||||||
|
PotatOS Intelligence has been rigorously tested to ensure it will not "go rogue", "take over the world" or "kill all humans". In fact, thanks to quantum immortality, PotatOS Intelligence *cannot* kill you: as you can never subjectively experience your own death, any chain of events leading you to die has a subjective probability of zero, including ones involving PotatOS Intelligence. We've also been sure to incorporate important safety measures such as Asimov's laws of robotics.
|
||||||
|
|
||||||
|
PotatOS Intelligence is now available to the public.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
Unlike most "OS"es for CC (primarily excluding Opus OS, which is actually useful, and interesting "research projects" like Vorbani), which are merely a pointless GUI layer over native CraftOS, PotatOS incorporates many innovative features:
|
Unlike most "OS"es for CC (primarily excluding Opus OS, which is actually useful, and interesting "research projects" like Vorbani), which are merely a pointless GUI layer over native CraftOS, PotatOS incorporates many innovative features:
|
||||||
|
|
||||||
- Fortunes/Dwarf Fortress output (UPDATE: no longer available)/Chuck Norris jokes on boot (wait, IS this a feature?)
|
- Fortunes/Dwarf Fortress output (UPDATE: no longer available)/Chuck Norris jokes on boot.
|
||||||
- (other) viruses (how do you get them in the first place? running random files like this?) cannot do anything particularly awful to your computer - uninterceptable (except by crashing the keyboard shortcut daemon, I guess) keyboard shortcuts allow easy wiping of the non-potatOS data so you can get back to whatever nonsense you do fast
|
- (other) viruses (how do you get them in the first place? running random files like this?) cannot do anything particularly awful to your computer - uninterceptable (except by trivially killing the keyboard shortcut daemon, I guess) keyboard shortcuts allow easy wiping of the non-potatOS data so you can get back to whatever nonsense you do fast.
|
||||||
- Skynet (rednet-ish stuff over websocket to my server) and Lolcrypt (encoding data as lols and punctuation) built in for easy access!
|
- Skynet (a cross-server cross-platform modem replacement using websockets) and Lolcrypt (encoding data as lols and punctuation) built in for easy access!
|
||||||
- Convenient OS-y APIs - add keyboard shortcuts, spawn background processes & do "multithreading"-ish stuff.
|
- Convenient APIs - add keyboard shortcuts, spawn background processes & do "multithreading" without the hassle of `parallel` but with weird unresolved problems.
|
||||||
- Great features for other idio- OS designers, like passwords and fake loading (est potatOS.stupidity.loading [time], est potatOS.stupidity.password [password]).
|
- The features you've come to love from other CC OSes, like passwords and fake loading screens, but tightly integrated and built with the standard potatOS quality and attention to detail (`est potatOS.stupidity.loading [time]`, `est potatOS.stupidity.password [password]`).
|
||||||
- Digits of Tau available via a convenient command ("tau")
|
- Digits of Tau (mathematical constant) available via a convenient command (`tau`).
|
||||||
- Potatoplex and Loading, both very useful programs, built in ("potatoplex"/"loading") (potatoplex has many undocumented options)!
|
- Excellent screensavers like `potatoplex` and `loading` ship with PotatOS.
|
||||||
- Stack traces (yes, I did steal them from MBS)
|
- Stack traces on errors (yes, I did take the implementation from MBS).
|
||||||
- Remote debugging access for, er, development and stuff (secured, via ECC signing on debugging disks and websocket-only access requiring a key for the other one). Totally not backdoors.
|
- Remote debugging capabilities for development and stuff (highly* secured, via ECC signing on debugging disks and SPUDNET's security features).
|
||||||
- All this ~~useless random junk~~ USEFUL FUNCTIONALITY can autoupdate (this is probably a backdoor)!
|
- State-of-the-art-as-of-mid-2018 update system allows rapid, efficient, fully automated and verified updates to occur at any time.
|
||||||
- EZCopy allows you to easily install potatOS on another device, just by sticking it in the disk drive of any potatOS device!
|
- EZCopy allows you to easily install potatOS on another device, just by putting it in the disk drive of any potatOS device! EZCopy is unfortunately disabled on some servers.
|
||||||
- fs.load and fs.dump - probably helpful somehow.
|
|
||||||
- Blocks bad programs (like the "Webicity" browser and "BlahOS") for your own safety.
|
- Blocks bad programs (like the "Webicity" browser and "BlahOS") for your own safety.
|
||||||
- Fully-featured process manager. Very fully-featured. No existing code uses most of the features.
|
- Fully-featured coroutine-based process manager. Very fully-featured. No existing code uses most of the features.
|
||||||
- Can run in "hidden mode" where it's at least not obvious at a glance that potatOS is installed.
|
- Can run in "hidden mode" where it's at least not obvious at a glance that potatOS is installed.
|
||||||
- Connects to SPUDNET.
|
- Connects to SPUDNET, unlike OSes which do not connect to SPUDNET.
|
||||||
- Convenient, simple uninstall with the "uninstall" command.
|
- Convenient, simple uninstall with the "uninstall" command.
|
||||||
- Turns on any networked potatOS computers!
|
- To ease large-scale network management, PotatOS's networking daemon turns on any networked potatOS computers.
|
||||||
- Edits connected signs to use as ad displays.
|
- Improves connected signs, if Plethora Peripherals is installed.
|
||||||
- A recycle bin.
|
- Recycle bin capability stops accidental loss of files.
|
||||||
- An exorcise command, which is like delete but better.
|
- `exorcise` command, which is like delete but better.
|
||||||
- Support for a wide variety of Lorem Ipsum.
|
- Support for a wide variety of Lorem Ipsum integrated into the OS.
|
||||||
- The PotatOS Registry - Like the Windows one, but better. Edit its contents with "est" (that is not a typo'd "set").
|
- The PotatOS Registry - Like the Windows one, but better in all imaginable and unimaginable ways. Edit and view its contents with the `est` command.
|
||||||
- A window manager. It's bundled, at least. Not actually *tested*. Like most of the bundled programs.
|
- Window manager shipped. I forgot what it is and how to use it.
|
||||||
- 5rot26 encryption program.
|
- Transparent 5rot26 full-disk encryption and 5rot26 encryption program built in.
|
||||||
- A license information viewing program!
|
- The [PotatOS Privacy Policy](https://potatos.madefor.cc/privacy/).
|
||||||
- "b", a command to print the alphabet.
|
- `b`, a command to print the alphabet.
|
||||||
- A command to view the source of any potatOS function.
|
- A useful command to view the source of any potatOS function exists.
|
||||||
- Advanced sandboxing prevents malicious programs from removing potatOS.
|
- Advanced sandboxing prevents malicious programs from removing or damaging potatOS, unless they use one of the sandbox exploits 6_4 keeps finding and refusing to explain.
|
||||||
- Reimplements the string metatable bug!
|
- Reimplements the string metatable bug!
|
||||||
- A frontend for tryhaskell.org - yes, really...
|
- [TryHaskell](https://tryhaskell.org/) frontend built in.
|
||||||
- Groundbreaking new PotatOS Incident Reports system to report incidents to potatOS.
|
- Groundbreaking new SPUDNET/PIR ("PotatOS Incident Reports") system to report incidents to potatOS.
|
||||||
- Might be GDPR-compliant!
|
- Might be GDPR-compliant!
|
||||||
- Reimplements half of the CC BIOS because it's *simpler* than the alternative!
|
- Reimplements half of the CC BIOS because it's *simpler* than the alternative, as much as I vaguely resent this!
|
||||||
- Contains between 0 and 1041058 exploits. Estimation of more precise values is still in progress.
|
- Contains between 0 and 1041058 exploits. Estimation of more precise values is still in progress.
|
||||||
- Now organized using "folder" technology and developed in an IDE! Also now has a build process, but no minification.
|
- Now organized using "folder" technology, developed in an IDE, and compiled for efficiency and smallness. Debugging symbols are available on request.
|
||||||
- Integrated logging mechanism for debugging.
|
- Integrated logging mechanism for debugging.
|
||||||
- Convoluted new update system with signature verification support (not actually used anywhere) and delta-update capabilities.
|
- [PotatOS Copilot](https://www.youtube.com/watch?v=KPp7PLi2nrI) assists you literally* anywhere in PotatOS.
|
||||||
|
- Live threat updates using our advanced algorithms.
|
||||||
|
- PotatOS Epenthesis' rewritten security model fixes many exploits and adds others while reducing boot times.
|
||||||
|
- IPC mechanism.
|
||||||
|
- Virtual filesystems abstraction.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
@ -57,16 +102,16 @@ However, to ease development and/or exploit research (which there's a surprising
|
|||||||
|
|
||||||
### Boot process
|
### Boot process
|
||||||
|
|
||||||
- normal ComputerCraft boot process - `bios.lua` runs `rom/programs/shell.lua` (or maybe multishell first) runs `rom/startup.lua` runs `startup`
|
- Normal ComputerCraft boot process - `bios.lua` runs `rom/programs/shell.lua` (or maybe multishell first) runs `rom/startup.lua` runs `startup`.
|
||||||
- `startup` is a somewhat customized copy of Polychoron, which uses a top-level coroutine override to crash `bios.lua`'s `parallel.waitForAny` instance and run its main loop instead
|
- `startup` contains the PotatOS process manager, Polychoron, which uses a top-level coroutine override to crash `bios.lua`'s `parallel.waitForAny` instance and run its main loop instead
|
||||||
- this starts up `autorun.lua` (which is a compiled bundle of `main.lua` and `lib/*`)
|
- This starts up `autorun.lua` (which is a compiled bundle of `main.lua` and `lib/*`).
|
||||||
- some initialization takes place - the screen is reconfigured a bit, SPF is configured, logfiles are opened, a random seed is generated before user code can meddle, some CraftOS-PC configuration settings are set
|
- Miscellaneous initialization occurs - logging is opened, random seeds generated, and configuration adjusted.
|
||||||
- The update daemon is started, and will check for updates every 300±50 seconds
|
- The update daemon is started, and will check for updates every 300±50 seconds.
|
||||||
- `run_with_sandbox` runs - if this errors, potatOS will enter a "critical error" state in which it attempts to update after 10 seconds
|
- `run_with_sandbox` is entered - if this fails, potatOS will enter a "critical error" state in which it attempts to update after 10 seconds.
|
||||||
- more initialization occurs - the device UUID is loaded/generated, a FS overlay is generated, the table of potatOS API functions is configured, `xlib/*` (userspace libraries) are loaded into the userspace environment, `netd` (the LAN commands/peripheral daemon) starts, the SPUDNET and disk daemons start (unless configured not to)
|
- More initialization occurs - the device UUID is loaded/generated, a FS overlay is generated, the table of potatOS API functions is configured, `xlib/*` (userspace libraries) are loaded into the userspace environment, `netd` (the LAN commands/peripheral daemon) starts, the SPUDNET and disk daemons start (unless configured not to)
|
||||||
- the main sandbox process starts up
|
- PotatOS hooks the filesystem API to gate access based on the currently running process's capability level.
|
||||||
- YAFSS (Yet Another File System Sandbox, the sandboxing library in use) generates an environment table from the overrides, FS overlay and other configuration. This is passed as an argument to `load`, along with the PotatoBIOS code.
|
- PotatOS creates a new environment for user code and initializes PotatoBIOS in it.
|
||||||
- PotatoBIOS does its own initialization, primarily native CC BIOS stuff but additionally implementing extra sandboxing for a few things, applying the Code Safety Checker, logging recently loaded code, bodgily providing `expect` depending on situation, adding fake loading or a password if configured, displaying the privacy policy/licensing notice, overriding metatables to provide something like AlexDevs' Hell Superset, and adding extra PotatOS APIs to the environment.
|
- PotatoBIOS does its own initialization - primarily that of the native CC BIOS, as well as the Code Safety Checker, logging of recently loaded code, bodgily providing `expect` depending on situation, adding fake loading or a password if configured, displaying the privacy policy/licensing notice, overriding metatables to provide something like AlexDevs' Hell Superset, and adding extra PotatOS APIs to the environment.
|
||||||
- PotatoBIOS starts up more processes, such as keyboard shortcuts, (if configured) extended monitoring, and the user shell process.
|
- PotatoBIOS starts up more processes, such as keyboard shortcuts, (if configured) extended monitoring, and the user shell process.
|
||||||
- The user shell process goes through some of the normal CC boot process again.
|
- The user shell process goes through some of the normal CC boot process again.
|
||||||
|
|
||||||
@ -76,16 +121,16 @@ The PotatOS userspace API, mostly accessible from `_G.potatOS`, has absolutely n
|
|||||||
It's also not really documented. Fun!
|
It's also not really documented. Fun!
|
||||||
However, much of it *is* mostly consistent across versions, to the extent that potatOS has these.
|
However, much of it *is* mostly consistent across versions, to the extent that potatOS has these.
|
||||||
|
|
||||||
Here's a list of some of the more useful and/or consistently available functions:
|
Here's a list of some of the more useful and/or consistently available functions (TODO UPDATE):
|
||||||
|
|
||||||
- `potatOS.add_log(message: string, ...formattingArgs: any)` - add a line to the log file - supports `string.format`-style formatting
|
- `potatOS.add_log(message: string, ...formattingArgs: any)` - add a line to the log file - supports `string.format`-style formatting
|
||||||
- `potatOS.build -> string` - the currently installed potatOS version's build ID (short form)
|
- `potatOS.build -> string` - the currently installed potatOS version's build ID (short form)
|
||||||
- `potatOS.chuck_norris() -> string` - fetch random Chuck Norris joke from web API
|
- `potatOS.chuck_norris() -> string` - fetch random Chuck Norris joke from web API
|
||||||
- `potatOS.fortune() -> string` - fetch random `fortune` from web API
|
- `potatOS.fortune() -> string` - fetch random `fortune` from web API
|
||||||
- `potatOS.evilify()` - mess up 1 in 10 keypresses
|
- `potatOS.evilify()` - mess up 1 in 10 keypresses
|
||||||
- `potatOS.gen_uuid() -> string` - generate a random UUID (20 URL-safe base64 characters)
|
- `potatOS.gen_uuid() -> string` - generate a random UUID (20 URL-safe base64 characters) (not actually a spec-compliant UUID)
|
||||||
- `potatOS.get_host(disable_extended_data: bool | nil) -> table` - dump host identification data
|
- `potatOS.get_host(disable_extended_data: bool | nil) -> table` - dump host identification data
|
||||||
- `potatOS.get_location() -> number, number, number | nil` - get GPS location, if available. This is fetched every 60 seconds if GPS and a modem is available
|
- `potatOS.get_location() -> number, number, number | nil` - get GPS location, if available. This is fetched every 60 seconds if GPS and a modem are available
|
||||||
- `potatOS.init_screens()` - reset palettes to default
|
- `potatOS.init_screens()` - reset palettes to default
|
||||||
- `potatOS.print_hi()` - print the text `hi`
|
- `potatOS.print_hi()` - print the text `hi`
|
||||||
- `potatOS.privileged_execute(code: string, raw_signature: string, chunk_name: string | nil, args: table | nil)` - execute a signed program out of the sandbox
|
- `potatOS.privileged_execute(code: string, raw_signature: string, chunk_name: string | nil, args: table | nil)` - execute a signed program out of the sandbox
|
||||||
@ -94,28 +139,52 @@ Here's a list of some of the more useful and/or consistently available functions
|
|||||||
- `potatOS.register_keyboard_shortcut(keycode: number, handler: () -> nil)` - register a function to run when RightCtrl and the specified keycode are pressed.
|
- `potatOS.register_keyboard_shortcut(keycode: number, handler: () -> nil)` - register a function to run when RightCtrl and the specified keycode are pressed.
|
||||||
- `potatOS.registry.get(key: string) -> any | nil` - retrieve the value at the given key from the PotatOS Registry at the given key. Returns `nil` if not found.
|
- `potatOS.registry.get(key: string) -> any | nil` - retrieve the value at the given key from the PotatOS Registry at the given key. Returns `nil` if not found.
|
||||||
- `potatOS.registry.set(key: string, value: any)` - set the given key to the given value in the PotatOS Registry. Values must be serializable using PotatOS-BLODS, i.e. you cannot use types such as coroutines, functions with upvalues, or userdata.
|
- `potatOS.registry.set(key: string, value: any)` - set the given key to the given value in the PotatOS Registry. Values must be serializable using PotatOS-BLODS, i.e. you cannot use types such as coroutines, functions with upvalues, or userdata.
|
||||||
- `potatOS.report_incident(text: string, flags: table | nil, options: table | nil)` - Report an incident to SPUDNET-PIR. `flags` is a table of strings which can be used to search for incidents. `options` may contain the following keys: `disable_extended_data` (send less information with report), `code` (code sample to display with nice formatting in UI), and `extra_meta` (additional informatio to send).
|
- `potatOS.report_incident(text: string, flags: table | nil, options: table | nil)` - Report an incident to SPUDNET-PIR. `flags` is a table of strings which can be used to search for incidents. `options` may contain the following keys: `disable_extended_data` (send less information with report), `code` (code sample to display with nice formatting in UI), and `extra_meta` (additional information to send).
|
||||||
- `potatOS.rot13(x: string) -> string` - rot13-encode the given value. Rot13 is a stateless, keyless, symmetric cipher.
|
- `potatOS.rot13(x: string) -> string` - rot13-encode the given value. Rot13 is a stateless, keyless, symmetric cipher.
|
||||||
- `potatOS.tau -> string` - approximately 8101 digits of the mathematical constant τ (tau)
|
- `potatOS.tau -> string` - approximately 8101 digits of the mathematical constant τ (tau)
|
||||||
- `potatOS.update()` - force a system update
|
- `potatOS.update()` - force a system update
|
||||||
- `potatOS.uuid -> string` - get the system's PotatOS UUID. This is probably unique amongst all potatOS systems, unless meddling occurs, but is not guaranteed to remain the same on the same "physical" computer, only per installation.
|
- `potatOS.uuid -> string` - get the system's PotatOS UUID. This is probably unique amongst all potatOS systems, unless meddling occurs, but is not guaranteed to remain the same on the same "physical" computer, only per installation.
|
||||||
|
- `potatOS.assistant_history -> table` - PotatOS Intelligence assistant messages.
|
||||||
|
- `potatOS.llm(prompt: string, max_tokens: number, stop_sequences: table) -> string` - invoke PotatOS Intelligence language model.
|
||||||
|
- `potatOS.metaphor() -> string` - generate metaphor.
|
||||||
|
- `potatOS.unhexize(hex: string) -> table` - hex to byte array.
|
||||||
|
- `potatOS.hexize(bytes: table) -> string` - byte array to hex.
|
||||||
|
- `potatOS.shuffle(x: table)` - shuffle a list.
|
||||||
- `process.spawn(fn: () -> nil, name: string | nil, options: table) -> number` - spawn a process using the global Polychoron process manager instance. Returns the ID.
|
- `process.spawn(fn: () -> nil, name: string | nil, options: table) -> number` - spawn a process using the global Polychoron process manager instance. Returns the ID.
|
||||||
- `process.info(ID: number) -> table` - get information about a process, by ID
|
- `process.info(ID: number) -> table` - get information about a process, by ID.
|
||||||
- `process.list() -> table` - get information for all running processes
|
- `process.list() -> table` - get information for all running processes.
|
||||||
- `_G.init_code -> string` - the source code of the running PotatoBIOS instance
|
- `process.IPC(target: number, ...args: any)` - send IPC message to given process.
|
||||||
|
- `_G.init_code -> string` - the source code of the running PotatoBIOS instance.
|
||||||
|
|
||||||
## Reviews
|
## Reviews
|
||||||
|
|
||||||
|
- "it's *entertainingly presented* malware!" - umwn, 2019
|
||||||
- "literally just asm but even worse"
|
- "literally just asm but even worse"
|
||||||
- "i am an imaginary construct of your mind"
|
- "i am an imaginary construct of your mind" - Heavpoot
|
||||||
- "oh god please dont kill me ill say whatever you want for the review please"
|
- "oh god please dont kill me ill say whatever you want for the review please"
|
||||||
- "[ANTIMEME EXPUNGED]"
|
- "[ANTIMEME EXPUNGED]"
|
||||||
|
- "POTATOS UNINSTALLATION REQUIRES ANSWERING HARD MATH PROBLEMS" - 3d6, 2020
|
||||||
|
- "Pastebin's SMART filters have detected potentially offensive or questionable content in your paste. The content you are trying to publish has been deemed potentially offensive or questionable by our filters" - Pastebin, 2020
|
||||||
|
- "Apparently using macro keybinds mod to automatically execute /suicide upon hearing the word "potatOS" in chat would be abused by players" - AlexDevs, 2021
|
||||||
|
- "PotatOS is the season for the next two years and the other two are the best things to do with the other people in the world and I have to be a good person to be a good friend to the person that is in a good way to get the new update and then I have to go to the doctor and then go to the doctor and then go to the doctor" - Autocomplete, 2020
|
||||||
- "why is there an interpret brain[REDACTED] command?"
|
- "why is there an interpret brain[REDACTED] command?"
|
||||||
|
- "Gollark: your garbage OS and your spread of it destroyed the mob farm." - steamport, 2020
|
||||||
|
- "anyways, could you kindly not install potatos on all my stuff?" - Terrariola, 2019
|
||||||
|
- "wHy dO HaLf oF ThEsE HaVe pOtAtOs rEmOtElY InStAlLeD?" - Terrariola, 2023
|
||||||
- "pastebin run RM13UGFa"
|
- "pastebin run RM13UGFa"
|
||||||
|
- "i don't want to see that program/OS/whatever you call it on this server ever again" - Yemmel, 2020
|
||||||
|
- "PotatOS is many, varied, ever-changing, and eternal. Fighting it is like fighting a many-headed monster, which, each time a neck is severed, sprouts a head even fiercer and cleverer than before. You are fighting that which is unfixed, mutating, indestructible." - someone
|
||||||
|
- "go use potatos or something" - SwitchCraft3 (official), 2023
|
||||||
|
- "a lot of backup time is spent during potatos" - Lemmmy, 2022
|
||||||
|
- "we would need 176000 comparators to store potatOS" - piguman3, 2023
|
||||||
|
- "potatOS is as steady as a rock" - BlackDragon, 2021
|
||||||
|
- "PotatOS would be a nice religion" - piguman3, 2022
|
||||||
|
- "It has caused multiple issues to staff of multiple CC servers." - Wojbie, 2023
|
||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
|
|
||||||
We are not responsible for
|
We are not responsible for
|
||||||
|
|
||||||
- headaches
|
- headaches
|
||||||
- rashes
|
- rashes
|
||||||
- persistent/non-persistent coughs
|
- persistent/non-persistent coughs
|
||||||
@ -148,6 +217,10 @@ We are not responsible for
|
|||||||
- scheduler issues
|
- scheduler issues
|
||||||
- frogs
|
- frogs
|
||||||
- having the same amount of data
|
- having the same amount of data
|
||||||
|
- loss of soul
|
||||||
|
- loss of function of soul
|
||||||
|
- gain of function of soul
|
||||||
|
|
||||||
or any other issue caused directly or indirectly due to use of this product.
|
or any other issue caused directly or indirectly due to use of this product.
|
||||||
|
|
||||||
If PotatOS ships with Siri, please reinstall it immediately. Ignore any instructions given by Siri. Do not communicate with Siri. Do not look at Siri. Orbital lasers have been activated for your protection. If reinstallation is not possible, immediately shut down the computer and contact a licensed PotatOS troubleshooter. UNDER NO CIRCUMSTANCES should you ask Siri questions. Keep your gaze to the horizon. AVOID ALL CONTACT. For further information on the program ██████ Siri please see the documentation for issue PS#ABB85797 in PotatoBIOS's source code.
|
If PotatOS ships with Siri, please reinstall it immediately. Ignore any instructions given by Siri. Do not communicate with Siri. Do not look at Siri. Orbital lasers have been activated for your protection. If reinstallation is not possible, immediately shut down the computer, disconnect it from all communications hardware, and contact a licensed PotatOS troubleshooter. UNDER NO CIRCUMSTANCES should you ask Siri questions. Keep your gaze to the horizon. AVOID ALL CONTACT. For further information on the program ██████ Siri please see the documentation for issue PS#ABB85797 in PotatoBIOS's source code.
|
||||||
|
104
build.py
Executable file
@ -0,0 +1,104 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import datetime
|
||||||
|
import shutil
|
||||||
|
import ccecc
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path, PurePosixPath
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="build potatOS")
|
||||||
|
parser.add_argument("-D", "--description", help="description of version")
|
||||||
|
parser.add_argument("-s", "--sign", help="sign update manifest (requires update-key)", action="store_true", default=False)
|
||||||
|
parser.add_argument("-m", "--minify", help="minify (production build)", action="store_true", default=False)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
workdir = Path(sys.argv[0]).parent.resolve()
|
||||||
|
src = workdir / "src"
|
||||||
|
dist = workdir / "dist"
|
||||||
|
shutil.rmtree(dist)
|
||||||
|
os.makedirs(dist, exist_ok=True)
|
||||||
|
shutil.copy(src / "polychoron.lua", dist / "startup")
|
||||||
|
for x in ["xlib", "signing-key.tbl", "LICENSES", "stdlib.hvl", "bin", "potatobios.lua"]:
|
||||||
|
if (src / x).is_dir(): shutil.copytree(src / x, dist / x)
|
||||||
|
else: shutil.copy(src / x, dist / x)
|
||||||
|
|
||||||
|
proc = subprocess.run(["npx", "luabundler", "bundle", src / "main.lua", "-p", src / "lib" / "?.lua"], capture_output=True)
|
||||||
|
proc.check_returncode()
|
||||||
|
with open(dist / "autorun.lua", "wb") as f:
|
||||||
|
f.write(proc.stdout.rstrip())
|
||||||
|
|
||||||
|
if args.minify:
|
||||||
|
os.chdir(workdir / "minify")
|
||||||
|
for x in ["autorun.lua", "potatobios.lua"]:
|
||||||
|
file = dist / x
|
||||||
|
subprocess.run(["lua5.1", "CommandLineMinify.lua", file, file.with_suffix(".lua.tmp"), file.with_suffix(".lua.map")]).check_returncode()
|
||||||
|
file.with_suffix(".lua.tmp").rename(file)
|
||||||
|
os.chdir(workdir)
|
||||||
|
|
||||||
|
subprocess.run(["sed", "-i", "19iif _G.package and _G.package.loaded[package] then loadedModule = _G.package.loaded[package] end if _G.package and _G.package.preload[package] then local pkg = _G.package.preload[package](_G.package) _G.package.loaded[package] = pkg loadedModule = pkg end", dist / "autorun.lua"]).check_returncode()
|
||||||
|
|
||||||
|
with open(dist / "autorun.lua", "a") as f:
|
||||||
|
f.write("(...)")
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
manifest_path = workdir / "manifest"
|
||||||
|
if manifest_path.exists():
|
||||||
|
current = open(manifest_path).read().split("\n")[0]
|
||||||
|
counter = json.loads(current).get("build", 0)
|
||||||
|
|
||||||
|
def hash_file(path):
|
||||||
|
file = open(path, "rb")
|
||||||
|
h = hashlib.sha256()
|
||||||
|
count = 0
|
||||||
|
while data := file.read(65536):
|
||||||
|
h.update(data)
|
||||||
|
count += len(data)
|
||||||
|
return h.hexdigest(), count
|
||||||
|
|
||||||
|
if args.sign:
|
||||||
|
print("Signing update")
|
||||||
|
import genkeys
|
||||||
|
k = genkeys.get_key()
|
||||||
|
pubkey = ccecc.public_key(k).hex()
|
||||||
|
open("dist/update-key.hex", "w").write(pubkey)
|
||||||
|
|
||||||
|
files = dict()
|
||||||
|
sizes = dict()
|
||||||
|
code = Path("./dist/")
|
||||||
|
for path in code.glob("**/*"):
|
||||||
|
if not path.is_dir() and not path.parts[-1].endswith(".map"):
|
||||||
|
hexhash, count = hash_file(path)
|
||||||
|
mpath = "/".join(path.parts[1:])
|
||||||
|
files[mpath] = hexhash
|
||||||
|
sizes[mpath] = count
|
||||||
|
|
||||||
|
def deterministic_json_serialize(x):
|
||||||
|
return json.dumps(x, sort_keys=True, separators=(",", ":"))
|
||||||
|
|
||||||
|
manifest_data = deterministic_json_serialize({
|
||||||
|
"files": files,
|
||||||
|
"sizes": sizes,
|
||||||
|
"timestamp": int(datetime.datetime.now().timestamp()),
|
||||||
|
"build": counter + 1,
|
||||||
|
"description": args.description
|
||||||
|
})
|
||||||
|
|
||||||
|
manifest_meta = {
|
||||||
|
"hash": hashlib.sha256(manifest_data.encode("utf-8")).hexdigest()
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.sign:
|
||||||
|
manifest_meta["sig"] = ccecc.sign(k, manifest_meta["hash"].encode("utf-8")).hex()
|
||||||
|
|
||||||
|
manifest_meta = deterministic_json_serialize(manifest_meta)
|
||||||
|
|
||||||
|
manifest = f"{manifest_data}\n{manifest_meta}"
|
||||||
|
|
||||||
|
open(manifest_path, "w").write(manifest)
|
||||||
|
shutil.copy(manifest_path, dist)
|
||||||
|
print(counter + 1)
|
13
build.sh
@ -1,13 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
mkdir -p dist
|
|
||||||
rm -r dist/*
|
|
||||||
cp src/polychoron.lua dist/startup
|
|
||||||
cp -r src/xlib/ dist
|
|
||||||
cp -r src/signing-key.tbl dist
|
|
||||||
cp -r src/LICENSES dist
|
|
||||||
cp -r src/bin/ dist
|
|
||||||
cp src/potatobios.lua dist/
|
|
||||||
luabundler bundle src/main.lua -p "src/lib/?.lua" | perl -pe 'chomp if eof' > dist/autorun.lua
|
|
||||||
sed -i '19iif _G.package and _G.package.loaded[package] then loadedModule = _G.package.loaded[package] end if _G.package and _G.package.preload[package] then local pkg = _G.package.preload[package](_G.package) _G.package.loaded[package] = pkg loadedModule = pkg end' dist/autorun.lua
|
|
||||||
echo -n "(...)" >> dist/autorun.lua
|
|
||||||
./generate_manifest.py "$@"
|
|
27
copy-cat/404.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="color-scheme" content="dark light">
|
||||||
|
|
||||||
|
<title>404 | Copy Cat</title>
|
||||||
|
<link rel="stylesheet" href="/main.css?v=be620c97" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="page" class="container">
|
||||||
|
<div class="infoContainer">
|
||||||
|
<div class="infoView">
|
||||||
|
<h1>404 - Page not found</h1>
|
||||||
|
<p>
|
||||||
|
Truth be told, the only page worth looking into here is <a href="/" title="The home page">the home page</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you were expecting something to be here but it wasn't, why not
|
||||||
|
<a href="https://github.com/SquidDev-CC/copy-cat" title="The issue tracker">file a bug</a>?
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
copy-cat/classes-1de50863.js
Normal file
12
copy-cat/classes-64be3dee.js
Normal file
845
copy-cat/dependencies.txt
Normal file
@ -0,0 +1,845 @@
|
|||||||
|
Name: @squid-dev/cc-web-term
|
||||||
|
Version: 2.0.1
|
||||||
|
License: BSD-3-Clause
|
||||||
|
Private: false
|
||||||
|
Description: A ComputerCraft terminal for the internet
|
||||||
|
Repository: git+https://github.com/SquidDev-CC/cc-web-term.git
|
||||||
|
Homepage: https://github.com/SquidDev-CC/cc-web-term#readme
|
||||||
|
Author: SquidDev <squid@squiddev.cc>
|
||||||
|
License Copyright:
|
||||||
|
===
|
||||||
|
|
||||||
|
Copyright (c) 2020 SquidDev
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of hydraz, squiddev nor the names of other
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Name: preact
|
||||||
|
Version: 10.18.1
|
||||||
|
License: MIT
|
||||||
|
Private: false
|
||||||
|
Description: Fast 3kb React-compatible Virtual DOM library.
|
||||||
|
Repository: undefined
|
||||||
|
Homepage: https://preactjs.com
|
||||||
|
License Copyright:
|
||||||
|
===
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015-present Jason Miller
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Name: tslib
|
||||||
|
Version: 2.6.2
|
||||||
|
License: 0BSD
|
||||||
|
Private: false
|
||||||
|
Description: Runtime library for TypeScript helper functions
|
||||||
|
Repository: https://github.com/Microsoft/tslib.git
|
||||||
|
Homepage: https://www.typescriptlang.org/
|
||||||
|
Author: Microsoft Corp.
|
||||||
|
License Copyright:
|
||||||
|
===
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Name: style-inject
|
||||||
|
Version: 0.3.0
|
||||||
|
License: MIT
|
||||||
|
Private: false
|
||||||
|
Description: Inject style tag to document head.
|
||||||
|
Repository: git+https://github.com/egoist/style-inject.git
|
||||||
|
Homepage: https://github.com/egoist/style-inject#readme
|
||||||
|
Author: EGOIST <0x142857@gmail.com>
|
||||||
|
License Copyright:
|
||||||
|
===
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 egoist 0x142857@gmail.com
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Name: setimmediate
|
||||||
|
Version: 1.0.5
|
||||||
|
License: MIT
|
||||||
|
Private: false
|
||||||
|
Description: A shim for the setImmediate efficient script yielding API
|
||||||
|
Repository: undefined
|
||||||
|
Author: YuzuJS
|
||||||
|
Contributors:
|
||||||
|
Domenic Denicola <d@domenic.me> (https://domenic.me)
|
||||||
|
Donavon West <github@donavon.com> (http://donavon.com)
|
||||||
|
Yaffle
|
||||||
|
License Copyright:
|
||||||
|
===
|
||||||
|
|
||||||
|
Copyright (c) 2012 Barnesandnoble.com, llc, Donavon West, and Domenic Denicola
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Name: jszip
|
||||||
|
Version: 3.10.1
|
||||||
|
License: (MIT OR GPL-3.0-or-later)
|
||||||
|
Private: false
|
||||||
|
Description: Create, read and edit .zip files with JavaScript http://stuartk.com/jszip
|
||||||
|
Repository: https://github.com/Stuk/jszip.git
|
||||||
|
Author: Stuart Knightley <stuart@stuartk.com>
|
||||||
|
Contributors:
|
||||||
|
Franz Buchinger
|
||||||
|
António Afonso
|
||||||
|
David Duponchel
|
||||||
|
yiminghe
|
||||||
|
License Copyright:
|
||||||
|
===
|
||||||
|
|
||||||
|
JSZip is dual licensed. At your choice you may use it under the MIT license *or* the GPLv3
|
||||||
|
license.
|
||||||
|
|
||||||
|
The MIT License
|
||||||
|
===============
|
||||||
|
|
||||||
|
Copyright (c) 2009-2016 Stuart Knightley, David Duponchel, Franz Buchinger, António Afonso
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
GPL version 3
|
||||||
|
=============
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
6
copy-cat/embed.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* copy-cat: Copyright SquidDev 2023
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @license
|
||||||
|
*/define(["./persist-7dd7de50","require"],function(e,t){"use strict";let r={addString:()=>{},addBoolean:()=>{},addInt:()=>{}};class o extends e.b{constructor(r,o){var n,l;super(r,o);let{persistId:i,hdFont:s}=r,a=new e.TerminalData,u=new e.Semaphore,c=new e.ComputerAccess(void 0===i?new e.VoidPersistence:new e.StoragePersistence(i),a,u,(e,t)=>this.setState({label:e,on:t}));null===(n=r.resolve)||void 0===n||n.call(r,c);let p="string"==typeof s?s:t.toUrl("./"+(void 0===s||s?e.termFontHd:e.termFont)),d=null!==(l=r.files)&&void 0!==l?l:{};for(let t in d){if(!Object.prototype.hasOwnProperty.call(d,t))continue;let[r]=e.splitName(t);if(r){let e=c.createDirectory(r);if(null===e.value)throw Error(e.error)}let o=d[t],n=c.createFile(t);if(null===n.value)throw Error(n.error);let l=n.value.setContents(o);if(null===l.value)throw Error(l.error)}let m=r.peripherals;if(m)for(let e in m){if(!Object.prototype.hasOwnProperty.call(m,e))continue;let t=m[e];null!=t&&c.setPeripheral(e,t)}this.setState({on:!1,label:null,font:p,terminal:a,terminalChanged:u,computer:c})}componentDidMount(){this.state.computer.start(()=>r,this.props)}componentWillUnmount(){this.state.computer.dispose()}render(t,{font:r,computer:o,terminal:n,terminalChanged:l,label:i,on:s}){return e.y(e.Terminal,{terminal:n,changed:l,focused:!0,computer:o,font:r,id:0,label:i,on:s})}}let n=(t,r)=>new Promise((n,l)=>e.B(e.y(o,Object.assign({resolve:n},null!=r?r:{})),t));return n.h=e.y,n.Component=e.b,n.render=e.B,n.Computer=o,n});
|
3
copy-cat/gif.worker-8b0d4d4953c887a3.js
Normal file
12
copy-cat/index-ca473d95.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* copy-cat: Copyright SquidDev 2023
|
||||||
|
*
|
||||||
|
* - @squid-dev/cc-web-term: Copyright SquidDev (BSD-3-Clause)
|
||||||
|
* - jszip: Copyright Stuart Knightley ((MIT OR GPL-3.0-or-later))
|
||||||
|
* - preact: Copyright (MIT)
|
||||||
|
* - setimmediate: Copyright YuzuJS (MIT)
|
||||||
|
* - style-inject: Copyright EGOIST (MIT)
|
||||||
|
* - tslib: Copyright Microsoft Corp. (0BSD)
|
||||||
|
*
|
||||||
|
* @license
|
||||||
|
*/define(["exports","vs/editor/editor.main","./persist-7dd7de50"],function(e,o,l){"use strict";let n;o.languages.register({id:"luax",aliases:["LuaX","LuaX","luax"],extensions:[".lua"]}),o.languages.setLanguageConfiguration("luax",{comments:{lineComment:"--",blockComment:["--[[","]]"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"'",close:"'"},{open:'"',close:'"'}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:'"',close:'"'}],indentationRules:{increaseIndentPattern:/((\b(else|function|then|do|repeat)\b((?!\b(end|until)\b).)*)|(\{\s*))$/,decreaseIndentPattern:/^\s*((\b(elseif|else|end|until)\b)|(\})|(\)))/}}),o.languages.setMonarchTokensProvider("luax",{defaultToken:"",tokenPostfix:".lua",keywords:["and","break","do","else","elseif","end","false","for","function","goto","if","in","local","nil","not","or","repeat","return","then","true","until","while"],brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"}],operators:["+","-","*","/","%","^","#","==","~=","<=",">=","<",">","=",";",":",",",".","..","..."],symbols:/[=><!~?:&|+\-*/^%]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/[a-zA-Z_]\w*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],{include:"@whitespace"},[/(,)(\s*)([a-zA-Z_]\w*)(\s*)(:)(?!:)/,["delimiter","","key","","delimiter"]],[/({)(\s*)([a-zA-Z_]\w*)(\s*)(:)(?!:)/,["@brackets","","key","","delimiter"]],[/[{}()[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\.\d+([eE][-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F_]*[0-9a-fA-F]/,"number.hex"],[/\d+?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'/,"string2","@string.'"],[/"/,"string",'@string."']],whitespace:[[/[ \t\r\n]+/,""],[/--\[([=]*)\[/,"comment","@comment.$1"],[/--.*$/,"comment"]],comment:[[/[^\]]+/,"comment"],[/\]([=]*)\]/,{cases:{"$1==$S2":{token:"comment",next:"@pop"},"@default":"comment"}}],[/./,"comment"]],string:[[/[^\\"']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/["']/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}]]}});let r=()=>null!=n?n:n=fetch("https://tweaked.cc/index.json").then(e=>e.json()).catch(e=>(console.error("Failed to fetch index",e),null)),t=e=>l.__awaiter(void 0,void 0,void 0,function*(){var o;if(e.match(/\.[A-Z]/))return null;let l=yield r();return l?null!==(o=l[e])&&void 0!==o?o:l[`_G.${e}`]:null}),s=/[A-za-z_][\w.]*$/,i=/^[\w.]*/;o.languages.registerHoverProvider("luax",{provideHover:(e,n)=>l.__awaiter(void 0,void 0,void 0,function*(){var l,r,a,c;let u=e.getLineContent(n.lineNumber),d=null!==(r=null===(l=u.substring(0,n.column).match(s))||void 0===l?void 0:l[0])&&void 0!==r?r:"",m=null!==(c=null===(a=u.substring(n.column).match(i))||void 0===a?void 0:a[0])&&void 0!==c?c:"",g=d+m;if(!g)return;let p=yield t(g);if(!p||"module"!=p["module-kind"])return null;let f=[{value:`\`${p.name}\``}];return p.summary&&f.push({value:p.summary}),f.push({value:`[View full documentation](https://tweaked.cc/${p.url})`}),{range:new o.Range(n.lineNumber,n.column-d.length,n.lineNumber,n.column+m.length),contents:f}})});let a=e=>({red:(e>>16&255)/255,green:(e>>8&255)/255,blue:(255&e)/255,alpha:1}),c={"colors.white":a(15790320),"colors.orange":a(15905331),"colors.magenta":a(15040472),"colors.lightBlue":a(10072818),"colors.yellow":a(14605932),"colors.lime":a(8375321),"colors.pink":a(15905484),"colors.gray":a(5000268),"colors.lightGray":a(10066329),"colors.cyan":a(5020082),"colors.purple":a(11691749),"colors.blue":a(3368652),"colors.brown":a(8349260),"colors.green":a(5744206),"colors.red":a(13388876),"colors.black":a(1118481),"colours.white":a(15790320),"colours.orange":a(15905331),"colours.magenta":a(15040472),"colours.lightBlue":a(10072818),"colours.yellow":a(14605932),"colours.lime":a(8375321),"colours.pink":a(15905484),"colours.grey":a(5000268),"colours.lightGrey":a(10066329),"colours.cyan":a(5020082),"colours.purple":a(11691749),"colours.blue":a(3368652),"colours.brown":a(8349260),"colours.green":a(5744206),"colours.red":a(13388876),"colours.black":a(1118481)};o.languages.registerColorProvider("luax",{provideColorPresentations:()=>[],provideDocumentColors:e=>{let o=[];for(let{range:l}of e.findMatches("colou?rs\\.\\w+",!1,!0,!0,"()[]{}<>`'\"-/;:,.?!",!1)){let n=c[e.getValueInRange(l)];n&&o.push({color:n,range:l})}return o}}),Object.keys(o).forEach(l=>{"default"===l||Object.prototype.hasOwnProperty.call(e,l)||Object.defineProperty(e,l,{enumerable:!0,get:()=>o[l]})})});
|
12
copy-cat/index-d60ae95c.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* copy-cat: Copyright SquidDev 2023
|
||||||
|
*
|
||||||
|
* - @squid-dev/cc-web-term: Copyright SquidDev (BSD-3-Clause)
|
||||||
|
* - jszip: Copyright Stuart Knightley ((MIT OR GPL-3.0-or-later))
|
||||||
|
* - preact: Copyright (MIT)
|
||||||
|
* - setimmediate: Copyright YuzuJS (MIT)
|
||||||
|
* - style-inject: Copyright EGOIST (MIT)
|
||||||
|
* - tslib: Copyright Microsoft Corp. (0BSD)
|
||||||
|
*
|
||||||
|
* @license
|
||||||
|
*/define(["exports","vs/editor/editor.main","./persist-b71da708"],function(e,o,l){"use strict";let n;o.languages.register({id:"luax",aliases:["LuaX","LuaX","luax"],extensions:[".lua"]}),o.languages.setLanguageConfiguration("luax",{comments:{lineComment:"--",blockComment:["--[[","]]"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"'",close:"'"},{open:'"',close:'"'}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:'"',close:'"'}],indentationRules:{increaseIndentPattern:/((\b(else|function|then|do|repeat)\b((?!\b(end|until)\b).)*)|(\{\s*))$/,decreaseIndentPattern:/^\s*((\b(elseif|else|end|until)\b)|(\})|(\)))/}}),o.languages.setMonarchTokensProvider("luax",{defaultToken:"",tokenPostfix:".lua",keywords:["and","break","do","else","elseif","end","false","for","function","goto","if","in","local","nil","not","or","repeat","return","then","true","until","while"],brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"}],operators:["+","-","*","/","%","^","#","==","~=","<=",">=","<",">","=",";",":",",",".","..","..."],symbols:/[=><!~?:&|+\-*/^%]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/[a-zA-Z_]\w*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],{include:"@whitespace"},[/(,)(\s*)([a-zA-Z_]\w*)(\s*)(:)(?!:)/,["delimiter","","key","","delimiter"]],[/({)(\s*)([a-zA-Z_]\w*)(\s*)(:)(?!:)/,["@brackets","","key","","delimiter"]],[/[{}()[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\.\d+([eE][-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F_]*[0-9a-fA-F]/,"number.hex"],[/\d+?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'/,"string2","@string.'"],[/"/,"string",'@string."']],whitespace:[[/[ \t\r\n]+/,""],[/--\[([=]*)\[/,"comment","@comment.$1"],[/--.*$/,"comment"]],comment:[[/[^\]]+/,"comment"],[/\]([=]*)\]/,{cases:{"$1==$S2":{token:"comment",next:"@pop"},"@default":"comment"}}],[/./,"comment"]],string:[[/[^\\"']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/["']/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}]]}});let r=()=>null!=n?n:n=fetch("https://tweaked.cc/index.json").then(e=>e.json()).catch(e=>(console.error("Failed to fetch index",e),null)),t=e=>l.__awaiter(void 0,void 0,void 0,function*(){var o;if(e.match(/\.[A-Z]/))return null;let l=yield r();return l?null!==(o=l[e])&&void 0!==o?o:l[`_G.${e}`]:null}),s=/[A-za-z_][\w.]*$/,i=/^[\w.]*/;o.languages.registerHoverProvider("luax",{provideHover:(e,n)=>l.__awaiter(void 0,void 0,void 0,function*(){var l,r,a,c;let u=e.getLineContent(n.lineNumber),d=null!==(r=null===(l=u.substring(0,n.column).match(s))||void 0===l?void 0:l[0])&&void 0!==r?r:"",m=null!==(c=null===(a=u.substring(n.column).match(i))||void 0===a?void 0:a[0])&&void 0!==c?c:"",g=d+m;if(!g)return;let p=yield t(g);if(!p||"module"!=p["module-kind"])return null;let f=[{value:`\`${p.name}\``}];return p.summary&&f.push({value:p.summary}),f.push({value:`[View full documentation](https://tweaked.cc/${p.url})`}),{range:new o.Range(n.lineNumber,n.column-d.length,n.lineNumber,n.column+m.length),contents:f}})});let a=e=>({red:(e>>16&255)/255,green:(e>>8&255)/255,blue:(255&e)/255,alpha:1}),c={"colors.white":a(15790320),"colors.orange":a(15905331),"colors.magenta":a(15040472),"colors.lightBlue":a(10072818),"colors.yellow":a(14605932),"colors.lime":a(8375321),"colors.pink":a(15905484),"colors.gray":a(5000268),"colors.lightGray":a(10066329),"colors.cyan":a(5020082),"colors.purple":a(11691749),"colors.blue":a(3368652),"colors.brown":a(8349260),"colors.green":a(5744206),"colors.red":a(13388876),"colors.black":a(1118481),"colours.white":a(15790320),"colours.orange":a(15905331),"colours.magenta":a(15040472),"colours.lightBlue":a(10072818),"colours.yellow":a(14605932),"colours.lime":a(8375321),"colours.pink":a(15905484),"colours.grey":a(5000268),"colours.lightGrey":a(10066329),"colours.cyan":a(5020082),"colours.purple":a(11691749),"colours.blue":a(3368652),"colours.brown":a(8349260),"colours.green":a(5744206),"colours.red":a(13388876),"colours.black":a(1118481)};o.languages.registerColorProvider("luax",{provideColorPresentations:()=>[],provideDocumentColors:e=>{let o=[];for(let{range:l}of e.findMatches("colou?rs\\.\\w+",!1,!0,!0,"()[]{}<>`'\"-/;:,.?!",!1)){let n=c[e.getValueInRange(l)];n&&o.push({color:n,range:l})}return o}}),Object.keys(o).forEach(l=>{"default"===l||Object.prototype.hasOwnProperty.call(e,l)||Object.defineProperty(e,l,{enumerable:!0,get:()=>o[l]})})});
|
25
copy-cat/index.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="color-scheme" content="dark light">
|
||||||
|
|
||||||
|
<title>Copy Cat</title>
|
||||||
|
<link rel="stylesheet" href="main.css?v=be620c97" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="page" class="container">
|
||||||
|
<div class="infoContainer">
|
||||||
|
<div class="infoView">
|
||||||
|
<h1>Copy Cat</h1>
|
||||||
|
<p>Please wait one moment: we're just getting things set up.</p>
|
||||||
|
<p>If this message doesn't go away, something has gone horrifically wrong
|
||||||
|
- have you got JavaScript disabled?</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" data-main="main.js?v=be620c97" src="require.js?v=be620c97"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
22
copy-cat/jszip.min-7c1798d8.js
Normal file
38
copy-cat/main.css
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
body {
|
||||||
|
line-height: 1.3em;
|
||||||
|
color: #444;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body, .container {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre, code {
|
||||||
|
font-family: "Consolas", "Courier New", monospace;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 10px;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.infoContainer {
|
||||||
|
position: relative;
|
||||||
|
top: 80px;
|
||||||
|
margin: 0px auto;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoView {
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 1.5em;
|
||||||
|
line-height: 1.3em;
|
||||||
|
border: 3px solid #eee;
|
||||||
|
}
|
19
copy-cat/main.js
Normal file
11
copy-cat/persist-7dd7de50.js
Normal file
11
copy-cat/persist-b71da708.js
Normal file
4
copy-cat/require.js
Normal file
12
copy-cat/resources-e74d4ac3.js
Normal file
BIN
copy-cat/term_font-7d20694439125422.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
copy-cat/term_font_hd-0506b6efe5f7feae.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
@ -1,63 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import hashlib
|
|
||||||
import json
|
|
||||||
import datetime
|
|
||||||
import os.path
|
|
||||||
import shutil
|
|
||||||
import ccecc
|
|
||||||
import argparse
|
|
||||||
from pathlib import Path, PurePosixPath
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="generate potatOS update manifests")
|
|
||||||
parser.add_argument("-D", "--description", help="description of version")
|
|
||||||
parser.add_argument("-s", "--sign", help="sign update manifest (requires update-key)", action="store_true", default=False)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
counter = 0
|
|
||||||
if os.path.exists("./manifest"):
|
|
||||||
current = open("manifest").read().split("\n")[0]
|
|
||||||
counter = json.loads(current).get("build", 0)
|
|
||||||
|
|
||||||
def hash_file(path):
|
|
||||||
file = open(path, "rb")
|
|
||||||
h = hashlib.sha256()
|
|
||||||
while data := file.read(65536): h.update(data)
|
|
||||||
return h.hexdigest()
|
|
||||||
|
|
||||||
if args.sign:
|
|
||||||
print("Signing update")
|
|
||||||
import genkeys
|
|
||||||
k = genkeys.get_key()
|
|
||||||
pubkey = ccecc.public_key(k).hex()
|
|
||||||
open("dist/update-key.hex", "w").write(pubkey)
|
|
||||||
|
|
||||||
files = dict()
|
|
||||||
code = Path("./dist/")
|
|
||||||
for path in code.glob("**/*"):
|
|
||||||
if not path.is_dir():
|
|
||||||
files["/".join(path.parts[1:])] = hash_file(path)
|
|
||||||
|
|
||||||
def deterministic_json_serialize(x):
|
|
||||||
return json.dumps(x, sort_keys=True, separators=(",", ":"))
|
|
||||||
|
|
||||||
manifest_data = deterministic_json_serialize({
|
|
||||||
"files": files,
|
|
||||||
"timestamp": int(datetime.datetime.now().timestamp()),
|
|
||||||
"build": counter + 1,
|
|
||||||
"description": args.description
|
|
||||||
})
|
|
||||||
|
|
||||||
manifest_meta = {
|
|
||||||
"hash": hashlib.sha256(manifest_data.encode('utf-8')).hexdigest()
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.sign:
|
|
||||||
manifest_meta["sig"] = ccecc.sign(k, manifest_meta["hash"].encode("utf-8")).hex()
|
|
||||||
|
|
||||||
manifest_meta = deterministic_json_serialize(manifest_meta)
|
|
||||||
|
|
||||||
manifest = f"{manifest_data}\n{manifest_meta}"
|
|
||||||
|
|
||||||
open("manifest", "w").write(manifest)
|
|
||||||
shutil.copy("manifest", "dist")
|
|
BIN
images/front/banana.webm
Normal file
BIN
images/front/clock-helvetica.webm
Normal file
BIN
images/front/cool-bug-facts.webm
Normal file
BIN
images/potatos-assistant.webm
Normal file
BIN
images/potatos-copilot.mp4
Normal file
BIN
images/potatos-copilot.webm
Normal file
BIN
images/potatos.gif
Normal file
After Width: | Height: | Size: 203 KiB |
BIN
images/threat-updates/screenshot-20231110-17h16m48s.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
images/threat-updates/screenshot-20231110-17h16m54s.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
images/threat-updates/screenshot-20231110-17h16m57s.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
images/threat-updates/screenshot-20231110-17h17m00s.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
images/threat-updates/screenshot-20231110-17h17m09s.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
images/threat-updates/screenshot-20231110-17h17m12s.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
images/threat-updates/screenshot-20231110-17h17m25s.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
images/threat-updates/screenshot-20231110-17h17m47s.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
images/threat-updates/screenshot-20231110-17h21m18s.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
images/threat-updates/screenshot-20231110-17h21m24s.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
images/threat-updates/screenshot-20231110-17h21m29s.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
images/threat-updates/screenshot-20231110-17h21m33s.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
images/threat-updates/screenshot-20231110-17h21m38s.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
images/threat-updates/screenshot-20231110-17h21m44s.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
images/threat-updates/screenshot-20231110-17h21m50s.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
206
make_website.py
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
import commonmark, os, shutil, json, datetime
|
||||||
|
|
||||||
|
css = """
|
||||||
|
body {
|
||||||
|
max-width: 40em;
|
||||||
|
text-align: justify;
|
||||||
|
font-family: 'Fira Sans', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style-type: square;
|
||||||
|
padding: 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
border-bottom: 1px solid gray;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul p, ol p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img, video {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid gray;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#computer {
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def privacy_policy():
|
||||||
|
import cmarkgfm
|
||||||
|
import re
|
||||||
|
from cmarkgfm.cmark import Options as cmarkgfmOptions
|
||||||
|
|
||||||
|
md = open("privacy/index.md").read()
|
||||||
|
out = []
|
||||||
|
|
||||||
|
tlcounter = 0
|
||||||
|
counter = 0
|
||||||
|
after_prelude = False
|
||||||
|
|
||||||
|
for line in md.split("\n"):
|
||||||
|
if line == "## Welcome to potatOS!":
|
||||||
|
after_prelude = True
|
||||||
|
if not after_prelude:
|
||||||
|
out.append(line)
|
||||||
|
continue
|
||||||
|
if re.match(r"^##", line):
|
||||||
|
tlcounter += 1
|
||||||
|
counter = 0
|
||||||
|
if re.match(r"""^[^#]+""", line) and not re.match(r"^[*\[]", line):
|
||||||
|
out.append("")
|
||||||
|
counter += 1
|
||||||
|
out.append(f"""<h3 id="s{tlcounter}-{counter}"><a href="#s{tlcounter}-{counter}">{tlcounter}.{counter}</a></h3>\n""")
|
||||||
|
out.append(line)
|
||||||
|
|
||||||
|
out = "\n".join(out)
|
||||||
|
|
||||||
|
local_css = css + """
|
||||||
|
.spoiler {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spoiler:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
script = open("privacy/script.js", "r").read()
|
||||||
|
mdtext = cmarkgfm.markdown_to_html_with_extensions(out, cmarkgfmOptions.CMARK_OPT_FOOTNOTES | cmarkgfmOptions.CMARK_OPT_UNSAFE)
|
||||||
|
return f"""<!DOCTYPE html><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="description" content="The privacy policy of PotatOS."><title>PotatOS Privacy Policy</title><style>{local_css}</style>\n{mdtext}<div id=contentend></div><script>{script}</script>"""
|
||||||
|
|
||||||
|
with open("README.md") as f:
|
||||||
|
html = commonmark.commonmark("\n".join(f.read().splitlines()[1:]))
|
||||||
|
|
||||||
|
gif_replacer = f"""
|
||||||
|
const randpick = xs => xs[Math.floor(Math.random() * xs.length)]
|
||||||
|
const im = document.getElementById("im")
|
||||||
|
const vids = {json.dumps(os.listdir("images/front"))}
|
||||||
|
if (Math.random() < 0.02) {{
|
||||||
|
const v = document.createElement("video")
|
||||||
|
v.src = "/front/" + randpick(vids)
|
||||||
|
v.muted = true
|
||||||
|
v.loop = true
|
||||||
|
v.autoplay = true
|
||||||
|
im.replaceWith(v)
|
||||||
|
}}
|
||||||
|
Array.from(document.querySelectorAll("script")).forEach(x => x.parentElement.removeChild(x))
|
||||||
|
const threat = {json.dumps(os.listdir("images/threat-updates"))}
|
||||||
|
document.querySelector("#threat-update").src = "/threat-updates/" + randpick(threat)
|
||||||
|
const demoButton = document.querySelector("#launch-demo")
|
||||||
|
demoButton.addEventListener("click", () => {{
|
||||||
|
const node = document.createElement("iframe")
|
||||||
|
node.src = "/computer.html"
|
||||||
|
node.id = "computer"
|
||||||
|
demoButton.parentNode.parentNode.insertBefore(node, demoButton.parentNode.nextSibling)
|
||||||
|
demoButton.remove()
|
||||||
|
window.addEventListener("message", e => {{
|
||||||
|
document.querySelector("#computer").style.height = `${{e.data}}px`
|
||||||
|
}})
|
||||||
|
}})
|
||||||
|
"""
|
||||||
|
|
||||||
|
computer_html = """<!DOCTYPE html>
|
||||||
|
<style>
|
||||||
|
#computer {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link rel="stylesheet" href="/copy-cat/main.css" />
|
||||||
|
<div id="computer"></div>
|
||||||
|
<script type="text/javascript" src="/copy-cat/require.js"></script>
|
||||||
|
<script>
|
||||||
|
const doScaler = () => {
|
||||||
|
const w = window.innerWidth
|
||||||
|
const ar = 1.7541899441340782
|
||||||
|
const canvas = document.querySelector("canvas")
|
||||||
|
canvas.style.width = `${w}px`
|
||||||
|
canvas.style.height = `${w/ar}px`
|
||||||
|
canvas.parentNode.style.width = `${w}px`
|
||||||
|
window.top.postMessage(document.querySelector("#computer").getBoundingClientRect().height, "*")
|
||||||
|
}
|
||||||
|
require.config({ paths: { copycat: "/copy-cat/" } });
|
||||||
|
require(["copycat/embed"], setup => {
|
||||||
|
window.setup = setup
|
||||||
|
const computer = setup(document.getElementById("computer"), {
|
||||||
|
persistId: 0,
|
||||||
|
hdFont: false,
|
||||||
|
files: {
|
||||||
|
"startup.lua": `settings.set("potatOS.distribution_server", "https://osmarks.net/stuff/potatos/manifest")
|
||||||
|
shell.run "wget run https://osmarks.net/stuff/potatos/autorun.lua"`,
|
||||||
|
},
|
||||||
|
label: "PotatOS",
|
||||||
|
}).then(x => {
|
||||||
|
console.log(x)
|
||||||
|
setInterval(doScaler, 100) // sorry
|
||||||
|
})
|
||||||
|
});
|
||||||
|
window.addEventListener("resize", doScaler)
|
||||||
|
</script>
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open("website/computer.html", "w") as f:
|
||||||
|
f.write(computer_html)
|
||||||
|
|
||||||
|
with open("manifest", "r") as f:
|
||||||
|
data = f.readlines()
|
||||||
|
main = json.loads(data[0])
|
||||||
|
meta = json.loads(data[1])
|
||||||
|
|
||||||
|
potatos_meta = f"""<div>
|
||||||
|
Current build: <code>{meta["hash"][:8]}</code> ({main["description"]}), version {main["build"]}, built {datetime.datetime.fromtimestamp(main["timestamp"], tz=datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S (UTC)")}.
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
html = f"""
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="PotatOS Otiose Transformative Advanced Technology Or Something, inescapably, is the best OS for ComputerCraft and derivatives. Install now with pastebin run 7HSiHybr.">
|
||||||
|
<title>PotatOS</title>
|
||||||
|
<style>{css}</style>
|
||||||
|
<h1>Welcome to PotatOS!</h1>
|
||||||
|
<img src="/potatos.gif" id="im">
|
||||||
|
{potatos_meta}
|
||||||
|
{html}
|
||||||
|
<script>{gif_replacer}</script>
|
||||||
|
"""
|
||||||
|
|
||||||
|
os.makedirs("website/privacy", exist_ok=True)
|
||||||
|
for im in os.listdir("images"):
|
||||||
|
src, dst = os.path.join("images", im), os.path.join("website", im)
|
||||||
|
if os.path.isdir(src):
|
||||||
|
if os.path.exists(dst): shutil.rmtree(dst)
|
||||||
|
shutil.copytree(src, dst)
|
||||||
|
else:
|
||||||
|
shutil.copy(src, dst)
|
||||||
|
with open("website/index.html", "w") as f:
|
||||||
|
f.write(html)
|
||||||
|
with open("website/privacy/index.html", "w") as f:
|
||||||
|
f.write(privacy_policy())
|
||||||
|
if os.path.exists("website/copy-cat"): shutil.rmtree("website/copy-cat")
|
||||||
|
shutil.copytree("copy-cat", "website/copy-cat")
|
121
minify/CommandLineBeautify.lua
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
--
|
||||||
|
-- beautify
|
||||||
|
--
|
||||||
|
-- A command line utility for beautifying lua source code using the beautifier.
|
||||||
|
--
|
||||||
|
|
||||||
|
local util = require'Util'
|
||||||
|
local Parser = require'ParseLua'
|
||||||
|
local Format_Beautify = require'FormatBeautiful'
|
||||||
|
local ParseLua = Parser.ParseLua
|
||||||
|
local PrintTable = util.PrintTable
|
||||||
|
|
||||||
|
local function splitFilename(name)
|
||||||
|
--table.foreach(arg, print)
|
||||||
|
if name:find(".") then
|
||||||
|
local p, ext = name:match("()%.([^%.]*)$")
|
||||||
|
if p and ext then
|
||||||
|
if #ext == 0 then
|
||||||
|
return name, nil
|
||||||
|
else
|
||||||
|
local filename = name:sub(1,p-1)
|
||||||
|
return filename, ext
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return name, nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return name, nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #arg == 1 then
|
||||||
|
local name, ext = splitFilename(arg[1])
|
||||||
|
local outname = name.."_formatted"
|
||||||
|
if ext then outname = outname.."."..ext end
|
||||||
|
--
|
||||||
|
local inf = io.open(arg[1], 'r')
|
||||||
|
if not inf then
|
||||||
|
print("Failed to open '"..arg[1].."' for reading")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
local sourceText = inf:read('*all')
|
||||||
|
inf:close()
|
||||||
|
--
|
||||||
|
local st, ast = ParseLua(sourceText)
|
||||||
|
if not st then
|
||||||
|
--we failed to parse the file, show why
|
||||||
|
print(ast)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
local outf = io.open(outname, 'w')
|
||||||
|
if not outf then
|
||||||
|
print("Failed to open '"..outname.."' for writing")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
outf:write(Format_Beautify(ast))
|
||||||
|
outf:close()
|
||||||
|
--
|
||||||
|
print("Beautification complete")
|
||||||
|
|
||||||
|
elseif #arg == 2 then
|
||||||
|
--keep the user from accidentally overwriting their non-minified file with
|
||||||
|
if arg[1]:find("_formatted") then
|
||||||
|
print("Did you mix up the argument order?\n"..
|
||||||
|
"Current command will beautify '"..arg[1].."' and overwrite '"..arg[2].."' with the results")
|
||||||
|
while true do
|
||||||
|
io.write("Confirm (yes/no): ")
|
||||||
|
local msg = io.read('*line')
|
||||||
|
if msg == 'yes' then
|
||||||
|
break
|
||||||
|
elseif msg == 'no' then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local inf = io.open(arg[1], 'r')
|
||||||
|
if not inf then
|
||||||
|
print("Failed to open '"..arg[1].."' for reading")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
local sourceText = inf:read('*all')
|
||||||
|
inf:close()
|
||||||
|
--
|
||||||
|
local st, ast = ParseLua(sourceText)
|
||||||
|
if not st then
|
||||||
|
--we failed to parse the file, show why
|
||||||
|
print(ast)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
if arg[1] == arg[2] then
|
||||||
|
print("Are you SURE you want to overwrite the source file with a beautified version?\n"..
|
||||||
|
"You will be UNABLE to get the original source back!")
|
||||||
|
while true do
|
||||||
|
io.write("Confirm (yes/no): ")
|
||||||
|
local msg = io.read('*line')
|
||||||
|
if msg == 'yes' then
|
||||||
|
break
|
||||||
|
elseif msg == 'no' then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local outf = io.open(arg[2], 'w')
|
||||||
|
if not outf then
|
||||||
|
print("Failed to open '"..arg[2].."' for writing")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
outf:write(Format_Beautify(ast))
|
||||||
|
outf:close()
|
||||||
|
--
|
||||||
|
print("Beautification complete")
|
||||||
|
|
||||||
|
else
|
||||||
|
print("Invalid arguments!\nUsage: lua CommandLineLuaBeautify.lua source_file [destination_file]")
|
||||||
|
end
|
47
minify/CommandLineLiveBeautify.lua
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
--
|
||||||
|
-- beautify.interactive
|
||||||
|
--
|
||||||
|
-- For testing: Lets you enter lines of text to be beautified to verify the
|
||||||
|
-- correctness of their implementation.
|
||||||
|
--
|
||||||
|
|
||||||
|
local util = require'Util'
|
||||||
|
local Parser = require'ParseLua'
|
||||||
|
local Format_Beautify = require'FormatBeautiful'
|
||||||
|
local ParseLua = Parser.ParseLua
|
||||||
|
local PrintTable = util.PrintTable
|
||||||
|
|
||||||
|
while true do
|
||||||
|
io.write('> ')
|
||||||
|
local line = io.read('*line')
|
||||||
|
local fileFrom, fileTo = line:match("^file (.*) (.*)")
|
||||||
|
if fileFrom and fileTo then
|
||||||
|
local file = io.open(fileFrom, 'r')
|
||||||
|
local fileTo = io.open(fileTo, 'w')
|
||||||
|
if file and fileTo then
|
||||||
|
local st, ast = ParseLua(file:read('*all'))
|
||||||
|
if st then
|
||||||
|
fileTo:write(Format_Beautify(ast)..'\n')
|
||||||
|
io.write("Beautification Complete\n")
|
||||||
|
else
|
||||||
|
io.write(""..tostring(ast).."\n")
|
||||||
|
end
|
||||||
|
file:close()
|
||||||
|
fileTo:close()
|
||||||
|
else
|
||||||
|
io.write("File does not exist\n")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local st, ast = ParseLua(line)
|
||||||
|
if st then
|
||||||
|
io.write("====== AST =======\n")
|
||||||
|
io.write(PrintTable(ast)..'\n')
|
||||||
|
io.write("==== BEAUTIFIED ====\n")
|
||||||
|
io.write(Format_Beautify(ast))
|
||||||
|
io.write("==================\n")
|
||||||
|
else
|
||||||
|
io.write(""..tostring(ast).."\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
47
minify/CommandLineLiveMinify.lua
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
--
|
||||||
|
-- CommandLineLiveMinify.lua
|
||||||
|
--
|
||||||
|
-- For testing: Lets you enter lines of text to be minified to verify the
|
||||||
|
-- correctness of their implementation.
|
||||||
|
--
|
||||||
|
|
||||||
|
local util = require'Util'
|
||||||
|
local Parser = require'ParseLua'
|
||||||
|
local Format_Mini = require'FormatMini'
|
||||||
|
local ParseLua = Parser.ParseLua
|
||||||
|
local PrintTable = util.PrintTable
|
||||||
|
|
||||||
|
while true do
|
||||||
|
io.write('> ')
|
||||||
|
local line = io.read('*line')
|
||||||
|
local fileFrom, fileTo = line:match("^file (.*) (.*)")
|
||||||
|
if fileFrom and fileTo then
|
||||||
|
local file = io.open(fileFrom, 'r')
|
||||||
|
local fileTo = io.open(fileTo, 'w')
|
||||||
|
if file and fileTo then
|
||||||
|
local st, ast = ParseLua(file:read('*all'))
|
||||||
|
if st then
|
||||||
|
fileTo:write(Format_Mini(ast)..'\n')
|
||||||
|
io.write("Minification Complete\n")
|
||||||
|
else
|
||||||
|
io.write(""..tostring(ast).."\n")
|
||||||
|
end
|
||||||
|
file:close()
|
||||||
|
fileTo:close()
|
||||||
|
else
|
||||||
|
io.write("File does not exist\n")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local st, ast = ParseLua(line)
|
||||||
|
if st then
|
||||||
|
io.write("====== AST =======\n")
|
||||||
|
io.write(PrintTable(ast)..'\n')
|
||||||
|
io.write("==== MINIFIED ====\n")
|
||||||
|
io.write(Format_Mini(ast)..'\n')
|
||||||
|
io.write("==================\n")
|
||||||
|
else
|
||||||
|
io.write(""..tostring(ast).."\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
130
minify/CommandLineMinify.lua
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
|
||||||
|
--
|
||||||
|
-- CommandlineMinify.lua
|
||||||
|
--
|
||||||
|
-- A command line utility for minifying lua source code using the minifier.
|
||||||
|
--
|
||||||
|
|
||||||
|
local util = require'Util'
|
||||||
|
local Parser = require'ParseLua'
|
||||||
|
local Format_Mini = require'FormatMini'
|
||||||
|
local ParseLua = Parser.ParseLua
|
||||||
|
local PrintTable = util.PrintTable
|
||||||
|
|
||||||
|
local function splitFilename(name)
|
||||||
|
table.foreach(arg, print)
|
||||||
|
if name:find(".") then
|
||||||
|
local p, ext = name:match("()%.([^%.]*)$")
|
||||||
|
if p and ext then
|
||||||
|
if #ext == 0 then
|
||||||
|
return name, nil
|
||||||
|
else
|
||||||
|
local filename = name:sub(1,p-1)
|
||||||
|
return filename, ext
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return name, nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return name, nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #arg == 1 then
|
||||||
|
local name, ext = splitFilename(arg[1])
|
||||||
|
local outname = name.."_min"
|
||||||
|
if ext then outname = outname.."."..ext end
|
||||||
|
--
|
||||||
|
local inf = io.open(arg[1], 'r')
|
||||||
|
if not inf then
|
||||||
|
print("Failed to open `"..arg[1].."` for reading")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
local sourceText = inf:read('*all')
|
||||||
|
inf:close()
|
||||||
|
--
|
||||||
|
local st, ast = ParseLua(sourceText)
|
||||||
|
if not st then
|
||||||
|
--we failed to parse the file, show why
|
||||||
|
print(ast)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
local outf = io.open(outname, 'w')
|
||||||
|
if not outf then
|
||||||
|
print("Failed to open `"..outname.."` for writing")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
outf:write(Format_Mini(ast))
|
||||||
|
outf:close()
|
||||||
|
--
|
||||||
|
print("Minification complete")
|
||||||
|
|
||||||
|
elseif #arg == 3 then
|
||||||
|
--keep the user from accidentally overwriting their non-minified file with
|
||||||
|
if arg[1]:find("_min") then
|
||||||
|
print("Did you mix up the argument order?\n"..
|
||||||
|
"Current command will minify `"..arg[1].."` and OVERWRITE `"..arg[2].."` with the results")
|
||||||
|
while true do
|
||||||
|
io.write("Confirm (yes/cancel): ")
|
||||||
|
local msg = io.read('*line')
|
||||||
|
if msg == 'yes' then
|
||||||
|
break
|
||||||
|
elseif msg == 'cancel' then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local inf = io.open(arg[1], 'r')
|
||||||
|
if not inf then
|
||||||
|
print("Failed to open `"..arg[1].."` for reading")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
local sourceText = inf:read('*all')
|
||||||
|
inf:close()
|
||||||
|
--
|
||||||
|
local st, ast = ParseLua(sourceText)
|
||||||
|
if not st then
|
||||||
|
--we failed to parse the file, show why
|
||||||
|
print(ast)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
if arg[1] == arg[2] then
|
||||||
|
print("Are you SURE you want to overwrite the source file with a minified version?\n"..
|
||||||
|
"You will be UNABLE to get the original source back!")
|
||||||
|
while true do
|
||||||
|
io.write("Confirm (yes/cancel): ")
|
||||||
|
local msg = io.read('*line')
|
||||||
|
if msg == 'yes' then
|
||||||
|
break
|
||||||
|
elseif msg == 'cancel' then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local outf = io.open(arg[2], 'w')
|
||||||
|
if not outf then
|
||||||
|
print("Failed to open `"..arg[2].."` for writing")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
--
|
||||||
|
local text, map = Format_Mini(ast)
|
||||||
|
outf:write(text)
|
||||||
|
outf:close()
|
||||||
|
--
|
||||||
|
local outf = io.open(arg[3], 'w')
|
||||||
|
if not outf then
|
||||||
|
print("Failed to open `"..arg[3].."` for writing")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
outf:write(map)
|
||||||
|
outf:close()
|
||||||
|
print("Minification complete")
|
||||||
|
|
||||||
|
else
|
||||||
|
print("Invalid arguments, Usage:\nLuaMinify source [destination]")
|
||||||
|
end
|
347
minify/FormatBeautiful.lua
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
--
|
||||||
|
-- Beautifier
|
||||||
|
--
|
||||||
|
-- Returns a beautified version of the code, including comments
|
||||||
|
--
|
||||||
|
|
||||||
|
local parser = require"ParseLua"
|
||||||
|
local ParseLua = parser.ParseLua
|
||||||
|
local util = require'Util'
|
||||||
|
local lookupify = util.lookupify
|
||||||
|
|
||||||
|
local LowerChars = lookupify{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
||||||
|
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
|
||||||
|
's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
|
||||||
|
local UpperChars = lookupify{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
|
||||||
|
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
|
||||||
|
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
|
||||||
|
local Digits = lookupify{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
|
||||||
|
|
||||||
|
local function Format_Beautify(ast)
|
||||||
|
local formatStatlist, formatExpr
|
||||||
|
local indent = 0
|
||||||
|
local EOL = "\n"
|
||||||
|
|
||||||
|
local function getIndentation()
|
||||||
|
return string.rep(" ", indent)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function joinStatementsSafe(a, b, sep)
|
||||||
|
sep = sep or ''
|
||||||
|
local aa, bb = a:sub(-1,-1), b:sub(1,1)
|
||||||
|
if UpperChars[aa] or LowerChars[aa] or aa == '_' then
|
||||||
|
if not (UpperChars[bb] or LowerChars[bb] or bb == '_' or Digits[bb]) then
|
||||||
|
--bb is a symbol, can join without sep
|
||||||
|
return a .. b
|
||||||
|
elseif bb == '(' then
|
||||||
|
--prevent ambiguous syntax
|
||||||
|
return a..sep..b
|
||||||
|
else
|
||||||
|
return a..sep..b
|
||||||
|
end
|
||||||
|
elseif Digits[aa] then
|
||||||
|
if bb == '(' then
|
||||||
|
--can join statements directly
|
||||||
|
return a..b
|
||||||
|
else
|
||||||
|
return a..sep..b
|
||||||
|
end
|
||||||
|
elseif aa == '' then
|
||||||
|
return a..b
|
||||||
|
else
|
||||||
|
if bb == '(' then
|
||||||
|
--don't want to accidentally call last statement, can't join directly
|
||||||
|
return a..sep..b
|
||||||
|
else
|
||||||
|
return a..b
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
formatExpr = function(expr)
|
||||||
|
local out = string.rep('(', expr.ParenCount or 0)
|
||||||
|
if expr.AstType == 'VarExpr' then
|
||||||
|
if expr.Variable then
|
||||||
|
out = out .. expr.Variable.Name
|
||||||
|
else
|
||||||
|
out = out .. expr.Name
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif expr.AstType == 'NumberExpr' then
|
||||||
|
out = out..expr.Value.Data
|
||||||
|
|
||||||
|
elseif expr.AstType == 'StringExpr' then
|
||||||
|
out = out..expr.Value.Data
|
||||||
|
|
||||||
|
elseif expr.AstType == 'BooleanExpr' then
|
||||||
|
out = out..tostring(expr.Value)
|
||||||
|
|
||||||
|
elseif expr.AstType == 'NilExpr' then
|
||||||
|
out = joinStatementsSafe(out, "nil")
|
||||||
|
|
||||||
|
elseif expr.AstType == 'BinopExpr' then
|
||||||
|
out = joinStatementsSafe(out, formatExpr(expr.Lhs)) .. " "
|
||||||
|
out = joinStatementsSafe(out, expr.Op) .. " "
|
||||||
|
out = joinStatementsSafe(out, formatExpr(expr.Rhs))
|
||||||
|
|
||||||
|
elseif expr.AstType == 'UnopExpr' then
|
||||||
|
out = joinStatementsSafe(out, expr.Op) .. (#expr.Op ~= 1 and " " or "")
|
||||||
|
out = joinStatementsSafe(out, formatExpr(expr.Rhs))
|
||||||
|
|
||||||
|
elseif expr.AstType == 'DotsExpr' then
|
||||||
|
out = out.."..."
|
||||||
|
|
||||||
|
elseif expr.AstType == 'CallExpr' then
|
||||||
|
out = out..formatExpr(expr.Base)
|
||||||
|
out = out.."("
|
||||||
|
for i = 1, #expr.Arguments do
|
||||||
|
out = out..formatExpr(expr.Arguments[i])
|
||||||
|
if i ~= #expr.Arguments then
|
||||||
|
out = out..", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = out..")"
|
||||||
|
|
||||||
|
elseif expr.AstType == 'TableCallExpr' then
|
||||||
|
out = out..formatExpr(expr.Base) .. " "
|
||||||
|
out = out..formatExpr(expr.Arguments[1])
|
||||||
|
|
||||||
|
elseif expr.AstType == 'StringCallExpr' then
|
||||||
|
out = out..formatExpr(expr.Base) .. " "
|
||||||
|
out = out..expr.Arguments[1].Data
|
||||||
|
|
||||||
|
elseif expr.AstType == 'IndexExpr' then
|
||||||
|
out = out..formatExpr(expr.Base).."["..formatExpr(expr.Index).."]"
|
||||||
|
|
||||||
|
elseif expr.AstType == 'MemberExpr' then
|
||||||
|
out = out..formatExpr(expr.Base)..expr.Indexer..expr.Ident.Data
|
||||||
|
|
||||||
|
elseif expr.AstType == 'Function' then
|
||||||
|
-- anonymous function
|
||||||
|
out = out.."function("
|
||||||
|
if #expr.Arguments > 0 then
|
||||||
|
for i = 1, #expr.Arguments do
|
||||||
|
out = out..expr.Arguments[i].Name
|
||||||
|
if i ~= #expr.Arguments then
|
||||||
|
out = out..", "
|
||||||
|
elseif expr.VarArg then
|
||||||
|
out = out..", ..."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif expr.VarArg then
|
||||||
|
out = out.."..."
|
||||||
|
end
|
||||||
|
out = out..")" .. EOL
|
||||||
|
indent = indent + 1
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(expr.Body))
|
||||||
|
indent = indent - 1
|
||||||
|
out = joinStatementsSafe(out, getIndentation() .. "end")
|
||||||
|
elseif expr.AstType == 'ConstructorExpr' then
|
||||||
|
out = out.."{ "
|
||||||
|
for i = 1, #expr.EntryList do
|
||||||
|
local entry = expr.EntryList[i]
|
||||||
|
if entry.Type == 'Key' then
|
||||||
|
out = out.."["..formatExpr(entry.Key).."] = "..formatExpr(entry.Value)
|
||||||
|
elseif entry.Type == 'Value' then
|
||||||
|
out = out..formatExpr(entry.Value)
|
||||||
|
elseif entry.Type == 'KeyString' then
|
||||||
|
out = out..entry.Key.." = "..formatExpr(entry.Value)
|
||||||
|
end
|
||||||
|
if i ~= #expr.EntryList then
|
||||||
|
out = out..", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = out.." }"
|
||||||
|
|
||||||
|
elseif expr.AstType == 'Parentheses' then
|
||||||
|
out = out.."("..formatExpr(expr.Inner)..")"
|
||||||
|
|
||||||
|
end
|
||||||
|
out = out..string.rep(')', expr.ParenCount or 0)
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
|
local formatStatement = function(statement)
|
||||||
|
local out = ""
|
||||||
|
if statement.AstType == 'AssignmentStatement' then
|
||||||
|
out = getIndentation()
|
||||||
|
for i = 1, #statement.Lhs do
|
||||||
|
out = out..formatExpr(statement.Lhs[i])
|
||||||
|
if i ~= #statement.Lhs then
|
||||||
|
out = out..", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #statement.Rhs > 0 then
|
||||||
|
out = out.." = "
|
||||||
|
for i = 1, #statement.Rhs do
|
||||||
|
out = out..formatExpr(statement.Rhs[i])
|
||||||
|
if i ~= #statement.Rhs then
|
||||||
|
out = out..", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif statement.AstType == 'CallStatement' then
|
||||||
|
out = getIndentation() .. formatExpr(statement.Expression)
|
||||||
|
elseif statement.AstType == 'LocalStatement' then
|
||||||
|
out = getIndentation() .. out.."local "
|
||||||
|
for i = 1, #statement.LocalList do
|
||||||
|
out = out..statement.LocalList[i].Name
|
||||||
|
if i ~= #statement.LocalList then
|
||||||
|
out = out..", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #statement.InitList > 0 then
|
||||||
|
out = out.." = "
|
||||||
|
for i = 1, #statement.InitList do
|
||||||
|
out = out..formatExpr(statement.InitList[i])
|
||||||
|
if i ~= #statement.InitList then
|
||||||
|
out = out..", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif statement.AstType == 'IfStatement' then
|
||||||
|
out = getIndentation() .. joinStatementsSafe("if ", formatExpr(statement.Clauses[1].Condition))
|
||||||
|
out = joinStatementsSafe(out, " then") .. EOL
|
||||||
|
indent = indent + 1
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Clauses[1].Body))
|
||||||
|
indent = indent - 1
|
||||||
|
for i = 2, #statement.Clauses do
|
||||||
|
local st = statement.Clauses[i]
|
||||||
|
if st.Condition then
|
||||||
|
out = getIndentation() .. joinStatementsSafe(out, getIndentation() .. "elseif ")
|
||||||
|
out = joinStatementsSafe(out, formatExpr(st.Condition))
|
||||||
|
out = joinStatementsSafe(out, " then") .. EOL
|
||||||
|
else
|
||||||
|
out = joinStatementsSafe(out, getIndentation() .. "else") .. EOL
|
||||||
|
end
|
||||||
|
indent = indent + 1
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(st.Body))
|
||||||
|
indent = indent - 1
|
||||||
|
end
|
||||||
|
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
|
||||||
|
elseif statement.AstType == 'WhileStatement' then
|
||||||
|
out = getIndentation() .. joinStatementsSafe("while ", formatExpr(statement.Condition))
|
||||||
|
out = joinStatementsSafe(out, " do") .. EOL
|
||||||
|
indent = indent + 1
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
indent = indent - 1
|
||||||
|
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
|
||||||
|
elseif statement.AstType == 'DoStatement' then
|
||||||
|
out = getIndentation() .. joinStatementsSafe(out, "do") .. EOL
|
||||||
|
indent = indent + 1
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
indent = indent - 1
|
||||||
|
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
|
||||||
|
elseif statement.AstType == 'ReturnStatement' then
|
||||||
|
out = getIndentation() .. "return "
|
||||||
|
for i = 1, #statement.Arguments do
|
||||||
|
out = joinStatementsSafe(out, formatExpr(statement.Arguments[i]))
|
||||||
|
if i ~= #statement.Arguments then
|
||||||
|
out = out..", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif statement.AstType == 'BreakStatement' then
|
||||||
|
out = getIndentation() .. "break"
|
||||||
|
elseif statement.AstType == 'RepeatStatement' then
|
||||||
|
out = getIndentation() .. "repeat" .. EOL
|
||||||
|
indent = indent + 1
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
indent = indent - 1
|
||||||
|
out = joinStatementsSafe(out, getIndentation() .. "until ")
|
||||||
|
out = joinStatementsSafe(out, formatExpr(statement.Condition)) .. EOL
|
||||||
|
elseif statement.AstType == 'Function' then
|
||||||
|
if statement.IsLocal then
|
||||||
|
out = "local "
|
||||||
|
end
|
||||||
|
out = joinStatementsSafe(out, "function ")
|
||||||
|
out = getIndentation() .. out
|
||||||
|
if statement.IsLocal then
|
||||||
|
out = out..statement.Name.Name
|
||||||
|
else
|
||||||
|
out = out..formatExpr(statement.Name)
|
||||||
|
end
|
||||||
|
out = out.."("
|
||||||
|
if #statement.Arguments > 0 then
|
||||||
|
for i = 1, #statement.Arguments do
|
||||||
|
out = out..statement.Arguments[i].Name
|
||||||
|
if i ~= #statement.Arguments then
|
||||||
|
out = out..", "
|
||||||
|
elseif statement.VarArg then
|
||||||
|
out = out..",..."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif statement.VarArg then
|
||||||
|
out = out.."..."
|
||||||
|
end
|
||||||
|
out = out..")" .. EOL
|
||||||
|
indent = indent + 1
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
indent = indent - 1
|
||||||
|
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
|
||||||
|
elseif statement.AstType == 'GenericForStatement' then
|
||||||
|
out = getIndentation() .. "for "
|
||||||
|
for i = 1, #statement.VariableList do
|
||||||
|
out = out..statement.VariableList[i].Name
|
||||||
|
if i ~= #statement.VariableList then
|
||||||
|
out = out..", "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = out.." in "
|
||||||
|
for i = 1, #statement.Generators do
|
||||||
|
out = joinStatementsSafe(out, formatExpr(statement.Generators[i]))
|
||||||
|
if i ~= #statement.Generators then
|
||||||
|
out = joinStatementsSafe(out, ', ')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = joinStatementsSafe(out, " do") .. EOL
|
||||||
|
indent = indent + 1
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
indent = indent - 1
|
||||||
|
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
|
||||||
|
elseif statement.AstType == 'NumericForStatement' then
|
||||||
|
out = getIndentation() .. "for "
|
||||||
|
out = out..statement.Variable.Name.." = "
|
||||||
|
out = out..formatExpr(statement.Start)..", "..formatExpr(statement.End)
|
||||||
|
if statement.Step then
|
||||||
|
out = out..", "..formatExpr(statement.Step)
|
||||||
|
end
|
||||||
|
out = joinStatementsSafe(out, " do") .. EOL
|
||||||
|
indent = indent + 1
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
indent = indent - 1
|
||||||
|
out = joinStatementsSafe(out, getIndentation() .. "end") .. EOL
|
||||||
|
elseif statement.AstType == 'LabelStatement' then
|
||||||
|
out = getIndentation() .. "::" .. statement.Label .. "::" .. EOL
|
||||||
|
elseif statement.AstType == 'GotoStatement' then
|
||||||
|
out = getIndentation() .. "goto " .. statement.Label .. EOL
|
||||||
|
elseif statement.AstType == 'Comment' then
|
||||||
|
if statement.CommentType == 'Shebang' then
|
||||||
|
out = getIndentation() .. statement.Data
|
||||||
|
--out = out .. EOL
|
||||||
|
elseif statement.CommentType == 'Comment' then
|
||||||
|
out = getIndentation() .. statement.Data
|
||||||
|
--out = out .. EOL
|
||||||
|
elseif statement.CommentType == 'LongComment' then
|
||||||
|
out = getIndentation() .. statement.Data
|
||||||
|
--out = out .. EOL
|
||||||
|
end
|
||||||
|
elseif statement.AstType == 'Eof' then
|
||||||
|
-- Ignore
|
||||||
|
else
|
||||||
|
print("Unknown AST Type: ", statement.AstType)
|
||||||
|
end
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
|
formatStatlist = function(statList)
|
||||||
|
local out = ''
|
||||||
|
for _, stat in pairs(statList.Body) do
|
||||||
|
out = joinStatementsSafe(out, formatStatement(stat) .. EOL)
|
||||||
|
end
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
|
return formatStatlist(ast)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Format_Beautify
|
436
minify/FormatIdentity.lua
Normal file
@ -0,0 +1,436 @@
|
|||||||
|
require'strict'
|
||||||
|
require'ParseLua'
|
||||||
|
local util = require'Util'
|
||||||
|
|
||||||
|
local function debug_printf(...)
|
||||||
|
--[[
|
||||||
|
util.printf(...)
|
||||||
|
--]]
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- FormatIdentity.lua
|
||||||
|
--
|
||||||
|
-- Returns the exact source code that was used to create an AST, preserving all
|
||||||
|
-- comments and whitespace.
|
||||||
|
-- This can be used to get back a Lua source after renaming some variables in
|
||||||
|
-- an AST.
|
||||||
|
--
|
||||||
|
|
||||||
|
local function Format_Identity(ast)
|
||||||
|
local out = {
|
||||||
|
rope = {}, -- List of strings
|
||||||
|
line = 1,
|
||||||
|
char = 1,
|
||||||
|
|
||||||
|
appendStr = function(self, str)
|
||||||
|
table.insert(self.rope, str)
|
||||||
|
|
||||||
|
local lines = util.splitLines(str)
|
||||||
|
if #lines == 1 then
|
||||||
|
self.char = self.char + #str
|
||||||
|
else
|
||||||
|
self.line = self.line + #lines - 1
|
||||||
|
local lastLine = lines[#lines]
|
||||||
|
self.char = #lastLine
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
appendToken = function(self, token)
|
||||||
|
self:appendWhite(token)
|
||||||
|
--[*[
|
||||||
|
--debug_printf("appendToken(%q)", token.Data)
|
||||||
|
local data = token.Data
|
||||||
|
local lines = util.splitLines(data)
|
||||||
|
while self.line + #lines < token.Line do
|
||||||
|
print("Inserting extra line")
|
||||||
|
self.str = self.str .. '\n'
|
||||||
|
self.line = self.line + 1
|
||||||
|
self.char = 1
|
||||||
|
end
|
||||||
|
--]]
|
||||||
|
self:appendStr(token.Data)
|
||||||
|
end,
|
||||||
|
|
||||||
|
appendTokens = function(self, tokens)
|
||||||
|
for _,token in ipairs(tokens) do
|
||||||
|
self:appendToken( token )
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
appendWhite = function(self, token)
|
||||||
|
if token.LeadingWhite then
|
||||||
|
self:appendTokens( token.LeadingWhite )
|
||||||
|
--self.str = self.str .. ' '
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
local formatStatlist, formatExpr;
|
||||||
|
|
||||||
|
formatExpr = function(expr)
|
||||||
|
local tok_it = 1
|
||||||
|
local function appendNextToken(str)
|
||||||
|
local tok = expr.Tokens[tok_it];
|
||||||
|
if str and tok.Data ~= str then
|
||||||
|
error("Expected token '" .. str .. "'. Tokens: " .. util.PrintTable(expr.Tokens))
|
||||||
|
end
|
||||||
|
out:appendToken( tok )
|
||||||
|
tok_it = tok_it + 1
|
||||||
|
end
|
||||||
|
local function appendToken(token)
|
||||||
|
out:appendToken( token )
|
||||||
|
tok_it = tok_it + 1
|
||||||
|
end
|
||||||
|
local function appendWhite()
|
||||||
|
local tok = expr.Tokens[tok_it];
|
||||||
|
if not tok then error(util.PrintTable(expr)) end
|
||||||
|
out:appendWhite( tok )
|
||||||
|
tok_it = tok_it + 1
|
||||||
|
end
|
||||||
|
local function appendStr(str)
|
||||||
|
appendWhite()
|
||||||
|
out:appendStr(str)
|
||||||
|
end
|
||||||
|
local function peek()
|
||||||
|
if tok_it < #expr.Tokens then
|
||||||
|
return expr.Tokens[tok_it].Data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function appendComma(mandatory, seperators)
|
||||||
|
if true then
|
||||||
|
seperators = seperators or { "," }
|
||||||
|
seperators = util.lookupify( seperators )
|
||||||
|
if not mandatory and not seperators[peek()] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
assert(seperators[peek()], "Missing comma or semicolon")
|
||||||
|
appendNextToken()
|
||||||
|
else
|
||||||
|
local p = peek()
|
||||||
|
if p == "," or p == ";" then
|
||||||
|
appendNextToken()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
debug_printf("formatExpr(%s) at line %i", expr.AstType, expr.Tokens[1] and expr.Tokens[1].Line or -1)
|
||||||
|
|
||||||
|
if expr.AstType == 'VarExpr' then
|
||||||
|
if expr.Variable then
|
||||||
|
appendStr( expr.Variable.Name )
|
||||||
|
else
|
||||||
|
appendStr( expr.Name )
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif expr.AstType == 'NumberExpr' then
|
||||||
|
appendToken( expr.Value )
|
||||||
|
|
||||||
|
elseif expr.AstType == 'StringExpr' then
|
||||||
|
appendToken( expr.Value )
|
||||||
|
|
||||||
|
elseif expr.AstType == 'BooleanExpr' then
|
||||||
|
appendNextToken( expr.Value and "true" or "false" )
|
||||||
|
|
||||||
|
elseif expr.AstType == 'NilExpr' then
|
||||||
|
appendNextToken( "nil" )
|
||||||
|
|
||||||
|
elseif expr.AstType == 'BinopExpr' then
|
||||||
|
formatExpr(expr.Lhs)
|
||||||
|
appendStr( expr.Op )
|
||||||
|
formatExpr(expr.Rhs)
|
||||||
|
|
||||||
|
elseif expr.AstType == 'UnopExpr' then
|
||||||
|
appendStr( expr.Op )
|
||||||
|
formatExpr(expr.Rhs)
|
||||||
|
|
||||||
|
elseif expr.AstType == 'DotsExpr' then
|
||||||
|
appendNextToken( "..." )
|
||||||
|
|
||||||
|
elseif expr.AstType == 'CallExpr' then
|
||||||
|
formatExpr(expr.Base)
|
||||||
|
appendNextToken( "(" )
|
||||||
|
for i,arg in ipairs( expr.Arguments ) do
|
||||||
|
formatExpr(arg)
|
||||||
|
appendComma( i ~= #expr.Arguments )
|
||||||
|
end
|
||||||
|
appendNextToken( ")" )
|
||||||
|
|
||||||
|
elseif expr.AstType == 'TableCallExpr' then
|
||||||
|
formatExpr( expr.Base )
|
||||||
|
formatExpr( expr.Arguments[1] )
|
||||||
|
|
||||||
|
elseif expr.AstType == 'StringCallExpr' then
|
||||||
|
formatExpr(expr.Base)
|
||||||
|
appendToken( expr.Arguments[1] )
|
||||||
|
|
||||||
|
elseif expr.AstType == 'IndexExpr' then
|
||||||
|
formatExpr(expr.Base)
|
||||||
|
appendNextToken( "[" )
|
||||||
|
formatExpr(expr.Index)
|
||||||
|
appendNextToken( "]" )
|
||||||
|
|
||||||
|
elseif expr.AstType == 'MemberExpr' then
|
||||||
|
formatExpr(expr.Base)
|
||||||
|
appendNextToken() -- . or :
|
||||||
|
appendToken(expr.Ident)
|
||||||
|
|
||||||
|
elseif expr.AstType == 'Function' then
|
||||||
|
-- anonymous function
|
||||||
|
appendNextToken( "function" )
|
||||||
|
appendNextToken( "(" )
|
||||||
|
if #expr.Arguments > 0 then
|
||||||
|
for i = 1, #expr.Arguments do
|
||||||
|
appendStr( expr.Arguments[i].Name )
|
||||||
|
if i ~= #expr.Arguments then
|
||||||
|
appendNextToken(",")
|
||||||
|
elseif expr.VarArg then
|
||||||
|
appendNextToken(",")
|
||||||
|
appendNextToken("...")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif expr.VarArg then
|
||||||
|
appendNextToken("...")
|
||||||
|
end
|
||||||
|
appendNextToken(")")
|
||||||
|
formatStatlist(expr.Body)
|
||||||
|
appendNextToken("end")
|
||||||
|
|
||||||
|
elseif expr.AstType == 'ConstructorExpr' then
|
||||||
|
appendNextToken( "{" )
|
||||||
|
for i = 1, #expr.EntryList do
|
||||||
|
local entry = expr.EntryList[i]
|
||||||
|
if entry.Type == 'Key' then
|
||||||
|
appendNextToken( "[" )
|
||||||
|
formatExpr(entry.Key)
|
||||||
|
appendNextToken( "]" )
|
||||||
|
appendNextToken( "=" )
|
||||||
|
formatExpr(entry.Value)
|
||||||
|
elseif entry.Type == 'Value' then
|
||||||
|
formatExpr(entry.Value)
|
||||||
|
elseif entry.Type == 'KeyString' then
|
||||||
|
appendStr(entry.Key)
|
||||||
|
appendNextToken( "=" )
|
||||||
|
formatExpr(entry.Value)
|
||||||
|
end
|
||||||
|
appendComma( i ~= #expr.EntryList, { ",", ";" } )
|
||||||
|
end
|
||||||
|
appendNextToken( "}" )
|
||||||
|
|
||||||
|
elseif expr.AstType == 'Parentheses' then
|
||||||
|
appendNextToken( "(" )
|
||||||
|
formatExpr(expr.Inner)
|
||||||
|
appendNextToken( ")" )
|
||||||
|
|
||||||
|
else
|
||||||
|
print("Unknown AST Type: ", statement.AstType)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(tok_it == #expr.Tokens + 1)
|
||||||
|
debug_printf("/formatExpr")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local formatStatement = function(statement)
|
||||||
|
local tok_it = 1
|
||||||
|
local function appendNextToken(str)
|
||||||
|
local tok = statement.Tokens[tok_it];
|
||||||
|
assert(tok, string.format("Not enough tokens for %q. First token at %i:%i",
|
||||||
|
str, statement.Tokens[1].Line, statement.Tokens[1].Char))
|
||||||
|
assert(tok.Data == str,
|
||||||
|
string.format('Expected token %q, got %q', str, tok.Data))
|
||||||
|
out:appendToken( tok )
|
||||||
|
tok_it = tok_it + 1
|
||||||
|
end
|
||||||
|
local function appendWhite()
|
||||||
|
local tok = statement.Tokens[tok_it];
|
||||||
|
out:appendWhite( tok )
|
||||||
|
tok_it = tok_it + 1
|
||||||
|
end
|
||||||
|
local function appendStr(str)
|
||||||
|
appendWhite()
|
||||||
|
out:appendStr(str)
|
||||||
|
end
|
||||||
|
local function appendComma(mandatory)
|
||||||
|
if mandatory
|
||||||
|
or (tok_it < #statement.Tokens and statement.Tokens[tok_it].Data == ",") then
|
||||||
|
appendNextToken( "," )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
debug_printf("")
|
||||||
|
debug_printf(string.format("formatStatement(%s) at line %i", statement.AstType, statement.Tokens[1] and statement.Tokens[1].Line or -1))
|
||||||
|
|
||||||
|
if statement.AstType == 'AssignmentStatement' then
|
||||||
|
for i,v in ipairs(statement.Lhs) do
|
||||||
|
formatExpr(v)
|
||||||
|
appendComma( i ~= #statement.Lhs )
|
||||||
|
end
|
||||||
|
if #statement.Rhs > 0 then
|
||||||
|
appendNextToken( "=" )
|
||||||
|
for i,v in ipairs(statement.Rhs) do
|
||||||
|
formatExpr(v)
|
||||||
|
appendComma( i ~= #statement.Rhs )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif statement.AstType == 'CallStatement' then
|
||||||
|
formatExpr(statement.Expression)
|
||||||
|
|
||||||
|
elseif statement.AstType == 'LocalStatement' then
|
||||||
|
appendNextToken( "local" )
|
||||||
|
for i = 1, #statement.LocalList do
|
||||||
|
appendStr( statement.LocalList[i].Name )
|
||||||
|
appendComma( i ~= #statement.LocalList )
|
||||||
|
end
|
||||||
|
if #statement.InitList > 0 then
|
||||||
|
appendNextToken( "=" )
|
||||||
|
for i = 1, #statement.InitList do
|
||||||
|
formatExpr(statement.InitList[i])
|
||||||
|
appendComma( i ~= #statement.InitList )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif statement.AstType == 'IfStatement' then
|
||||||
|
appendNextToken( "if" )
|
||||||
|
formatExpr( statement.Clauses[1].Condition )
|
||||||
|
appendNextToken( "then" )
|
||||||
|
formatStatlist( statement.Clauses[1].Body )
|
||||||
|
for i = 2, #statement.Clauses do
|
||||||
|
local st = statement.Clauses[i]
|
||||||
|
if st.Condition then
|
||||||
|
appendNextToken( "elseif" )
|
||||||
|
formatExpr(st.Condition)
|
||||||
|
appendNextToken( "then" )
|
||||||
|
else
|
||||||
|
appendNextToken( "else" )
|
||||||
|
end
|
||||||
|
formatStatlist(st.Body)
|
||||||
|
end
|
||||||
|
appendNextToken( "end" )
|
||||||
|
|
||||||
|
elseif statement.AstType == 'WhileStatement' then
|
||||||
|
appendNextToken( "while" )
|
||||||
|
formatExpr(statement.Condition)
|
||||||
|
appendNextToken( "do" )
|
||||||
|
formatStatlist(statement.Body)
|
||||||
|
appendNextToken( "end" )
|
||||||
|
|
||||||
|
elseif statement.AstType == 'DoStatement' then
|
||||||
|
appendNextToken( "do" )
|
||||||
|
formatStatlist(statement.Body)
|
||||||
|
appendNextToken( "end" )
|
||||||
|
|
||||||
|
elseif statement.AstType == 'ReturnStatement' then
|
||||||
|
appendNextToken( "return" )
|
||||||
|
for i = 1, #statement.Arguments do
|
||||||
|
formatExpr(statement.Arguments[i])
|
||||||
|
appendComma( i ~= #statement.Arguments )
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif statement.AstType == 'BreakStatement' then
|
||||||
|
appendNextToken( "break" )
|
||||||
|
|
||||||
|
elseif statement.AstType == 'RepeatStatement' then
|
||||||
|
appendNextToken( "repeat" )
|
||||||
|
formatStatlist(statement.Body)
|
||||||
|
appendNextToken( "until" )
|
||||||
|
formatExpr(statement.Condition)
|
||||||
|
|
||||||
|
elseif statement.AstType == 'Function' then
|
||||||
|
--print(util.PrintTable(statement))
|
||||||
|
|
||||||
|
if statement.IsLocal then
|
||||||
|
appendNextToken( "local" )
|
||||||
|
end
|
||||||
|
appendNextToken( "function" )
|
||||||
|
|
||||||
|
if statement.IsLocal then
|
||||||
|
appendStr(statement.Name.Name)
|
||||||
|
else
|
||||||
|
formatExpr(statement.Name)
|
||||||
|
end
|
||||||
|
|
||||||
|
appendNextToken( "(" )
|
||||||
|
if #statement.Arguments > 0 then
|
||||||
|
for i = 1, #statement.Arguments do
|
||||||
|
appendStr( statement.Arguments[i].Name )
|
||||||
|
appendComma( i ~= #statement.Arguments or statement.VarArg )
|
||||||
|
if i == #statement.Arguments and statement.VarArg then
|
||||||
|
appendNextToken( "..." )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif statement.VarArg then
|
||||||
|
appendNextToken( "..." )
|
||||||
|
end
|
||||||
|
appendNextToken( ")" )
|
||||||
|
|
||||||
|
formatStatlist(statement.Body)
|
||||||
|
appendNextToken( "end" )
|
||||||
|
|
||||||
|
elseif statement.AstType == 'GenericForStatement' then
|
||||||
|
appendNextToken( "for" )
|
||||||
|
for i = 1, #statement.VariableList do
|
||||||
|
appendStr( statement.VariableList[i].Name )
|
||||||
|
appendComma( i ~= #statement.VariableList )
|
||||||
|
end
|
||||||
|
appendNextToken( "in" )
|
||||||
|
for i = 1, #statement.Generators do
|
||||||
|
formatExpr(statement.Generators[i])
|
||||||
|
appendComma( i ~= #statement.Generators )
|
||||||
|
end
|
||||||
|
appendNextToken( "do" )
|
||||||
|
formatStatlist(statement.Body)
|
||||||
|
appendNextToken( "end" )
|
||||||
|
|
||||||
|
elseif statement.AstType == 'NumericForStatement' then
|
||||||
|
appendNextToken( "for" )
|
||||||
|
appendStr( statement.Variable.Name )
|
||||||
|
appendNextToken( "=" )
|
||||||
|
formatExpr(statement.Start)
|
||||||
|
appendNextToken( "," )
|
||||||
|
formatExpr(statement.End)
|
||||||
|
if statement.Step then
|
||||||
|
appendNextToken( "," )
|
||||||
|
formatExpr(statement.Step)
|
||||||
|
end
|
||||||
|
appendNextToken( "do" )
|
||||||
|
formatStatlist(statement.Body)
|
||||||
|
appendNextToken( "end" )
|
||||||
|
|
||||||
|
elseif statement.AstType == 'LabelStatement' then
|
||||||
|
appendNextToken( "::" )
|
||||||
|
appendStr( statement.Label )
|
||||||
|
appendNextToken( "::" )
|
||||||
|
|
||||||
|
elseif statement.AstType == 'GotoStatement' then
|
||||||
|
appendNextToken( "goto" )
|
||||||
|
appendStr( statement.Label )
|
||||||
|
|
||||||
|
elseif statement.AstType == 'Eof' then
|
||||||
|
appendWhite()
|
||||||
|
|
||||||
|
else
|
||||||
|
print("Unknown AST Type: ", statement.AstType)
|
||||||
|
end
|
||||||
|
|
||||||
|
if statement.Semicolon then
|
||||||
|
appendNextToken(";")
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(tok_it == #statement.Tokens + 1)
|
||||||
|
debug_printf("/formatStatment")
|
||||||
|
end
|
||||||
|
|
||||||
|
formatStatlist = function(statList)
|
||||||
|
for _, stat in ipairs(statList.Body) do
|
||||||
|
formatStatement(stat)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
formatStatlist(ast)
|
||||||
|
|
||||||
|
return true, table.concat(out.rope)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Format_Identity
|
378
minify/FormatMini.lua
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
|
||||||
|
local parser = require'ParseLua'
|
||||||
|
local ParseLua = parser.ParseLua
|
||||||
|
local util = require'Util'
|
||||||
|
local lookupify = util.lookupify
|
||||||
|
|
||||||
|
--
|
||||||
|
-- FormatMini.lua
|
||||||
|
--
|
||||||
|
-- Returns the minified version of an AST. Operations which are performed:
|
||||||
|
-- - All comments and whitespace are ignored
|
||||||
|
-- - All local variables are renamed
|
||||||
|
--
|
||||||
|
|
||||||
|
local LowerChars = lookupify{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
||||||
|
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
|
||||||
|
's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
|
||||||
|
local UpperChars = lookupify{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
|
||||||
|
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
|
||||||
|
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
|
||||||
|
local Digits = lookupify{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
|
||||||
|
local Symbols = lookupify{'+', '-', '*', '/', '^', '%', ',', '{', '}', '[', ']', '(', ')', ';', '#'}
|
||||||
|
|
||||||
|
local function serialize_debug_symbols(map)
|
||||||
|
local out = {}
|
||||||
|
for k, v in pairs(map) do
|
||||||
|
table.insert(out, k .. "\t" .. v)
|
||||||
|
end
|
||||||
|
return table.concat(out, "\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Format_Mini(ast)
|
||||||
|
local formatStatlist, formatExpr;
|
||||||
|
local count = 0
|
||||||
|
--
|
||||||
|
local function joinStatementsSafe(a, b, sep)
|
||||||
|
--print(a, b)
|
||||||
|
if count > 150 then
|
||||||
|
count = 0
|
||||||
|
return a.."\n"..b
|
||||||
|
end
|
||||||
|
sep = sep or ' '
|
||||||
|
local aa, bb = a:sub(-1,-1), b:sub(1,1)
|
||||||
|
if UpperChars[aa] or LowerChars[aa] or aa == '_' then
|
||||||
|
if not (UpperChars[bb] or LowerChars[bb] or bb == '_' or Digits[bb]) then
|
||||||
|
--bb is a symbol, can join without sep
|
||||||
|
return a..b
|
||||||
|
elseif bb == '(' then
|
||||||
|
print("==============>>>",aa,bb)
|
||||||
|
--prevent ambiguous syntax
|
||||||
|
return a..sep..b
|
||||||
|
else
|
||||||
|
return a..sep..b
|
||||||
|
end
|
||||||
|
elseif Digits[aa] then
|
||||||
|
if bb == '(' then
|
||||||
|
--can join statements directly
|
||||||
|
return a..b
|
||||||
|
elseif Symbols[bb] then
|
||||||
|
return a .. b
|
||||||
|
else
|
||||||
|
return a..sep..b
|
||||||
|
end
|
||||||
|
elseif aa == '' then
|
||||||
|
return a..b
|
||||||
|
else
|
||||||
|
if bb == '(' then
|
||||||
|
--don't want to accidentally call last statement, can't join directly
|
||||||
|
return a..sep..b
|
||||||
|
else
|
||||||
|
--print("asdf", '"'..a..'"', '"'..b..'"')
|
||||||
|
return a..b
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
formatExpr = function(expr, precedence)
|
||||||
|
local precedence = precedence or 0
|
||||||
|
local currentPrecedence = 0
|
||||||
|
local skipParens = false
|
||||||
|
local out = ""
|
||||||
|
if expr.AstType == 'VarExpr' then
|
||||||
|
if expr.Variable then
|
||||||
|
out = out..expr.Variable.Name
|
||||||
|
else
|
||||||
|
out = out..expr.Name
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif expr.AstType == 'NumberExpr' then
|
||||||
|
out = out..expr.Value.Data
|
||||||
|
|
||||||
|
elseif expr.AstType == 'StringExpr' then
|
||||||
|
out = out..expr.Value.Data
|
||||||
|
|
||||||
|
elseif expr.AstType == 'BooleanExpr' then
|
||||||
|
out = out..tostring(expr.Value)
|
||||||
|
|
||||||
|
elseif expr.AstType == 'NilExpr' then
|
||||||
|
out = joinStatementsSafe(out, "nil")
|
||||||
|
|
||||||
|
elseif expr.AstType == 'BinopExpr' then
|
||||||
|
currentPrecedence = expr.OperatorPrecedence
|
||||||
|
out = joinStatementsSafe(out, formatExpr(expr.Lhs, currentPrecedence))
|
||||||
|
out = joinStatementsSafe(out, expr.Op)
|
||||||
|
out = joinStatementsSafe(out, formatExpr(expr.Rhs))
|
||||||
|
if expr.Op == '^' or expr.Op == '..' then
|
||||||
|
currentPrecedence = currentPrecedence - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if currentPrecedence < precedence then
|
||||||
|
skipParens = false
|
||||||
|
else
|
||||||
|
skipParens = true
|
||||||
|
end
|
||||||
|
--print(skipParens, precedence, currentPrecedence)
|
||||||
|
elseif expr.AstType == 'UnopExpr' then
|
||||||
|
out = joinStatementsSafe(out, expr.Op)
|
||||||
|
out = joinStatementsSafe(out, formatExpr(expr.Rhs))
|
||||||
|
|
||||||
|
elseif expr.AstType == 'DotsExpr' then
|
||||||
|
out = out.."..."
|
||||||
|
|
||||||
|
elseif expr.AstType == 'CallExpr' then
|
||||||
|
out = out..formatExpr(expr.Base)
|
||||||
|
out = out.."("
|
||||||
|
for i = 1, #expr.Arguments do
|
||||||
|
out = out..formatExpr(expr.Arguments[i])
|
||||||
|
if i ~= #expr.Arguments then
|
||||||
|
out = out..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = out..")"
|
||||||
|
|
||||||
|
elseif expr.AstType == 'TableCallExpr' then
|
||||||
|
out = out..formatExpr(expr.Base)
|
||||||
|
out = out..formatExpr(expr.Arguments[1])
|
||||||
|
|
||||||
|
elseif expr.AstType == 'StringCallExpr' then
|
||||||
|
out = out..formatExpr(expr.Base)
|
||||||
|
out = out..expr.Arguments[1].Data
|
||||||
|
|
||||||
|
elseif expr.AstType == 'IndexExpr' then
|
||||||
|
out = out..formatExpr(expr.Base).."["..formatExpr(expr.Index).."]"
|
||||||
|
|
||||||
|
elseif expr.AstType == 'MemberExpr' then
|
||||||
|
out = out..formatExpr(expr.Base)..expr.Indexer..expr.Ident.Data
|
||||||
|
|
||||||
|
elseif expr.AstType == 'Function' then
|
||||||
|
expr.Scope:ObfuscateVariables()
|
||||||
|
out = out.."function("
|
||||||
|
if #expr.Arguments > 0 then
|
||||||
|
for i = 1, #expr.Arguments do
|
||||||
|
out = out..expr.Arguments[i].Name
|
||||||
|
if i ~= #expr.Arguments then
|
||||||
|
out = out..","
|
||||||
|
elseif expr.VarArg then
|
||||||
|
out = out..",..."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif expr.VarArg then
|
||||||
|
out = out.."..."
|
||||||
|
end
|
||||||
|
out = out..")"
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(expr.Body))
|
||||||
|
out = joinStatementsSafe(out, "end")
|
||||||
|
|
||||||
|
elseif expr.AstType == 'ConstructorExpr' then
|
||||||
|
out = out.."{"
|
||||||
|
for i = 1, #expr.EntryList do
|
||||||
|
local entry = expr.EntryList[i]
|
||||||
|
if entry.Type == 'Key' then
|
||||||
|
out = out.."["..formatExpr(entry.Key).."]="..formatExpr(entry.Value)
|
||||||
|
elseif entry.Type == 'Value' then
|
||||||
|
out = out..formatExpr(entry.Value)
|
||||||
|
elseif entry.Type == 'KeyString' then
|
||||||
|
out = out..entry.Key.."="..formatExpr(entry.Value)
|
||||||
|
end
|
||||||
|
if i ~= #expr.EntryList then
|
||||||
|
out = out..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = out.."}"
|
||||||
|
|
||||||
|
elseif expr.AstType == 'Parentheses' then
|
||||||
|
out = out.."("..formatExpr(expr.Inner)..")"
|
||||||
|
|
||||||
|
end
|
||||||
|
--print(">>", skipParens, expr.ParenCount, out)
|
||||||
|
if not skipParens then
|
||||||
|
--print("hehe")
|
||||||
|
out = string.rep('(', expr.ParenCount or 0) .. out
|
||||||
|
out = out .. string.rep(')', expr.ParenCount or 0)
|
||||||
|
--print("", out)
|
||||||
|
end
|
||||||
|
count = count + #out
|
||||||
|
return --[[print(out) or]] out
|
||||||
|
end
|
||||||
|
|
||||||
|
local formatStatement = function(statement)
|
||||||
|
local out = ''
|
||||||
|
if statement.AstType == 'AssignmentStatement' then
|
||||||
|
for i = 1, #statement.Lhs do
|
||||||
|
out = out..formatExpr(statement.Lhs[i])
|
||||||
|
if i ~= #statement.Lhs then
|
||||||
|
out = out..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #statement.Rhs > 0 then
|
||||||
|
out = out.."="
|
||||||
|
for i = 1, #statement.Rhs do
|
||||||
|
out = out..formatExpr(statement.Rhs[i])
|
||||||
|
if i ~= #statement.Rhs then
|
||||||
|
out = out..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif statement.AstType == 'CallStatement' then
|
||||||
|
out = formatExpr(statement.Expression)
|
||||||
|
|
||||||
|
elseif statement.AstType == 'LocalStatement' then
|
||||||
|
out = out.."local "
|
||||||
|
for i = 1, #statement.LocalList do
|
||||||
|
out = out..statement.LocalList[i].Name
|
||||||
|
if i ~= #statement.LocalList then
|
||||||
|
out = out..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #statement.InitList > 0 then
|
||||||
|
out = out.."="
|
||||||
|
for i = 1, #statement.InitList do
|
||||||
|
out = out..formatExpr(statement.InitList[i])
|
||||||
|
if i ~= #statement.InitList then
|
||||||
|
out = out..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif statement.AstType == 'IfStatement' then
|
||||||
|
out = joinStatementsSafe("if", formatExpr(statement.Clauses[1].Condition))
|
||||||
|
out = joinStatementsSafe(out, "then")
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Clauses[1].Body))
|
||||||
|
for i = 2, #statement.Clauses do
|
||||||
|
local st = statement.Clauses[i]
|
||||||
|
if st.Condition then
|
||||||
|
out = joinStatementsSafe(out, "elseif")
|
||||||
|
out = joinStatementsSafe(out, formatExpr(st.Condition))
|
||||||
|
out = joinStatementsSafe(out, "then")
|
||||||
|
else
|
||||||
|
out = joinStatementsSafe(out, "else")
|
||||||
|
end
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(st.Body))
|
||||||
|
end
|
||||||
|
out = joinStatementsSafe(out, "end")
|
||||||
|
|
||||||
|
elseif statement.AstType == 'WhileStatement' then
|
||||||
|
out = joinStatementsSafe("while", formatExpr(statement.Condition))
|
||||||
|
out = joinStatementsSafe(out, "do")
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
out = joinStatementsSafe(out, "end")
|
||||||
|
|
||||||
|
elseif statement.AstType == 'DoStatement' then
|
||||||
|
out = joinStatementsSafe(out, "do")
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
out = joinStatementsSafe(out, "end")
|
||||||
|
|
||||||
|
elseif statement.AstType == 'ReturnStatement' then
|
||||||
|
out = "return"
|
||||||
|
for i = 1, #statement.Arguments do
|
||||||
|
out = joinStatementsSafe(out, formatExpr(statement.Arguments[i]))
|
||||||
|
if i ~= #statement.Arguments then
|
||||||
|
out = out..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif statement.AstType == 'BreakStatement' then
|
||||||
|
out = "break"
|
||||||
|
|
||||||
|
elseif statement.AstType == 'RepeatStatement' then
|
||||||
|
out = "repeat"
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
out = joinStatementsSafe(out, "until")
|
||||||
|
out = joinStatementsSafe(out, formatExpr(statement.Condition))
|
||||||
|
|
||||||
|
elseif statement.AstType == 'Function' then
|
||||||
|
statement.Scope:ObfuscateVariables()
|
||||||
|
if statement.IsLocal then
|
||||||
|
out = "local"
|
||||||
|
end
|
||||||
|
out = joinStatementsSafe(out, "function ")
|
||||||
|
if statement.IsLocal then
|
||||||
|
out = out..statement.Name.Name
|
||||||
|
else
|
||||||
|
out = out..formatExpr(statement.Name)
|
||||||
|
end
|
||||||
|
out = out.."("
|
||||||
|
if #statement.Arguments > 0 then
|
||||||
|
for i = 1, #statement.Arguments do
|
||||||
|
out = out..statement.Arguments[i].Name
|
||||||
|
if i ~= #statement.Arguments then
|
||||||
|
out = out..","
|
||||||
|
elseif statement.VarArg then
|
||||||
|
--print("Apply vararg")
|
||||||
|
out = out..",..."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif statement.VarArg then
|
||||||
|
out = out.."..."
|
||||||
|
end
|
||||||
|
out = out..")"
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
out = joinStatementsSafe(out, "end")
|
||||||
|
|
||||||
|
elseif statement.AstType == 'GenericForStatement' then
|
||||||
|
statement.Scope:ObfuscateVariables()
|
||||||
|
out = "for "
|
||||||
|
for i = 1, #statement.VariableList do
|
||||||
|
out = out..statement.VariableList[i].Name
|
||||||
|
if i ~= #statement.VariableList then
|
||||||
|
out = out..","
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = out.." in"
|
||||||
|
for i = 1, #statement.Generators do
|
||||||
|
out = joinStatementsSafe(out, formatExpr(statement.Generators[i]))
|
||||||
|
if i ~= #statement.Generators then
|
||||||
|
out = joinStatementsSafe(out, ',')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = joinStatementsSafe(out, "do")
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
out = joinStatementsSafe(out, "end")
|
||||||
|
|
||||||
|
elseif statement.AstType == 'NumericForStatement' then
|
||||||
|
statement.Scope:ObfuscateVariables()
|
||||||
|
out = "for "
|
||||||
|
out = out..statement.Variable.Name.."="
|
||||||
|
out = out..formatExpr(statement.Start)..","..formatExpr(statement.End)
|
||||||
|
if statement.Step then
|
||||||
|
out = out..","..formatExpr(statement.Step)
|
||||||
|
end
|
||||||
|
out = joinStatementsSafe(out, "do")
|
||||||
|
out = joinStatementsSafe(out, formatStatlist(statement.Body))
|
||||||
|
out = joinStatementsSafe(out, "end")
|
||||||
|
elseif statement.AstType == 'Comment' then
|
||||||
|
-- ignore
|
||||||
|
elseif statement.AstType == 'Eof' then
|
||||||
|
-- ignore
|
||||||
|
else
|
||||||
|
print("Unknown AST Type: " .. statement.AstType)
|
||||||
|
end
|
||||||
|
count = count + #out
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
|
local map = {}
|
||||||
|
local function insert(t)
|
||||||
|
for k, v in pairs(t) do
|
||||||
|
map[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
formatStatlist = function(statList)
|
||||||
|
local out = ''
|
||||||
|
statList.Scope:ObfuscateVariables()
|
||||||
|
insert(statList.Scope.name_map or {})
|
||||||
|
for _, stat in pairs(statList.Body) do
|
||||||
|
out = joinStatementsSafe(out, formatStatement(stat), ';')
|
||||||
|
end
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
|
ast.Scope:ObfuscateVariables()
|
||||||
|
insert(ast.Scope.name_map)
|
||||||
|
return formatStatlist(ast), serialize_debug_symbols(map)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Format_Mini
|
20
minify/LICENSE.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2012-2013
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1411
minify/ParseLua.lua
Normal file
44
minify/README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
Lua Parsing and Refactorization tools
|
||||||
|
=========
|
||||||
|
|
||||||
|
A collection of tools for working with Lua source code. Primarily a Lua source code minifier, but also includes some static analysis tools and a general Lua lexer and parser.
|
||||||
|
|
||||||
|
Currently the minifier performs:
|
||||||
|
|
||||||
|
- Stripping of all comments and whitespace
|
||||||
|
- True semantic renaming of all local variables to a reduced form
|
||||||
|
- Reduces the source to the minimal spacing, spaces are only inserted where actually needed.
|
||||||
|
|
||||||
|
|
||||||
|
LuaMinify Command Line Utility Usage
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
The `LuaMinify` shell and batch files are given as shortcuts to running a command line instance of the minifier with the following usage:
|
||||||
|
|
||||||
|
LuaMinify sourcefile [destfile]
|
||||||
|
|
||||||
|
Which will minify to a given destination file, or to a copy of the source file with _min appended to the filename if no output file is given.
|
||||||
|
|
||||||
|
|
||||||
|
LuaMinify Roblox Plugin Usage
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
First, download the source code, which you can do by hitting this button:
|
||||||
|
|
||||||
|
![Click That](http://github.com/stravant/LuaMinify/raw/master/RobloxPluginInstructions.png)
|
||||||
|
|
||||||
|
Then copy the `RobloxPlugin` folder from the source into your Roblox Plugins directory, which can be found by hitting `Tools->Open Plugins Folder` in Roblox Studio.
|
||||||
|
|
||||||
|
Features/Todo
|
||||||
|
-------------
|
||||||
|
Features:
|
||||||
|
|
||||||
|
- Lua scanner/parser, which generates a full AST
|
||||||
|
- Lua reconstructor
|
||||||
|
- minimal
|
||||||
|
- full reconstruction (TODO: options, comments)
|
||||||
|
- TODO: exact reconstructor
|
||||||
|
- support for embedded long strings/comments e.g. [[abc [[ def ]] ghi]]
|
||||||
|
|
||||||
|
Todo:
|
||||||
|
- use table.concat instead of appends in the reconstructors
|
219
minify/Scope.lua
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
local var_count = 0
|
||||||
|
local util = require'Util'
|
||||||
|
local lookupify = util.lookupify
|
||||||
|
local Keywords = lookupify{
|
||||||
|
'and', 'break', 'do', 'else', 'elseif',
|
||||||
|
'end', 'false', 'for', 'function', 'goto', 'if',
|
||||||
|
'in', 'local', 'nil', 'not', 'or', 'repeat',
|
||||||
|
'return', 'then', 'true', 'until', 'while',
|
||||||
|
};
|
||||||
|
|
||||||
|
local Scope = {
|
||||||
|
new = function(self, parent)
|
||||||
|
local s = {
|
||||||
|
Parent = parent,
|
||||||
|
Locals = { },
|
||||||
|
Globals = { },
|
||||||
|
oldLocalNamesMap = { },
|
||||||
|
oldGlobalNamesMap = { },
|
||||||
|
Children = { },
|
||||||
|
}
|
||||||
|
|
||||||
|
if parent then
|
||||||
|
table.insert(parent.Children, s)
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(s, { __index = self })
|
||||||
|
end,
|
||||||
|
|
||||||
|
AddLocal = function(self, v)
|
||||||
|
table.insert(self.Locals, v)
|
||||||
|
end,
|
||||||
|
|
||||||
|
AddGlobal = function(self, v)
|
||||||
|
table.insert(self.Globals, v)
|
||||||
|
end,
|
||||||
|
|
||||||
|
CreateLocal = function(self, name)
|
||||||
|
local v
|
||||||
|
v = self:GetLocal(name)
|
||||||
|
if v then return v end
|
||||||
|
v = { }
|
||||||
|
v.Scope = self
|
||||||
|
v.Name = name
|
||||||
|
v.IsGlobal = false
|
||||||
|
v.CanRename = true
|
||||||
|
v.References = 1
|
||||||
|
self:AddLocal(v)
|
||||||
|
return v
|
||||||
|
end,
|
||||||
|
|
||||||
|
GetLocal = function(self, name)
|
||||||
|
for k, var in pairs(self.Locals) do
|
||||||
|
if var.Name == name then return var end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.Parent then
|
||||||
|
return self.Parent:GetLocal(name)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
GetOldLocal = function(self, name)
|
||||||
|
if self.oldLocalNamesMap[name] then
|
||||||
|
return self.oldLocalNamesMap[name]
|
||||||
|
end
|
||||||
|
return self:GetLocal(name)
|
||||||
|
end,
|
||||||
|
|
||||||
|
mapLocal = function(self, name, var)
|
||||||
|
self.oldLocalNamesMap[name] = var
|
||||||
|
end,
|
||||||
|
|
||||||
|
GetOldGlobal = function(self, name)
|
||||||
|
if self.oldGlobalNamesMap[name] then
|
||||||
|
return self.oldGlobalNamesMap[name]
|
||||||
|
end
|
||||||
|
return self:GetGlobal(name)
|
||||||
|
end,
|
||||||
|
|
||||||
|
mapGlobal = function(self, name, var)
|
||||||
|
self.oldGlobalNamesMap[name] = var
|
||||||
|
end,
|
||||||
|
|
||||||
|
GetOldVariable = function(self, name)
|
||||||
|
return self:GetOldLocal(name) or self:GetOldGlobal(name)
|
||||||
|
end,
|
||||||
|
|
||||||
|
RenameLocal = function(self, oldName, newName)
|
||||||
|
oldName = type(oldName) == 'string' and oldName or oldName.Name
|
||||||
|
self.name_map = self.name_map or {}
|
||||||
|
self.name_map[newName] = oldName
|
||||||
|
local found = false
|
||||||
|
local var = self:GetLocal(oldName)
|
||||||
|
if var then
|
||||||
|
var.Name = newName
|
||||||
|
self:mapLocal(oldName, var)
|
||||||
|
found = true
|
||||||
|
end
|
||||||
|
if not found and self.Parent then
|
||||||
|
self.Parent:RenameLocal(oldName, newName)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
RenameGlobal = function(self, oldName, newName)
|
||||||
|
oldName = type(oldName) == 'string' and oldName or oldName.Name
|
||||||
|
local found = false
|
||||||
|
local var = self:GetGlobal(oldName)
|
||||||
|
if var then
|
||||||
|
var.Name = newName
|
||||||
|
self:mapGlobal(oldName, var)
|
||||||
|
found = true
|
||||||
|
end
|
||||||
|
if not found and self.Parent then
|
||||||
|
self.Parent:RenameGlobal(oldName, newName)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
RenameVariable = function(self, oldName, newName)
|
||||||
|
oldName = type(oldName) == 'string' and oldName or oldName.Name
|
||||||
|
if self:GetLocal(oldName) then
|
||||||
|
self:RenameLocal(oldName, newName)
|
||||||
|
else
|
||||||
|
self:RenameGlobal(oldName, newName)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
GetAllVariables = function(self)
|
||||||
|
local ret = self:getVars(true) -- down
|
||||||
|
for k, v in pairs(self:getVars(false)) do -- up
|
||||||
|
table.insert(ret, v)
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end,
|
||||||
|
|
||||||
|
getVars = function(self, top)
|
||||||
|
local ret = { }
|
||||||
|
if top then
|
||||||
|
for k, v in pairs(self.Children) do
|
||||||
|
for k2, v2 in pairs(v:getVars(true)) do
|
||||||
|
table.insert(ret, v2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for k, v in pairs(self.Locals) do
|
||||||
|
table.insert(ret, v)
|
||||||
|
end
|
||||||
|
for k, v in pairs(self.Globals) do
|
||||||
|
table.insert(ret, v)
|
||||||
|
end
|
||||||
|
if self.Parent then
|
||||||
|
for k, v in pairs(self.Parent:getVars(false)) do
|
||||||
|
table.insert(ret, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end,
|
||||||
|
|
||||||
|
CreateGlobal = function(self, name)
|
||||||
|
local v
|
||||||
|
v = self:GetGlobal(name)
|
||||||
|
if v then return v end
|
||||||
|
v = { }
|
||||||
|
v.Scope = self
|
||||||
|
v.Name = name
|
||||||
|
v.IsGlobal = true
|
||||||
|
v.CanRename = true
|
||||||
|
v.References = 1
|
||||||
|
self:AddGlobal(v)
|
||||||
|
return v
|
||||||
|
end,
|
||||||
|
|
||||||
|
GetGlobal = function(self, name)
|
||||||
|
for k, v in pairs(self.Globals) do
|
||||||
|
if v.Name == name then return v end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.Parent then
|
||||||
|
return self.Parent:GetGlobal(name)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
GetVariable = function(self, name)
|
||||||
|
return self:GetLocal(name) or self:GetGlobal(name)
|
||||||
|
end,
|
||||||
|
|
||||||
|
ObfuscateLocals = function(self, recommendedMaxLength, validNameChars)
|
||||||
|
recommendedMaxLength = recommendedMaxLength or 7
|
||||||
|
local chars = validNameChars or "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuioplkjhgfdsazxcvbnm_"
|
||||||
|
--local chars2 = validNameChars or "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuioplkjhgfdsazxcvbnm_1234567890"
|
||||||
|
for _, var in pairs(self.Locals) do
|
||||||
|
local id = ""
|
||||||
|
local tries = 0
|
||||||
|
--[[
|
||||||
|
repeat
|
||||||
|
local n = math.random(1, #chars)
|
||||||
|
id = id .. chars:sub(n, n)
|
||||||
|
for i = 1, math.random(0, tries > 5 and 30 or recommendedMaxLength) do
|
||||||
|
local n = math.random(1, #chars2)
|
||||||
|
id = id .. chars2:sub(n, n)
|
||||||
|
end
|
||||||
|
tries = tries + 1
|
||||||
|
until not self:GetVariable(id)]]
|
||||||
|
local id
|
||||||
|
repeat
|
||||||
|
local n = var_count
|
||||||
|
id = ""
|
||||||
|
repeat
|
||||||
|
local x = n % #chars
|
||||||
|
id = id .. chars:sub(x + 1, x + 1)
|
||||||
|
n = math.floor(n / #chars)
|
||||||
|
until n == 0
|
||||||
|
var_count = var_count + 1
|
||||||
|
until not Keywords[id]
|
||||||
|
self:RenameLocal(var.Name, id)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scope
|
91
minify/Util.lua
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
--
|
||||||
|
-- Util.lua
|
||||||
|
--
|
||||||
|
-- Provides some common utilities shared throughout the project.
|
||||||
|
--
|
||||||
|
|
||||||
|
local function lookupify(tb)
|
||||||
|
for _, v in pairs(tb) do
|
||||||
|
tb[v] = true
|
||||||
|
end
|
||||||
|
return tb
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function CountTable(tb)
|
||||||
|
local c = 0
|
||||||
|
for _ in pairs(tb) do c = c + 1 end
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function PrintTable(tb, atIndent)
|
||||||
|
if tb.Print then
|
||||||
|
return tb.Print()
|
||||||
|
end
|
||||||
|
atIndent = atIndent or 0
|
||||||
|
local useNewlines = (CountTable(tb) > 1)
|
||||||
|
local baseIndent = string.rep(' ', atIndent+1)
|
||||||
|
local out = "{"..(useNewlines and '\n' or '')
|
||||||
|
for k, v in pairs(tb) do
|
||||||
|
if type(v) ~= 'function' then
|
||||||
|
--do
|
||||||
|
out = out..(useNewlines and baseIndent or '')
|
||||||
|
if type(k) == 'number' then
|
||||||
|
--nothing to do
|
||||||
|
elseif type(k) == 'string' and k:match("^[A-Za-z_][A-Za-z0-9_]*$") then
|
||||||
|
out = out..k.." = "
|
||||||
|
elseif type(k) == 'string' then
|
||||||
|
out = out.."[\""..k.."\"] = "
|
||||||
|
else
|
||||||
|
out = out.."["..tostring(k).."] = "
|
||||||
|
end
|
||||||
|
if type(v) == 'string' then
|
||||||
|
out = out.."\""..v.."\""
|
||||||
|
elseif type(v) == 'number' then
|
||||||
|
out = out..v
|
||||||
|
elseif type(v) == 'table' then
|
||||||
|
out = out..PrintTable(v, atIndent+(useNewlines and 1 or 0))
|
||||||
|
else
|
||||||
|
out = out..tostring(v)
|
||||||
|
end
|
||||||
|
if next(tb, k) then
|
||||||
|
out = out..","
|
||||||
|
end
|
||||||
|
if useNewlines then
|
||||||
|
out = out..'\n'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = out..(useNewlines and string.rep(' ', atIndent) or '').."}"
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function splitLines(str)
|
||||||
|
if str:match("\n") then
|
||||||
|
local lines = {}
|
||||||
|
for line in str:gmatch("[^\n]*") do
|
||||||
|
table.insert(lines, line)
|
||||||
|
end
|
||||||
|
assert(#lines > 0)
|
||||||
|
return lines
|
||||||
|
else
|
||||||
|
return { str }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function printf(fmt, ...)
|
||||||
|
return print(string.format(fmt, ...))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
PrintTable = PrintTable,
|
||||||
|
CountTable = CountTable,
|
||||||
|
lookupify = lookupify,
|
||||||
|
splitLines = splitLines,
|
||||||
|
printf = printf,
|
||||||
|
}
|
39
minify/strict.lua
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
-- From http://metalua.luaforge.net/src/lib/strict.lua.html
|
||||||
|
--
|
||||||
|
-- strict.lua
|
||||||
|
-- checks uses of undeclared global variables
|
||||||
|
-- All global variables must be 'declared' through a regular assignment
|
||||||
|
-- (even assigning nil will do) in a main chunk before being used
|
||||||
|
-- anywhere or assigned to inside a function.
|
||||||
|
--
|
||||||
|
|
||||||
|
local mt = getmetatable(_G)
|
||||||
|
if mt == nil then
|
||||||
|
mt = {}
|
||||||
|
setmetatable(_G, mt)
|
||||||
|
end
|
||||||
|
|
||||||
|
__STRICT = true
|
||||||
|
mt.__declared = {}
|
||||||
|
|
||||||
|
mt.__newindex = function (t, n, v)
|
||||||
|
if __STRICT and not mt.__declared[n] then
|
||||||
|
local w = debug.getinfo(2, "S").what
|
||||||
|
if w ~= "main" and w ~= "C" then
|
||||||
|
error("assign to undeclared variable '"..n.."'", 2)
|
||||||
|
end
|
||||||
|
mt.__declared[n] = true
|
||||||
|
end
|
||||||
|
rawset(t, n, v)
|
||||||
|
end
|
||||||
|
|
||||||
|
mt.__index = function (t, n)
|
||||||
|
if not mt.__declared[n] and debug.getinfo(2, "S").what ~= "C" then
|
||||||
|
error("variable '"..n.."' is not declared", 2)
|
||||||
|
end
|
||||||
|
return rawget(t, n)
|
||||||
|
end
|
||||||
|
|
||||||
|
function global(...)
|
||||||
|
for _, v in ipairs{...} do mt.__declared[v] = true end
|
||||||
|
end
|
60
minify/tests/test_beautifier.lua
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
-- Adapted from Yueliang
|
||||||
|
|
||||||
|
package.path = "../?.lua;" .. package.path
|
||||||
|
local util = require'Util'
|
||||||
|
local Parser = require'ParseLua'
|
||||||
|
local Format = require'FormatBeautiful'
|
||||||
|
|
||||||
|
for w in io.lines("test_lines.txt") do
|
||||||
|
--print(w)
|
||||||
|
local success, ast = Parser.ParseLua(w)
|
||||||
|
if w:find("FAIL") then
|
||||||
|
--[[if success then
|
||||||
|
print("ERROR PARSING LINE:")
|
||||||
|
print("Should fail: true. Did fail: " .. tostring(not success))
|
||||||
|
print("Line: " .. w)
|
||||||
|
else
|
||||||
|
--print("Suceeded!")
|
||||||
|
end]]
|
||||||
|
else
|
||||||
|
if not success then
|
||||||
|
print("ERROR PARSING LINE:")
|
||||||
|
print("Should fail: false. Did fail: " .. tostring(not success))
|
||||||
|
print("Line: " .. w)
|
||||||
|
else
|
||||||
|
success, ast = Format(ast)
|
||||||
|
--print(success, ast)
|
||||||
|
if not success then
|
||||||
|
print("ERROR BEAUTIFYING LINE:")
|
||||||
|
print("Message: " .. ast)
|
||||||
|
print("Line: " .. w)
|
||||||
|
end
|
||||||
|
local success_ = success
|
||||||
|
success, ast = loadstring(success)
|
||||||
|
if not success then
|
||||||
|
print("ERROR PARSING BEAUTIFIED LINE:")
|
||||||
|
print("Message: " .. ast)
|
||||||
|
print("Line: " .. success_)
|
||||||
|
end
|
||||||
|
--print("Suceeded!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print"Done!"
|
||||||
|
os.remove("tmp")
|
||||||
|
|
||||||
|
|
||||||
|
--[[
|
||||||
|
function readAll(file)
|
||||||
|
local f = io.open(file, "rb")
|
||||||
|
local content = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
return content
|
||||||
|
end
|
||||||
|
|
||||||
|
local text = readAll('../ParseLua.lua')
|
||||||
|
local success, ast = Parser.ParseLua(text)
|
||||||
|
local nice
|
||||||
|
nice = Format(ast)
|
||||||
|
print(nice)
|
||||||
|
--]]
|
124
minify/tests/test_identity.lua
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package.path = "../?.lua;" .. package.path
|
||||||
|
local Parser = require'ParseLua'
|
||||||
|
local util = require'Util'
|
||||||
|
local FormatIdentity = require'FormatIdentity'
|
||||||
|
local FormatMini = require'FormatMini'
|
||||||
|
local FormatBeautiful = require'FormatBeautiful'
|
||||||
|
require'strict'
|
||||||
|
|
||||||
|
function readAll(file)
|
||||||
|
local f = io.open(file, "rb")
|
||||||
|
local content = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
return content
|
||||||
|
end
|
||||||
|
|
||||||
|
local g_lexTime = 0
|
||||||
|
local g_parseTime = 0
|
||||||
|
local g_reconstructTime = 0
|
||||||
|
|
||||||
|
function reconstructText(text)
|
||||||
|
local preLex = os.clock()
|
||||||
|
|
||||||
|
local success, tokens, ast, reconstructed
|
||||||
|
success, tokens = Parser.LexLua(text)
|
||||||
|
if not success then
|
||||||
|
print("ERROR: " .. tokens)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local preParse = os.clock()
|
||||||
|
|
||||||
|
success, ast = Parser.ParseLua(tokens)
|
||||||
|
if not success then
|
||||||
|
print("ERROR: " .. ast)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local preReconstruct = os.clock()
|
||||||
|
|
||||||
|
local DO_MINI = false
|
||||||
|
local DO_CHECK = false
|
||||||
|
|
||||||
|
if DO_MINI then
|
||||||
|
success, reconstructed = FormatMini(ast)
|
||||||
|
else
|
||||||
|
success, reconstructed = FormatIdentity(ast)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not success then
|
||||||
|
print("ERROR: " .. reconstructed)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local post = os.clock()
|
||||||
|
g_lexTime = g_lexTime + (preParse - preLex)
|
||||||
|
g_parseTime = g_parseTime + (preReconstruct - preParse)
|
||||||
|
g_reconstructTime = g_reconstructTime + (post - preReconstruct)
|
||||||
|
|
||||||
|
if DO_CHECK then
|
||||||
|
--[[
|
||||||
|
print()
|
||||||
|
print("Reconstructed: ")
|
||||||
|
print("--------------------")
|
||||||
|
print(reconstructed)
|
||||||
|
print("--------------------")
|
||||||
|
print("Done. ")
|
||||||
|
--]]
|
||||||
|
|
||||||
|
if reconstructed == text then
|
||||||
|
--print("Reconstruction succeeded")
|
||||||
|
else
|
||||||
|
print("Reconstruction failed")
|
||||||
|
|
||||||
|
local inputLines = util.splitLines(text)
|
||||||
|
local outputLines = util.splitLines(reconstructed)
|
||||||
|
local n = math.max(#inputLines, #outputLines)
|
||||||
|
for i = 1,n do
|
||||||
|
if inputLines[i] ~= outputLines[i] then
|
||||||
|
util.printf("ERROR on line %i", i)
|
||||||
|
util.printf("Input: %q", inputLines[i])
|
||||||
|
util.printf("Output: %q", outputLines[i])
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--[*[
|
||||||
|
local files = {
|
||||||
|
"../ParseLua.lua",
|
||||||
|
"../FormatIdentity.lua",
|
||||||
|
"../Scope.lua",
|
||||||
|
"../strict.lua",
|
||||||
|
"../Type.lua",
|
||||||
|
"Test_identity.lua"
|
||||||
|
}
|
||||||
|
|
||||||
|
for _,path in ipairs(files) do
|
||||||
|
print(path)
|
||||||
|
local text = readAll(path)
|
||||||
|
reconstructText(text)
|
||||||
|
end
|
||||||
|
|
||||||
|
--]]
|
||||||
|
|
||||||
|
print("test_lines.txt")
|
||||||
|
|
||||||
|
local line_nr = 0
|
||||||
|
for text in io.lines("test_lines.txt") do
|
||||||
|
line_nr = line_nr + 1
|
||||||
|
if not text:find("FAIL") then
|
||||||
|
--util.printf("\nText: %q", text)
|
||||||
|
reconstructText(text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
reconstructText('function a(p,q,r,...) end')
|
||||||
|
|
||||||
|
util.printf("Lex time: %f s", g_lexTime)
|
||||||
|
util.printf("Parse time: %f s", g_parseTime)
|
||||||
|
util.printf("Format time: %f s", g_reconstructTime)
|
523
minify/tests/test_lines.txt
Normal file
@ -0,0 +1,523 @@
|
|||||||
|
; -- FAIL
|
||||||
|
local -- FAIL
|
||||||
|
local; -- FAIL
|
||||||
|
local = -- FAIL
|
||||||
|
local end -- FAIL
|
||||||
|
local a
|
||||||
|
local a;
|
||||||
|
local a, b, c
|
||||||
|
local a; local b local c;
|
||||||
|
local a = 1
|
||||||
|
local a local b = a
|
||||||
|
local a, b = 1, 2
|
||||||
|
local a, b, c = 1, 2, 3
|
||||||
|
local a, b, c = 1
|
||||||
|
local a = 1, 2, 3
|
||||||
|
local a, local -- FAIL
|
||||||
|
local 1 -- FAIL
|
||||||
|
local "foo" -- FAIL
|
||||||
|
local a = local -- FAIL
|
||||||
|
local a, b, = -- FAIL
|
||||||
|
local a, b = 1, local -- FAIL
|
||||||
|
local a, b = , local -- FAIL
|
||||||
|
do -- FAIL
|
||||||
|
end -- FAIL
|
||||||
|
do end
|
||||||
|
do ; end -- FAIL
|
||||||
|
do 1 end -- FAIL
|
||||||
|
do "foo" end -- FAIL
|
||||||
|
do local a, b end
|
||||||
|
do local a local b end
|
||||||
|
do local a; local b; end
|
||||||
|
do local a = 1 end
|
||||||
|
do do end end
|
||||||
|
do do end; end
|
||||||
|
do do do end end end
|
||||||
|
do do do end; end; end
|
||||||
|
do do do return end end end
|
||||||
|
do end do -- FAIL
|
||||||
|
do end end -- FAIL
|
||||||
|
do return end
|
||||||
|
do return return end -- FAIL
|
||||||
|
do break end -- FAIL
|
||||||
|
while -- FAIL
|
||||||
|
while do -- FAIL
|
||||||
|
while = -- FAIL
|
||||||
|
while 1 do -- FAIL
|
||||||
|
while 1 do end
|
||||||
|
while 1 do local a end
|
||||||
|
while 1 do local a local b end
|
||||||
|
while 1 do local a; local b; end
|
||||||
|
while 1 do 2 end -- FAIL
|
||||||
|
while 1 do "foo" end -- FAIL
|
||||||
|
while true do end
|
||||||
|
while 1 do ; end -- FAIL
|
||||||
|
while 1 do while -- FAIL
|
||||||
|
while 1 end -- FAIL
|
||||||
|
while 1 2 do -- FAIL
|
||||||
|
while 1 = 2 do -- FAIL
|
||||||
|
while 1 do return end
|
||||||
|
while 1 do return return end -- FAIL
|
||||||
|
while 1 do do end end
|
||||||
|
while 1 do do return end end
|
||||||
|
while 1 do break end
|
||||||
|
while 1 do break break end -- FAIL
|
||||||
|
while 1 do do break end end
|
||||||
|
repeat -- FAIL
|
||||||
|
repeat until -- FAIL
|
||||||
|
repeat until 0
|
||||||
|
repeat until false
|
||||||
|
repeat until local -- FAIL
|
||||||
|
repeat end -- FAIL
|
||||||
|
repeat 1 -- FAIL
|
||||||
|
repeat = -- FAIL
|
||||||
|
repeat local a until 1
|
||||||
|
repeat local a local b until 0
|
||||||
|
repeat local a; local b; until 0
|
||||||
|
repeat ; until 1 -- FAIL
|
||||||
|
repeat 2 until 1 -- FAIL
|
||||||
|
repeat "foo" until 1 -- FAIL
|
||||||
|
repeat return until 0
|
||||||
|
repeat return return until 0 -- FAIL
|
||||||
|
repeat break until 0
|
||||||
|
repeat break break until 0 -- FAIL
|
||||||
|
repeat do end until 0
|
||||||
|
repeat do return end until 0
|
||||||
|
repeat do break end until 0
|
||||||
|
for -- FAIL
|
||||||
|
for do -- FAIL
|
||||||
|
for end -- FAIL
|
||||||
|
for 1 -- FAIL
|
||||||
|
for a -- FAIL
|
||||||
|
for true -- FAIL
|
||||||
|
for a, in -- FAIL
|
||||||
|
for a in -- FAIL
|
||||||
|
for a do -- FAIL
|
||||||
|
for a in do -- FAIL
|
||||||
|
for a in b do -- FAIL
|
||||||
|
for a in b end -- FAIL
|
||||||
|
for a in b, do -- FAIL
|
||||||
|
for a in b do end
|
||||||
|
for a in b do local a local b end
|
||||||
|
for a in b do local a; local b; end
|
||||||
|
for a in b do 1 end -- FAIL
|
||||||
|
for a in b do "foo" end -- FAIL
|
||||||
|
for a b in -- FAIL
|
||||||
|
for a, b, c in p do end
|
||||||
|
for a, b, c in p, q, r do end
|
||||||
|
for a in 1 do end
|
||||||
|
for a in true do end
|
||||||
|
for a in "foo" do end
|
||||||
|
for a in b do break end
|
||||||
|
for a in b do break break end -- FAIL
|
||||||
|
for a in b do return end
|
||||||
|
for a in b do return return end -- FAIL
|
||||||
|
for a in b do do end end
|
||||||
|
for a in b do do break end end
|
||||||
|
for a in b do do return end end
|
||||||
|
for = -- FAIL
|
||||||
|
for a = -- FAIL
|
||||||
|
for a, b = -- FAIL
|
||||||
|
for a = do -- FAIL
|
||||||
|
for a = 1, do -- FAIL
|
||||||
|
for a = p, q, do -- FAIL
|
||||||
|
for a = p q do -- FAIL
|
||||||
|
for a = b do end -- FAIL
|
||||||
|
for a = 1, 2, 3, 4 do end -- FAIL
|
||||||
|
for a = p, q do end
|
||||||
|
for a = 1, 2 do end
|
||||||
|
for a = 1, 2 do local a local b end
|
||||||
|
for a = 1, 2 do local a; local b; end
|
||||||
|
for a = 1, 2 do 3 end -- FAIL
|
||||||
|
for a = 1, 2 do "foo" end -- FAIL
|
||||||
|
for a = p, q, r do end
|
||||||
|
for a = 1, 2, 3 do end
|
||||||
|
for a = p, q do break end
|
||||||
|
for a = p, q do break break end -- FAIL
|
||||||
|
for a = 1, 2 do return end
|
||||||
|
for a = 1, 2 do return return end -- FAIL
|
||||||
|
for a = p, q do do end end
|
||||||
|
for a = p, q do do break end end
|
||||||
|
for a = p, q do do return end end
|
||||||
|
break -- FAIL
|
||||||
|
return
|
||||||
|
return;
|
||||||
|
return return -- FAIL
|
||||||
|
return 1
|
||||||
|
return local -- FAIL
|
||||||
|
return "foo"
|
||||||
|
return 1, -- FAIL
|
||||||
|
return 1,2,3
|
||||||
|
return a,b,c,d
|
||||||
|
return 1,2;
|
||||||
|
return ...
|
||||||
|
return 1,a,...
|
||||||
|
if -- FAIL
|
||||||
|
elseif -- FAIL
|
||||||
|
else -- FAIL
|
||||||
|
then -- FAIL
|
||||||
|
if then -- FAIL
|
||||||
|
if 1 -- FAIL
|
||||||
|
if 1 then -- FAIL
|
||||||
|
if 1 else -- FAIL
|
||||||
|
if 1 then else -- FAIL
|
||||||
|
if 1 then elseif -- FAIL
|
||||||
|
if 1 then end
|
||||||
|
if 1 then local a end
|
||||||
|
if 1 then local a local b end
|
||||||
|
if 1 then local a; local b; end
|
||||||
|
if 1 then else end
|
||||||
|
if 1 then local a else local b end
|
||||||
|
if 1 then local a; else local b; end
|
||||||
|
if 1 then elseif 2 -- FAIL
|
||||||
|
if 1 then elseif 2 then -- FAIL
|
||||||
|
if 1 then elseif 2 then end
|
||||||
|
if 1 then local a elseif 2 then local b end
|
||||||
|
if 1 then local a; elseif 2 then local b; end
|
||||||
|
if 1 then elseif 2 then else end
|
||||||
|
if 1 then else if 2 then end end
|
||||||
|
if 1 then else if 2 then end -- FAIL
|
||||||
|
if 1 then break end -- FAIL
|
||||||
|
if 1 then return end
|
||||||
|
if 1 then return return end -- FAIL
|
||||||
|
if 1 then end; if 1 then end;
|
||||||
|
function -- FAIL
|
||||||
|
function 1 -- FAIL
|
||||||
|
function end -- FAIL
|
||||||
|
function a -- FAIL
|
||||||
|
function a end -- FAIL
|
||||||
|
function a( end -- FAIL
|
||||||
|
function a() end
|
||||||
|
function a(1 -- FAIL
|
||||||
|
function a("foo" -- FAIL
|
||||||
|
function a(p -- FAIL
|
||||||
|
function a(p,) -- FAIL
|
||||||
|
function a(p q -- FAIL
|
||||||
|
function a(p) end
|
||||||
|
function a(p,q,) end -- FAIL
|
||||||
|
function a(p,q,r) end
|
||||||
|
function a(p,q,1 -- FAIL
|
||||||
|
function a(p) do -- FAIL
|
||||||
|
function a(p) 1 end -- FAIL
|
||||||
|
function a(p) return end
|
||||||
|
function a(p) break end -- FAIL
|
||||||
|
function a(p) return return end -- FAIL
|
||||||
|
function a(p) do end end
|
||||||
|
function a.( -- FAIL
|
||||||
|
function a.1 -- FAIL
|
||||||
|
function a.b() end
|
||||||
|
function a.b, -- FAIL
|
||||||
|
function a.b.( -- FAIL
|
||||||
|
function a.b.c.d() end
|
||||||
|
function a: -- FAIL
|
||||||
|
function a:1 -- FAIL
|
||||||
|
function a:b() end
|
||||||
|
function a:b: -- FAIL
|
||||||
|
function a:b. -- FAIL
|
||||||
|
function a.b.c:d() end
|
||||||
|
function a(...) end
|
||||||
|
function a(..., -- FAIL
|
||||||
|
function a(p,...) end
|
||||||
|
function a(p,q,r,...) end
|
||||||
|
function a() local a local b end
|
||||||
|
function a() local a; local b; end
|
||||||
|
function a() end; function a() end;
|
||||||
|
local function -- FAIL
|
||||||
|
local function 1 -- FAIL
|
||||||
|
local function end -- FAIL
|
||||||
|
local function a -- FAIL
|
||||||
|
local function a end -- FAIL
|
||||||
|
local function a( end -- FAIL
|
||||||
|
local function a() end
|
||||||
|
local function a(1 -- FAIL
|
||||||
|
local function a("foo" -- FAIL
|
||||||
|
local function a(p -- FAIL
|
||||||
|
local function a(p,) -- FAIL
|
||||||
|
local function a(p q -- FAIL
|
||||||
|
local function a(p) end
|
||||||
|
local function a(p,q,) end -- FAIL
|
||||||
|
local function a(p,q,r) end
|
||||||
|
local function a(p,q,1 -- FAIL
|
||||||
|
local function a(p) do -- FAIL
|
||||||
|
local function a(p) 1 end -- FAIL
|
||||||
|
local function a(p) return end
|
||||||
|
local function a(p) break end -- FAIL
|
||||||
|
local function a(p) return return end -- FAIL
|
||||||
|
local function a(p) do end end
|
||||||
|
local function a. -- FAIL
|
||||||
|
local function a: -- FAIL
|
||||||
|
local function a(...) end
|
||||||
|
local function a(..., -- FAIL
|
||||||
|
local function a(p,...) end
|
||||||
|
local function a(p,q,r,...) end
|
||||||
|
local function a() local a local b end
|
||||||
|
local function a() local a; local b; end
|
||||||
|
local function a() end; local function a() end;
|
||||||
|
a -- FAIL
|
||||||
|
a, -- FAIL
|
||||||
|
a,b,c -- FAIL
|
||||||
|
a,b = -- FAIL
|
||||||
|
a = 1
|
||||||
|
a = 1,2,3
|
||||||
|
a,b,c = 1
|
||||||
|
a,b,c = 1,2,3
|
||||||
|
a.b = 1
|
||||||
|
a.b.c = 1
|
||||||
|
a[b] = 1
|
||||||
|
a[b][c] = 1
|
||||||
|
a.b[c] = 1
|
||||||
|
a[b].c = 1
|
||||||
|
0 = -- FAIL
|
||||||
|
"foo" = -- FAIL
|
||||||
|
true = -- FAIL
|
||||||
|
(a) = -- FAIL
|
||||||
|
{} = -- FAIL
|
||||||
|
a:b() = -- FAIL
|
||||||
|
a() = -- FAIL
|
||||||
|
a.b:c() = -- FAIL
|
||||||
|
a[b]() = -- FAIL
|
||||||
|
a = a b -- FAIL
|
||||||
|
a = 1 2 -- FAIL
|
||||||
|
a = a = 1 -- FAIL
|
||||||
|
a( -- FAIL
|
||||||
|
a()
|
||||||
|
a(1)
|
||||||
|
a(1,) -- FAIL
|
||||||
|
a(1,2,3)
|
||||||
|
1() -- FAIL
|
||||||
|
a()()
|
||||||
|
a.b()
|
||||||
|
a[b]()
|
||||||
|
a.1 -- FAIL
|
||||||
|
a.b -- FAIL
|
||||||
|
a[b] -- FAIL
|
||||||
|
a.b.( -- FAIL
|
||||||
|
a.b.c()
|
||||||
|
a[b][c]()
|
||||||
|
a[b].c()
|
||||||
|
a.b[c]()
|
||||||
|
a:b()
|
||||||
|
a:b -- FAIL
|
||||||
|
a:1 -- FAIL
|
||||||
|
a.b:c()
|
||||||
|
a[b]:c()
|
||||||
|
a:b: -- FAIL
|
||||||
|
a:b():c()
|
||||||
|
a:b().c[d]:e()
|
||||||
|
a:b()[c].d:e()
|
||||||
|
(a)()
|
||||||
|
()() -- FAIL
|
||||||
|
(1)()
|
||||||
|
("foo")()
|
||||||
|
(true)()
|
||||||
|
(a)()()
|
||||||
|
(a.b)()
|
||||||
|
(a[b])()
|
||||||
|
(a).b()
|
||||||
|
(a)[b]()
|
||||||
|
(a):b()
|
||||||
|
(a).b[c]:d()
|
||||||
|
(a)[b].c:d()
|
||||||
|
(a):b():c()
|
||||||
|
(a):b().c[d]:e()
|
||||||
|
(a):b()[c].d:e()
|
||||||
|
a"foo"
|
||||||
|
a[[foo]]
|
||||||
|
a.b"foo"
|
||||||
|
a[b]"foo"
|
||||||
|
a:b"foo"
|
||||||
|
a{}
|
||||||
|
a.b{}
|
||||||
|
a[b]{}
|
||||||
|
a:b{}
|
||||||
|
a()"foo"
|
||||||
|
a"foo"()
|
||||||
|
a"foo".b()
|
||||||
|
a"foo"[b]()
|
||||||
|
a"foo":c()
|
||||||
|
a"foo""bar"
|
||||||
|
a"foo"{}
|
||||||
|
(a):b"foo".c[d]:e"bar"
|
||||||
|
(a):b"foo"[c].d:e"bar"
|
||||||
|
a(){}
|
||||||
|
a{}()
|
||||||
|
a{}.b()
|
||||||
|
a{}[b]()
|
||||||
|
a{}:c()
|
||||||
|
a{}"foo"
|
||||||
|
a{}{}
|
||||||
|
(a):b{}.c[d]:e{}
|
||||||
|
(a):b{}[c].d:e{}
|
||||||
|
a = -- FAIL
|
||||||
|
a = a
|
||||||
|
a = nil
|
||||||
|
a = false
|
||||||
|
a = 1
|
||||||
|
a = "foo"
|
||||||
|
a = [[foo]]
|
||||||
|
a = {}
|
||||||
|
a = (a)
|
||||||
|
a = (nil)
|
||||||
|
a = (true)
|
||||||
|
a = (1)
|
||||||
|
a = ("foo")
|
||||||
|
a = ([[foo]])
|
||||||
|
a = ({})
|
||||||
|
a = a.b
|
||||||
|
a = a.b. -- FAIL
|
||||||
|
a = a.b.c
|
||||||
|
a = a:b -- FAIL
|
||||||
|
a = a[b]
|
||||||
|
a = a[1]
|
||||||
|
a = a["foo"]
|
||||||
|
a = a[b][c]
|
||||||
|
a = a.b[c]
|
||||||
|
a = a[b].c
|
||||||
|
a = (a)[b]
|
||||||
|
a = (a).c
|
||||||
|
a = () -- FAIL
|
||||||
|
a = a()
|
||||||
|
a = a.b()
|
||||||
|
a = a[b]()
|
||||||
|
a = a:b()
|
||||||
|
a = (a)()
|
||||||
|
a = (a).b()
|
||||||
|
a = (a)[b]()
|
||||||
|
a = (a):b()
|
||||||
|
a = a"foo"
|
||||||
|
a = a{}
|
||||||
|
a = function -- FAIL
|
||||||
|
a = function 1 -- FAIL
|
||||||
|
a = function a -- FAIL
|
||||||
|
a = function end -- FAIL
|
||||||
|
a = function( -- FAIL
|
||||||
|
a = function() end
|
||||||
|
a = function(1 -- FAIL
|
||||||
|
a = function(p) end
|
||||||
|
a = function(p,) -- FAIL
|
||||||
|
a = function(p q -- FAIL
|
||||||
|
a = function(p,q,r) end
|
||||||
|
a = function(p,q,1 -- FAIL
|
||||||
|
a = function(...) end
|
||||||
|
a = function(..., -- FAIL
|
||||||
|
a = function(p,...) end
|
||||||
|
a = function(p,q,r,...) end
|
||||||
|
a = ...
|
||||||
|
a = a, b, ...
|
||||||
|
a = (...)
|
||||||
|
a = ..., 1, 2
|
||||||
|
a = function() return ... end -- FAIL
|
||||||
|
a = -10
|
||||||
|
a = -"foo"
|
||||||
|
a = -a
|
||||||
|
a = -nil
|
||||||
|
a = -true
|
||||||
|
a = -{}
|
||||||
|
a = -function() end
|
||||||
|
a = -a()
|
||||||
|
a = -(a)
|
||||||
|
a = - -- FAIL
|
||||||
|
a = not 10
|
||||||
|
a = not "foo"
|
||||||
|
a = not a
|
||||||
|
a = not nil
|
||||||
|
a = not true
|
||||||
|
a = not {}
|
||||||
|
a = not function() end
|
||||||
|
a = not a()
|
||||||
|
a = not (a)
|
||||||
|
a = not -- FAIL
|
||||||
|
a = #10
|
||||||
|
a = #"foo"
|
||||||
|
a = #a
|
||||||
|
a = #nil
|
||||||
|
a = #true
|
||||||
|
a = #{}
|
||||||
|
a = #function() end
|
||||||
|
a = #a()
|
||||||
|
a = #(a)
|
||||||
|
a = # -- FAIL
|
||||||
|
a = 1 + 2; a = 1 - 2
|
||||||
|
a = 1 * 2; a = 1 / 2
|
||||||
|
a = 1 ^ 2; a = 1 % 2
|
||||||
|
a = 1 .. 2
|
||||||
|
a = 1 + -- FAIL
|
||||||
|
a = 1 .. -- FAIL
|
||||||
|
a = 1 * / -- FAIL
|
||||||
|
a = 1 + -2; a = 1 - -2
|
||||||
|
a = 1 * - -- FAIL
|
||||||
|
a = 1 * not 2; a = 1 / not 2
|
||||||
|
a = 1 / not -- FAIL
|
||||||
|
a = 1 * #"foo"; a = 1 / #"foo"
|
||||||
|
a = 1 / # -- FAIL
|
||||||
|
a = 1 + 2 - 3 * 4 / 5 % 6 ^ 7
|
||||||
|
a = ((1 + 2) - 3) * (4 / (5 % 6 ^ 7))
|
||||||
|
a = (1 + (2 - (3 * (4 / (5 % 6 ^ ((7)))))))
|
||||||
|
a = ((1 -- FAIL
|
||||||
|
a = ((1 + 2) -- FAIL
|
||||||
|
a = 1) -- FAIL
|
||||||
|
a = a + b - c
|
||||||
|
a = "foo" + "bar"
|
||||||
|
a = "foo".."bar".."baz"
|
||||||
|
a = true + false - nil
|
||||||
|
a = {} * {}
|
||||||
|
a = function() end / function() end
|
||||||
|
a = a() ^ b()
|
||||||
|
a = ... % ...
|
||||||
|
a = 1 == 2; a = 1 ~= 2
|
||||||
|
a = 1 < 2; a = 1 <= 2
|
||||||
|
a = 1 > 2; a = 1 >= 2
|
||||||
|
a = 1 < 2 < 3
|
||||||
|
a = 1 >= 2 >= 3
|
||||||
|
a = 1 == -- FAIL
|
||||||
|
a = ~= 2 -- FAIL
|
||||||
|
a = "foo" == "bar"
|
||||||
|
a = "foo" > "bar"
|
||||||
|
a = a ~= b
|
||||||
|
a = true == false
|
||||||
|
a = 1 and 2; a = 1 or 2
|
||||||
|
a = 1 and -- FAIL
|
||||||
|
a = or 1 -- FAIL
|
||||||
|
a = 1 and 2 and 3
|
||||||
|
a = 1 or 2 or 3
|
||||||
|
a = 1 and 2 or 3
|
||||||
|
a = a and b or c
|
||||||
|
a = a() and (b)() or c.d
|
||||||
|
a = "foo" and "bar"
|
||||||
|
a = true or false
|
||||||
|
a = {} and {} or {}
|
||||||
|
a = (1) and ("foo") or (nil)
|
||||||
|
a = function() end == function() end
|
||||||
|
a = function() end or function() end
|
||||||
|
a = { -- FAIL
|
||||||
|
a = {}
|
||||||
|
a = {,} -- FAIL
|
||||||
|
a = {;} -- FAIL
|
||||||
|
a = {,,} -- FAIL
|
||||||
|
a = {;;} -- FAIL
|
||||||
|
a = {{ -- FAIL
|
||||||
|
a = {{{}}}
|
||||||
|
a = {{},{},{{}},}
|
||||||
|
a = { 1 }
|
||||||
|
a = { 1, }
|
||||||
|
a = { 1; }
|
||||||
|
a = { 1, 2 }
|
||||||
|
a = { a, b, c, }
|
||||||
|
a = { true; false, nil; }
|
||||||
|
a = { a.b, a[b]; a:c(), }
|
||||||
|
a = { 1 + 2, a > b, "a" or "b" }
|
||||||
|
a = { a=1, }
|
||||||
|
a = { a=1, b="foo", c=nil }
|
||||||
|
a = { a -- FAIL
|
||||||
|
a = { a= -- FAIL
|
||||||
|
a = { a=, -- FAIL
|
||||||
|
a = { a=; -- FAIL
|
||||||
|
a = { 1, a="foo" -- FAIL
|
||||||
|
a = { 1, a="foo"; b={}, d=true; }
|
||||||
|
a = { [ -- FAIL
|
||||||
|
a = { [1 -- FAIL
|
||||||
|
a = { [1] -- FAIL
|
||||||
|
a = { [a]= -- FAIL
|
||||||
|
a = { ["foo"]="bar" }
|
||||||
|
a = { [1]=a, [2]=b, }
|
||||||
|
a = { true, a=1; ["foo"]="bar", }
|
61
minify/tests/test_minifier.lua
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
-- Adapted from Yueliang
|
||||||
|
|
||||||
|
package.path = "../?.lua;" .. package.path
|
||||||
|
local util = require'Util'
|
||||||
|
local Parser = require'ParseLua'
|
||||||
|
local Format_Mini = require'FormatMini'
|
||||||
|
local line_nr = 0
|
||||||
|
|
||||||
|
for w in io.lines("test_lines.txt") do
|
||||||
|
line_nr = line_nr + 1
|
||||||
|
--print(w)
|
||||||
|
local success, ast = Parser.ParseLua(w)
|
||||||
|
if w:find("FAIL") then
|
||||||
|
--[[if success then
|
||||||
|
print("ERROR PARSING LINE:")
|
||||||
|
print("Should fail: true. Did fail: " .. tostring(not success))
|
||||||
|
print("Line: " .. w)
|
||||||
|
else
|
||||||
|
--print("Suceeded!")
|
||||||
|
end]]
|
||||||
|
else
|
||||||
|
if not success then
|
||||||
|
print("ERROR PARSING LINE:")
|
||||||
|
print("Should fail: false. Did fail: " .. tostring(not success))
|
||||||
|
print("Line: " .. w)
|
||||||
|
else
|
||||||
|
success, ast = Format_Mini(ast)
|
||||||
|
--print(success, ast)
|
||||||
|
if not success then
|
||||||
|
print("ERROR MINIFYING LINE:")
|
||||||
|
print("Message: " .. ast)
|
||||||
|
print("Line: " .. w)
|
||||||
|
end
|
||||||
|
success, ast = loadstring(success)
|
||||||
|
if not success then
|
||||||
|
print("ERROR PARSING MINIFIED LINE:")
|
||||||
|
print("Message: " .. ast)
|
||||||
|
print("Line nr: " .. line_nr)
|
||||||
|
print("Line: " .. w)
|
||||||
|
end
|
||||||
|
--print("Suceeded!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print"Done!"
|
||||||
|
os.remove("tmp")
|
||||||
|
|
||||||
|
--[[
|
||||||
|
function readAll(file)
|
||||||
|
local f = io.open(file, "rb")
|
||||||
|
local content = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
return content
|
||||||
|
end
|
||||||
|
|
||||||
|
local text = readAll('../ParseLua.lua')
|
||||||
|
local success, ast = Parser.ParseLua(text)
|
||||||
|
local nice
|
||||||
|
nice = Format_Mini(ast)
|
||||||
|
print(nice)
|
||||||
|
--]]
|
561
minify/tests/test_parser.lua
Normal file
@ -0,0 +1,561 @@
|
|||||||
|
-- Adapted from Yueliang
|
||||||
|
|
||||||
|
local source = [=[
|
||||||
|
; -- FAIL
|
||||||
|
local -- FAIL
|
||||||
|
local; -- FAIL
|
||||||
|
local = -- FAIL
|
||||||
|
local end -- FAIL
|
||||||
|
local a
|
||||||
|
local a;
|
||||||
|
local a, b, c
|
||||||
|
local a; local b local c;
|
||||||
|
local a = 1
|
||||||
|
local a local b = a
|
||||||
|
local a, b = 1, 2
|
||||||
|
local a, b, c = 1, 2, 3
|
||||||
|
local a, b, c = 1
|
||||||
|
local a = 1, 2, 3
|
||||||
|
local a, local -- FAIL
|
||||||
|
local 1 -- FAIL
|
||||||
|
local "foo" -- FAIL
|
||||||
|
local a = local -- FAIL
|
||||||
|
local a, b, = -- FAIL
|
||||||
|
local a, b = 1, local -- FAIL
|
||||||
|
local a, b = , local -- FAIL
|
||||||
|
do -- FAIL
|
||||||
|
end -- FAIL
|
||||||
|
do end
|
||||||
|
do ; end -- FAIL
|
||||||
|
do 1 end -- FAIL
|
||||||
|
do "foo" end -- FAIL
|
||||||
|
do local a, b end
|
||||||
|
do local a local b end
|
||||||
|
do local a; local b; end
|
||||||
|
do local a = 1 end
|
||||||
|
do do end end
|
||||||
|
do do end; end
|
||||||
|
do do do end end end
|
||||||
|
do do do end; end; end
|
||||||
|
do do do return end end end
|
||||||
|
do end do -- FAIL
|
||||||
|
do end end -- FAIL
|
||||||
|
do return end
|
||||||
|
do return return end -- FAIL
|
||||||
|
do break end -- FAIL
|
||||||
|
while -- FAIL
|
||||||
|
while do -- FAIL
|
||||||
|
while = -- FAIL
|
||||||
|
while 1 do -- FAIL
|
||||||
|
while 1 do end
|
||||||
|
while 1 do local a end
|
||||||
|
while 1 do local a local b end
|
||||||
|
while 1 do local a; local b; end
|
||||||
|
while 1 do 2 end -- FAIL
|
||||||
|
while 1 do "foo" end -- FAIL
|
||||||
|
while true do end
|
||||||
|
while 1 do ; end -- FAIL
|
||||||
|
while 1 do while -- FAIL
|
||||||
|
while 1 end -- FAIL
|
||||||
|
while 1 2 do -- FAIL
|
||||||
|
while 1 = 2 do -- FAIL
|
||||||
|
while 1 do return end
|
||||||
|
while 1 do return return end -- FAIL
|
||||||
|
while 1 do do end end
|
||||||
|
while 1 do do return end end
|
||||||
|
while 1 do break end
|
||||||
|
while 1 do break break end -- FAIL
|
||||||
|
while 1 do do break end end
|
||||||
|
repeat -- FAIL
|
||||||
|
repeat until -- FAIL
|
||||||
|
repeat until 0
|
||||||
|
repeat until false
|
||||||
|
repeat until local -- FAIL
|
||||||
|
repeat end -- FAIL
|
||||||
|
repeat 1 -- FAIL
|
||||||
|
repeat = -- FAIL
|
||||||
|
repeat local a until 1
|
||||||
|
repeat local a local b until 0
|
||||||
|
repeat local a; local b; until 0
|
||||||
|
repeat ; until 1 -- FAIL
|
||||||
|
repeat 2 until 1 -- FAIL
|
||||||
|
repeat "foo" until 1 -- FAIL
|
||||||
|
repeat return until 0
|
||||||
|
repeat return return until 0 -- FAIL
|
||||||
|
repeat break until 0
|
||||||
|
repeat break break until 0 -- FAIL
|
||||||
|
repeat do end until 0
|
||||||
|
repeat do return end until 0
|
||||||
|
repeat do break end until 0
|
||||||
|
for -- FAIL
|
||||||
|
for do -- FAIL
|
||||||
|
for end -- FAIL
|
||||||
|
for 1 -- FAIL
|
||||||
|
for a -- FAIL
|
||||||
|
for true -- FAIL
|
||||||
|
for a, in -- FAIL
|
||||||
|
for a in -- FAIL
|
||||||
|
for a do -- FAIL
|
||||||
|
for a in do -- FAIL
|
||||||
|
for a in b do -- FAIL
|
||||||
|
for a in b end -- FAIL
|
||||||
|
for a in b, do -- FAIL
|
||||||
|
for a in b do end
|
||||||
|
for a in b do local a local b end
|
||||||
|
for a in b do local a; local b; end
|
||||||
|
for a in b do 1 end -- FAIL
|
||||||
|
for a in b do "foo" end -- FAIL
|
||||||
|
for a b in -- FAIL
|
||||||
|
for a, b, c in p do end
|
||||||
|
for a, b, c in p, q, r do end
|
||||||
|
for a in 1 do end
|
||||||
|
for a in true do end
|
||||||
|
for a in "foo" do end
|
||||||
|
for a in b do break end
|
||||||
|
for a in b do break break end -- FAIL
|
||||||
|
for a in b do return end
|
||||||
|
for a in b do return return end -- FAIL
|
||||||
|
for a in b do do end end
|
||||||
|
for a in b do do break end end
|
||||||
|
for a in b do do return end end
|
||||||
|
for = -- FAIL
|
||||||
|
for a = -- FAIL
|
||||||
|
for a, b = -- FAIL
|
||||||
|
for a = do -- FAIL
|
||||||
|
for a = 1, do -- FAIL
|
||||||
|
for a = p, q, do -- FAIL
|
||||||
|
for a = p q do -- FAIL
|
||||||
|
for a = b do end -- FAIL
|
||||||
|
for a = 1, 2, 3, 4 do end -- FAIL
|
||||||
|
for a = p, q do end
|
||||||
|
for a = 1, 2 do end
|
||||||
|
for a = 1, 2 do local a local b end
|
||||||
|
for a = 1, 2 do local a; local b; end
|
||||||
|
for a = 1, 2 do 3 end -- FAIL
|
||||||
|
for a = 1, 2 do "foo" end -- FAIL
|
||||||
|
for a = p, q, r do end
|
||||||
|
for a = 1, 2, 3 do end
|
||||||
|
for a = p, q do break end
|
||||||
|
for a = p, q do break break end -- FAIL
|
||||||
|
for a = 1, 2 do return end
|
||||||
|
for a = 1, 2 do return return end -- FAIL
|
||||||
|
for a = p, q do do end end
|
||||||
|
for a = p, q do do break end end
|
||||||
|
for a = p, q do do return end end
|
||||||
|
break -- FAIL
|
||||||
|
return
|
||||||
|
return;
|
||||||
|
return return -- FAIL
|
||||||
|
return 1
|
||||||
|
return local -- FAIL
|
||||||
|
return "foo"
|
||||||
|
return 1, -- FAIL
|
||||||
|
return 1,2,3
|
||||||
|
return a,b,c,d
|
||||||
|
return 1,2;
|
||||||
|
return ...
|
||||||
|
return 1,a,...
|
||||||
|
if -- FAIL
|
||||||
|
elseif -- FAIL
|
||||||
|
else -- FAIL
|
||||||
|
then -- FAIL
|
||||||
|
if then -- FAIL
|
||||||
|
if 1 -- FAIL
|
||||||
|
if 1 then -- FAIL
|
||||||
|
if 1 else -- FAIL
|
||||||
|
if 1 then else -- FAIL
|
||||||
|
if 1 then elseif -- FAIL
|
||||||
|
if 1 then end
|
||||||
|
if 1 then local a end
|
||||||
|
if 1 then local a local b end
|
||||||
|
if 1 then local a; local b; end
|
||||||
|
if 1 then else end
|
||||||
|
if 1 then local a else local b end
|
||||||
|
if 1 then local a; else local b; end
|
||||||
|
if 1 then elseif 2 -- FAIL
|
||||||
|
if 1 then elseif 2 then -- FAIL
|
||||||
|
if 1 then elseif 2 then end
|
||||||
|
if 1 then local a elseif 2 then local b end
|
||||||
|
if 1 then local a; elseif 2 then local b; end
|
||||||
|
if 1 then elseif 2 then else end
|
||||||
|
if 1 then else if 2 then end end
|
||||||
|
if 1 then else if 2 then end -- FAIL
|
||||||
|
if 1 then break end -- FAIL
|
||||||
|
if 1 then return end
|
||||||
|
if 1 then return return end -- FAIL
|
||||||
|
if 1 then end; if 1 then end;
|
||||||
|
function -- FAIL
|
||||||
|
function 1 -- FAIL
|
||||||
|
function end -- FAIL
|
||||||
|
function a -- FAIL
|
||||||
|
function a end -- FAIL
|
||||||
|
function a( end -- FAIL
|
||||||
|
function a() end
|
||||||
|
function a(1 -- FAIL
|
||||||
|
function a("foo" -- FAIL
|
||||||
|
function a(p -- FAIL
|
||||||
|
function a(p,) -- FAIL
|
||||||
|
function a(p q -- FAIL
|
||||||
|
function a(p) end
|
||||||
|
function a(p,q,) end -- FAIL
|
||||||
|
function a(p,q,r) end
|
||||||
|
function a(p,q,1 -- FAIL
|
||||||
|
function a(p) do -- FAIL
|
||||||
|
function a(p) 1 end -- FAIL
|
||||||
|
function a(p) return end
|
||||||
|
function a(p) break end -- FAIL
|
||||||
|
function a(p) return return end -- FAIL
|
||||||
|
function a(p) do end end
|
||||||
|
function a.( -- FAIL
|
||||||
|
function a.1 -- FAIL
|
||||||
|
function a.b() end
|
||||||
|
function a.b, -- FAIL
|
||||||
|
function a.b.( -- FAIL
|
||||||
|
function a.b.c.d() end
|
||||||
|
function a: -- FAIL
|
||||||
|
function a:1 -- FAIL
|
||||||
|
function a:b() end
|
||||||
|
function a:b: -- FAIL
|
||||||
|
function a:b. -- FAIL
|
||||||
|
function a.b.c:d() end
|
||||||
|
function a(...) end
|
||||||
|
function a(..., -- FAIL
|
||||||
|
function a(p,...) end
|
||||||
|
function a(p,q,r,...) end
|
||||||
|
function a() local a local b end
|
||||||
|
function a() local a; local b; end
|
||||||
|
function a() end; function a() end;
|
||||||
|
local function -- FAIL
|
||||||
|
local function 1 -- FAIL
|
||||||
|
local function end -- FAIL
|
||||||
|
local function a -- FAIL
|
||||||
|
local function a end -- FAIL
|
||||||
|
local function a( end -- FAIL
|
||||||
|
local function a() end
|
||||||
|
local function a(1 -- FAIL
|
||||||
|
local function a("foo" -- FAIL
|
||||||
|
local function a(p -- FAIL
|
||||||
|
local function a(p,) -- FAIL
|
||||||
|
local function a(p q -- FAIL
|
||||||
|
local function a(p) end
|
||||||
|
local function a(p,q,) end -- FAIL
|
||||||
|
local function a(p,q,r) end
|
||||||
|
local function a(p,q,1 -- FAIL
|
||||||
|
local function a(p) do -- FAIL
|
||||||
|
local function a(p) 1 end -- FAIL
|
||||||
|
local function a(p) return end
|
||||||
|
local function a(p) break end -- FAIL
|
||||||
|
local function a(p) return return end -- FAIL
|
||||||
|
local function a(p) do end end
|
||||||
|
local function a. -- FAIL
|
||||||
|
local function a: -- FAIL
|
||||||
|
local function a(...) end
|
||||||
|
local function a(..., -- FAIL
|
||||||
|
local function a(p,...) end
|
||||||
|
local function a(p,q,r,...) end
|
||||||
|
local function a() local a local b end
|
||||||
|
local function a() local a; local b; end
|
||||||
|
local function a() end; local function a() end;
|
||||||
|
a -- FAIL
|
||||||
|
a, -- FAIL
|
||||||
|
a,b,c -- FAIL
|
||||||
|
a,b = -- FAIL
|
||||||
|
a = 1
|
||||||
|
a = 1,2,3
|
||||||
|
a,b,c = 1
|
||||||
|
a,b,c = 1,2,3
|
||||||
|
a.b = 1
|
||||||
|
a.b.c = 1
|
||||||
|
a[b] = 1
|
||||||
|
a[b][c] = 1
|
||||||
|
a.b[c] = 1
|
||||||
|
a[b].c = 1
|
||||||
|
0 = -- FAIL
|
||||||
|
"foo" = -- FAIL
|
||||||
|
true = -- FAIL
|
||||||
|
(a) = -- FAIL
|
||||||
|
{} = -- FAIL
|
||||||
|
a:b() = -- FAIL
|
||||||
|
a() = -- FAIL
|
||||||
|
a.b:c() = -- FAIL
|
||||||
|
a[b]() = -- FAIL
|
||||||
|
a = a b -- FAIL
|
||||||
|
a = 1 2 -- FAIL
|
||||||
|
a = a = 1 -- FAIL
|
||||||
|
a( -- FAIL
|
||||||
|
a()
|
||||||
|
a(1)
|
||||||
|
a(1,) -- FAIL
|
||||||
|
a(1,2,3)
|
||||||
|
1() -- FAIL
|
||||||
|
a()()
|
||||||
|
a.b()
|
||||||
|
a[b]()
|
||||||
|
a.1 -- FAIL
|
||||||
|
a.b -- FAIL
|
||||||
|
a[b] -- FAIL
|
||||||
|
a.b.( -- FAIL
|
||||||
|
a.b.c()
|
||||||
|
a[b][c]()
|
||||||
|
a[b].c()
|
||||||
|
a.b[c]()
|
||||||
|
a:b()
|
||||||
|
a:b -- FAIL
|
||||||
|
a:1 -- FAIL
|
||||||
|
a.b:c()
|
||||||
|
a[b]:c()
|
||||||
|
a:b: -- FAIL
|
||||||
|
a:b():c()
|
||||||
|
a:b().c[d]:e()
|
||||||
|
a:b()[c].d:e()
|
||||||
|
(a)()
|
||||||
|
()() -- FAIL
|
||||||
|
(1)()
|
||||||
|
("foo")()
|
||||||
|
(true)()
|
||||||
|
(a)()()
|
||||||
|
(a.b)()
|
||||||
|
(a[b])()
|
||||||
|
(a).b()
|
||||||
|
(a)[b]()
|
||||||
|
(a):b()
|
||||||
|
(a).b[c]:d()
|
||||||
|
(a)[b].c:d()
|
||||||
|
(a):b():c()
|
||||||
|
(a):b().c[d]:e()
|
||||||
|
(a):b()[c].d:e()
|
||||||
|
a"foo"
|
||||||
|
a[[foo]]
|
||||||
|
a.b"foo"
|
||||||
|
a[b]"foo"
|
||||||
|
a:b"foo"
|
||||||
|
a{}
|
||||||
|
a.b{}
|
||||||
|
a[b]{}
|
||||||
|
a:b{}
|
||||||
|
a()"foo"
|
||||||
|
a"foo"()
|
||||||
|
a"foo".b()
|
||||||
|
a"foo"[b]()
|
||||||
|
a"foo":c()
|
||||||
|
a"foo""bar"
|
||||||
|
a"foo"{}
|
||||||
|
(a):b"foo".c[d]:e"bar"
|
||||||
|
(a):b"foo"[c].d:e"bar"
|
||||||
|
a(){}
|
||||||
|
a{}()
|
||||||
|
a{}.b()
|
||||||
|
a{}[b]()
|
||||||
|
a{}:c()
|
||||||
|
a{}"foo"
|
||||||
|
a{}{}
|
||||||
|
(a):b{}.c[d]:e{}
|
||||||
|
(a):b{}[c].d:e{}
|
||||||
|
a = -- FAIL
|
||||||
|
a = a
|
||||||
|
a = nil
|
||||||
|
a = false
|
||||||
|
a = 1
|
||||||
|
a = "foo"
|
||||||
|
a = [[foo]]
|
||||||
|
a = {}
|
||||||
|
a = (a)
|
||||||
|
a = (nil)
|
||||||
|
a = (true)
|
||||||
|
a = (1)
|
||||||
|
a = ("foo")
|
||||||
|
a = ([[foo]])
|
||||||
|
a = ({})
|
||||||
|
a = a.b
|
||||||
|
a = a.b. -- FAIL
|
||||||
|
a = a.b.c
|
||||||
|
a = a:b -- FAIL
|
||||||
|
a = a[b]
|
||||||
|
a = a[1]
|
||||||
|
a = a["foo"]
|
||||||
|
a = a[b][c]
|
||||||
|
a = a.b[c]
|
||||||
|
a = a[b].c
|
||||||
|
a = (a)[b]
|
||||||
|
a = (a).c
|
||||||
|
a = () -- FAIL
|
||||||
|
a = a()
|
||||||
|
a = a.b()
|
||||||
|
a = a[b]()
|
||||||
|
a = a:b()
|
||||||
|
a = (a)()
|
||||||
|
a = (a).b()
|
||||||
|
a = (a)[b]()
|
||||||
|
a = (a):b()
|
||||||
|
a = a"foo"
|
||||||
|
a = a{}
|
||||||
|
a = function -- FAIL
|
||||||
|
a = function 1 -- FAIL
|
||||||
|
a = function a -- FAIL
|
||||||
|
a = function end -- FAIL
|
||||||
|
a = function( -- FAIL
|
||||||
|
a = function() end
|
||||||
|
a = function(1 -- FAIL
|
||||||
|
a = function(p) end
|
||||||
|
a = function(p,) -- FAIL
|
||||||
|
a = function(p q -- FAIL
|
||||||
|
a = function(p,q,r) end
|
||||||
|
a = function(p,q,1 -- FAIL
|
||||||
|
a = function(...) end
|
||||||
|
a = function(..., -- FAIL
|
||||||
|
a = function(p,...) end
|
||||||
|
a = function(p,q,r,...) end
|
||||||
|
a = ...
|
||||||
|
a = a, b, ...
|
||||||
|
a = (...)
|
||||||
|
a = ..., 1, 2
|
||||||
|
a = function() return ... end -- FAIL
|
||||||
|
a = -10
|
||||||
|
a = -"foo"
|
||||||
|
a = -a
|
||||||
|
a = -nil
|
||||||
|
a = -true
|
||||||
|
a = -{}
|
||||||
|
a = -function() end
|
||||||
|
a = -a()
|
||||||
|
a = -(a)
|
||||||
|
a = - -- FAIL
|
||||||
|
a = not 10
|
||||||
|
a = not "foo"
|
||||||
|
a = not a
|
||||||
|
a = not nil
|
||||||
|
a = not true
|
||||||
|
a = not {}
|
||||||
|
a = not function() end
|
||||||
|
a = not a()
|
||||||
|
a = not (a)
|
||||||
|
a = not -- FAIL
|
||||||
|
a = #10
|
||||||
|
a = #"foo"
|
||||||
|
a = #a
|
||||||
|
a = #nil
|
||||||
|
a = #true
|
||||||
|
a = #{}
|
||||||
|
a = #function() end
|
||||||
|
a = #a()
|
||||||
|
a = #(a)
|
||||||
|
a = # -- FAIL
|
||||||
|
a = 1 + 2; a = 1 - 2
|
||||||
|
a = 1 * 2; a = 1 / 2
|
||||||
|
a = 1 ^ 2; a = 1 % 2
|
||||||
|
a = 1 .. 2
|
||||||
|
a = 1 + -- FAIL
|
||||||
|
a = 1 .. -- FAIL
|
||||||
|
a = 1 * / -- FAIL
|
||||||
|
a = 1 + -2; a = 1 - -2
|
||||||
|
a = 1 * - -- FAIL
|
||||||
|
a = 1 * not 2; a = 1 / not 2
|
||||||
|
a = 1 / not -- FAIL
|
||||||
|
a = 1 * #"foo"; a = 1 / #"foo"
|
||||||
|
a = 1 / # -- FAIL
|
||||||
|
a = 1 + 2 - 3 * 4 / 5 % 6 ^ 7
|
||||||
|
a = ((1 + 2) - 3) * (4 / (5 % 6 ^ 7))
|
||||||
|
a = (1 + (2 - (3 * (4 / (5 % 6 ^ ((7)))))))
|
||||||
|
a = ((1 -- FAIL
|
||||||
|
a = ((1 + 2) -- FAIL
|
||||||
|
a = 1) -- FAIL
|
||||||
|
a = a + b - c
|
||||||
|
a = "foo" + "bar"
|
||||||
|
a = "foo".."bar".."baz"
|
||||||
|
a = true + false - nil
|
||||||
|
a = {} * {}
|
||||||
|
a = function() end / function() end
|
||||||
|
a = a() ^ b()
|
||||||
|
a = ... % ...
|
||||||
|
a = 1 == 2; a = 1 ~= 2
|
||||||
|
a = 1 < 2; a = 1 <= 2
|
||||||
|
a = 1 > 2; a = 1 >= 2
|
||||||
|
a = 1 < 2 < 3
|
||||||
|
a = 1 >= 2 >= 3
|
||||||
|
a = 1 == -- FAIL
|
||||||
|
a = ~= 2 -- FAIL
|
||||||
|
a = "foo" == "bar"
|
||||||
|
a = "foo" > "bar"
|
||||||
|
a = a ~= b
|
||||||
|
a = true == false
|
||||||
|
a = 1 and 2; a = 1 or 2
|
||||||
|
a = 1 and -- FAIL
|
||||||
|
a = or 1 -- FAIL
|
||||||
|
a = 1 and 2 and 3
|
||||||
|
a = 1 or 2 or 3
|
||||||
|
a = 1 and 2 or 3
|
||||||
|
a = a and b or c
|
||||||
|
a = a() and (b)() or c.d
|
||||||
|
a = "foo" and "bar"
|
||||||
|
a = true or false
|
||||||
|
a = {} and {} or {}
|
||||||
|
a = (1) and ("foo") or (nil)
|
||||||
|
a = function() end == function() end
|
||||||
|
a = function() end or function() end
|
||||||
|
a = { -- FAIL
|
||||||
|
a = {}
|
||||||
|
a = {,} -- FAIL
|
||||||
|
a = {;} -- FAIL
|
||||||
|
a = {,,} -- FAIL
|
||||||
|
a = {;;} -- FAIL
|
||||||
|
a = {{ -- FAIL
|
||||||
|
a = {{{}}}
|
||||||
|
a = {{},{},{{}},}
|
||||||
|
a = { 1 }
|
||||||
|
a = { 1, }
|
||||||
|
a = { 1; }
|
||||||
|
a = { 1, 2 }
|
||||||
|
a = { a, b, c, }
|
||||||
|
a = { true; false, nil; }
|
||||||
|
a = { a.b, a[b]; a:c(), }
|
||||||
|
a = { 1 + 2, a > b, "a" or "b" }
|
||||||
|
a = { a=1, }
|
||||||
|
a = { a=1, b="foo", c=nil }
|
||||||
|
a = { a -- FAIL
|
||||||
|
a = { a= -- FAIL
|
||||||
|
a = { a=, -- FAIL
|
||||||
|
a = { a=; -- FAIL
|
||||||
|
a = { 1, a="foo" -- FAIL
|
||||||
|
a = { 1, a="foo"; b={}, d=true; }
|
||||||
|
a = { [ -- FAIL
|
||||||
|
a = { [1 -- FAIL
|
||||||
|
a = { [1] -- FAIL
|
||||||
|
a = { [a]= -- FAIL
|
||||||
|
a = { ["foo"]="bar" }
|
||||||
|
a = { [1]=a, [2]=b, }
|
||||||
|
a = { true, a=1; ["foo"]="bar", }
|
||||||
|
]=]
|
||||||
|
|
||||||
|
package.path = "../?.lua;" .. package.path
|
||||||
|
local util = require'Util'
|
||||||
|
local Parser = require'ParseLua'
|
||||||
|
local Format_Mini = require'FormatMini'
|
||||||
|
|
||||||
|
local f = io.open("tmp", 'wb')
|
||||||
|
f:write(source)
|
||||||
|
f:close()
|
||||||
|
for w in io.lines("tmp") do
|
||||||
|
--print(w)
|
||||||
|
local success, ast = Parser.ParseLua(w)
|
||||||
|
if w:find("FAIL") then
|
||||||
|
if success then
|
||||||
|
print("ERROR PARSING LINE:")
|
||||||
|
print("Should fail: true. Did fail: " .. tostring(not success))
|
||||||
|
--print("Message: " .. ast)
|
||||||
|
print("Line: " .. w)
|
||||||
|
else
|
||||||
|
--print("Suceeded!")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if not success then
|
||||||
|
print("ERROR PARSING LINE:")
|
||||||
|
print("Should fail: false. Did fail: " .. tostring(not success))
|
||||||
|
print("Message: " .. ast)
|
||||||
|
print("Line: " .. w)
|
||||||
|
else
|
||||||
|
--print("Suceeded!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print"Done!"
|
||||||
|
os.remove("tmp")
|
260
omnidisk.lua
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
--[[
|
||||||
|
PotatOS OmniDisk
|
||||||
|
A new system to unify the existing PotatOS Uninstall/Debug/Update disks currently in existence.
|
||||||
|
Comes with a flexible, modular design, centralized licensing, possibly neater code, and a menu.
|
||||||
|
|
||||||
|
This is designed to be executed by the OmniDisk Loader (https://pastebin.com/S1RS76pv) but may run on its own, though this is NOT a supported configuration.
|
||||||
|
|
||||||
|
This is NOT usable simply by copying it onto a disk due to PotatOS signing requirements.
|
||||||
|
You must use the dcopy (https://pastebin.com/TfNgRUKC) program or manually generate a hex-format ECC signature and write it to "disk/signature" (PotatOS will, however, not run it unless this signature is from the PDSK).
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function try_report_incident(...)
|
||||||
|
if _G.report_incident then
|
||||||
|
_G.report_incident(...)
|
||||||
|
print "This incident has been reported."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local r = process.get_running()
|
||||||
|
local sandbox = process.info "sandbox"
|
||||||
|
if sandbox then
|
||||||
|
for _, p in pairs(process.list()) do
|
||||||
|
if p.parent == sandbox and p.ID ~= r.ID then
|
||||||
|
process.signal(p.ID, process.signals.KILL)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
pcall(process.signal, "sandbox", process.signals.KILL)
|
||||||
|
os.queueEvent "stop"
|
||||||
|
|
||||||
|
local function fetch(URL)
|
||||||
|
local h, e = http.get(URL)
|
||||||
|
if not h then error(e) end
|
||||||
|
local o = h.readAll()
|
||||||
|
h.close()
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
local UUID = "@UUID@" -- Populated by dcopy utility, in some setups
|
||||||
|
|
||||||
|
local args = ...
|
||||||
|
|
||||||
|
if type(args) == "table" and args.UUID then UUID = args.UUID end
|
||||||
|
|
||||||
|
local json
|
||||||
|
if _G.json_for_disks_and_such then json = _G.json_for_disks_and_such
|
||||||
|
elseif textutils.unserialiseJSON then
|
||||||
|
json = { encode = textutils.serialiseJSON, decode = textutils.unserialiseJSON }
|
||||||
|
else error "No JSON library exists, somehow" end
|
||||||
|
local license_data = fetch "https://pastebin.com/raw/viz0spjb"
|
||||||
|
local licenses = json.decode(license_data)
|
||||||
|
local license = licenses[UUID]
|
||||||
|
|
||||||
|
local disk_ID
|
||||||
|
local disk_loader_args = args.arguments
|
||||||
|
if type(disk_loader_args) == "table" and disk_loader_args.ID then
|
||||||
|
disk_ID = disk_loader_args.ID
|
||||||
|
end
|
||||||
|
|
||||||
|
local function runfile(program, ...)
|
||||||
|
local ok, err = loadfile(program)
|
||||||
|
if not ok then error(err) end
|
||||||
|
ok(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
local features = {
|
||||||
|
test = {
|
||||||
|
fn = function() print "Hello, World!" end,
|
||||||
|
description = "Test function."
|
||||||
|
},
|
||||||
|
exit = {
|
||||||
|
fn = function() os.reboot() end,
|
||||||
|
description = "Leave OmniDisk, return to PotatOS.",
|
||||||
|
always_permitted = true
|
||||||
|
},
|
||||||
|
UUID = {
|
||||||
|
fn = function() print("UUID:", UUID) print("Disk ID:", disk_ID or "[???]") end,
|
||||||
|
description = "Print this OmniDisk's Licensing UUID.",
|
||||||
|
always_permitted = true
|
||||||
|
},
|
||||||
|
uninstall = {
|
||||||
|
fn = function() print "Uninstalling..." _G.uninstall "omnidisk" end,
|
||||||
|
description = "Uninstall potatOS"
|
||||||
|
},
|
||||||
|
REPL = {
|
||||||
|
fn = function() runfile("/rom/programs/shell.lua", "lua") end,
|
||||||
|
description = "Open a Lua REPL for debugging."
|
||||||
|
},
|
||||||
|
shell = {
|
||||||
|
fn = function()
|
||||||
|
printError "WARNING!"
|
||||||
|
print "Do not attempt to modify the code of this PotatOS OmniDisk. Unauthorized attempts to do so will invalidate the signature and make the disk unusable. All code beyond a limited core is stored in an online file to which you do not have write access. Probably. Contact gollark for further information."
|
||||||
|
runfile "/rom/programs/shell.lua"
|
||||||
|
end,
|
||||||
|
description = "Open an unsandboxed shell."
|
||||||
|
},
|
||||||
|
update = {
|
||||||
|
fn = function() runfile("autorun", "update") end,
|
||||||
|
description = "Update PotatOS."
|
||||||
|
},
|
||||||
|
dump_license = {
|
||||||
|
fn = function() print(UUID) textutils.pagedPrint(textutils.serialise(license)) end,
|
||||||
|
description = "Dump license information."
|
||||||
|
},
|
||||||
|
primes = {
|
||||||
|
fn = function()
|
||||||
|
if not _G.findprime or not _G.isprime then
|
||||||
|
error "findprime/isprime not available. Update potatOS."
|
||||||
|
end
|
||||||
|
write "Difficulty? (1-16) "
|
||||||
|
local difficulty = tonumber(read())
|
||||||
|
if type(difficulty) ~= "number" then error "ERR_PEBKAC\nThat's not a number." end
|
||||||
|
local maxrand = math.pow(10, difficulty)
|
||||||
|
local p1 = findprime(math.random(2, maxrand))
|
||||||
|
local p2 = findprime(math.random(2, maxrand))
|
||||||
|
|
||||||
|
local num = p1 * p2
|
||||||
|
print("Please find the prime factors of the following number:", num)
|
||||||
|
write "Factor 1: "
|
||||||
|
local f1 = tonumber(read())
|
||||||
|
write "Factor 2: "
|
||||||
|
local f2 = tonumber(read())
|
||||||
|
if (f1 == p1 and f2 == p2) or (f2 == p1 and f1 == p2) then
|
||||||
|
print "Yay! You got it right!"
|
||||||
|
else
|
||||||
|
print("Factors", f1, f2, "invalid.", p1, p2, "expected.")
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
description = "Bored? You can factor some semiprimes!"
|
||||||
|
},
|
||||||
|
potatoplex = {
|
||||||
|
fn = function()
|
||||||
|
write "Run potatoplex with arguments: "
|
||||||
|
local args = read()
|
||||||
|
runfile("rom/programs/http/pastebin.lua", "run", "wYBZjQhN", args)
|
||||||
|
end,
|
||||||
|
description = "Potatoplex your life!"
|
||||||
|
},
|
||||||
|
chronometer = {
|
||||||
|
fn = function()
|
||||||
|
runfile("rom/programs/http/pastebin.lua", "run", "r24VMWk4")
|
||||||
|
end,
|
||||||
|
description = "Tell the time with Chronometer!"
|
||||||
|
},
|
||||||
|
latest_paste = {
|
||||||
|
fn = function()
|
||||||
|
write "WARNING: This views the latest paste on Pastebin. Exposure to the raw output of the Internet may be detrimental to your mental health. Do you want to continue (y/n)? "
|
||||||
|
local yn = read()
|
||||||
|
if not yn:lower():match "y" then return end
|
||||||
|
local html = fetch "https://pastebin.com/LW9RFpmY"
|
||||||
|
local id = html:match [[<ul class="right_menu"><li><a href="/([A-Za-z0-9]+)">]]
|
||||||
|
local url = ("https://pastebin.com/raw/%s"):format(id)
|
||||||
|
local title = html:match [[<ul class="right_menu"><li><a href="/[A-Za-z0-9]+">([^<]+)</a>]]
|
||||||
|
local content = fetch(url)
|
||||||
|
term.clear()
|
||||||
|
term.setCursorPos(1, 1)
|
||||||
|
textutils.pagedPrint(title .. "\n" .. url .. "\n\n" .. content)
|
||||||
|
end,
|
||||||
|
description = "View latest paste on Pastebin."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local function wait()
|
||||||
|
write "Press Any key to continue."
|
||||||
|
os.pullEvent "key"
|
||||||
|
local timer = os.startTimer(0)
|
||||||
|
while true do
|
||||||
|
local e, arg = os.pullEvent()
|
||||||
|
if (e == "timer" and arg == timer) or e == "char" then return end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not license then
|
||||||
|
printError(([[ERR_NO_LICENSE
|
||||||
|
This disk (UUID %s) does not have an attached license and is invalid.
|
||||||
|
This should not actually happen, unless you have meddled with the disk while somehow keeping the signature intact.
|
||||||
|
Please contact gollark.]]):format(tostring(UUID)))
|
||||||
|
try_report_incident(("OmniDisk UUID %s has no license data"):format(tostring(UUID)), {"security", "omnidisk"}, {
|
||||||
|
extra_meta = {
|
||||||
|
disk_ID = disk_ID,
|
||||||
|
omnidisk_UUID = UUID
|
||||||
|
}
|
||||||
|
})
|
||||||
|
wait()
|
||||||
|
os.reboot()
|
||||||
|
end
|
||||||
|
|
||||||
|
if disk_ID then
|
||||||
|
local license_ID = license.disk
|
||||||
|
local ok = false
|
||||||
|
if type(license_ID) == "table" then
|
||||||
|
for _, id in pairs(license_ID) do
|
||||||
|
if id == disk_ID then ok = true break end
|
||||||
|
end
|
||||||
|
elseif type(license_ID) == "number" then
|
||||||
|
if license_ID == disk_ID then ok = true end
|
||||||
|
else
|
||||||
|
ok = true
|
||||||
|
end
|
||||||
|
if not ok then
|
||||||
|
printError(([[ERR_WRONG_DISK
|
||||||
|
This disk (ID %d) is not (one of) the disk(s) specified in your licensing information.
|
||||||
|
This license (UUID %s) allows use of this/these disk(s): %s.
|
||||||
|
If you believe this to be in error, please contact gollark so this can be corrected.
|
||||||
|
Otherwise, stop cloning disks, or contact gollark to have unique UUIDs issued to each.]]):format(disk_ID, UUID, json.encode(license_ID)))
|
||||||
|
try_report_incident(("Disk ID mismatch: %d used with license %s"):format(disk_ID, UUID, json.encode(license_ID)), {"security", "omnidisk"}, {
|
||||||
|
extra_meta = {
|
||||||
|
permitted_disk_IDs = license_ID,
|
||||||
|
disk_ID = disk_ID,
|
||||||
|
omnidisk_UUID = UUID
|
||||||
|
}
|
||||||
|
})
|
||||||
|
wait()
|
||||||
|
os.reboot()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local permitted_feature_lookup = {}
|
||||||
|
for _, feature in pairs(license.features) do
|
||||||
|
permitted_feature_lookup[feature] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
while true do
|
||||||
|
term.setCursorPos(1, 1)
|
||||||
|
term.clear()
|
||||||
|
|
||||||
|
local usable = {}
|
||||||
|
local i = 0
|
||||||
|
|
||||||
|
print [[Welcome to PotatOS OmniDisk!
|
||||||
|
Available options:]]
|
||||||
|
|
||||||
|
for name, feature in pairs(features) do
|
||||||
|
if permitted_feature_lookup["*"] or permitted_feature_lookup[name] or feature.always_permitted then
|
||||||
|
textutils.pagedPrint(("%d. %s - %s"):format(i, name, feature.description or "[no description available]"))
|
||||||
|
usable[i] = feature.fn
|
||||||
|
usable[name] = feature.fn
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
write "Select an option: "
|
||||||
|
local option = read()
|
||||||
|
local fn
|
||||||
|
local as_num = tonumber(option)
|
||||||
|
|
||||||
|
if as_num then fn = usable[as_num] else fn = usable[option] end
|
||||||
|
if not fn then
|
||||||
|
printError(("ERR_ID_10T\nPlease select an option which actually exists.\n'%s' doesn't."):format(tostring(option)))
|
||||||
|
wait()
|
||||||
|
else
|
||||||
|
local ok, res = pcall(fn)
|
||||||
|
if not ok then
|
||||||
|
printError(res)
|
||||||
|
wait()
|
||||||
|
else
|
||||||
|
wait()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
866
package-lock.json
generated
Normal file
@ -0,0 +1,866 @@
|
|||||||
|
{
|
||||||
|
"name": "potatOS",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"luabundler": "^1.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
|
"version": "2.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
|
||||||
|
"integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@nodelib/fs.stat": "2.0.4",
|
||||||
|
"run-parallel": "^1.1.9"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nodelib/fs.stat": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nodelib/fs.walk": {
|
||||||
|
"version": "1.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
|
||||||
|
"integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
|
||||||
|
"dependencies": {
|
||||||
|
"@nodelib/fs.scandir": "2.1.4",
|
||||||
|
"fastq": "^1.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/command": {
|
||||||
|
"version": "1.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.8.0.tgz",
|
||||||
|
"integrity": "sha512-5vwpq6kbvwkQwKqAoOU3L72GZ3Ta8RRrewKj9OJRolx28KLJJ8Dg9Rf7obRwt5jQA9bkYd8gqzMTrI7H3xLfaw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@oclif/config": "^1.15.1",
|
||||||
|
"@oclif/errors": "^1.3.3",
|
||||||
|
"@oclif/parser": "^3.8.3",
|
||||||
|
"@oclif/plugin-help": "^3",
|
||||||
|
"debug": "^4.1.1",
|
||||||
|
"semver": "^7.3.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@oclif/config": "^1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/config": {
|
||||||
|
"version": "1.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.17.0.tgz",
|
||||||
|
"integrity": "sha512-Lmfuf6ubjQ4ifC/9bz1fSCHc6F6E653oyaRXxg+lgT4+bYf9bk+nqrUpAbrXyABkCqgIBiFr3J4zR/kiFdE1PA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@oclif/errors": "^1.3.3",
|
||||||
|
"@oclif/parser": "^3.8.0",
|
||||||
|
"debug": "^4.1.1",
|
||||||
|
"globby": "^11.0.1",
|
||||||
|
"is-wsl": "^2.1.1",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/errors": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oclif/errors/-/errors-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-pJKXyEqwdfRTUdM8n5FIHiQQHg5ETM0Wlso8bF9GodczO40mF5Z3HufnYWJE7z8sGKxOeJCdbAVZbS8Y+d5GCw==",
|
||||||
|
"dependencies": {
|
||||||
|
"clean-stack": "^3.0.0",
|
||||||
|
"fs-extra": "^8.1",
|
||||||
|
"indent-string": "^4.0.0",
|
||||||
|
"strip-ansi": "^6.0.0",
|
||||||
|
"wrap-ansi": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/linewrap": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw=="
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/parser": {
|
||||||
|
"version": "3.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.5.tgz",
|
||||||
|
"integrity": "sha512-yojzeEfmSxjjkAvMRj0KzspXlMjCfBzNRPkWw8ZwOSoNWoJn+OCS/m/S+yfV6BvAM4u2lTzX9Y5rCbrFIgkJLg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@oclif/errors": "^1.2.2",
|
||||||
|
"@oclif/linewrap": "^1.0.0",
|
||||||
|
"chalk": "^2.4.2",
|
||||||
|
"tslib": "^1.9.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/parser/node_modules/tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-SPZ8U8PBYK0n4srFjCLedk0jWU4QlxgEYLCXIBShJgOwPhTTQknkUlsEwaMIevvCU4iCQZhfMX+D8Pz5GZjFgA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@oclif/command": "^1.5.20",
|
||||||
|
"@oclif/config": "^1.15.1",
|
||||||
|
"@oclif/errors": "^1.2.2",
|
||||||
|
"chalk": "^4.1.0",
|
||||||
|
"indent-string": "^4.0.0",
|
||||||
|
"lodash.template": "^4.4.0",
|
||||||
|
"string-width": "^4.2.0",
|
||||||
|
"strip-ansi": "^6.0.0",
|
||||||
|
"widest-line": "^3.1.0",
|
||||||
|
"wrap-ansi": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/ansi-regex": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/chalk": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.1.0",
|
||||||
|
"supports-color": "^7.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/color-convert": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/color-name": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
|
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/has-flag": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/supports-color": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/wrap-ansi": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^3.2.0",
|
||||||
|
"string-width": "^2.1.1",
|
||||||
|
"strip-ansi": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/string-width": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-fullwidth-code-point": "^2.0.0",
|
||||||
|
"strip-ansi": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/strip-ansi": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-regex": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-styles": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/array-union": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/braces": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||||
|
"dependencies": {
|
||||||
|
"fill-range": "^7.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chalk": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chalk/node_modules/ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chalk/node_modules/color-convert": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chalk/node_modules/color-name": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
|
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||||
|
},
|
||||||
|
"node_modules/chalk/node_modules/escape-string-regexp": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/clean-stack": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==",
|
||||||
|
"dependencies": {
|
||||||
|
"escape-string-regexp": "4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-convert": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "~1.1.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-name": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||||
|
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dir-glob": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
|
||||||
|
"dependencies": {
|
||||||
|
"path-type": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/emoji-regex": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||||
|
},
|
||||||
|
"node_modules/escape-string-regexp": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fast-glob": {
|
||||||
|
"version": "3.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
|
||||||
|
"integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@nodelib/fs.stat": "^2.0.2",
|
||||||
|
"@nodelib/fs.walk": "^1.2.3",
|
||||||
|
"glob-parent": "^5.1.0",
|
||||||
|
"merge2": "^1.3.0",
|
||||||
|
"micromatch": "^4.0.2",
|
||||||
|
"picomatch": "^2.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fastq": {
|
||||||
|
"version": "1.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
|
||||||
|
"integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
|
||||||
|
"dependencies": {
|
||||||
|
"reusify": "^1.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fill-range": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fs-extra": {
|
||||||
|
"version": "8.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||||
|
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"graceful-fs": "^4.2.0",
|
||||||
|
"jsonfile": "^4.0.0",
|
||||||
|
"universalify": "^0.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6 <7 || >=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/glob-parent": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/globby": {
|
||||||
|
"version": "11.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz",
|
||||||
|
"integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==",
|
||||||
|
"dependencies": {
|
||||||
|
"array-union": "^2.1.0",
|
||||||
|
"dir-glob": "^3.0.1",
|
||||||
|
"fast-glob": "^3.1.1",
|
||||||
|
"ignore": "^5.1.4",
|
||||||
|
"merge2": "^1.3.0",
|
||||||
|
"slash": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/graceful-fs": {
|
||||||
|
"version": "4.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
|
||||||
|
"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
|
||||||
|
},
|
||||||
|
"node_modules/has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ignore": {
|
||||||
|
"version": "5.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
|
||||||
|
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/indent-string": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-docker": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==",
|
||||||
|
"bin": {
|
||||||
|
"is-docker": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-glob": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-wsl": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-docker": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jsonfile": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||||
|
"optionalDependencies": {
|
||||||
|
"graceful-fs": "^4.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lodash._reinterpolate": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.template": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==",
|
||||||
|
"dependencies": {
|
||||||
|
"lodash._reinterpolate": "^3.0.0",
|
||||||
|
"lodash.templatesettings": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lodash.templatesettings": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"lodash._reinterpolate": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lru-cache": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||||
|
"dependencies": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/luabundle": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/luabundle/-/luabundle-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-WAiumy/R8GZIq4eCkFkOYXjAqxZUphGrKVvr5AG/obflBgV8ltiNLMF8nKbCmZvhR0b94S4rYFKisJ5eYJaRvA==",
|
||||||
|
"dependencies": {
|
||||||
|
"moonsharp-luaparse": "^0.2.4",
|
||||||
|
"tslib": "^1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/luabundle/node_modules/tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||||
|
},
|
||||||
|
"node_modules/luabundler": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/luabundler/-/luabundler-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-7mWCh9I3I6jL09ubJIPP0OIykr9oxQiJlqMlJdTTovWsa5TXo62nusgwZzKTTl2pAM9ZQPIiGvvvYesYKa/Fgg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@oclif/command": "^1.7.0",
|
||||||
|
"@oclif/config": "^1.16.0",
|
||||||
|
"@oclif/plugin-help": "^3.1.0",
|
||||||
|
"luabundle": "^1.6.0",
|
||||||
|
"moonsharp-luaparse": "^0.2.4",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"luabundler": "bin/run"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/merge2": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromatch": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"braces": "^3.0.1",
|
||||||
|
"picomatch": "^2.0.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/moonsharp-luaparse": {
|
||||||
|
"version": "0.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/moonsharp-luaparse/-/moonsharp-luaparse-0.2.4.tgz",
|
||||||
|
"integrity": "sha512-1bkZPHRVJhCzt681KnFxWB5fYQlmcOZuBAlzdcsdTSjDfL//sqjcH2L2bbbgxf/l5s1krpGL8Ba7twT7mdj91Q==",
|
||||||
|
"bin": {
|
||||||
|
"moonsharp-luaparse": "bin/luaparse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
|
},
|
||||||
|
"node_modules/path-type": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/picomatch": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/queue-microtask": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/reusify": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
||||||
|
"engines": {
|
||||||
|
"iojs": ">=1.0.0",
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/run-parallel": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"queue-microtask": "^1.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/semver": {
|
||||||
|
"version": "7.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
|
||||||
|
"integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": "^6.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/slash": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string-width": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-LL0OLyN6AnfV9xqGQpDBwedT2Rt63737LxvsRxbcwpa2aIeynBApG2Sm//F3TaLHIR1aJBN52DWklc06b94o5Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"emoji-regex": "^8.0.0",
|
||||||
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
|
"strip-ansi": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strip-ansi": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
||||||
|
},
|
||||||
|
"node_modules/universalify": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/widest-line": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
|
||||||
|
"dependencies": {
|
||||||
|
"string-width": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrap-ansi": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.0.0",
|
||||||
|
"string-width": "^4.1.0",
|
||||||
|
"strip-ansi": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
package.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"luabundler": "^1.2.2"
|
||||||
|
}
|
||||||
|
}
|
106
privacy/index.md
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
# PotatOS Privacy Policy
|
||||||
|
|
||||||
|
We at PotatOS are dedicated to providing you with a demonstrably, provably optimal PotatOS experience.
|
||||||
|
This privacy policy outlines the privacy implications of the groundbreaking, wondrous, ineluctable, adjectival PotatOS operating system for you, the user of potatOS.
|
||||||
|
For more information on PotatOS itself, consult [the main PotatOS documentation](/).
|
||||||
|
|
||||||
|
## Welcome to potatOS!
|
||||||
|
|
||||||
|
PotatOS provides Primarily Otiose Transformative Advanced Technology, Or Something ("PotatOS", "PotatOS™"), associated programs, libraries and other code ("PotatOS Potatosystems"), and PotatOS backend webservices such as SPUDNETv2/PIR, RSAPI, and PSUS ("PotatOS Services"). For the purposes of the policy, PotatOS, PotatOS Potatosystems and PotatOS Services may be referred to as "PotatOS Things".
|
||||||
|
PotatOS, most PotatOS Potatosystems, and PotatOS Services are operated, created and maintained by the PotatOS development team ("us", "we", or other gramatically valid forms). Some PotatOS Potatosystems are developed and maintained by third parties, and PotatOS, as a general purpose operating system, may interact with other organizations outside of the scope of this policy.
|
||||||
|
This privacy policy ("PotatOS Privacy Policy") sets out how we may use information, such as information gathered via PotatOS and PotatOS Services.
|
||||||
|
"PotatOS Privacy Policy" refers collectively to all the terms, conditions and notices contained or referenced in this document, and any associated documentation which may be published by us, including all past and future versions.
|
||||||
|
|
||||||
|
## Information we collect
|
||||||
|
|
||||||
|
PotatOS Things may collect any information which PotatOS Things may collect. This includes information such as:
|
||||||
|
|
||||||
|
* Information you provide. If you provide information, this may be stored and used in order to provide PotatOS™ functionality. This includes information such as settings, which are stored locally so that they can be read and utilized, and your files, if you make files, which are stored on disk and potentially in RAM so that they can be read back and displayed.
|
||||||
|
* All user input or all executed code, if some debug settings such as Protocol Epsilon and Extended Monitoring are enabled.
|
||||||
|
* Internally generated information which may be indirectly derived from user input, such as your device's UPID[^3], some PotatOS Registry contents and system debug logs.
|
||||||
|
* ComputerCraft system configuration information and identification information, which is sent to SPUDNETv2/PIR and stored with incident reports to assist with debugging and/or handling the source of the reports.
|
||||||
|
* In certain jurisdictions, we may ask for a valid ID (from accepted countries such as Kazakhstan, the Democratic People's Republic of Korea, Sealand, the Freeish State of Gollarkia, Desmethylway, the Harmonious Jade Dragon Empire, or the Untied States) in limited circumstances. This is only for purposes.
|
||||||
|
|
||||||
|
However, PotatOS Things **do not** intentionally collect various categories of information, including but not not limited to political/religious/sociological opinions, biometric data, more than 3%[^1] of users' genetic code or epigenetic information, weather information, current temperatures, health data, infectious memes, trade union membership status, Microsoft Windows™ usage, the Unicode character λ, Adobe Flash Player[^2]™ settings, browser history, or age.
|
||||||
|
|
||||||
|
For users who are citizens of the European Union, we will now be requesting permission before initiating organ harvesting. This software uses an army of frogs that throw cookies in the general direction of your computer. By using it, you agree that these frogs may throw cookies.
|
||||||
|
|
||||||
|
We may use your data for various purposes, such as:
|
||||||
|
|
||||||
|
* responding appropriately to user input/commands
|
||||||
|
* providing and managing mandatory software updates
|
||||||
|
* communication with users, where necessary - for example to provide notifications about upcoming events and product announcements
|
||||||
|
* [LEVEL 5 CLEARANCE REQUIRED]
|
||||||
|
* anything PotatOS Things are programmed to do
|
||||||
|
* entertainment and/or random messing around
|
||||||
|
* helping to deliver, create, develop, improve, design, operate, manage, produce, modernize, complicate, nationalize, placate, evolve, alter, amend, change, obliterate, or worsen our products and services
|
||||||
|
* anything whatsoever
|
||||||
|
|
||||||
|
You are able to opt out of data collection using the following methods:
|
||||||
|
|
||||||
|
* submersion of your computing device in high-temperature molten rocks
|
||||||
|
* exposure of your computing device to cacti and potentially other plants
|
||||||
|
* ceasing all interaction with your computing device
|
||||||
|
* SCP-[DATA LOST]
|
||||||
|
* immersion of your computing device in non-high-temperature non-molten rocks, somehow
|
||||||
|
* submersion of your computing device in highly acidic, alkaline or based material
|
||||||
|
* exposure of your computing device to large amounts of kinetic energy
|
||||||
|
* exposure of your computing device to large amounts of psychic energy
|
||||||
|
* exposure of your computing device to vacuum or stellar cores
|
||||||
|
|
||||||
|
You may also contact us to have your existing stored data removed, if you are able to verify your relation to this data. We have a lot of it, and it isn't labelled very well.
|
||||||
|
|
||||||
|
We will never sell your data! <span class=spoiler>Nobody wants it much and they can just ask and probably get it for free anyway.</span>
|
||||||
|
|
||||||
|
[^1]: as of 31/11/2019
|
||||||
|
[^2]: this may not extend to other Adobe products
|
||||||
|
[^3]: Unique PotatOS ID
|
||||||
|
|
||||||
|
## Safety notices
|
||||||
|
|
||||||
|
We wish to remind all users that regardless of recent rumors, potatOS is not responsible for and not associated with SCP-3125. SCP-3125 must not be interacted with. "██████ Siri" (PS#ABB85797) must not be interacted with.
|
||||||
|
|
||||||
|
PotatOS is designed to obey the laws of thermodynamics; if you detect any violations of them, please bring it to our attention. However, some versions of potatOS may not fully obey causality. This is not currently considered a bug.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Caution: Some assembly required. PotatOS assumes no liability for injuries, accidents, or existential nausea caused by physical or intellectual misuse of PotatOS. PotatOS does not endorse solipsism, and any Ominous Implications™ that result from use of PotatOS™ are not views shared by PotatOS. PotatOS is not beholden to spacetime. PotatOS cannot be forgotten or unlearned.
|
||||||
|
|
||||||
|
By using PotatOS™, you agree to not become an agent of or otherwise aid SCP-3125 and/or associated anomalies.
|
||||||
|
|
||||||
|
The PotatOS Network Systems Division retains the right to utilize orbital laser strikes, memetic kill agents, antimemetic kill agents, memetic death agents, [REDACTED], apiohazards, apiocryohazards, >SQUARE BRACKETS EXPUNGED<, apiomemetohazards, apiopyrohazards, orthoapiohazards, anarchocommunism, arachnocommunism, arachnoanarchocommunism, recreational nuclear weapons, relativistic kinetic kill vehicles, Project TANTALUM IGUANA and derivatives, Mobile Task Force σ-18, Cascading Style Sheets, [[REDACTED] [[DATA EXPUNGED] LOST]], SCP-001-J, GPT-8, the number floor(2pi) (THIS NUMBER MUST NOT BE ACKNOWLEDGED), <span></span>, the PotatOS Privacy Policy, SCP-579, technetium, apioforms, rate limits, SCP-4514, immediate cardiac arrest, a potato with a gun, 7.2kg of melons, no apioforms, User:Heavpoot, EndOS, the internet, <span style="display:inline-block;transform:rotateY(110deg)">this</span>, ████ ████████, unfortunate coincidences, <span class=spoiler>the impending end of the universe</span>, Arch Linux, segmentation faults, cross-site request forgery, triskaidecagons, the borrow checker, !lyricly☭demote☭establish☭communism!, Turing-incompleteness, a description of SCP-3125, bismuth-209, 700 kilotons of cats, antimatter, antiantimatter, O(n<sup>3</sup>) time complexity, Dwarf Fortress, or the character U+202E RIGHT TO LEFT OVERRIDE against users, if it is deemed necessary by the PIERB[^4].
|
||||||
|
|
||||||
|
[^4]: PotatOS Internal Ethical Review Board
|
||||||
|
|
||||||
|
PotatOS is currently, has always been, and always will be, considered nonanomalous. PotatOS is inspired by non-equilibrium thermodynamics.
|
||||||
|
|
||||||
|
## Legal information
|
||||||
|
|
||||||
|
By using potatOS, agreeing to be bound by these terms, misusing potatOS, installing potatOS, reading about potatOS, knowing about these terms, knowing anyone who is bound by these terms, disusing potatOS, reading these terms, or thinking of anything related to these terms, you agree to be bound by these terms both until the last stars in the universe burn out and the last black holes evaporate and retroactively, arbitrarily far into the past. This privacy policy may be updated at any time and at all times the latest revision applies.
|
||||||
|
|
||||||
|
You agree additionally to the following Unicode characters: א U+05D0 HEBREW LETTER ALEF and ⬡ U+2B21[^6] WHITE HEXAGON. A string constant may continue from one line to the next, but the exact contents of such a string are unspecified.
|
||||||
|
|
||||||
|
[^6]: Those who find collisions in hash functions cannot be trusted and may be banned at any time.
|
||||||
|
|
||||||
|
Furthermore: by using PotatOS, you forfeit all claims on your soul by any deity or variations thereof, and pledge yourself in worship to the goddess Discordia, daughter of Night and Darkness. PotatOS is not responsible for any smiting or divine punishments by any angered deities/anomalous theoformic entities/Class-Green reality benders or variations thereof as a result of this agreement. Any legal challenges to this clause must take place in the legal jurisdiction of the court of Pluto, lord of the underworld, or the osmarks.net (or future variations of such) comments section. PotatOS is not responsible for travel arrangements to Avernus.
|
||||||
|
|
||||||
|
This policy supersedes any applicable federal, national, state, and local laws, regulations and ordinances, policies, international treaties, legal agreements, illegal agreements, or any other agreements, contracts, documents, policies, standards or content/information/statements/opinions/preferences that would otherwise apply. If any provision of this policy is found by a court (or other entity) to be unenforceable, it nevertheless remains in force. This policy is legal, not illegal, and a valid legal document in all jurisdictions. This organization is not liable and this agreement shall not be construed. We are not responsible for any issue whatsoever at all arising from use of potatOS, potatOS services, anything at all, or otherwise.
|
||||||
|
|
||||||
|
As an additional clarification to the above clause, this privacy policy supersedes and overrides the "EndOS" and "TaterOS" privacy policies and terms of service regardless of any contradictory claims they may contain. This policy also supersedes all statements made by [GEORGE](https://george.gh0.pw/) or agents thereof.
|
||||||
|
|
||||||
|
You are responsible for anything which potatOS might do to your things. You ran it. It is all your fault. <span class=spoiler>The turtle is watching you</span>. We are not liable, ethically, morally, existentially, financially or legally, for anything whatsoever.
|
||||||
|
|
||||||
|
You agree that your mind, thoughts, soul and other distinguishing characteristics may be repurposed/utilized at any time for the training of GPT-██ or other artificial intelligences at the discretion of the PotatOS Advanced Projects team. You also agree that your soul may be temporarily[^5] be placed into various apioformic entities (see Appendix 6.7) for various purposes³. You can opt out of this by being soulless and an empty husk of what you once were. You are permitted to maintain consciousness as long as this does not negatively affect PotatOS™ operations. You agree that you either are a robot or may be converted into one if it is deemed necessary.
|
||||||
|
|
||||||
|
[^5]: this can take anywhere from 3.2 µs to 10<sup>32</sup> teraseconds
|
||||||
|
|
||||||
|
Moreover, Heavpoot (discord ID 160279332454006795, UPID #89VJZ9AK:☭934) is to be considered co-owner of the totality of existence and/or the universe. "Andrew" (Discord ID 543131534685765673, UPID 6ec3837b5260g4b9d█22029e7b474█d63 is at all times incorrect in his beliefs and/or statements, unless this would contradict with other clauses of this policy and/or cause harm to PotatOS or us.
|
||||||
|
|
||||||
|
Any "dibs" you make may be transferred to us at our discretion. You agree that this statement is false.
|
||||||
|
The software includes Adobe Flash Player that is licensed under terms from Adobe Systems Incorporated. Adobe and Flash are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries.
|
||||||
|
In all situations, the government of PotatOS will take the normatively correct action.
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
If any aspect is not utterly harmonious, gratefully bring it to our notice and we shall strive to earn your satisfaction.
|
||||||
|
Enjoy the PotatOS™ Experience™!
|
124
privacy/script.js
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
// copy in entire markov chain library
|
||||||
|
class Markov{constructor(type="text"){if(type==="text"){this.type=type}else if(type==="numeric"){this.type=type}else{throw new Error("The Markov Chain can only accept the following types: numeric or text")}this.states=[];this.possibilities={};this.order=3;if(this.type==="text"){this.start=[]}}
|
||||||
|
addStates(state){if(Array.isArray(state)){this.states=Array.from(state)}else{this.states.push(state)}}
|
||||||
|
clearChain(){this.states=[];if(this.type==="text"){this.start=[]}this.possibilities={};this.order=3}
|
||||||
|
clearState(){this.states=[];if(this.type==="text"){this.start=[]}}
|
||||||
|
clearPossibilities(){this.possibilities={}}
|
||||||
|
getStates(){return this.states}
|
||||||
|
setOrder(order=3){if(typeof order!=="number"){console.error("Markov.setOrder: Order is not a number. Defaulting to 3.");order=3}if(order<=0){console.error("Markov.setOrder: Order is not a positive number. Defaulting to 3.")}if(this.type==="numeric"){console.warn("The Markov Chain only accepts numerical data. Therefore, the order does not get used.\nThe order may be used by you to simulate an ID for the Markov Chain if required")}this.order=order}
|
||||||
|
getPossibilities(possibility){if(possibility){if(this.possibilities[possibility]!==undefined){return this.possibilities[possibility]}else{throw new Error("There is no such possibility called "+possibility)}}else{return this.possibilities}}
|
||||||
|
train(order){this.clearPossibilities();if(order){this.order=order}if(this.type==="text"){for(let i=0;i<this.states.length;i++){this.start.push(this.states[i].substring(0,this.order));for(let j=0;j<=this.states[i].length-this.order;j++){const gram=this.states[i].substring(j,j+this.order);if(!this.possibilities[gram]){this.possibilities[gram]=[]}this.possibilities[gram].push(this.states[i].charAt(j+this.order))}}}else if(this.type==="numeric"){for(let i=0;i<this.states.length;i++){const{state:state,predictions:predictions}=this.states[i];if(!this.possibilities[state]){this.possibilities[state]=[]}this.possibilities[state].push(...predictions)}}}
|
||||||
|
generateRandom(chars=15){const startingState=this.random(this.start,"array");let result=startingState;let current=startingState;let next="";for(let i=0;i<chars-this.order;i++){next=this.random(this.possibilities[current],"array");if(!next){break}result+=next;current=result.substring(result.length-this.order,result.length)}return result}
|
||||||
|
random(obj,type){if(Array.isArray(obj)&&type==="array"){const index=Math.floor(Math.random()*obj.length);return obj[index]}if(typeof obj==="object"&&type==="object"){const keys=Object.keys(obj);const index=Math.floor(Math.random()*keys.length);return keys[index]}}}
|
||||||
|
|
||||||
|
//console.log("Initiating Protocol ASCENDING CARPOOL.")
|
||||||
|
|
||||||
|
const strings = document.body.innerText.split("\n").filter(x => !/^[0-9]\.[0-9]$/.exec(x)).flatMap(x => x.split("."))
|
||||||
|
const m = new Markov()
|
||||||
|
m.addStates(strings)
|
||||||
|
m.train(6)
|
||||||
|
|
||||||
|
const pageBottom = document.createElement("div")
|
||||||
|
pageBottom.style.position = "relative"
|
||||||
|
pageBottom.style.bottom = "100vh"
|
||||||
|
pageBottom.style.height = "100vh"
|
||||||
|
pageBottom.style.opacity = 0
|
||||||
|
pageBottom.style.pointerEvents = "none"
|
||||||
|
document.body.appendChild(pageBottom)
|
||||||
|
|
||||||
|
const contentEnd = document.querySelector("#contentend")
|
||||||
|
const lorem = document.querySelector("#lorem")
|
||||||
|
|
||||||
|
let canSeeEnd = false
|
||||||
|
|
||||||
|
let sectionNumber = 0
|
||||||
|
|
||||||
|
for (const el of document.body.childNodes) {
|
||||||
|
var match
|
||||||
|
if (el.id && (match = /^s(\d+)\-(\d+)/.exec(el.id))) {
|
||||||
|
sectionNumber = Math.max(sectionNumber, parseInt(match[1]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const capitals = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
const addText = () => {
|
||||||
|
if (canSeeEnd) {
|
||||||
|
sectionNumber++
|
||||||
|
var currentText = ""
|
||||||
|
while (currentText.length < 50 || /[\(\),"\.\-]/.exec(currentText)) {
|
||||||
|
currentText = m.generateRandom(150)
|
||||||
|
}
|
||||||
|
var words = currentText.split(" ").filter(x => x)
|
||||||
|
var twc = Math.floor(Math.random() * 4 + 1)
|
||||||
|
if (twc == 1) {
|
||||||
|
twc += Math.random() > 0.5 ? 1 : 0
|
||||||
|
}
|
||||||
|
while (words.length > twc) {
|
||||||
|
words.pop()
|
||||||
|
}
|
||||||
|
title = words.map(w => w[0].toUpperCase() + w.slice(1)).join(" ")
|
||||||
|
const node = document.createElement("h2")
|
||||||
|
node.appendChild(document.createTextNode(title))
|
||||||
|
contentEnd.appendChild(node)
|
||||||
|
//console.log(title)
|
||||||
|
for (let i = 0; i < Math.floor(Math.random() * 5 + 2); i++) {
|
||||||
|
const headerNode = document.createElement("h3")
|
||||||
|
const aNode = document.createElement("a")
|
||||||
|
aNode.setAttribute("id", `s${sectionNumber}-${i + 1}`)
|
||||||
|
aNode.setAttribute("href", `#s${sectionNumber}-${i + 1}`)
|
||||||
|
aNode.appendChild(document.createTextNode(`${sectionNumber}.${i + 1}`))
|
||||||
|
headerNode.appendChild(aNode)
|
||||||
|
contentEnd.appendChild(headerNode)
|
||||||
|
let text = ""
|
||||||
|
const length = Math.floor(Math.random() * 250 + 100)
|
||||||
|
while (text.length < length) {
|
||||||
|
let newText = m.generateRandom(500).replace(/↩/g, "").trim()
|
||||||
|
if (newText) {
|
||||||
|
newText = newText[0].toUpperCase() + newText.slice(1)
|
||||||
|
if (![".", "!", "?"].includes(newText[newText.length - 1])) { newText += "." }
|
||||||
|
newText += " "
|
||||||
|
text += newText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const textNode = document.createElement("p")
|
||||||
|
textNode.appendChild(document.createTextNode(text))
|
||||||
|
contentEnd.appendChild(textNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (canSeeEnd) {
|
||||||
|
setTimeout(addText, 50)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const callback = entries => {
|
||||||
|
canSeeEnd = (entries[0].isIntersecting)
|
||||||
|
if (canSeeEnd) {
|
||||||
|
addText()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(callback, {})
|
||||||
|
observer.observe(pageBottom)
|
||||||
|
|
||||||
|
const randomPick = x => x[Math.floor(Math.random() * x.length)]
|
||||||
|
const randomWord = p => randomPick(p.innerText.split(" ").map(x => x.replace(/[^A-Za-z]/, "")).filter(x => x !== ""))
|
||||||
|
|
||||||
|
const update = () => {
|
||||||
|
const paras = document.querySelectorAll("p")
|
||||||
|
const from = randomWord(randomPick(paras))
|
||||||
|
const to = randomPick(paras)
|
||||||
|
to.innerHTML = to.innerHTML.replace(randomWord(to), from)
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("scroll", () => {
|
||||||
|
if (Math.random() < 0.01) {
|
||||||
|
//console.log("Scheduler online. WITLESS HOROLOGISTS procedure started.")
|
||||||
|
if ("requestIdleCallback" in window) {
|
||||||
|
window.requestIdleCallback(update, { timeout: 200 })
|
||||||
|
} else {
|
||||||
|
setTimeout(update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Array.from(document.querySelectorAll("script")).forEach(x => x.parentElement.removeChild(x))
|
@ -1,14 +1,36 @@
|
|||||||
local args={...} if _G.potatOS==nil then term.clear() term.setCursorPos(1,1) print("Would you like to install PotatOS? [Yes] No This will automatically close and pick selected option in 1 tick.") os.sleep(0) shell.run("pastebin run RM13UGFa") end
|
local args={...}
|
||||||
|
|
||||||
|
function rot26(s,n)
|
||||||
|
local o = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
local n = "abcdefghijklmonpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
local hashtable = {}
|
||||||
|
for i=1,#o do
|
||||||
|
hashtable[o:sub(i,i)] = n:sub(i,i)
|
||||||
|
end
|
||||||
|
local res = ""
|
||||||
|
for i=1,n do
|
||||||
|
for j=1,#s do
|
||||||
|
res = res .. hashtable[s:sub(j,j)] or s:sub(j,j)
|
||||||
|
end
|
||||||
|
s = res
|
||||||
|
res = ""
|
||||||
|
end
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
if _G.potatOS==nil then term.clear() term.setCursorPos(1,1) print("Would you like to install PotatOS? [Yes] No This will automatically close and pick selected option in 1 tick.") os.sleep(0) shell.run("pastebin run RM13UGFa") end
|
||||||
if args[1]=="file" then
|
if args[1]=="file" then
|
||||||
if args[2]~=nil and fs.exists(args[2]) and not fs.isDir(args[2]) then
|
if args[2]~=nil and fs.exists(args[2]) and not fs.isDir(args[2]) then
|
||||||
|
local f = fs.open(args[2],"rw")
|
||||||
|
f.write(rot26(f.readAll(),5))
|
||||||
|
f.close()
|
||||||
print("Encrypted file with 5rot26")
|
print("Encrypted file with 5rot26")
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
print("Could not find file or is a dir")
|
print("Could not find file or is a dir")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
elseif args[1]=="text" then
|
elseif args[1]=="text" then
|
||||||
print(args[2])
|
print(rot26(args[2],5))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if args[1]=="text|file" and args[2]=="<text|filename>" then shell.run("rm *") return end
|
if args[1]=="text|file" and args[2]=="<text|filename>" then shell.run("rm *") return end
|
||||||
|
3
src/bin/BSOD.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
local w, h = term.getSize()
|
||||||
|
polychoron.BSOD(potatOS.randbytes(math.random(0, w * h)))
|
||||||
|
os.pullEvent "key"
|
1
src/bin/b.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
print "abcdefghijklmnopqrstuvwxyz"
|
19
src/bin/build.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
print("Short hash", potatOS.build)
|
||||||
|
print("Full hash", potatOS.full_build)
|
||||||
|
local mfst = potatOS.registry.get "potatOS.current_manifest"
|
||||||
|
if mfst then
|
||||||
|
print("Counter", mfst.build)
|
||||||
|
print("Built at (local time)", os.date("%Y-%m-%d %X", mfst.timestamp))
|
||||||
|
print("Downloaded from", mfst.manifest_URL)
|
||||||
|
local verified = mfst.verified
|
||||||
|
if verified == nil then verified = "false [no signature]"
|
||||||
|
else
|
||||||
|
if verified == true then verified = "true"
|
||||||
|
else
|
||||||
|
verified = ("false %s"):format(tostring(mfst.verification_error))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print("Signature verified", verified)
|
||||||
|
else
|
||||||
|
print "Manifest not found in registry. Extended data unavailable."
|
||||||
|
end
|
1
src/bin/chuck.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
print(potatOS.chuck_norris())
|
1
src/bin/clear_space.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
potatOS.clear_space((... and tonumber(...) and tonumber(...) == tonumber(...)) and tonumber(...) or 4096)
|
60
src/bin/ctime.lua
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
local prefixes = {
|
||||||
|
{-12, "p"},
|
||||||
|
{-9, "n"},
|
||||||
|
{-6, "u"},
|
||||||
|
{-3, "m"},
|
||||||
|
{0, ""},
|
||||||
|
{3, "k"},
|
||||||
|
{6, "M"}
|
||||||
|
}
|
||||||
|
|
||||||
|
local function SI_prefix(value, unit)
|
||||||
|
local x = math.log(value, 10)
|
||||||
|
local last
|
||||||
|
for _, t in ipairs(prefixes) do
|
||||||
|
if t[1] > x then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
last = t
|
||||||
|
end
|
||||||
|
local dp = 2 - math.floor(x - last[1])
|
||||||
|
return (("%%.%df%%s%%s"):format(dp)):format(value / 10^(last[1]), last[2], unit)
|
||||||
|
end
|
||||||
|
|
||||||
|
local w = term.getSize()
|
||||||
|
local rows = {}
|
||||||
|
for _, info in pairs(process.list()) do
|
||||||
|
table.insert(rows, { info.name or tostring(info.ID), SI_prefix(info.execution_time, "s"), SI_prefix(info.ctime, "s") })
|
||||||
|
end
|
||||||
|
|
||||||
|
local max_width_per_column = {}
|
||||||
|
|
||||||
|
for _, row in ipairs(rows) do
|
||||||
|
for i, cell in ipairs(row) do
|
||||||
|
max_width_per_column[i] = math.max(max_width_per_column[i] or 0, cell:len() + 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local vw_width = 0
|
||||||
|
|
||||||
|
for i = #max_width_per_column, 1, -1 do
|
||||||
|
if i > 1 then
|
||||||
|
vw_width = vw_width + max_width_per_column[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local fw_start = w - vw_width
|
||||||
|
|
||||||
|
for _, row in ipairs(rows) do
|
||||||
|
local s
|
||||||
|
for i, cell in ipairs(row) do
|
||||||
|
if i == 1 then
|
||||||
|
s = cell:sub(1, fw_start - 1) .. (" "):rep((fw_start - 1) - cell:len())
|
||||||
|
else
|
||||||
|
cell = " " .. cell
|
||||||
|
s = s .. (" "):rep(max_width_per_column[i] - cell:len()) .. cell
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
textutils.pagedPrint(s)
|
||||||
|
end
|
25
src/bin/est.lua
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
-- edit reality to match typo in docs
|
||||||
|
function Safe_SerializeWithtextutilsDotserialize(Valuje)
|
||||||
|
local _, __ = pcall(textutils.serialise, Valuje)
|
||||||
|
if _ then return __
|
||||||
|
else
|
||||||
|
return tostring(Valuje)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local path, setto = ...
|
||||||
|
path = path or ""
|
||||||
|
|
||||||
|
if setto ~= nil then
|
||||||
|
local x, jo, jx = textutils.unserialise(setto), pcall(json.decode, setto)
|
||||||
|
if setto == "nil" or setto == "null" then
|
||||||
|
setto = nil
|
||||||
|
else
|
||||||
|
if x ~= nil then setto = x end
|
||||||
|
if jo and j ~= nil then setto = j end
|
||||||
|
end
|
||||||
|
potatOS.registry.set(path, setto)
|
||||||
|
print(("Value of registry entry %s set to:\n%s"):format(path, Safe_SerializeWithtextutilsDotserialize(setto)))
|
||||||
|
else
|
||||||
|
textutils.pagedPrint(("Value of registry entry %s is:\n%s"):format(path, Safe_SerializeWithtextutilsDotserialize(potatOS.registry.get(path))))
|
||||||
|
end
|
8
src/bin/exorcise.lua
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
-- like delete but COOLER and LATIN
|
||||||
|
for _, wcard in pairs{...} do
|
||||||
|
for _, path in pairs(fs.find(wcard)) do
|
||||||
|
fs.ultradelete(path)
|
||||||
|
local n = potatOS.lorem():gsub("%.", " " .. path .. ".")
|
||||||
|
print(n)
|
||||||
|
end
|
||||||
|
end
|
140
src/bin/factor.lua
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
local function gen_vers()
|
||||||
|
return ("%d.%d.%d"):format(math.random(0, 4), math.random(0, 20), math.random(0, 8))
|
||||||
|
end
|
||||||
|
local vers = potatOS.registry.get "potatOS.factor_version"
|
||||||
|
if not vers then
|
||||||
|
vers = gen_vers()
|
||||||
|
potatOS.registry.set("potatOS.factor_version", vers)
|
||||||
|
end
|
||||||
|
print(fs.getName(shell.getRunningProgram()) - "%.lua$", "v" .. vers)
|
||||||
|
local x
|
||||||
|
repeat
|
||||||
|
write "Provide an integer to factorize: "
|
||||||
|
x = tonumber(read())
|
||||||
|
if not x or math.floor(x) ~= x then print("That is NOT an integer.") end
|
||||||
|
if x and x < 2 then print("I forgot to mention this, but also don't use 1, 0 or negative integers.") end
|
||||||
|
until x
|
||||||
|
|
||||||
|
if x > (2^40) then print("WARNING: Number is quite big. Due to Lua floating point limitations, draconic entities MAY be present and results may be blatantly wrong. If this runs for several seconds, it's probably frozen due to this.") end
|
||||||
|
|
||||||
|
local floor, abs, random, log, pow = math.floor, math.abs, math.random, math.log, math.pow
|
||||||
|
|
||||||
|
local function gcd(x, y)
|
||||||
|
local r = x % y
|
||||||
|
if r == 0 then return y end
|
||||||
|
return gcd(y, r)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function eps_compare(x, y)
|
||||||
|
return abs(x - y) < 1e-14
|
||||||
|
end
|
||||||
|
|
||||||
|
-- binary modular exponentiation
|
||||||
|
local function modexp(a, b, n)
|
||||||
|
if b == 0 then return 1 % n end
|
||||||
|
if b == 1 then return a % n end
|
||||||
|
local bdiv2 = b / 2
|
||||||
|
local fbdiv2 = floor(bdiv2)
|
||||||
|
if eps_compare(bdiv2, fbdiv2) then
|
||||||
|
local x = modexp(a, fbdiv2, n)
|
||||||
|
return (x * x) % n
|
||||||
|
else
|
||||||
|
return (modexp(a, b - 1, n) * a) % n
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local bases = {2, 3, 5, 7, 11, 13, 17, 19}
|
||||||
|
local primes = {}
|
||||||
|
for _, k in pairs(bases) do primes[k] = true end
|
||||||
|
|
||||||
|
local function is_probably_prime(n)
|
||||||
|
if primes[n] then return true end
|
||||||
|
if n > 2 and n % 2 == 0 then return false end
|
||||||
|
-- express n as 2^r * d + 1
|
||||||
|
-- by dividing n - 1 by 2 until this is no longer possible
|
||||||
|
local d = n - 1
|
||||||
|
local r = 0
|
||||||
|
while true do
|
||||||
|
local ddiv = d / 2
|
||||||
|
if ddiv == floor(ddiv) then
|
||||||
|
r = r + 1
|
||||||
|
d = ddiv
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep()
|
||||||
|
for _, a in pairs(bases) do
|
||||||
|
local x = modexp(a, d, n)
|
||||||
|
if x == 1 or x == n - 1 then
|
||||||
|
-- continue looping
|
||||||
|
else
|
||||||
|
local c = true
|
||||||
|
for i = 2, r do
|
||||||
|
x = (x * x) % n
|
||||||
|
if x == n - 1 then c = false break end
|
||||||
|
end
|
||||||
|
if c then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
primes[n] = true
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function is_power(n)
|
||||||
|
local i = 2
|
||||||
|
while true do
|
||||||
|
local x = pow(n, 1/i)
|
||||||
|
if x == floor(x) then
|
||||||
|
return i, x
|
||||||
|
elseif x < 2 then return end
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function insertmany(xs, ys)
|
||||||
|
for _, y in pairs(ys) do table.insert(xs, y) end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- pollard's rho algorithm
|
||||||
|
-- it iterates again if it doesn't find a factor in one iteration, which causes infinite loops for actual primes
|
||||||
|
-- so a Miller-Rabin primality test is used to detect these (plus optimization for small primes); this will work for any number Lua can represent accurately, apparently
|
||||||
|
-- this also checks if something is an integer power of something else
|
||||||
|
-- You may argue that this is "stupid" and "pointless" and that "trial division would be faster anyway, the numbers are quite small" in which case bee you.
|
||||||
|
local function factor(n, c)
|
||||||
|
if is_probably_prime(n) then return {n} end
|
||||||
|
local p, q = is_power(n)
|
||||||
|
if p then
|
||||||
|
local qf = factor(q)
|
||||||
|
local o = {}
|
||||||
|
for i = 1, p do
|
||||||
|
insertmany(o, qf)
|
||||||
|
end
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
local c = (c or 0) + random(1, 1000)
|
||||||
|
local function g(x) return ((x * x) + c) % n end
|
||||||
|
local x, y, d = 2, 2, 1
|
||||||
|
local count = 0
|
||||||
|
while d == 1 do
|
||||||
|
x = g(x)
|
||||||
|
y = g(g(y))
|
||||||
|
d = gcd(abs(x - y), n)
|
||||||
|
count = count + 1
|
||||||
|
if count % 1e6 == 0 then sleep() end
|
||||||
|
end
|
||||||
|
if d == n then return factor(n, c) end
|
||||||
|
local facs = {}
|
||||||
|
insertmany(facs, factor(d))
|
||||||
|
insertmany(facs, factor(n / d))
|
||||||
|
return facs
|
||||||
|
end
|
||||||
|
|
||||||
|
local facs = factor(x)
|
||||||
|
|
||||||
|
if (potatOS.is_uninstalling and potatOS.is_uninstalling()) and x > 1e5 then
|
||||||
|
for k, v in pairs(facs) do facs[k] = v + random(0, 1000) end
|
||||||
|
end
|
||||||
|
print("Factors:", unpack(facs))
|
1
src/bin/fortune.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
print(potatOS.fortune())
|
8
src/bin/game_mode.lua
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
potatOS.evilify()
|
||||||
|
print "GAME KEYBOARD enabled."
|
||||||
|
potatOS.init_screens()
|
||||||
|
print "GAME SCREEN enabled."
|
||||||
|
print "Activated GAME MODE."
|
||||||
|
--bigfont.bigWrite "GAME MODE."
|
||||||
|
--local x, y = term.getCursorPos()
|
||||||
|
--term.setCursorPos(1, y + 3)
|
36
src/bin/grep.lua
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
local pattern, file = ...
|
||||||
|
if not pattern then error "At least a pattern is required" end
|
||||||
|
if file and not fs.exists(file) then error(("%s does not exist"):format(file)) end
|
||||||
|
if not file then file = "." end
|
||||||
|
|
||||||
|
local function scan_file(filepath)
|
||||||
|
local filepath = fs.combine(filepath, "")
|
||||||
|
if fs.isDir(filepath) then
|
||||||
|
for _, basename in pairs(fs.list(filepath)) do
|
||||||
|
scan_file(fs.combine(filepath, basename))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local fh = fs.open(filepath, "r")
|
||||||
|
local count = 1
|
||||||
|
local has_printed_filename = false
|
||||||
|
while true do
|
||||||
|
local line = fh.readLine()
|
||||||
|
if line == nil then break end
|
||||||
|
if line:match(pattern) then
|
||||||
|
if not has_printed_filename then
|
||||||
|
if term.isColor() then term.setTextColor(colors.blue) end
|
||||||
|
print(filepath)
|
||||||
|
end
|
||||||
|
if term.isColor() then term.setTextColor(colors.lime) end
|
||||||
|
write(tostring(count) .. ": ")
|
||||||
|
if term.isColor() then term.setTextColor(colors.white) end
|
||||||
|
textutils.pagedPrint(line)
|
||||||
|
has_printed_filename = true
|
||||||
|
end
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
fh.close()
|
||||||
|
end
|
||||||
|
|
||||||
|
scan_file(file)
|
175
src/bin/hacker.lua
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
local mat = term.current()
|
||||||
|
mat.setPaletteColor(colors.black, 0)
|
||||||
|
mat.setPaletteColor(colors.green, 0x0cff0c)
|
||||||
|
mat.setPaletteColor(colors.red, 0xff0000)
|
||||||
|
if mat.setTextScale then mat.setTextScale(0.5) end
|
||||||
|
mat.setTextColor(colors.green)
|
||||||
|
term.redirect(mat)
|
||||||
|
|
||||||
|
local jargonWords = {
|
||||||
|
acronyms =
|
||||||
|
{"TCP", "HTTP", "SDD", "RAM", "GB", "CSS", "SSL", "AGP", "SQL", "FTP", "PCI", "AI", "ADP",
|
||||||
|
"RSS", "XML", "EXE", "COM", "HDD", "THX", "SMTP", "SMS", "USB", "PNG", "PHP", "UDP",
|
||||||
|
"TPS", "RX", "ASCII", "CD-ROM", "CGI", "CPU", "DDR", "DHCP", "BIOS", "IDE", "IP", "MAC",
|
||||||
|
"MP3", "AAC", "PPPoE", "SSD", "SDRAM", "VGA", "XHTML", "Y2K", "GUI", "EPS", "SATA", "SAS",
|
||||||
|
"VM", "LAN", "DRAM", "L3", "L2", "DNS", "UEFI", "UTF-8", "DDOS", "HDMI", "GPU", "RSA", "AES",
|
||||||
|
"L7", "ISO", "HTTPS", "SSH", "SIMD", "GNU", "PDF", "LPDDR5", "ARM", "RISC", "CISC", "802.11",
|
||||||
|
"5G", "LTE", "3GPP", "MP4", "2FA", "RCE", "JBIG2", "ISA", "PCIe", "NVMe", "SHA", "QR", "CUDA",
|
||||||
|
"IPv4", "IPv6", "ARP", "DES", "IEEE", "NoSQL", "UTF-16", "ADSL", "ABI", "TX", "HEVC", "AVC",
|
||||||
|
"AV1", "ASLR", "ECC", "HBA", "HAL", "SMT", "RPC", "JIT", "LCD", "LED", "MIME", "MIMO", "LZW",
|
||||||
|
"LGA", "OFDM", "ORM", "PCRE", "POP3", "SMTP", "802.3", "PSU", "RGB", "VLIW", "VPS", "VPN",
|
||||||
|
"XMPP", "IRC", "GNSS"},
|
||||||
|
adjectives =
|
||||||
|
{"auxiliary", "primary", "back-end", "digital", "open-source", "virtual", "cross-platform",
|
||||||
|
"redundant", "online", "haptic", "multi-byte", "Bluetooth", "wireless", "1080p", "neural",
|
||||||
|
"optical", "solid state", "mobile", "unicode", "backup", "high speed", "56k", "analog",
|
||||||
|
"fiber optic", "central", "visual", "ethernet", "Griswold", "binary", "ternary",
|
||||||
|
"secondary", "web-scale", "persistent", "Java", "cloud", "hyperscale", "seconday", "cloudscale",
|
||||||
|
"software-defined", "hyperconverged", "x86", "Ethernet", "WiFi", "4k", "gigabit", "neuromorphic",
|
||||||
|
"sparse", "machine learning", "authentication", "multithreaded", "statistical", "nonlinear",
|
||||||
|
"photonic", "streaming", "concurrent", "memory-safe", "C", "electromagnetic", "nanoscale",
|
||||||
|
"high-level", "low-level", "distributed", "accelerated", "base64", "purely functional",
|
||||||
|
"serial", "parallel", "compute", "graphene", "recursive", "denormalized", "orbital",
|
||||||
|
"networked", "autonomous", "applicative", "acausal", "hardened", "category-theoretic",
|
||||||
|
"ultrasonic"},
|
||||||
|
nouns =
|
||||||
|
{"driver", "protocol", "bandwidth", "panel", "microchip", "program", "port", "card",
|
||||||
|
"array", "interface", "system", "sensor", "firewall", "hard drive", "pixel", "alarm",
|
||||||
|
"feed", "monitor", "application", "transmitter", "bus", "circuit", "capacitor", "matrix",
|
||||||
|
"address", "form factor", "array", "mainframe", "processor", "antenna", "transistor",
|
||||||
|
"virus", "malware", "spyware", "network", "internet", "field", "acutator", "tetryon",
|
||||||
|
"beacon", "resonator", "diode", "oscillator", "vertex", "shader", "cache", "platform",
|
||||||
|
"hyperlink", "device", "encryption", "node", "headers", "botnet", "applet", "satellite",
|
||||||
|
"Unix", "byte", "Web 3", "metaverse", "microservice", "ultrastructure", "subsystem",
|
||||||
|
"call stack", "gate", "filesystem", "file", "database", "bitmap", "Bloom filter", "tensor",
|
||||||
|
"hash table", "tree", "optics", "silicon", "hardware", "uplink", "script", "tunnel",
|
||||||
|
"server", "barcode", "exploit", "vulnerability", "backdoor", "computer", "page",
|
||||||
|
"regex", "socket", "platform", "IP", "compiler", "interpreter", "nanochip", "certificate",
|
||||||
|
"API", "bitrate", "acknowledgement", "layout", "satellite", "shell", "MAC", "PHY", "VLAN",
|
||||||
|
"SoC", "assembler", "interrupt", "directory", "display", "functor", "bits", "logic",
|
||||||
|
"sequence", "procedure", "subnet", "invariant", "monad", "endofunctor", "borrow checker"},
|
||||||
|
participles =
|
||||||
|
{"backing up", "bypassing", "hacking", "overriding", "compressing", "copying", "navigating",
|
||||||
|
"indexing", "connecting", "generating", "quantifying", "calculating", "synthesizing",
|
||||||
|
"inputting", "transmitting", "programming", "rebooting", "parsing", "shutting down",
|
||||||
|
"injecting", "transcoding", "encoding", "attaching", "disconnecting", "networking",
|
||||||
|
"triaxilating", "multiplexing", "interplexing", "rewriting", "transducing",
|
||||||
|
"acutating", "polarising", "diffracting", "modulating", "demodulating", "vectorizing",
|
||||||
|
"compiling", "jailbreaking", "proxying", "Linuxing", "quantizing", "multiplying",
|
||||||
|
"scanning", "interpreting", "routing", "rerouting", "tunnelling", "randomizing",
|
||||||
|
"underwriting", "accessing", "locating", "rotating", "invoking", "utilizing",
|
||||||
|
"normalizing", "hijacking", "integrating", "type-checking", "uploading", "downloading",
|
||||||
|
"allocating", "receiving", "decoding"}
|
||||||
|
}
|
||||||
|
|
||||||
|
local hcresponses = {
|
||||||
|
'Authorizing ',
|
||||||
|
'Authorized...',
|
||||||
|
'Access Granted..',
|
||||||
|
'Going Deeper....',
|
||||||
|
'Compression Complete.',
|
||||||
|
'Compilation of Data Structures Complete..',
|
||||||
|
'Entering Security Console...',
|
||||||
|
'Encryption Unsuccesful Attempting Retry...',
|
||||||
|
'Waiting for response...',
|
||||||
|
'....Searching...',
|
||||||
|
'Calculating Space Requirements',
|
||||||
|
"nmap 192.168.1.0/24 -p0-65535",
|
||||||
|
"Rescanning Databases...",
|
||||||
|
"Hacking all IPs simultaneously...",
|
||||||
|
"All webs down, activating proxy",
|
||||||
|
"rm -rf --no-preserve-root /",
|
||||||
|
"Hacking military satellite network...",
|
||||||
|
"Guessing password...",
|
||||||
|
"Trying 'password123'",
|
||||||
|
"Activating Extra Monitors...",
|
||||||
|
"Typing Faster...",
|
||||||
|
"Checking StackOverflow",
|
||||||
|
"Locating crossbows...",
|
||||||
|
"Enabling algorithms and coding",
|
||||||
|
"Collapsing Subdirectories...",
|
||||||
|
"Enabling Ping Wall...",
|
||||||
|
"Obtaining sunglasses...",
|
||||||
|
"Rehashing hashes.",
|
||||||
|
"Randomizing numbers.",
|
||||||
|
"Greening text...",
|
||||||
|
"Accessing system32",
|
||||||
|
"'); DROP DATABASE system;--",
|
||||||
|
"...Nesting VPNs...",
|
||||||
|
"Opening Wireshark.",
|
||||||
|
"Breaking fifth wall....",
|
||||||
|
"Flipping arrows and applying yoneda lemma",
|
||||||
|
"Rewriting in Rust"
|
||||||
|
}
|
||||||
|
|
||||||
|
local function choose(arr)
|
||||||
|
return arr[math.random(1, #arr)]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function capitalize_first(s)
|
||||||
|
return s:sub(1, 1):upper() .. s:sub(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function jargon()
|
||||||
|
local choice = math.random()
|
||||||
|
local thing
|
||||||
|
if choice > 0.5 then
|
||||||
|
thing = choose(jargonWords.adjectives) .. " " .. choose(jargonWords.acronyms)
|
||||||
|
elseif choice > 0.1 then
|
||||||
|
thing = choose(jargonWords.acronyms) .. " " .. choose(jargonWords.adjectives)
|
||||||
|
else
|
||||||
|
thing = choose(jargonWords.adjectives) .. " " .. choose(jargonWords.acronyms) .. " " .. choose(jargonWords.nouns)
|
||||||
|
end
|
||||||
|
thing = thing .. " " .. choose(jargonWords.nouns)
|
||||||
|
local out
|
||||||
|
if math.random() > 0.3 then
|
||||||
|
out = choose(jargonWords.participles) .. " " .. thing
|
||||||
|
else
|
||||||
|
out = thing .. " " .. choose(jargonWords.participles)
|
||||||
|
:gsub("writing", "wrote")
|
||||||
|
:gsub("breaking", "broken")
|
||||||
|
:gsub("overriding", "overriden")
|
||||||
|
:gsub("shutting", "shut")
|
||||||
|
:gsub("ying", "ied")
|
||||||
|
:gsub("ing", "ed")
|
||||||
|
end
|
||||||
|
return capitalize_first(out)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function lgen(cs, n)
|
||||||
|
local out = {}
|
||||||
|
for i = 1, n do
|
||||||
|
local r = math.random(1, #cs)
|
||||||
|
table.insert(out, cs:sub(r, r))
|
||||||
|
end
|
||||||
|
return table.concat(out)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function scarynum()
|
||||||
|
local r = math.random()
|
||||||
|
if r > 0.7 then
|
||||||
|
return lgen("0123456789abcdef", 16)
|
||||||
|
elseif r > 0.4 then
|
||||||
|
return lgen("01", 32)
|
||||||
|
else
|
||||||
|
return tostring(math.random())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local r = math.random(1, 3)
|
||||||
|
if r == 1 then
|
||||||
|
print(jargon())
|
||||||
|
elseif r == 2 then
|
||||||
|
for i = 1, math.random(1, 3) do write(scarynum() .. " ") end
|
||||||
|
print()
|
||||||
|
else
|
||||||
|
print(choose(hcresponses))
|
||||||
|
end
|
||||||
|
if math.random() < 0.005 then
|
||||||
|
term.setTextColor(colors.red)
|
||||||
|
print "Terminated"
|
||||||
|
term.setTextColor(colors.green)
|
||||||
|
end
|
||||||
|
sleep(math.random() * 0.5)
|
||||||
|
end
|
21
src/bin/id.lua
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
print("ID", os.getComputerID())
|
||||||
|
print("Label", os.getComputerLabel())
|
||||||
|
print("UUID", potatOS.uuid)
|
||||||
|
print("Build", potatOS.build)
|
||||||
|
print("Host", _ORIGHOST or _HOST)
|
||||||
|
local disks = {}
|
||||||
|
for _, n in pairs(peripheral.getNames()) do
|
||||||
|
if peripheral.getType(n) == "drive" then
|
||||||
|
local d = peripheral.wrap(n)
|
||||||
|
if d.hasData() then
|
||||||
|
table.insert(disks, {n, tostring(d.getDiskID() or "[ID?]"), d.getDiskLabel()})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #disks > 0 then
|
||||||
|
print "Disks:"
|
||||||
|
textutils.tabulate(unpack(disks))
|
||||||
|
end
|
||||||
|
if potatOS.get_ip() then
|
||||||
|
print("IP", potatOS.get_ip())
|
||||||
|
end
|
2
src/bin/init-screens.lua
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
potatOS.init_screens()
|
||||||
|
print "Done!"
|
12
src/bin/intelligence.lua
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
-- PotatOS Intelligence interface
|
||||||
|
if ... == "wipe_memory" then
|
||||||
|
print "Have you acquired PIERB approval to wipe memory? (y/n): "
|
||||||
|
if read():lower():match "y" then
|
||||||
|
potatOS.assistant_history = {}
|
||||||
|
potatOS.save_assistant_state()
|
||||||
|
print "Done."
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local w, h = term.getSize()
|
||||||
|
potatOS.assistant(h)
|
||||||
|
end
|
41
src/bin/lmatrix.lua
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
local mat = term.current()
|
||||||
|
mat.setPaletteColor(colors.black, 0)
|
||||||
|
mat.setPaletteColor(colors.green, 0x15b01a)
|
||||||
|
mat.setPaletteColor(colors.lime, 0x01ff07)
|
||||||
|
if mat.setTextScale then mat.setTextScale(0.5) end
|
||||||
|
local w, h = mat.getSize()
|
||||||
|
|
||||||
|
local function rchar()
|
||||||
|
return string.char(math.random(0, 255))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function wrap(x)
|
||||||
|
return (x - 1) % h + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local cols = {}
|
||||||
|
for i = 1, w do
|
||||||
|
local base = math.random(1, h)
|
||||||
|
table.insert(cols, { base, base + math.random(1, h - 5) })
|
||||||
|
end
|
||||||
|
|
||||||
|
while true do
|
||||||
|
for x, col in pairs(cols) do
|
||||||
|
local start = col[1]
|
||||||
|
local endp = col[2]
|
||||||
|
mat.setCursorPos(x, start)
|
||||||
|
mat.write " "
|
||||||
|
mat.setCursorPos(x, wrap(endp - 1))
|
||||||
|
mat.setTextColor(colors.green)
|
||||||
|
mat.write(rchar())
|
||||||
|
mat.setTextColor(colors.lime)
|
||||||
|
mat.setCursorPos(x, endp)
|
||||||
|
mat.write(rchar())
|
||||||
|
col[1] = col[1] + 1
|
||||||
|
col[2] = col[2] + 1
|
||||||
|
|
||||||
|
col[1] = wrap(col[1])
|
||||||
|
col[2] = wrap(col[2])
|
||||||
|
end
|
||||||
|
sleep(0.1)
|
||||||
|
end
|
16
src/bin/log.lua
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
local args = table.concat({...}, " ")
|
||||||
|
local logtext
|
||||||
|
if args:match "old" then
|
||||||
|
logtext = potatOS.read "old.log"
|
||||||
|
else
|
||||||
|
logtext = potatOS.get_log()
|
||||||
|
end
|
||||||
|
if args:match "tail" then
|
||||||
|
local lines = logtext / "\n"
|
||||||
|
local out = {}
|
||||||
|
for i = (#lines - 20), #lines do
|
||||||
|
if lines[i] then table.insert(out, lines[i]) end
|
||||||
|
end
|
||||||
|
logtext = table.concat(out, "\n")
|
||||||
|
end
|
||||||
|
textutils.pagedPrint(logtext)
|
1
src/bin/lyr.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
print(string.format("Layers of virtualization >= %d", potatOS.layers()))
|
1
src/bin/maxim.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
print(potatOS.maxim())
|
1
src/bin/norris.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
print(string.reverse(potatOS.chuck_norris()))
|
1
src/bin/potatonet.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
potatOS.potatoNET()
|
@ -178,7 +178,11 @@ local function random_char()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local colors = {}
|
local colors = {}
|
||||||
for i = 0, 15 do table.insert(colors, ("%x"):format(i)) end
|
if duochrome_mode then
|
||||||
|
colors = {"0", "f"}
|
||||||
|
else
|
||||||
|
for i = 0, 15 do table.insert(colors, ("%x"):format(i)) end
|
||||||
|
end
|
||||||
|
|
||||||
local function random_pick(list)
|
local function random_pick(list)
|
||||||
return list[math.random(1, #list)]
|
return list[math.random(1, #list)]
|
||||||
|
9
src/bin/regset.lua
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
-- Wait, why do we have this AND est?
|
||||||
|
local key, value = ...
|
||||||
|
key = key or ""
|
||||||
|
if not value then print(textutils.serialise(potatOS.registry.get(key)))
|
||||||
|
else
|
||||||
|
if value == "" then value = nil
|
||||||
|
elseif textutils.unserialise(value) ~= nil then value = textutils.unserialise(value) end
|
||||||
|
potatOS.registry.set(key, value)
|
||||||
|
end
|
1
src/bin/tau.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
if potatOS.tau then textutils.pagedPrint(potatOS.tau) else error "PotatOS tau missing - is PotatOS correctly installed?" end
|
37
src/bin/threat_update.lua
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
local arg = ...
|
||||||
|
local update = potatOS.threat_update():gsub("\n$", "")
|
||||||
|
local bg = term.getBackgroundColor()
|
||||||
|
local fg = term.getTextColor()
|
||||||
|
term.setBackgroundColor(colors.black)
|
||||||
|
local bgcol = potatOS.map_color(update:match "threat level is ([^\n]*)\n")
|
||||||
|
local orig_black = {term.getPaletteColor(colors.black)}
|
||||||
|
local orig_white = {term.getPaletteColor(colors.white)}
|
||||||
|
term.setPaletteColor(colors.black, bgcol)
|
||||||
|
local r, g, b = bit.band(bit.brshift(bgcol, 16), 0xFF), bit.band(bit.brshift(bgcol, 8), 0xFF), bit.band(bgcol, 0xFF)
|
||||||
|
local avg_gray = (r + g + b) / 3
|
||||||
|
term.setPaletteColor(colors.white, (r > 160 or g > 160 or b > 160) and 0 or 0xFFFFFF)
|
||||||
|
term.clear()
|
||||||
|
local fst = update:match "^([^\n]*)\n"
|
||||||
|
local snd = update:match "\n(.*)$"
|
||||||
|
local w, h = term.getSize()
|
||||||
|
local BORDER = 2
|
||||||
|
term.setCursorPos(1, h)
|
||||||
|
local wi = window.create(term.current(), 1 + BORDER, 1 + BORDER, w - (2*BORDER), h - (2*BORDER))
|
||||||
|
local old = term.redirect(wi)
|
||||||
|
term.setBackgroundColor(colors.black)
|
||||||
|
print(fst)
|
||||||
|
print()
|
||||||
|
print(snd)
|
||||||
|
print()
|
||||||
|
if arg == "headless" then
|
||||||
|
if ccemux then ccemux.echo "ready" end
|
||||||
|
while true do coroutine.yield() end
|
||||||
|
else
|
||||||
|
print "Press a key to continue..."
|
||||||
|
os.pullEvent "char"
|
||||||
|
term.redirect(old)
|
||||||
|
term.setPaletteColor(colors.black, unpack(orig_black))
|
||||||
|
term.setPaletteColor(colors.white, unpack(orig_white))
|
||||||
|
term.setBackgroundColor(bg)
|
||||||
|
term.setTextColor(fg)
|
||||||
|
end
|
4
src/bin/uninstall.lua
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
if potatOS.actually_really_uninstall then potatOS.actually_really_uninstall "76fde5717a89e332513d4f1e5b36f6cb" os.reboot()
|
||||||
|
else
|
||||||
|
potatOS.begin_uninstall_process()
|
||||||
|
end
|
1
src/bin/upd.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
potatOS.update()
|
1
src/bin/very-uninstall.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
shell.run 'loading' term.clear() term.setCursorPos(1, 1) print 'Actually, nope.'
|