mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-05 21:29:01 +00:00
213 lines
6.2 KiB
JavaScript
213 lines
6.2 KiB
JavaScript
/*
|
|
* notion-enhancer
|
|
* (c) 2020 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
|
* (https://dragonwocky.me/notion-enhancer) under the MIT license
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const os = require('os'),
|
|
path = require('path'),
|
|
fs = require('fs-extra'),
|
|
{ execSync } = require('child_process');
|
|
|
|
// used to differentiate between "enhancer failed" and "code broken" errors.
|
|
class EnhancerError extends Error {
|
|
constructor(message) {
|
|
super(message);
|
|
this.name = 'EnhancerError';
|
|
}
|
|
}
|
|
|
|
// checks if being run on the windows subsystem for linux:
|
|
// used to modify windows notion app.
|
|
const is_wsl =
|
|
process.platform === 'linux' &&
|
|
os.release().toLowerCase().includes('microsoft'),
|
|
// ~/.notion-enhancer absolute path.
|
|
__data = path.resolve(
|
|
`${
|
|
is_wsl
|
|
? (() => {
|
|
const stdout = execSync('cmd.exe /c echo %systemdrive%%homepath%', {
|
|
encoding: 'utf8',
|
|
}),
|
|
drive = stdout[0];
|
|
return `/mnt/${drive.toLowerCase()}${stdout
|
|
.replace(/\\/g, '/')
|
|
.slice(2)
|
|
.trim()}`;
|
|
})()
|
|
: os.homedir()
|
|
}/.notion-enhancer`
|
|
),
|
|
// gets possible system notion app filepaths.
|
|
__notion = (() => {
|
|
let folder = '';
|
|
switch (process.platform) {
|
|
case 'darwin':
|
|
folder = '/Applications/Notion.app/Contents/Resources';
|
|
break;
|
|
case 'win32':
|
|
folder = process.env.LOCALAPPDATA + '\\Programs\\Notion\\resources';
|
|
break;
|
|
case 'linux':
|
|
if (is_wsl) {
|
|
const stdout = execSync('cmd.exe /c echo %localappdata%', {
|
|
encoding: 'utf8',
|
|
}),
|
|
drive = stdout[0];
|
|
folder = `/mnt/${drive.toLowerCase()}${stdout
|
|
.replace(/\\/g, '/')
|
|
.slice(2)
|
|
.trim()}/Programs/Notion/resources`;
|
|
} else {
|
|
for (let loc of [
|
|
'/usr/lib/notion-desktop/resources', // https://github.com/haydn/notion-deb-builder/
|
|
'/opt/notion-app', // https://aur.archlinux.org/packages/notion-app/
|
|
'/opt/notion', // https://github.com/jaredallard/notion-app
|
|
]) {
|
|
if (fs.pathExistsSync(loc)) folder = loc;
|
|
}
|
|
}
|
|
}
|
|
if (!folder)
|
|
throw new EnhancerError('nothing found: platform not supported.');
|
|
// check if actual app files are present.
|
|
// if app/app.asar are missing but app.asar.bak present it will be moved to app.asar
|
|
const app_asar = path.resolve(`${folder}/app.asar`);
|
|
if (
|
|
!(
|
|
fs.pathExistsSync(folder) &&
|
|
(fs.pathExistsSync(app_asar) ||
|
|
fs.pathExistsSync(path.resolve(`${folder}/app`)))
|
|
)
|
|
) {
|
|
const asar_bak = path.resolve(`${folder}/app.asar.bak`);
|
|
if (fs.pathExistsSync(asar_bak)) {
|
|
fs.moveSync(asar_bak, app_asar);
|
|
} else
|
|
throw new EnhancerError(
|
|
'nothing found: notion installation is either corrupted or non-existent.'
|
|
);
|
|
}
|
|
return folder;
|
|
})();
|
|
|
|
// transform a wsl filepath to its relative windows filepath if necessary.
|
|
function realpath(hack_path) {
|
|
if (!is_wsl) return hack_path.replace(/\\/g, '/');
|
|
hack_path = fs.realpathSync(hack_path);
|
|
if (hack_path.startsWith('/mnt/')) {
|
|
hack_path = `${hack_path[5].toUpperCase()}:${hack_path.slice(6)}`;
|
|
} else hack_path = `//wsl$/${process.env.WSL_DISTRO_NAME}${hack_path}`;
|
|
return hack_path;
|
|
}
|
|
|
|
// lists/fetches all available extensions + themes
|
|
function getEnhancements() {
|
|
const modules = {
|
|
loaded: [],
|
|
invalid: [],
|
|
dirs: fs
|
|
.readdirSync(path.resolve(`${__dirname}/../mods`))
|
|
.filter((dir) => !dir.startsWith('.')),
|
|
IDs: [],
|
|
};
|
|
for (let dir of modules.dirs) {
|
|
try {
|
|
const mod = require(`../mods/${dir}/mod.js`);
|
|
if (!mod.tags) mod.tags = [];
|
|
if (
|
|
!mod.id ||
|
|
modules.IDs.includes(mod.id) ||
|
|
!mod.name ||
|
|
!mod.version ||
|
|
!mod.author ||
|
|
!mod.tags.every((tag) => typeof tag === 'string') ||
|
|
(mod.fonts && !mod.fonts.every((font) => typeof font === 'string')) ||
|
|
(mod.options &&
|
|
!mod.options.every((opt) =>
|
|
['toggle', 'select', 'input', 'file', 'color'].includes(opt.type)
|
|
))
|
|
)
|
|
throw Error;
|
|
mod.defaults = {};
|
|
for (let opt of mod.options || []) {
|
|
if (
|
|
Object.keys(opt.platformOverwrite || {}).some(
|
|
(platform) => process.platform === platform
|
|
)
|
|
) {
|
|
mod.defaults[opt.key] = opt.platformOverwrite[process.platform];
|
|
} else
|
|
mod.defaults[opt.key] = Array.isArray(opt.value)
|
|
? opt.value[0]
|
|
: opt.value;
|
|
}
|
|
modules.IDs.push(mod.id);
|
|
modules.loaded.push({
|
|
...mod,
|
|
dir,
|
|
});
|
|
if (!mod.tags.includes('core')) mod.alwaysActive = false;
|
|
} catch (err) {
|
|
// console.error(err);
|
|
modules.invalid.push(dir);
|
|
}
|
|
}
|
|
modules.loaded = modules.loaded.sort((a, b) => a.name.localeCompare(b.name));
|
|
const priority = require('./store.js')('mods', { priority: [] }).priority;
|
|
modules.loaded = [
|
|
...modules.loaded.filter((m) => m.tags.includes('core')),
|
|
...modules.loaded.filter(
|
|
(m) => !m.tags.includes('core') && !priority.includes(m.id)
|
|
),
|
|
...priority
|
|
.map((id) => modules.loaded.find((m) => m.id === id))
|
|
.filter((m) => m),
|
|
];
|
|
return modules;
|
|
}
|
|
|
|
// attempts to read a JSON file, falls back to empty object.
|
|
function getJSON(from) {
|
|
try {
|
|
return fs.readJsonSync(from);
|
|
} catch (err) {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
// wait for console input, returns keys when enter pressed.
|
|
function readline() {
|
|
return new Promise((res, rej) => {
|
|
process.stdin.resume();
|
|
process.stdin.setEncoding('utf8');
|
|
process.stdin.on('data', (key) => {
|
|
if (key === '\u0003') process.exit(); // CTRL+C
|
|
process.stdin.pause();
|
|
res(key.trim());
|
|
});
|
|
});
|
|
}
|
|
|
|
// construct a HTMLElement from a string
|
|
function createElement(html) {
|
|
const template = document.createElement('template');
|
|
template.innerHTML = html.trim();
|
|
return template.content.firstElementChild;
|
|
}
|
|
|
|
module.exports = {
|
|
EnhancerError,
|
|
is_wsl,
|
|
__data,
|
|
__notion,
|
|
realpath,
|
|
getEnhancements,
|
|
getJSON,
|
|
readline,
|
|
createElement,
|
|
};
|