Hi, it's Takuya.
I'm publishing YouTube content, sharing my dev workflows.
Want a side-by-side preview in a terminal app
For web coding tutorials, it'd be great to show your coding and output side-by-side.
Typically, you would do that by simply arranging two windows: An editor and a browser.
But that's annoying because every time you make a tutorial, you have to align the windows side-by-side.
Hyper, a terminal app built with web standards, once had a built-in webview feature:
As you can see above, it displays a preview on the right side of the terminal window.
It looks pretty neat.
So, you can make tutorials without having a separate window for preview.
But it looks like the feature has been removed for security reasons:
It was 3 years ago, a quite old issue.
I understand the risk of loading web pages in Electron apps.
However, webview
of the recent Electron prohibits NodeJS integration by default. So, I think it's safe to embed in Hyper, especially when you understand what you do.
Hacking Hyper to get back the built-in webview feature
So, I decided to get that feature back to Hyper, and successfully did it.
Here is how it looks like:
Demo video:
How to build
I've made built-in-webview
branch for the hack:
https://github.com/craftzdog/hyper/tree/built-in-webview
Clone this repo and built it yourself as following.
npm i
npm run dev
# On another terminal session
npm run app
How to use
Split the window right by pressing Cmd-D
.
Then, type echo <URL-to-open>
and hit Return
.
Click the URL in the terminal.
Then, the pane becomes a webview that loads the URL.
How I hacked Hyper
Check out the diffs
First, you have to allow webview
tags in app/ui/window.ts
:
const winOpts: BrowserWindowConstructorOptions = {
minWidth: 370,
minHeight: 190,
backgroundColor: toElectronBackgroundColor(cfg.backgroundColor || '#000'),
titleBarStyle: 'hiddenInset',
title: 'Hyper.app',
// we want to go frameless on Windows and Linux
frame: process.platform === 'darwin',
transparent: process.platform === 'darwin',
icon,
show: Boolean(process.env.HYPER_DEBUG || process.env.HYPERTERM_DEBUG || isDev),
acceptFirstMouse: true,
webPreferences: {
nodeIntegration: true,
navigateOnDragDrop: true,
enableRemoteModule: true,
- contextIsolation: false
+ contextIsolation: false,
+ webviewTag: true
},
...options_
};
Hyper partially remains the old implementations. You can reuse them.
The terminal component already has url
prop.
You can display webview
when the component has url
prop.
In lib/components/term.tsx
, change the terminal component class like so:
@@ -430,18 +436,35 @@ export default class Term extends React.PureComponent<TermProps> {
style={{padding: this.props.padding}}
onMouseUp={this.onMouseUp}
>
- {this.props.customChildrenBefore}
- <div ref={this.onTermWrapperRef} className="term_fit term_wrapper" />
- {this.props.customChildren}
- {this.props.search ? (
- <SearchBox
- search={this.search}
- next={this.searchNext}
- prev={this.searchPrevious}
- close={this.closeSearchBox}
+ {this.props.url ? (
+ <webview
+ src={this.props.url}
+ style={{
+ background: '#fff',
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ display: 'inline-flex',
+ width: '100%',
+ height: '100%'
+ }}
/>
) : (
- ''
+ <>
+ {this.props.customChildrenBefore}
+ <div ref={this.onTermWrapperRef} className="term_fit term_wrapper" />
+ {this.props.customChildren}
+ {this.props.search ? (
+ <SearchBox
+ search={this.search}
+ next={this.searchNext}
+ prev={this.searchPrevious}
+ close={this.closeSearchBox}
+ />
+ ) : (
+ ''
+ )}
+ </>
)}
<style jsx global>{`
And, change the URL click handler to dispatch an action instead of opening up the page in an external browser:
@@ -160,7 +160,13 @@ export default class Term extends React.PureComponent<TermProps> {
this.term.loadAddon(
new WebLinksAddon(
(event: MouseEvent | undefined, uri: string) => {
- if (shallActivateWebLink(event)) void shell.openExternal(uri);
+ // if (shallActivateWebLink(event)) void shell.openExternal(uri);
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+ store.dispatch({
+ type: 'SESSION_URL_SET',
+ uid: props.uid,
+ url: uri
+ });
},
{
// prevent default electron link handling to allow selection, e.g. via double-click
In lib/reducers/sessions.ts
, add the reducer for SESSION_URL_SET
like so:
@@ -11,7 +11,8 @@ import {
SESSION_SET_XTERM_TITLE,
SESSION_SET_CWD,
SESSION_SEARCH,
- SESSION_SEARCH_CLOSE
+ SESSION_SEARCH_CLOSE,
+ SESSION_URL_SET
} from '../constants/sessions';
import {sessionState, session, Mutable, ISessionReducer} from '../hyper';
@@ -129,6 +130,9 @@ const reducer: ISessionReducer = (state = initialState, action) => {
}
return state;
+ case SESSION_URL_SET:
+ return state.setIn(['sessions', action.uid, 'url'], action.url);
+
default:
return state;
}
It works like a charm!
Follow me online
- Check out my app called Inkdrop - A Markdown note-taking app
- Subscribe Newsletter http://eepurl.com/dNgJo6
- Twitter https://twitter.com/inkdrop_app
- YouTube channel https://youtube.com/c/devaslife
- Blog https://blog.inkdrop.app/
- Discord community https://discord.gg/QfsG5Kj
- Instagram https://instagram.com/craftzdog
Top comments (15)
Was looking for this after I saw the YouTube video and it is awesome, will do this and see how it goes, coding on terminal hard tho ๐
yeah lol. hope it's helpful for your videos
Seguir seu tutorial, mas quando rodo o comando "npm run app" ou "yarn run app" recebo esse erro. Utilizo ubuntu linux.
Error launching app
Unable to find Electron app at /home/antonio/hyper/target
Cannot find module '/home/antonio/hyper/target'
Require stack:
- /home/antonio/hyper/node_modules/electron/dist/resources/default_app.asar/main.js
for who ever fail to compile try to disable typescript check
with put
// @ts-nocheck
at the top levelto all over error file that printed when run dev, because it used old version and we just want the feature so i think is fair. Then after notice run dev got no error u safe to go with run app. Hopes help y'all have a nice day!
And for windows it should works fine or you can build by ur self it maybe just a little confusing for some newcomers but do a little bit research and it will solved.
I have problems with the dependencies as I have 23 vulnerabilities and I tried to solve them but I could not, someone could or there is a tutorial on youtube?

hello,
for windows ?
did you get it to work for windows?
Hello Mr. Takuya,
please tell me how can I compile this exe for Windows?
Please help me....
I could compile it on mac node v: 18 everything works grea
t
What version of node did you use?
Did you ever figure out how to get it on windows?
Dev mode works, but the error "store" is not found. I also get an error trying to package the binary file.
(window as any).store did the trick for me
What was the node version when the changes were node. Cannot get it running.
Did anyone have trying it on Ubuntu and works? Wondering how to make it work since I can't install it properly, got node-pty error