Skip to content

Commit

Permalink
feat(#103): open at scroll on same tab
Browse files Browse the repository at this point in the history
  • Loading branch information
jannis-baum committed Jul 23, 2024
1 parent 1c1a5ab commit fed6722
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 46 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"@viz-js/viz": "^3.7.0",
"ansi_up": "^6.0.2",
"axios": "^1.7.2",
"express": "^4.19.2",
"glob": "10.4.5",
"highlight.js": "^11.10.0",
Expand Down
44 changes: 2 additions & 42 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { createServer, get } from 'http';
import { resolve as presolve } from 'path';

import express from 'express';
import open from 'open';

import config from './parser/config.js';
import { router as healthRouter } from './routes/health.js';
import { router as staticRouter } from './routes/static.js';
import { router as viewerRouter } from './routes/viewer.js';
import { setupSockets } from './sockets.js';
import { pathToURL, preferredPath, urlToPath } from './utils/path.js';
import { existsSync } from 'fs';
import { urlToPath } from './utils/path.js';
import { address, handleArgs } from './cli.js';

const app = express();
app.use(express.json());
Expand Down Expand Up @@ -39,44 +37,6 @@ export const { clientsAt, messageClients } = setupSockets(
},
);

const address = `http://localhost:${config.port}`;
const handleArgs = async () => {
try {
const args = process.argv.slice(2);
const options = args.filter((arg) => arg.startsWith('-'));
for (const option of options) {
switch (option) {
case '-v':
case '--version':
console.log(`vivify-server ${process.env.VERSION ?? 'dev'}`);
break;
default:
console.log(`unknown option "${option}"`);
}
}

const paths = args.filter((arg) => !arg.startsWith('-'));
await Promise.all(
paths.map(async (path) => {
if (!existsSync(path)) {
console.log(`File not found: ${path}`);
return;
}
const target = preferredPath(presolve(path));
const url = `${address}${pathToURL(target)}`;
await open(url);
}),
);
} finally {
if (process.env['NODE_ENV'] !== 'development') {
// - viv executable waits for this string and then stops printing
// vivify-server's output and terminates
// - the string itself is not shown to the user
console.log('STARTUP COMPLETE');
}
}
};

get(`${address}/health`, async () => {
// server is already running
await handleArgs();
Expand Down
82 changes: 82 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { existsSync } from 'fs';
import { resolve as presolve } from 'path';
import config from './parser/config.js';
import open from 'open';
import { pathToURL, preferredPath } from './utils/path.js';
import axios from 'axios';

export const address = `http://localhost:${config.port}`;

const openTarget = async (path: string, scroll: string | undefined) => {
// scroll position is zero-char seperated because that
// character is not allowed in file paths
if (!existsSync(path)) {
console.error(`File not found: ${path}`);
return;
}

const absolutePath = pathToURL(presolve(path));
const absoluteURL = `${address}/viewer${absolutePath}`;
const preferredURL = `${address}/viewer${preferredPath(absolutePath)}`;
// if scroll position is provided
if (scroll !== undefined) {
// we send scroll request to clients
const {
data: { clients },
} = await axios.post<{ clients: number }>(absoluteURL, {
cursor: scroll,
});
// if there were clients, we can just open the plain
// URL/existing tab because it will have scrolled
if (!clients) {
// if not we open a new tab at the scroll position
await open(preferredURL + `?cursor=${scroll}`);
return;
}
}
await open(preferredURL, { newInstance: false });
};

export const handleArgs = async () => {
try {
const args = process.argv.slice(2);
const parsed: { target?: string; scroll?: string } = {};
const setArg = (arg: keyof typeof parsed, value: string) => {
if (parsed[arg]) {
console.error(`Duplicate argument for "${arg}", skipping`);
} else {
parsed[arg] = value;
}
};

for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (!arg.startsWith('-')) {
setArg('target', arg);
continue;
}
switch (arg) {
case '-v':
case '--version':
console.log(`vivify-server ${process.env.VERSION ?? 'dev'}`);
break;
case '-s':
case '--scroll':
setArg('scroll', args[++i]);
break;
default:
console.log(`Unknown option "${arg}"`);
}
}
if (parsed.target) {
await openTarget(parsed.target, parsed.scroll);
}
} finally {
if (process.env['NODE_ENV'] !== 'development') {
// - viv executable waits for this string and then stops printing
// vivify-server's output and terminates
// - the string itself is not shown to the user
console.log('STARTUP COMPLETE');
}
}
};
2 changes: 1 addition & 1 deletion src/routes/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const pageTitle = (path: string) => {
if (config.preferHomeTilde) {
router.use((req, res, next) => {
if (req.method === 'GET' && req.path.startsWith(homedir())) {
res.redirect(req.baseUrl + req.path.replace(homedir(), '/~'));
res.redirect(req.originalUrl.replace(homedir(), '/~'));
} else {
next();
}
Expand Down
4 changes: 2 additions & 2 deletions viv
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/bin/sh

print_usage() {
echo "viv [--help] files/directories"
echo "View files/directories in browser and lazily start vivify-server"
echo "viv [--help] file/directory"
echo "View file/directory in browser and lazily start vivify-server"
}

if [ "$#" -lt 1 -o "$1" = "-h" -o "$1" = "--help" ]; then
Expand Down
47 changes: 46 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,20 @@ array-union@^2.1.0:
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==

asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==

axios@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621"
integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==
dependencies:
follow-redirects "^1.15.6"
form-data "^4.0.0"
proxy-from-env "^1.1.0"

balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
Expand Down Expand Up @@ -856,6 +870,13 @@ colorette@^2.0.14:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==

combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"

commander@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
Expand Down Expand Up @@ -961,6 +982,11 @@ define-lazy-prop@^3.0.0:
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f"
integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==

delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==

depd@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
Expand Down Expand Up @@ -1331,6 +1357,11 @@ flatted@^3.2.9:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==

follow-redirects@^1.15.6:
version "1.15.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==

foreground-child@^3.1.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7"
Expand All @@ -1339,6 +1370,15 @@ foreground-child@^3.1.0:
cross-spawn "^7.0.0"
signal-exit "^4.0.1"

form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"

forwarded@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
Expand Down Expand Up @@ -1855,7 +1895,7 @@ mime-db@1.52.0:
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==

mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34:
mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
Expand Down Expand Up @@ -2120,6 +2160,11 @@ proxy-addr@~2.0.7:
forwarded "0.2.0"
ipaddr.js "1.9.1"

proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==

pstree.remy@^1.1.8:
version "1.1.8"
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a"
Expand Down

0 comments on commit fed6722

Please sign in to comment.