mirror of
https://github.com/networkmastered/obsidian-compress.git
synced 2026-07-22 12:10:26 +00:00
Compare commits
No commits in common. "master" and "1.0.0" have entirely different histories.
22 changed files with 181 additions and 20599 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -20,7 +20,3 @@ data.json
|
|||
|
||||
# Exclude macOS Finder (System Explorer) View States
|
||||
.DS_Store
|
||||
|
||||
util/dictionaryBIGUnusedWiki.json
|
||||
util/temp.js
|
||||
archive/versions
|
||||
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (C) 2020-2025 by NetworkMastered.
|
||||
Copyright (C) 2020-2025 by Dynalist Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
|
||||
|
|
|
|||
79
README.md
79
README.md
|
|
@ -1,67 +1,36 @@
|
|||
# File Compressor
|
||||
<i>This is a plugin made for Obsidian.</i>
|
||||
# Obsidian File Compressor
|
||||
|
||||
File compressor creates a new file type which is a .ctxt(compressed txt). Although it says txt it does support markdown. The plugin is designed to be as automated as possible. Which means that you do not need to compress and decompress the files yourself. All you need to do is click the "Create new ctxt" button. Which will then create the new ctxt in the root directory of your vault.
|
||||
|
||||
Once you have a new ctxt file you just need to edit it like a normal file. The plugin will do the rest. If you ever see the compressed data then you should close the tab and re-open it.
|
||||
|
||||
The editor works by taking Obsidian's default markdown editor and then telling it to not refresh it to the saved data(which doesnt always work), then once Obsidian saves the plugin will then copy all of the contents of the file and then compress it.
|
||||
|
||||
Only .MD files have been tested. But we plan on making it work with multiple plugins by only compressing the data once youre done! This will come later though. But as of now it should still be able to compress any file. As long as it is just plain text. Once again though if you do convert a file then the plugin wont read it. If the plugin also uses a specific file type then it will not be saved. Instead itll be converted to a MD. This is planned to change.
|
||||
This plugin is designed to take large files and then compress them. Can typically do most file types. If you are compressing something other than a MD(MarkDown) please copy it so you have a backup. When a file is in a compressed state if its not human-readable or a plugin manages it then it may have issues.
|
||||
|
||||
## Installation
|
||||
You can install/update the plugin in one of two ways:
|
||||
There are two ways to install this plugin which are as follows:
|
||||
1. Install it from the obsidian community plugins tab.
|
||||
2. Get the latest main.js and manifest.json from the github releases and drag it into your vault's ".obsidian/plugins/compressor" folder. The "compressor" folder may not be there. If not then you should be able to create one. If you are on linux the .obsidian folder may be hidden, depending on your operating system it will be different. You should be able to look up how to view hidden folders. Or optionally you can cd into it.
|
||||
|
||||
1. You can install and update the plugin from the Obsidian community plugin marketplace.
|
||||
## How to use
|
||||
This plugin is made to need as little interaction as possible. All you need to do it create a new ctxt file(compressed text) and then open it up. Then it will do the compression for you.
|
||||
|
||||
2. You may also go to this repositorys github releases and then download the latest main and manifest then go into your vaults directory, open up your .Obsidian folder, if you are on linux you may need to find out how to view hidden files. Then you just need to open up the plugins folder, create a new folder. You can name the folder whatever you like, or just "FileCompressor" or "compressor" then just drag the main and manifest files you downloaded into the folder!
|
||||
If you wish to turn a file to a ctxt you can press the button with 2 arrows which will then convert the file. If you do use this then you will need to minimise and re open obsidian. Or click on the taskbar and back. This is an unknown bug.
|
||||
|
||||
*simplified/stepped:*
|
||||
- Go to releases and download the main.js and manifest.json files
|
||||
- Goto your Obsidian vault
|
||||
- Open vault/.Obsidian/Plugins/compressor (or create compressor folder)
|
||||
- Place the main.js and manifest.json files you downloaded into the compressor plugin folder.
|
||||
- Open obsidian or save your files and reload Obsidian(Ctrl+p Reload app without saving)
|
||||
This plugin does support markdown and uses the same editor as markdown files.
|
||||
|
||||
## What are the differences like?
|
||||
The differences cannot be defined. But the bigger the file is the more it should be able to do. At the start it will not compress as it will not be any smaller.
|
||||
|
||||
## Buttons
|
||||
This plugin comes with two buttons.
|
||||
> **Create CTXT** - creates a new compressed file.
|
||||
|
||||
> **Convert to CTXT** - converts the currently open file to a ctxt file.
|
||||
|
||||
## Settings
|
||||
> **Print Results** - Each time a compressed file is saved it will show the compression ratio(percentage of file size)
|
||||
|
||||
> **Show File Size** - This setting shows the currently opened/editing file's size in the status bar.
|
||||
|
||||
|
||||
## NOTICE:
|
||||
1. Changing a files contents to a more obscure one will come with the risk of data loss.
|
||||
2. Links do work but will not show up in the Graph.
|
||||
3. Plugins may fail to read the data.
|
||||
4. This uses a CLOSED source build script along with esbuild. You will need to remove the " && node archive/versions/execute.js" in the package in order to build.
|
||||
5. The larger your file is the more intensive the compression system will be. Each time a file is saved it runs multiple compression algorithems. If you are using large files then you may need to
|
||||
|
||||
## Uninstalling
|
||||
>[!WARNING]
|
||||
>BEFORE UNINSTALLING/DISABLING THIS PLUGIN. CONVERT YOUR FILES BACK TO A MARKDOWN!<br>
|
||||
If not, you will NOT be able to access compressed files. You will still be able to reinstall the plugin and convert the files.
|
||||
|
||||
## Future
|
||||
We plan on adding better compression and a better system to allow files to be in plaintext while editing.
|
||||
|
||||
## What comes packaged:
|
||||
The compression plugin is packaged with pako, a compression library and a custom one. The plugin also comes with the following
|
||||
|
||||
**features**:
|
||||
|
||||
Buttons:
|
||||
> "**Create new ctxt**" - will create a new .ctxt file.<br>
|
||||
> "**Convert open file**" - This will convert the currently opened/most recently edited file from whatever it is to a ctxt. If it is a ctxt it gets converted to .md
|
||||
|
||||
<br>Settings:
|
||||
> "**Show compression results**" - This setting shows a toast of the compression ratio of the most recently saved file(if it does get compressed)<br>
|
||||
> "**Show file storage in statusbar**" - This does what it says and will show the most recently opened/edited file's storage space in bytes at the bottom on the statusbar.
|
||||
|
||||
## Compression Ratios:
|
||||
These ratios will be based off of the bee movie script as it provides a realistic use case and has variations in the words.
|
||||
|
||||
*(can be found at https://gist.githubusercontent.com/MattIPv4/045239bc27b16b2bcf7a3a9a4648c08a/raw)*
|
||||
|
||||
> What is a compression ratio?<br>a compression ratio is how much the compressed version takes up of the raw version. (25kB compressed of 100kB = 25%, 25kB compressed of 50kB = 50%)
|
||||
|
||||
1.0.0-1.0.2-1.1.0 PRE-RELEASE: Error<br>
|
||||
1.0.0: 55.4% ( Initial Release )<br>
|
||||
1.1.0: 55.4% ( Ready for publishing )<br>
|
||||
1.1.2: 55.4% ( Follow Obsidian's publishing )<br>
|
||||
1.2.2: 55.4% ( Huffman encoding added. )<br>
|
||||
1.2.5: 55.4% ( Performance Improvements 10s-4s )
|
||||
If there are any issues or requests, make sure to create a request!
|
||||
12
TODO
12
TODO
|
|
@ -1,12 +0,0 @@
|
|||
[ ] Finish Compression on plugins
|
||||
[ ] If compression is only on open file check for ![[]] links for rendering
|
||||
[ ] Search for more custom data plugins
|
||||
[ ] Compressed Vault?
|
||||
[ ] Custom ViewType/Leaf
|
||||
[ ] Block the data
|
||||
[ ] checksum the data
|
||||
[ ] implament some kind of repairer
|
||||
[ ] Rewrite README to make it more polished and add links for easier reading
|
||||
[ ] Create a version control system so i dont accidently publish broken or same versions
|
||||
[ ] Create a setting for "Uncompress entire Vault" and "Uncompress open file and requisite"
|
||||
[x] Seperate each plugin compression type to a new script
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
# Obsidian File Compressor
|
||||
|
||||
This plugin is designed to take large files and then compress them. Can typically do most file types. If you are compressing something other than a MD(MarkDown) please copy it so you have a backup. When a file is in a compressed state if its not human-readable or a plugin manages it then it may have issues.
|
||||
|
||||
## Installation
|
||||
There are two ways to install this plugin which are as follows:
|
||||
|
||||
1. Install it from the obsidian community plugins tab.
|
||||
|
||||
2. Get the latest main.js and manifest.json from the github releases and drag it into your vault's ".obsidian/plugins/compressor" folder. The "compressor" folder may not be there. If not then you should be able to create one. If you are on linux the .obsidian folder may be hidden, depending on your operating system it will be different. You should be able to look up how to view hidden folders. Or optionally you can cd into it.
|
||||
|
||||
## How to use
|
||||
This plugin is made to need as little interaction as possible. All you need to do it create a new ctxt file(compressed text) and then open it up. Then it will do the compression for you.
|
||||
|
||||
If you wish to turn a file to a ctxt you can press the button with 2 arrows which will then convert the file. If you do use this then you will need to minimise and re open obsidian. Or click on the taskbar and back. This is an unknown bug.
|
||||
|
||||
This plugin does support markdown and uses the same editor as markdown files.
|
||||
|
||||
## What are the differences like?
|
||||
The differences cannot be defined. But the bigger the file is the more it should be able to do. At the start it will not compress as it will not be any smaller.
|
||||
|
||||
## Buttons
|
||||
This plugin comes with two buttons.
|
||||
> **Create CTXT** - creates a new compressed file.
|
||||
|
||||
> **Convert to CTXT** - converts the currently open file to a ctxt file.
|
||||
|
||||
## Settings
|
||||
> **Print Results** - Each time a compressed file is saved it will show the compression ratio(percentage of file size)
|
||||
|
||||
> **Show File Size** - This setting shows the currently opened/editing file's size in the status bar.
|
||||
|
||||
|
||||
|
||||
NOTICE:
|
||||
- By using this plugin the "Graph View" will NOT show links(if you know of a way to do this, please let me know). Linking to a ctxt file will also not show it.!
|
||||
|
||||
- Compressing a file that another plugin edits will stop that plugin from being able to open it, re convert it.
|
||||
|
||||
- This plugin is not perfect. Data loss is possible. In the case of dataloss, please make sure that you didnt accidently edit/tamper with the compressed data. Then and only if your fine with sharing the file you could upload an issue request with the contents. DO NOT SHARE PERSONAL INFO!
|
||||
|
||||
|
||||
If there are any issues or requests, make sure to create a request!
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
Generated log file from WDIR/version/execute.js
|
||||
|
||||
$> Executed Build.
|
||||
|
||||
> compress@1.1.2 build
|
||||
> node archive/testchecks.js && tsc -noEmit -skipLibCheck && node esbuild.config.mjs production && node archive/versions/execute.js
|
||||
|
||||
$> Executed Tests.
|
||||
Test netcompress 1. Passed ✔
|
||||
Test netcompress 2. Passed ✔
|
||||
Test netcompress 3. Passed ✔
|
||||
Test netcompress 4. Passed ✔
|
||||
Test netcompress 5. Passed ✔
|
||||
Test netcompress 6. Passed ✔
|
||||
Test netcompress 7. Passed ✔
|
||||
Test netcompress 8. Passed ✔
|
||||
Test netdecompress 9. Passed ✔
|
||||
Test netdecompress 10. Passed ✔
|
||||
Test netdecompress 11. Passed ✔
|
||||
Test encodeSafe 12. Passed ✔
|
||||
Test encodeSafe 13. Passed ✔
|
||||
Test encodeSafe 14. Passed ✔
|
||||
Test encodeSafe 15. Passed ✔
|
||||
Test encodeSafe 16. Passed ✔
|
||||
Test encodeSafe 17. Passed ✔
|
||||
Test encodeSafe 18. Passed ✔
|
||||
Test encodeSafe 19. Passed ✔
|
||||
Test encodeSafe 20. Passed ✔
|
||||
Test encodeSafe 21. Passed ✔
|
||||
Test encodeSafe 22. Passed ✔
|
||||
Test encodeSafe 23. Passed ✔
|
||||
Test decodeSafe 24. Passed ✔
|
||||
Test decodeSafe 25. Passed ✔
|
||||
Test decodeSafe 26. Passed ✔
|
||||
Test decodeSafe 27. Passed ✔
|
||||
Test decodeSafe 28. Passed ✔
|
||||
Test decodeSafe 29. Passed ✔
|
||||
Test decodeSafe 30. Passed ✔
|
||||
Test decodeSafe 31. Passed ✔
|
||||
Test decodeSafe 32. Passed ✔
|
||||
Test decodeSafe 33. Passed ✔
|
||||
Test decodeSafe 34. Passed ✔
|
||||
Test decodeSafe 35. Passed ✔
|
||||
Finished. 35 have passed 0 have failed 35/0
|
||||
(node:14788) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///C:/Users/user/Desktop/Repos/TextEditorObsidianPluginPublic/util/BB.js is not specified and it doesn't parse as CommonJS.
|
||||
Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
|
||||
To eliminate this warning, add "type": "module" to C:\Users\user\Desktop\Repos\TextEditorObsidianPluginPublic\package.json.
|
||||
(Use `node --trace-warnings ...` to show where the warning was created)
|
||||
|
||||
$> Executed NMJSCompress
|
||||
VC Created new TS213484. FS 56. FLAGS: --master --full --repush -m -vc --bumpall -wl --save --mini2 --complvl5 -pr --MoveTo:LENV["ObsidianDir"] --ignore:myselfAndParent -wd:ParParPar
|
||||
|
||||
Running minifier V2
|
||||
minifier[LL:WARN]: Level 5 enabled. Level 5 is significently low. Set to approx 10+ (0-100). Use 'execute.js --printlvllist' or 'execute.js --pll' or click: [NetworkMasterCLIEnums.ConsoleLogging.EmbedTypes.New.V2.Button]{NWK::'EXEC',WTR:'/-=E;PR!BtnFt',STL:'BoxButton;BoldAndUnderline',WYD:NetworkMasterCLIEnums.ConsoleLogging.PrintingFunctions.Events.Execute_By_Meta_PREM,PREM:"__DIR.F;CD %F;EXEC_CMD __DIR.CR -pll"}(This.)
|
||||
Size Difference: 857 B
|
||||
|
||||
Copied over files to: LENV.ObsidianDir.
|
||||
|
||||
$> Execution Finished
|
||||
|
||||
$> ?? --wl detected. Written to wd[wiesl]/netwrkjscmp.log
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
const { encodeSafe, decodeSafe } = require("../util/runlength")
|
||||
const LZ = require("../util/runlengthMatch")
|
||||
const { netcompress, netdecompress } = require("../util/networkmastercompression")
|
||||
const funcs = [netcompress, netdecompress, encodeSafe, decodeSafe, LZ.compress, LZ.decompress]
|
||||
const names = ["netcompress", "netdecompress", "encodeSafe", "decodeSafe", "LZcompress", "LZdecompress"]
|
||||
|
||||
const tests = [
|
||||
{ type: 0, inputs: ["hi", "type1"], output: "hABoE" },
|
||||
{ type: 0, inputs: ["hi,", "type1"], output: "UNCOMPhi," },
|
||||
{ type: 0, inputs: ["abcdefg formats", "type2"], output: "óBUBiQDRURGdESBcEUT5kQVRF" },
|
||||
{ type: 0, inputs: ["master file true", "type3"], output: "hBBoOabmMbXmNdL31dZA" },
|
||||
{ type: 0, inputs: ["zygote", "type3"], output: "hBB8_D" },
|
||||
{ type: 0, inputs: ["zygotezygote", "type3"], output: "hBB8_z_P" },
|
||||
{ type: 0, inputs: ["hello World", "type4"], output: "BCBhello World" },
|
||||
{ type: 0, inputs: ["test test test test test", "type5"], output: "hCB4-6C3XX4-6C⁑" },
|
||||
{ type: 0, inputs: ["test test test test test", "type6"], output: "BDBhAB0y0D;FsmTzp50caA" },
|
||||
{ type: 1, inputs: ["UNCOMPhi,"], output: "hi,"},
|
||||
{ type: 1, inputs: ["hAfoE"], output: "hi" },
|
||||
{ type: 1, inputs: ["BCfhello World"], output: "hello World" },
|
||||
{ type: 1, inputs: ["hCB4-6C3XX4-6C•\" K"], output: "test test test test test" },
|
||||
{ type: 1, inputs: ["BDfhAf0y0D;FsmTzp50caA"], output: "test test test test test" },
|
||||
{ type: 2, inputs: ["A"], output: "A" },
|
||||
{ type: 2, inputs: ["AA"], output: "AA" },
|
||||
{ type: 2, inputs: ["AAA"], output: "óA" },
|
||||
{ type: 2, inputs: ["AAAA"], output: "úA" },
|
||||
{ type: 2, inputs: ["AAAAA"], output: "üA" },
|
||||
{ type: 2, inputs: ["AAAAAA"], output: "ñA" },
|
||||
{ type: 2, inputs: ["AAAAAAA"], output: "çA" },
|
||||
{ type: 2, inputs: ["AAAAAAAA"], output: "¿A" },
|
||||
{ type: 2, inputs: ["AAAAAAAAA"], output: "¡A" },
|
||||
{ type: 2, inputs: ["AAAAAAAAAA"], output: "éáA" },
|
||||
{ type: 2, inputs: ["AAAAAAAAAAA"], output: "ééA" },
|
||||
{ type: 2, inputs: ["AAAAAAAAAAAA"], output: "éíA" },
|
||||
{ type: 3, inputs: ["A"], output: "A" },
|
||||
{ type: 3, inputs: ["AA"], output: "AA" },
|
||||
{ type: 3, inputs: ["óA"], output: "AAA" },
|
||||
{ type: 3, inputs: ["úA"], output: "AAAA" },
|
||||
{ type: 3, inputs: ["üA"], output: "AAAAA" },
|
||||
{ type: 3, inputs: ["ñA"], output: "AAAAAA" },
|
||||
{ type: 3, inputs: ["çA"], output: "AAAAAAA" },
|
||||
{ type: 3, inputs: ["¿A"], output: "AAAAAAAA" },
|
||||
{ type: 3, inputs: ["¡A"], output: "AAAAAAAAA" },
|
||||
{ type: 3, inputs: ["éáA"], output: "AAAAAAAAAA" },
|
||||
{ type: 3, inputs: ["ééA"], output: "AAAAAAAAAAA" },
|
||||
{ type: 3, inputs: ["éíA"], output: "AAAAAAAAAAAA" },
|
||||
// { type: 0, inputs: ["hi"], output: "" },
|
||||
]
|
||||
|
||||
var pass = 0
|
||||
var fail = 0
|
||||
|
||||
for (let idx = 0; idx < tests.length; idx++) {
|
||||
let test = tests[idx]
|
||||
var name = names[test.type]
|
||||
var func = funcs[test.type]
|
||||
var out = ""
|
||||
try {
|
||||
out = func(...test.inputs)
|
||||
} catch (err) {
|
||||
throw new Error(err)
|
||||
}
|
||||
if (test.output == out) {
|
||||
console.log(`\u001b[32mTest ${name} ${idx + 1}. Passed ✔\u001b[30m`)
|
||||
pass++
|
||||
} else {
|
||||
console.log(`\u001b[31mTest ${name} ${idx + 1}. Failed ❌(${out} ~= ${test.output})\u001b[30m`)
|
||||
fail++
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Finished. \u001b[32m${pass} have passed\u001b[31m ${fail} have failed \u001b[32m${pass}\u001b[30m/\u001b[31m${fail}\u001b[30m`)
|
||||
|
||||
if (fail > 0) {
|
||||
|
||||
throw new Error("failed")
|
||||
|
||||
}
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
import esbuild from "esbuild";
|
||||
import process from "process";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import builtins from "builtin-modules";
|
||||
import { execSync } from "child_process";
|
||||
|
||||
const banner = ""
|
||||
const banner =
|
||||
`/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin
|
||||
*/
|
||||
`;
|
||||
|
||||
const prod = (process.argv[2] === "production");
|
||||
|
||||
|
|
@ -39,52 +41,9 @@ const context = await esbuild.context({
|
|||
minify: prod,
|
||||
});
|
||||
|
||||
const cyrb53 = (str, seed = 0) => {
|
||||
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
|
||||
for (let i = 0, ch; i < str.length; i++) {
|
||||
ch = str.charCodeAt(i);
|
||||
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||||
h2 = Math.imul(h2 ^ ch, 1597334677);
|
||||
}
|
||||
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
|
||||
h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
||||
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);
|
||||
h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
||||
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
||||
};
|
||||
|
||||
async function fscn(pth = "./") {
|
||||
let hashr = '';
|
||||
let files = fs.readdirSync(pth)
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
let file = files[i]
|
||||
const filePath = path.join(pth, file)
|
||||
if (fs.statSync(filePath).isFile()) {
|
||||
hashr += fs.readFileSync(filePath, 'utf-8')
|
||||
} else if (fs.statSync(filePath).isDirectory() && !filePath.includes("node_modules") && !filePath.includes("copies") && !filePath.includes(".git")) {
|
||||
hashr += await fscn(filePath)
|
||||
}
|
||||
}
|
||||
return hashr
|
||||
}
|
||||
if (prod) {
|
||||
await context.rebuild();
|
||||
process.exit(0);
|
||||
} else {
|
||||
let lh = 0
|
||||
setTimeout(async () => {
|
||||
let ls = async () => {
|
||||
await fscn().then((data) => {
|
||||
let nh = cyrb53(data, 1)
|
||||
if (lh != nh) {
|
||||
execSync("node archive/versions/execute.js", { stdio: "inherit" })
|
||||
lh = nh
|
||||
}
|
||||
})
|
||||
await new Promise((r)=>setTimeout(r,250))
|
||||
ls()
|
||||
}
|
||||
ls()
|
||||
}, 1)
|
||||
await context.watch();
|
||||
}
|
||||
|
|
|
|||
332
main.ts
332
main.ts
|
|
@ -1,44 +1,38 @@
|
|||
import { App, MarkdownView, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian';
|
||||
import { inflate, deflate } from "./util/pakoMinified"
|
||||
import { BB } from "./util/BB"
|
||||
import { encodeSafe, decodeSafe } from "./util/runlength"
|
||||
|
||||
import { App, MarkdownView, Notice, Plugin, PluginSettingTab, Setting, FileView } from 'obsidian';
|
||||
// import { inflate, deflate } from "./util/pako"
|
||||
// import { encodeSafe, decodeSafe } from "./util/runlength"
|
||||
import { netcompress, netdecompress, plugincompress, plugindecompress } from "./util/networkmastercompression"
|
||||
|
||||
interface compressorSettingsData {
|
||||
// mySetting: string;
|
||||
PrintResult: boolean;
|
||||
FileSize: boolean;
|
||||
LeaveRawLinks: boolean;
|
||||
Debug: boolean;
|
||||
// PakoCompress: boolean;
|
||||
ExcalidrawPrecision: number;
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: compressorSettingsData = {
|
||||
// mySetting: 'default',
|
||||
PrintResult: false,
|
||||
FileSize: false,
|
||||
LeaveRawLinks: true,
|
||||
Debug: false,
|
||||
// PakoCompress: true,
|
||||
ExcalidrawPrecision: 2,
|
||||
PrintResult: true,
|
||||
FileSize: true,
|
||||
LeaveRawLinks: true
|
||||
}
|
||||
let globalLeafs: any[] = []
|
||||
let NoticePool: Notice[] = []
|
||||
let statusBarItemEl2: (undefined | HTMLElement);
|
||||
var globalLeafs: any[] = []
|
||||
var NoticePool: Notice[] = []
|
||||
var statusBarItemEl2: (undefined | HTMLElement);
|
||||
export default class compressorPlugin extends Plugin {
|
||||
settings: compressorSettingsData;
|
||||
|
||||
async onload() {
|
||||
let loadTime = new Date().getTime()
|
||||
var loadTime = new Date().getTime()
|
||||
|
||||
this.registerExtensions(["ctxt"], "ctxt")
|
||||
|
||||
this.registerView("ctxt",
|
||||
(leaf) => {
|
||||
let hook = new MarkdownView(leaf)
|
||||
let f = setInterval(() => {
|
||||
let file = hook.file || this.app.workspace.getActiveFile()
|
||||
var hook = new MarkdownView(leaf)
|
||||
var f = setInterval(() => {
|
||||
var file = hook.file || this.app.workspace.getActiveFile()
|
||||
if (file) {
|
||||
clearInterval(f)
|
||||
if (file && file.extension == "ctxt") {
|
||||
|
|
@ -48,13 +42,12 @@ export default class compressorPlugin extends Plugin {
|
|||
hook.editor.refresh = () => { }
|
||||
globalLeafs.push(["ctxt", file.path, hook])
|
||||
this.app.vault.read(file).then((data) => {
|
||||
// if (file && data && (!data.includes("\n") && !data.includes(" "))) {
|
||||
if (file && data && checkCompFile(data)) {
|
||||
if (file && data && (!data.includes("\n") && !data.includes(" "))) {
|
||||
new Notice("Attempting to load.")
|
||||
setTimeout(() => {
|
||||
let decompress = null
|
||||
var decompress = null
|
||||
try {
|
||||
decompress = decompressfile(data, this.settings.Debug || false)
|
||||
decompress = decompressfile(data)
|
||||
} catch (err) { console.log(err) }
|
||||
if (decompress) {
|
||||
hook.setViewData(decompress, true)
|
||||
|
|
@ -67,11 +60,13 @@ export default class compressorPlugin extends Plugin {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
}, 10)
|
||||
return hook
|
||||
}
|
||||
)
|
||||
this.registerEvent(this.app.workspace.on("file-open", (file) => {
|
||||
|
||||
this.app.workspace.on("file-open", (file) => {
|
||||
if (file && file.extension == "ctxt" && globalLeafs.length <= 0 && (new Date().getTime() - loadTime) < 1000) {
|
||||
this.app.workspace.getMostRecentLeaf()?.openFile(file)
|
||||
}
|
||||
|
|
@ -80,23 +75,24 @@ export default class compressorPlugin extends Plugin {
|
|||
if (statusBarItemEl2 && this.settings.FileSize) statusBarItemEl2.setText(data.length + "B")
|
||||
})
|
||||
}
|
||||
}))
|
||||
})
|
||||
|
||||
this.registerEvent(this.app.vault.on('modify', (file) => {
|
||||
let file2 = this.app.vault.getFileByPath(file.path)
|
||||
var file2 = this.app.vault.getFileByPath(file.path)
|
||||
if (file2 && file2.extension == "ctxt") {
|
||||
this.app.vault.read(file2).then((data) => {
|
||||
if (statusBarItemEl2 && this.settings.FileSize) statusBarItemEl2.setText(data.length + "B")
|
||||
// if (file2 && data && (data.includes("\n") || data.includes(" "))) {
|
||||
if (file2 && data && !checkCompFile(data)) {
|
||||
let compress = null
|
||||
if (file2 && data && (data.includes("\n") || data.includes(" "))) {
|
||||
var compress = null
|
||||
try {
|
||||
NoticePool.forEach((n) => {
|
||||
if (n) n.hide()
|
||||
})
|
||||
compress = compressfile(data, this.settings.Debug || false, this.settings)
|
||||
compress = compressfile(data, false, this.settings)
|
||||
} catch (err) { console.log(err) }
|
||||
if (compress) {
|
||||
globalLeafs.forEach((leaf) => {
|
||||
console.log(leaf)
|
||||
if (leaf[0] == "ctxt" && leaf[2] == file.path && leaf[3]) {
|
||||
// leaf[3].editor.setLine("")
|
||||
leaf[3].unload()
|
||||
|
|
@ -109,6 +105,7 @@ export default class compressorPlugin extends Plugin {
|
|||
leaf[3].setViewData(data, true)
|
||||
}
|
||||
})
|
||||
console.log(file.name + " has been saved")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -125,10 +122,10 @@ export default class compressorPlugin extends Plugin {
|
|||
// this.startAction()
|
||||
// });
|
||||
const ribbonIconEl2 = this.addRibbonIcon('checkmark', 'Create new ctxt', (evt: MouseEvent) => {
|
||||
let filen = `newctxtfile${(new Date().getTime().toString().substring(10))}${Math.floor(Math.random() * 500)}.ctxt`
|
||||
var filen = `newctxtfile${(new Date().getTime().toString().substring(10))}${Math.floor(Math.random() * 500)}.ctxt`
|
||||
this.app.vault.create("./" + filen, "Write away!")//.then((filex) => {
|
||||
// setTimeout(()=>{
|
||||
// let file = this.app.vault.getFileByPath(filen)
|
||||
// var file = this.app.vault.getFileByPath(filen)
|
||||
// if (file) {
|
||||
// console.log(file, this.app.workspace.getMostRecentLeaf())
|
||||
// this.app.workspace.getMostRecentLeaf()?.openFile(file)
|
||||
|
|
@ -139,13 +136,14 @@ export default class compressorPlugin extends Plugin {
|
|||
});
|
||||
const ribbonIconEl3 = this.addRibbonIcon('up-and-down-arrows', 'Convert currently opened file', (evt: MouseEvent) => {
|
||||
if (confirm("Are you sure you want to convert")) { //will this work? electron confirms dont exit. Oh it does
|
||||
let file = this.app.workspace.getActiveFile()
|
||||
var file = this.app.workspace.getActiveFile()
|
||||
console.log(file)
|
||||
if (file) {
|
||||
if (file.extension == "ctxt") {
|
||||
this.app.vault.read(file).then((data) => {
|
||||
let raw = data
|
||||
var raw = data
|
||||
try {
|
||||
let dc = decompressfile(data, this.settings.Debug || false)
|
||||
var dc = decompressfile(data, true)
|
||||
if (dc) raw = dc
|
||||
} catch (_) {
|
||||
new Notice("Failed to decompress, plainText?")
|
||||
|
|
@ -167,9 +165,9 @@ export default class compressorPlugin extends Plugin {
|
|||
})
|
||||
} else {
|
||||
this.app.vault.read(file).then((data) => {
|
||||
let raw = data
|
||||
var raw = data
|
||||
try {
|
||||
let dc = compressfile(data, this.settings.Debug || false)
|
||||
var dc = compressfile(data, true)
|
||||
if (dc) raw = dc
|
||||
} catch (_) {
|
||||
new Notice("Failed to compress.")
|
||||
|
|
@ -201,13 +199,13 @@ export default class compressorPlugin extends Plugin {
|
|||
//set elsewhere
|
||||
statusBarItemEl2 = this.addStatusBarItem();
|
||||
statusBarItemEl2.setText("");
|
||||
statusBarItemEl2.title = "File size"
|
||||
statusBarItemEl2.title = "File Size"
|
||||
|
||||
this.addCommand({
|
||||
id: 'createctxt',
|
||||
name: 'Create a new ctxt file in root',
|
||||
callback: () => {
|
||||
let filen = `newctxtfile${(new Date().getTime().toString().substring(10))}${Math.floor(Math.random() * 500)}.ctxt`
|
||||
var filen = `newctxtfile${(new Date().getTime().toString().substring(10))}${Math.floor(Math.random() * 500)}.ctxt`
|
||||
this.app.vault.create("./" + filen, "Write away!")
|
||||
}
|
||||
});
|
||||
|
|
@ -216,18 +214,26 @@ export default class compressorPlugin extends Plugin {
|
|||
|
||||
|
||||
// this.registerInterval(window.setInterval(() => {
|
||||
// let file = this.app.workspace.getActiveFile()
|
||||
// var file = this.app.workspace.getActiveFile()
|
||||
// if (file != null) {
|
||||
|
||||
// this.app.vault.read(file).then((data) => {
|
||||
// if (!data.includes("\n") && /[A-z0-9\-_]/gm.test(data) && !data.includes(" ")) {
|
||||
// let isctxt = false
|
||||
// try {
|
||||
// decompressfile(data)
|
||||
// isctxt = true
|
||||
// } catch (_) { }
|
||||
// if (isctxt) {
|
||||
// if (pane) pane.innerHTML += `<div id="AEDTCOMPDNEOUTSNTTIS!" style="position: absolute;left:0%;right:0%;width:100%;height:100%;background-color:rgba(20,20,20,0.6);z-index: 99999999999;">Content Compressed.</div>`
|
||||
// var bb = new BB()
|
||||
// bb.G(data)
|
||||
// var precont = []
|
||||
// while (true) {
|
||||
// var now = bb.RU()
|
||||
// if (now >= 0) {
|
||||
// precont[precont.length] = now
|
||||
// } else break
|
||||
// }
|
||||
// var cont = new Uint8Array(precont)
|
||||
// if (cont && cont.length > 0) {
|
||||
// var decomp = inflate(cont)
|
||||
// if (typeof (decomp) == "object") {
|
||||
// if (pane) pane.innerHTML += `<div id="AEDTCOMPDNEOUTSNTTIS!" style="position: absolute;left:0%;right:0%;width:100%;height:100%;background-color:rgba(20,20,20,0.6);z-index: 99999999999;">Content Compressed.</div>`
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
|
|
@ -237,49 +243,9 @@ export default class compressorPlugin extends Plugin {
|
|||
// }
|
||||
// }, 100));
|
||||
//<div style="position: absolute;left:0%;right:0%;width:100%;height:100%;background-color:rgba(20,20,20,0.6);z-index: 99999999999;">Content Compressed.</div>
|
||||
|
||||
|
||||
|
||||
//NOT FINISHED.
|
||||
// ; (async () => {
|
||||
// while (true) {
|
||||
// await new Promise((r) => { setTimeout(r, 100) })
|
||||
// if (this.app.vault.getFiles().length > 0) break
|
||||
// }
|
||||
// var hn = false
|
||||
// this.app.vault.getFiles().forEach((file) => {
|
||||
// console.log(file.name)
|
||||
// this.app.vault.read(file).then((data) => {
|
||||
// if (file) {
|
||||
// if (data.includes("excalidraw") && data.includes("```compressed-json") && !hn) {
|
||||
// alert("File Compressor: You have excalidraw installed with compression, please go to settings -> excalidraw -> Saving -> Compression and disable it. That way it can be compressed by this plugin. Source cause: " + file.path)
|
||||
// hn = true
|
||||
// }
|
||||
// // var out = plugindecompress(file, data)
|
||||
// plugincompress(file, data, this.settings)
|
||||
// var out = plugindecompress(file, data)
|
||||
// // if (out) this.app.vault.modify(file, out)
|
||||
// console.log("WRITER DISABLED.")
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
// })()
|
||||
|
||||
this.app.workspace.on("quit", () => {
|
||||
//NOT FINISHED.
|
||||
// this.app.vault.getFiles().forEach((file) => {
|
||||
// console.log(file.name)
|
||||
// this.app.vault.read(file).then((data) => {
|
||||
// if (file) {
|
||||
// var out = plugincompress(file, data)
|
||||
// if (out) this.app.vault.modify(file, out)
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
})
|
||||
}
|
||||
onunload() {
|
||||
// alert("In order to view CTXT files you will need to re-enable the plugin. If you are deleting the plugin, please convert your files back before.")
|
||||
alert("In order to view CTXT files you will need to re-enable the plugin. If you are deleting the plugin, please convert your files back before.")
|
||||
}
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
|
|
@ -288,113 +254,64 @@ export default class compressorPlugin extends Plugin {
|
|||
await this.saveData(this.settings);
|
||||
}
|
||||
}
|
||||
// function compressfile(data: string, notice?: boolean, settings?: compressorSettingsData) {
|
||||
// if (notice) new Notice("Started", 3000)
|
||||
// const comp = deflate(data)
|
||||
// let inf = inflate(comp)
|
||||
// if (inf && typeof (inf) != "string" && new TextDecoder().decode(inf) != data) {
|
||||
// if (notice) new Notice("Revert is corrupted.", 3000)
|
||||
// throw new Error("Revert not same,")
|
||||
// }
|
||||
// if (comp) {
|
||||
// if (notice) new Notice("MEST", 3000)
|
||||
// let bb = new BB()
|
||||
// comp.forEach((byte: Number) => {
|
||||
// // console.log(byte)
|
||||
// bb.WU(8,byte)
|
||||
// })
|
||||
// if (notice) new Notice("SWAP", 3000)
|
||||
// // let linkblk = ""
|
||||
// // ;[...data.matchAll(/\[\[[^\]]*\]\]/gm)].forEach((match) => {
|
||||
// // console.log(match)
|
||||
// // linkblk += match[0]
|
||||
// // })
|
||||
// let encd = encodeSafe(bb.G())
|
||||
// if (notice) new Notice("RLE", 3000)
|
||||
// if (encd) {
|
||||
// if (notice) new Notice("METADATA SET.", 3000)
|
||||
// let content = `DATABLK` + encd
|
||||
// if (content && content.length < data.length) {
|
||||
// if (notice) new Notice("Success!")
|
||||
// if (settings && settings.PrintResult) {
|
||||
// NoticePool.push(new Notice(`Compression:\nratio:${((content.length / data.length) * 100).toFixed(1)}%`))
|
||||
// }
|
||||
// return content
|
||||
// } else {
|
||||
// if (notice) new Notice("File isnt smaller.")
|
||||
// }
|
||||
// } else {
|
||||
// new Notice("Encoder failure.")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// function decompressfile(data: string, notice?: boolean) {
|
||||
// if (notice) new Notice("START", 3000)
|
||||
// let bb = new BB()
|
||||
// bb.F(decodeSafe(data.substring(data.indexOf("DATABLK") + 7)))
|
||||
// let precont: number[] = []
|
||||
// while (true) {
|
||||
// let now = bb.RU(8)
|
||||
// if (!isNaN(now)) {
|
||||
// precont[precont.length] = now
|
||||
// } else break
|
||||
// }
|
||||
// if (notice) new Notice("OUT", 3000)
|
||||
// let cont = new Uint8Array(precont)
|
||||
// if (notice) console.log(precont)
|
||||
// if (notice) console.log(cont)
|
||||
// if (notice) new Notice("SWAP", 3000)
|
||||
// if (cont && cont.length > 0) {
|
||||
// if (notice) new Notice("INF", 3000)
|
||||
// let decomp = inflate(cont)
|
||||
// if (notice) console.log(decomp)
|
||||
// if (notice) new Notice("DONE, DECODE", 3000)
|
||||
// if (typeof (decomp) == "object") {
|
||||
// decomp = new TextDecoder().decode(decomp)
|
||||
// if (notice) new Notice("Success!")
|
||||
// return decomp
|
||||
// } else {
|
||||
// if (notice) new Notice("Failed.")
|
||||
// }
|
||||
// } else {
|
||||
// if (notice) new Notice("Couldnt Decompress.")
|
||||
// }
|
||||
// }
|
||||
function compressfile(data: string, notice?: boolean, settings?: compressorSettingsData) {
|
||||
if (notice) new Notice("Started C", 3000)
|
||||
let result: (string | undefined) = ""
|
||||
try {
|
||||
result = netcompress(data, null, settings)
|
||||
if (notice) new Notice("Done!")
|
||||
if (settings && settings.PrintResult && result) {
|
||||
NoticePool.push(new Notice(`Compression:\nratio:${((result.length / data.length) * 100).toFixed(1)}%`))
|
||||
}
|
||||
} catch (err) {
|
||||
new Notice(err, 3000)
|
||||
throw new Error(err)
|
||||
const comp = deflate(data)
|
||||
var inf = inflate(comp)
|
||||
if (inf && new TextDecoder().decode(inf) != data) {
|
||||
if (notice) new Notice("Revert is corrupted.", 3000)
|
||||
throw new Error("Revert not same,")
|
||||
}
|
||||
if (comp) {
|
||||
var bb = new BB()
|
||||
comp.forEach((byte) => {
|
||||
// console.log(byte)
|
||||
bb.WU(byte)
|
||||
})
|
||||
// var linkblk = ""
|
||||
// ;[...data.matchAll(/\[\[[^\]]*\]\]/gm)].forEach((match) => {
|
||||
// console.log(match)
|
||||
// linkblk += match[0]
|
||||
// })
|
||||
var encd = encodeSafe(bb.G())
|
||||
if (encd) {
|
||||
var content = `DATABLK` + encd
|
||||
if (content && content.length < data.length) {
|
||||
if (notice) new Notice("Success!")
|
||||
if (settings && settings.PrintResult) {
|
||||
NoticePool.push(new Notice(`Compression:\nratio:${((content.length / data.length) * 100).toFixed(1)}%`))
|
||||
}
|
||||
return content
|
||||
} else {
|
||||
if (notice) new Notice("File isnt smaller.")
|
||||
}
|
||||
} else {
|
||||
new Notice("Encoder failure.")
|
||||
}
|
||||
}
|
||||
if (result == "" || !result) throw new Error("Empty")
|
||||
return result
|
||||
}
|
||||
function decompressfile(data: string, notice?: boolean) {
|
||||
if (notice) new Notice("Started D", 3000)
|
||||
let result: (string | undefined) = ""
|
||||
try {
|
||||
result = netdecompress(data)
|
||||
if (notice) new Notice("Done!")
|
||||
} catch (err) {
|
||||
new Notice(err, 3000)
|
||||
throw new Error(err)
|
||||
var bb = new BB()
|
||||
bb.F(decodeSafe(data.substring(data.indexOf("DATABLK") + 7)))
|
||||
var precont: number[] = []
|
||||
while (true) {
|
||||
var now = bb.RU()
|
||||
if (!isNaN(now)) {
|
||||
precont[precont.length] = now
|
||||
} else break
|
||||
}
|
||||
var cont = new Uint8Array(precont)
|
||||
if (cont && cont.length > 0) {
|
||||
var decomp = inflate(cont)
|
||||
if (typeof (decomp) == "object") {
|
||||
decomp = new TextDecoder().decode(decomp)
|
||||
if (notice) new Notice("Success!")
|
||||
return decomp
|
||||
} else {
|
||||
if (notice) new Notice("Failed.")
|
||||
}
|
||||
} else {
|
||||
if (notice) new Notice("Couldnt Decompress.")
|
||||
}
|
||||
if (result == "" || !result) throw new Error("Empty")
|
||||
return result
|
||||
}
|
||||
function checkCompFile(data: string) {
|
||||
var state = false
|
||||
try {
|
||||
state = (netdecompress(data) || "").length > 0
|
||||
} catch (_) { }
|
||||
return state
|
||||
}
|
||||
class compressorSettings extends PluginSettingTab {
|
||||
plugin: compressorPlugin;
|
||||
|
|
@ -427,41 +344,8 @@ class compressorSettings extends PluginSettingTab {
|
|||
this.plugin.settings.FileSize = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
// new Setting(containerEl)
|
||||
// .setName('Pako')
|
||||
// .setDesc('Use Pako to improve compression. May be intensive.')
|
||||
// .addToggle(bool => bool
|
||||
// .setValue(this.plugin.settings.PakoCompress)
|
||||
// .onChange(async (value) => {
|
||||
// this.plugin.settings.PakoCompress = value;
|
||||
// await this.plugin.saveSettings();
|
||||
// }));
|
||||
new Setting(containerEl)
|
||||
.setName('NOTICE:')
|
||||
.setDesc('Unfortunetly the graph view will not maintain links. The graph cannot read the compressed data. Nor if the links are raw')
|
||||
new Setting(containerEl)
|
||||
.setName('Debug')
|
||||
.setDesc('Toasts all the events that are happening. Useful for debugging.')
|
||||
.addToggle(bool => bool
|
||||
.setValue(this.plugin.settings.Debug)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.Debug = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
// new Setting(containerEl)
|
||||
// .setName('-----Plugin Data Compression-----')
|
||||
// .setDesc('Settings for compressing data that plugins save to vault')
|
||||
//useless excelidraw uses whole offsets
|
||||
// var ex_DP = new Setting(containerEl)
|
||||
// .setName('Excalidraw: Decimal Precision')
|
||||
// .setDesc(`How many decimals to have when saving numbers (${this.plugin.settings.ExcalidrawPrecision} DP)`)
|
||||
// .addSlider(num => num
|
||||
// .setValue(this.plugin.settings.ExcalidrawPrecision)
|
||||
// .setLimits(0, 5, 1)
|
||||
// .onChange(async (value) => {
|
||||
// this.plugin.settings.ExcalidrawPrecision = value;
|
||||
// ex_DP.setDesc(`How many decimals to have when saving numbers (${this.plugin.settings.ExcalidrawPrecision} DP) ${(this.plugin.settings.ExcalidrawPrecision==0)?"NO DECIMALS(VERY BAD)":""}`)
|
||||
// await this.plugin.saveSettings();
|
||||
// }));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
{
|
||||
"id": "compress",
|
||||
"name": "File Compressor",
|
||||
"version": "1.2.5",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Make your files smaller with compression!",
|
||||
"description": "This plugin will add the .ctxt file type which will allow you to compress notes to a smaller size.",
|
||||
"author": "networkmastered",
|
||||
"authorUrl": "https://github.com/networkmastered",
|
||||
"fundingUrl": "https://github.com/networkmastered",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
package-lock.json
generated
2
package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "compress",
|
||||
"version": "1.2.5",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "compress",
|
||||
"version": "1.2.5",
|
||||
"description": "Make your files smaller with compression!",
|
||||
"version": "1.0.0",
|
||||
"description": "This plugin will add the .ctxt file type which will allow you to compress notes to a smaller version.\nNOTE: If you create a link in a compressed file it will NOT show in graph view.\nWhen using this plugin data loss is possible, we've tried to minimise it. But theres always a change. If you do experiance data loss we are not liable. But you may create an issue request with the raw data(do not provide personal info).",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "node archive/testchecks.js && tsc -noEmit -skipLibCheck && node esbuild.config.mjs",
|
||||
"build": "node archive/testchecks.js && tsc -noEmit -skipLibCheck && node esbuild.config.mjs production && node archive/versions/execute.js",
|
||||
"dev": "node esbuild.config.mjs",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
||||
},
|
||||
"keywords": [],
|
||||
|
|
|
|||
35
util/BB.js
35
util/BB.js
|
|
@ -17,7 +17,6 @@ export class BB {
|
|||
ch = Math.floor(ch / 2)
|
||||
}
|
||||
}
|
||||
this.PT = 0
|
||||
}
|
||||
G() {
|
||||
let str = ""
|
||||
|
|
@ -34,19 +33,33 @@ export class BB {
|
|||
}
|
||||
return str
|
||||
}
|
||||
WU(r, val) {
|
||||
for (let i = 0; i < r; i++) {
|
||||
WU(value) {
|
||||
this.BB[this.PT + 1] = value % 2
|
||||
value = Math.floor(value / 2)
|
||||
this.BB[this.PT + 2] = value % 2
|
||||
value = Math.floor(value / 2)
|
||||
this.BB[this.PT + 3] = value % 2
|
||||
value = Math.floor(value / 2)
|
||||
this.BB[this.PT + 4] = value % 2
|
||||
value = Math.floor(value / 2)
|
||||
this.BB[this.PT + 5] = value % 2
|
||||
value = Math.floor(value / 2)
|
||||
this.BB[this.PT + 6] = value % 2
|
||||
value = Math.floor(value / 2)
|
||||
this.BB[this.PT + 7] = value % 2
|
||||
value = Math.floor(value / 2)
|
||||
this.BB[this.PT + 8] = value % 2
|
||||
value = Math.floor(value / 2)
|
||||
this.PT += 8
|
||||
for (let i = 0; i < 8; i++) {
|
||||
this.PT++
|
||||
this.BB[this.PT] = val % 2
|
||||
val = Math.floor(val / 2)
|
||||
this.BB[this.PT] = value % 2
|
||||
value = Math.floor(value / 2)
|
||||
}
|
||||
}
|
||||
RU(val) {
|
||||
let r = 0
|
||||
for (let i = 0; i < val; i++) {
|
||||
this.PT++
|
||||
r += this.BB[this.PT] * this.PO[i]
|
||||
}
|
||||
RU() {
|
||||
let r = this.BB[this.PT+1] * this.PO[0] + this.BB[this.PT + 2] * this.PO[1] + this.BB[this.PT + 3] * this.PO[2] + this.BB[this.PT + 4] * this.PO[3] + this.BB[this.PT + 5] * this.PO[4] + this.BB[this.PT + 6] * this.PO[5] + this.BB[this.PT + 7] * this.PO[6] + this.BB[this.PT + 8] * this.PO[7]
|
||||
this.PT += 8
|
||||
return r
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
6890
util/pako.js
6890
util/pako.js
File diff suppressed because it is too large
Load diff
2
util/pakoMinified.js
Normal file
2
util/pakoMinified.js
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,148 +0,0 @@
|
|||
export function CanDo(file, str, set) {
|
||||
console.log(str.startsWith(`---\n\nexcalidraw-plugin: parsed\ntags: [excalidraw]\n\n---\n==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠== You can decompress Drawing data with the command palette: \'Decompress current Excalidraw file\'. For more info check in plugin settings under \'Saving\'\n\n\n# Excalidraw Data\n\n`), str.includes("```json"), str)
|
||||
return str.startsWith(`---\n\nexcalidraw-plugin: parsed\ntags: [excalidraw]\n\n---\n==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠== You can decompress Drawing data with the command palette: \'Decompress current Excalidraw file\'. For more info check in plugin settings under \'Saving\'\n\n\n# Excalidraw Data\n\n`) && str.includes("```json")
|
||||
}
|
||||
export function CanUnDo(file, str) {
|
||||
console.log(str.startsWith(`---\n\nexcalidraw-plugin: parsed\ntags: [excalidraw]\n\n---\n==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠== You can decompress Drawing data with the command palette: \'Decompress current Excalidraw file\'. For more info check in plugin settings under \'Saving\'\n\n\n# Excalidraw Data\n\n`), str.includes("```json"), str)
|
||||
return str.startsWith("COMPDATA_-EXCALI:")
|
||||
}
|
||||
var brushTypes = [
|
||||
"line",
|
||||
"ellipse",
|
||||
"diamond",
|
||||
"arrow",
|
||||
"freedraw",
|
||||
"image",
|
||||
"text",
|
||||
"rectangle",
|
||||
]
|
||||
var Styles = {
|
||||
fills: ["cross-hatch", "hachure", "solid"],
|
||||
stroke: ["dotted", "dashed", "solid"],
|
||||
|
||||
}
|
||||
class saveconstruct {
|
||||
constructor(intl, type) {
|
||||
this.out = intl || ""
|
||||
this.type = type
|
||||
}
|
||||
addData(data) {
|
||||
if (this.type && this.type == "master") {
|
||||
this.out += data
|
||||
} else {
|
||||
this.out += data + ","
|
||||
}
|
||||
}
|
||||
export() {
|
||||
if (this.type == "master") return this.out
|
||||
return this.out.substring(0, this.out.length - 1)
|
||||
}
|
||||
}
|
||||
|
||||
export function Compress(file, str, set, BB) {
|
||||
// try {
|
||||
var textdata = str.substring(str.indexOf("## Text Elements"), str.indexOf("%%")).substring(17)
|
||||
var lack = str.substring(str.indexOf("## Drawing"), str.indexOf("%%", str.indexOf("## Drawing"))).substring(18).trim()
|
||||
lack = lack.substring(0, lack.length - 3).trim()
|
||||
console.log(lack)
|
||||
var drawdata = JSON.parse(lack)
|
||||
if (drawdata && drawdata) {
|
||||
let meta = new BB()
|
||||
meta.WU(5, drawdata.version || 2)
|
||||
meta.WU(5, set.ExcalidrawPrecision)
|
||||
drawdata.source.substring(69).split(".").forEach((v) => {
|
||||
meta.WU(5, v)
|
||||
})
|
||||
let bld = new saveconstruct(meta.G(), "master")
|
||||
// let bld = new saveconstruct(drawdata.version + "" + set.ExcalidrawPrecision + "@" + drawdata.source.substring(69), "master")
|
||||
console.log(drawdata)
|
||||
drawdata.elements.forEach((stroke) => {
|
||||
let localStroke = new saveconstruct(";" + stroke.id + ":")
|
||||
// let localStroke = stroke.id + ":"
|
||||
localStroke.addData(brushTypes.indexOf(stroke.type))
|
||||
localStroke.addData(Math.round(stroke.x * (10 ** set.ExcalidrawPrecision)))
|
||||
localStroke.addData(Math.round(stroke.y * (10 ** set.ExcalidrawPrecision)))
|
||||
|
||||
localStroke.addData(Math.round(stroke.width * (10 ** set.ExcalidrawPrecision)))
|
||||
localStroke.addData(Math.round(stroke.height * (10 ** set.ExcalidrawPrecision)))
|
||||
|
||||
localStroke.addData(Math.round(stroke.angle * (10 ** set.ExcalidrawPrecision)) % 360)
|
||||
|
||||
if (stroke.strokeColor.startsWith("#")) {
|
||||
localStroke.addData(stroke.strokeColor.substring(1))
|
||||
} else {
|
||||
localStroke.addData(stroke.strokeColor)
|
||||
}
|
||||
if (stroke.backgroundColor.startsWith("#")) {
|
||||
localStroke.addData(stroke.backgroundColor.substring(1))
|
||||
} else {
|
||||
localStroke.addData(stroke.backgroundColor)
|
||||
}
|
||||
|
||||
if (stroke.backgroundColor.startsWith("#")) {
|
||||
localStroke.addData(stroke.backgroundColor.substring(1))
|
||||
} else {
|
||||
localStroke.addData(stroke.backgroundColor)
|
||||
}
|
||||
|
||||
localStroke.addData(Styles.fills.indexOf(stroke.fillStyle))
|
||||
localStroke.addData(stroke.strokeWidth || 0)
|
||||
localStroke.addData(Styles.stroke.indexOf(stroke.strokeStyle))
|
||||
|
||||
localStroke.addData(stroke.roughness || 0)
|
||||
localStroke.addData(stroke.opacity >= 100 ? -1 : stroke.opacity)
|
||||
|
||||
localStroke.addData((stroke.groupIds && stroke.groupIds.length > 0) ? JSON.stringify(stroke.groupIds) : 0)
|
||||
|
||||
localStroke.addData(stroke.frameId || "")
|
||||
|
||||
localStroke.addData(stroke.index)
|
||||
|
||||
if (stroke.roundness) {
|
||||
localStroke.addData(stroke.roundness.type || 0)
|
||||
} else {
|
||||
localStroke.addData(0)
|
||||
}
|
||||
|
||||
if (stroke.seed && stroke.roughness > 0) {
|
||||
localStroke.addData(stroke.seed)
|
||||
} else {
|
||||
localStroke.addData(0)
|
||||
}
|
||||
|
||||
localStroke.addData(stroke.version || 0)
|
||||
|
||||
localStroke.addData(stroke.versionNonce || 0)
|
||||
|
||||
localStroke.addData(stroke.isDeleted ? 1 : 0)
|
||||
|
||||
localStroke.addData((stroke.boundElements && stroke.boundElements.length > 0) ? JSON.stringify(stroke.boundElements) : 0)
|
||||
|
||||
localStroke.addData(stroke.updated)
|
||||
|
||||
if (stroke.link) {
|
||||
if (stroke.link.startsWith("https://")) {
|
||||
localStroke.addData("”" + stroke.link.substring(8) || "")
|
||||
} else if (stroke.link.startsWith("http://")) {
|
||||
localStroke.addData("⁕" + stroke.link.substring(7) || "")
|
||||
} else {
|
||||
localStroke.addData(stroke.link || "")
|
||||
}
|
||||
}
|
||||
|
||||
localStroke.addData(stroke.locked ? 1 : 0)
|
||||
|
||||
bld.addData(localStroke.export())
|
||||
})
|
||||
console.log(bld.export())
|
||||
return "COMPDATA_-EXCALI:" + bld.export()
|
||||
} else {
|
||||
throw new Error("OOD")
|
||||
}
|
||||
return str
|
||||
// } catch (e) { return undefined }
|
||||
}
|
||||
export function Decompress(file, str, BB) {
|
||||
str = str.substring(7)
|
||||
console.log(str)
|
||||
}
|
||||
|
|
@ -29,9 +29,9 @@ function DNum(encoded) {
|
|||
}
|
||||
//V2
|
||||
export function encodeSafe(str) {
|
||||
let count = 0
|
||||
let typ = ""
|
||||
let out = ""
|
||||
var count = 0
|
||||
var typ = ""
|
||||
var out = ""
|
||||
str.split("").forEach((char) => {
|
||||
if (char != typ && typ != "") {
|
||||
if (count > 2) {
|
||||
|
|
@ -56,8 +56,8 @@ export function encodeSafe(str) {
|
|||
}
|
||||
}
|
||||
export function decodeSafe(str) {
|
||||
let count = ""
|
||||
let out = ""
|
||||
var count = ""
|
||||
var out = ""
|
||||
str.split("").forEach((char) => {
|
||||
if (charMap.includes(char)) {
|
||||
count += char
|
||||
|
|
|
|||
|
|
@ -1,242 +0,0 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
// - - -
|
||||
// # LZ77
|
||||
// ** A minimal LZ77 [de]compressor **
|
||||
var LZ77 = function () {
|
||||
// ##### Private Variables
|
||||
var
|
||||
self = {}
|
||||
, settings = {
|
||||
refPrefix: '`',
|
||||
refIntBase: 96,
|
||||
refIntFloorCode: ' '.charCodeAt(0),
|
||||
refIntCeilCode: undefined,
|
||||
maxStringDistance: undefined,
|
||||
minStringLength: 5,
|
||||
maxStringLength: undefined,
|
||||
defaultWindow: 144,
|
||||
maxWindow: undefined,
|
||||
windowLength: undefined
|
||||
}
|
||||
;
|
||||
|
||||
// ##### Public Variables
|
||||
|
||||
// ##### Private Methods
|
||||
var setup = function (params) {
|
||||
params = params || {};
|
||||
settings = extend(settings, params);
|
||||
|
||||
settings.refIntCeilCode = settings.refIntFloorCode + settings.refIntBase - 1;
|
||||
settings.maxStringDistance = Math.pow(settings.refIntBase, 2) - 1;
|
||||
settings.maxStringLength = Math.pow(settings.refIntBase, 1) - 1 + settings.minStringLength;
|
||||
settings.maxWindow = settings.maxStringDistance + settings.minStringLength;
|
||||
};
|
||||
|
||||
// #### each()
|
||||
// >`@param obj [collection]` our source collection
|
||||
// >`@param iterator [function]` the function that will be called for each element in the collection
|
||||
// >`@param context [object]` the context our iterator should operate within
|
||||
//
|
||||
// essentially copied from underscore.js
|
||||
var each = function (obj, iterator, context) {
|
||||
var breaker = {};
|
||||
if (obj === null) { return; }
|
||||
if (Array.prototype.forEach && obj.forEach === Array.prototype.forEach) {
|
||||
obj.forEach(iterator, context);
|
||||
} else if (obj.length === +obj.length) {
|
||||
for (var i = 0, l = obj.length; i < l; i++) {
|
||||
if (iterator.call(context, obj[i], i, obj) === breaker) { return; }
|
||||
}
|
||||
} else {
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
if (iterator.call(context, obj[key], key, obj) === breaker) { return; }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// #### extend()
|
||||
// >`@param obj [object]` our destination object
|
||||
// >`@params * [object(s)]` objects that will overwrite the data in the destination object, in order
|
||||
//
|
||||
// essentially copied from underscore.js
|
||||
var extend = function (obj) {
|
||||
each(Array.prototype.slice.call(arguments, 1), function (source) {
|
||||
if (source) {
|
||||
for (var prop in source) {
|
||||
obj[prop] = source[prop];
|
||||
}
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
};
|
||||
|
||||
var encodeRefInt = function (value, width) {
|
||||
if ((value >= 0) && (value < (Math.pow(settings.refIntBase, width) - 1))) {
|
||||
var encoded = '';
|
||||
while (value > 0) {
|
||||
encoded = (String.fromCharCode((value % settings.refIntBase) + settings.refIntFloorCode)) + encoded;
|
||||
value = Math.floor(value / settings.refIntBase);
|
||||
}
|
||||
var missingLength = width - encoded.length;
|
||||
var i = 0;
|
||||
for (; i < missingLength; i++) {
|
||||
encoded = String.fromCharCode(settings.refIntFloorCode) + encoded;
|
||||
}
|
||||
return encoded;
|
||||
} else {
|
||||
throw 'Reference int out of range: ' + value + ' (width = ' + width + ')';
|
||||
}
|
||||
};
|
||||
|
||||
var encodeRefLength = function (length) {
|
||||
return encodeRefInt(length - settings.minStringLength, 1);
|
||||
};
|
||||
|
||||
var decodeRefInt = function (data, width) {
|
||||
var
|
||||
value = 0
|
||||
, charCode
|
||||
, i = 0
|
||||
;
|
||||
for (; i < width; i++) {
|
||||
value *= settings.refIntBase;
|
||||
charCode = data.charCodeAt(i);
|
||||
if ((charCode >= settings.refIntFloorCode) && (charCode <= settings.refIntCeilCode)) {
|
||||
value += charCode - settings.refIntFloorCode;
|
||||
} else {
|
||||
throw 'Invalid char code in reference int: ' + charCode;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
var decodeRefLength = function (data) {
|
||||
return decodeRefInt(data, 1) + settings.minStringLength;
|
||||
};
|
||||
|
||||
|
||||
// ##### Public Methods
|
||||
|
||||
// #### LZ77.compress()
|
||||
// >`@param source [string]` the source string we will be compressing
|
||||
// >`@param params [object]` this allows us to overwrite defaults at call-time
|
||||
//
|
||||
// This is our compression method, taking the input string (and allowing for call-time
|
||||
// paramters) and returning the compressed representation
|
||||
self.compress = function (source, params) {
|
||||
if (Object.prototype.toString.call(source) !== '[object String]') { return false; }
|
||||
|
||||
setup(params);
|
||||
|
||||
var windowLength = settings.windowLength || settings.defaultWindow;
|
||||
if (windowLength > settings.maxWindow) { throw 'Window length too large'; }
|
||||
|
||||
var
|
||||
compressed = ''
|
||||
, pos = 0
|
||||
, lastPos = source.length - settings.minStringLength
|
||||
;
|
||||
|
||||
while (pos < lastPos) {
|
||||
var
|
||||
searchStart = Math.max(pos - windowLength, 0)
|
||||
, matchLength = settings.minStringLength
|
||||
, foundMatch = false
|
||||
, bestMatch = {
|
||||
distance: settings.maxStringDistance,
|
||||
length: 0
|
||||
}
|
||||
, newCompressed = null
|
||||
, isValidMatch
|
||||
, realMatchLength
|
||||
;
|
||||
|
||||
while ((searchStart + matchLength) < pos) {
|
||||
isValidMatch = ((source.substr(searchStart, matchLength) === source.substr(pos, matchLength)) && (matchLength < settings.maxStringLength));
|
||||
if (isValidMatch) {
|
||||
matchLength++;
|
||||
foundMatch = true;
|
||||
} else {
|
||||
realMatchLength = matchLength - 1;
|
||||
if (foundMatch && (realMatchLength > bestMatch.length)) {
|
||||
bestMatch.distance = pos - searchStart - realMatchLength;
|
||||
bestMatch.length = realMatchLength;
|
||||
}
|
||||
matchLength = settings.minStringLength;
|
||||
searchStart++;
|
||||
foundMatch = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestMatch.length) {
|
||||
newCompressed = settings.refPrefix + encodeRefInt(bestMatch.distance, 2) + encodeRefLength(bestMatch.length);
|
||||
pos += bestMatch.length;
|
||||
} else {
|
||||
if (source.charAt(pos) !== settings.refPrefix) {
|
||||
newCompressed = source.charAt(pos);
|
||||
} else {
|
||||
newCompressed = settings.refPrefix + settings.refPrefix;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
compressed += newCompressed;
|
||||
}
|
||||
return compressed + source.slice(pos).replace(/`/g, '``');
|
||||
};
|
||||
|
||||
// #### LZ77.decompress()
|
||||
// >`@param source [string]` the source string of compressed data
|
||||
// >`@param params [object]` this allows us to overwrite defaults at call-time
|
||||
//
|
||||
// decompression method, taking the compressed data (as a string, and allowing for
|
||||
// call-time paramters) and returning the decompressed data
|
||||
self.decompress = function (source, params) {
|
||||
if (Object.prototype.toString.call(source) !== '[object String]') { return false; }
|
||||
|
||||
var
|
||||
decompressed = ''
|
||||
, pos = 0
|
||||
, currentChar
|
||||
, nextChar
|
||||
, distance
|
||||
, length
|
||||
;
|
||||
|
||||
setup(params);
|
||||
while (pos < source.length) {
|
||||
currentChar = source.charAt(pos);
|
||||
if (currentChar !== settings.refPrefix) {
|
||||
decompressed += currentChar;
|
||||
pos++;
|
||||
} else {
|
||||
nextChar = source.charAt(pos + 1);
|
||||
if (nextChar !== settings.refPrefix) {
|
||||
distance = decodeRefInt(source.substr(pos + 1, 2), 2);
|
||||
length = decodeRefLength(source.charAt(pos + 3));
|
||||
decompressed += decompressed.substr(decompressed.length - distance - length, length);
|
||||
pos += settings.minStringLength - 1;
|
||||
} else {
|
||||
decompressed += settings.refPrefix;
|
||||
pos += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return decompressed;
|
||||
};
|
||||
|
||||
return self;
|
||||
}();
|
||||
|
||||
if (typeof define !== 'undefined' && define.amd) { // requirejs/amd
|
||||
define([], function () { return LZ77; });
|
||||
} else if (typeof module !== 'undefined' && module.exports) { // node
|
||||
module.exports = LZ77;
|
||||
} else if (window !== undefined) {
|
||||
window.LZ77 = LZ77;
|
||||
}
|
||||
})();
|
||||
|
|
@ -1,8 +1,3 @@
|
|||
{
|
||||
"1.0.0": "0.15.0",
|
||||
"1.0.1": "0.15.0",
|
||||
"1.1.0": "0.15.0",
|
||||
"1.1.2": "0.15.0",
|
||||
"1.2.2": "0.15.0",
|
||||
"1.2.5": "0.15.0"
|
||||
}
|
||||
"1.0.0": "0.15.0"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue