diff --git a/package.json b/package.json
index 3ce39b3..3572b3b 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,9 @@
"dependencies": {
"classnames": "^2.3.1",
"codemirror": "^5.65.2",
+ "js-base64": "^3.7.2",
"lodash-es": "^4.17.21",
+ "pako": "^2.0.4",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0"
diff --git a/src/App.js b/src/App.js
index f6e7722..b91ceac 100644
--- a/src/App.js
+++ b/src/App.js
@@ -8,6 +8,7 @@ import styles from './App.module.css'
export default class App extends React.Component {
state = {
error: null,
+ shareUrl: null
}
componentDidMount() {
if (!window.Terser) {
@@ -16,6 +17,9 @@ export default class App extends React.Component {
})
}
}
+ onReplShareUrlChange(shareUrl) {
+ this.setState({ shareUrl })
+ }
render() {
const { error } = this.state
@@ -27,13 +31,13 @@ export default class App extends React.Component {
)
} else {
- return
+ return
}
})()
return (
-
+
{body}
)
diff --git a/src/Header.js b/src/Header.js
index 4b81664..6adfae8 100644
--- a/src/Header.js
+++ b/src/Header.js
@@ -1,20 +1,41 @@
-import React from 'react';
+import React, { useCallback, useState } from 'react';
import styles from './Header.module.css';
-const Header = () => {
+const Header = ({ shareUrl = '' }) => {
+ const [buttonText, setButtonText] = useState('Share');
+
+ const handleShareButtonClick = useCallback(async () => {
+ // update addressbar with shareUrl
+ window.history.replaceState(null, '', shareUrl)
+
+ if (!navigator.clipboard) {
+ prompt('Clipboard API is not supported in your environment. Please manually copy the following URL', shareUrl);
+ } else {
+ await navigator.clipboard.writeText(shareUrl)
+ setButtonText('URL is copied to clipboard!')
+
+ setTimeout(() => {
+ setButtonText('Share')
+ }, 3000)
+ }
+ }, [shareUrl]);
+
return (
);
diff --git a/src/Header.module.css b/src/Header.module.css
index 41f185e..dba986c 100644
--- a/src/Header.module.css
+++ b/src/Header.module.css
@@ -11,6 +11,7 @@
display: -webkit-box;
display: flex;
-webkit-box-orient: horizontal;
+ justify-content: space-between;
flex-flow: row nowrap;
align-items: center;
position: relative;
@@ -19,6 +20,18 @@
user-select: none;
}
+.container header div {
+ display: -webkit-box;
+ display: flex;
+ -webkit-box-orient: horizontal;
+ justify-content: space-between;
+ flex-flow: row nowrap;
+ align-items: center;
+ position: relative;
+ text-align: left;
+ user-select: none;
+}
+
.container header img {
border-style: none;
box-sizing: content-box;
@@ -57,3 +70,28 @@
height: 34px;
text-decoration: none;
}
+
+.container button {
+ display: inline-flex;
+ appearance: none;
+ -webkit-box-align: center;
+ align-items: center;
+ user-select: none;
+ position: relative;
+ white-space: nowrap;
+ vertical-align: middle;
+ outline: transparent solid 2px;
+ outline-offset: 2px;
+ line-height: 1.2;
+ border-radius: 6px;
+ height: 28px;
+ margin-right: 1.20%;
+ font-weight: 600;
+ min-width: 28px;
+ font-size: 15px;
+ padding-inline-start: 8px;
+ padding-inline-end: 8px;
+ background: rgba(255, 255, 255, 0.8);
+ cursor: pointer;
+ border: 0;
+}
diff --git a/src/Repl.js b/src/Repl.js
index 143525b..5602553 100644
--- a/src/Repl.js
+++ b/src/Repl.js
@@ -5,6 +5,9 @@ import CodeMirrorPanel from './CodeMirrorPanel';
import { getCodeSizeInBytes } from './lib/helpers';
import terserOptions, { evalOptions } from './lib/terser-options';
+import { gzip, ungzip } from 'pako'
+import { Base64 } from 'js-base64'
+
import styles from './Repl.module.css';
const DEBOUNCE_DELAY = 500;
@@ -64,18 +67,47 @@ class Repl extends Component {
);
}
+ componentDidMount() {
+ const url = new URL(window.location.href)
+ const encodedInput = url.searchParams.get('code')
+ const encodedOptionsCode = url.searchParams.get('options')
+
+ if (encodedOptionsCode) {
+ const decodedOptionsCode = evalOptions(ungzip(Base64.toUint8Array(encodedOptionsCode), { to: 'string' }));
+ this.setState({
+ optionsCode: decodedOptionsCode
+ })
+ this._updateTerserOptions(decodedOptionsCode);
+ }
+
+ if (encodedInput) {
+ const decodedCode = ungzip(Base64.toUint8Array(encodedInput), { to: 'string' });
+ this._updateCode(decodedCode);
+ this._minify();
+ }
+ }
+
+ _getShareUrl = (code, optionsCode) => {
+ const url = new URL(window.location.href)
+ const encodedInput = Base64.fromUint8Array(gzip(code))
+ url.searchParams.set('code', encodedInput)
+ const encodedConfig = Base64.fromUint8Array(gzip(JSON.stringify(optionsCode)))
+ url.searchParams.set('options', encodedConfig)
+ return url.toString()
+ }
+
_updateCode = code => {
this.setState({
code,
rawSize: getCodeSizeInBytes(code)
});
this._minifyToState(code);
+ this.props.onReplShareUrlChange(this._getShareUrl(code, this.state.optionsCode))
};
_updateTerserOptions = options => {
try {
const parsedOptions = evalOptions(options);
-
this.setState({
terserOptions: parsedOptions,
optionsErrorMessage: null
@@ -84,6 +116,7 @@ class Repl extends Component {
this.setState({ optionsErrorMessage: e.message });
}
+ this.props.onReplShareUrlChange(this._getShareUrl(this.state.code, options))
this._minify(this.state.code);
};
@@ -110,6 +143,8 @@ class Repl extends Component {
});
}
} catch (e) {
+ console.error(e);
+ console.log(terserOpts);
this.setState({ errorMessage: e.message });
}
};
diff --git a/yarn.lock b/yarn.lock
index 97fa871..bf919a5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5936,6 +5936,11 @@ jest@^27.4.3:
import-local "^3.0.2"
jest-cli "^27.5.1"
+js-base64@^3.7.2:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.2.tgz#816d11d81a8aff241603d19ce5761e13e41d7745"
+ integrity sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==
+
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -6786,6 +6791,11 @@ p-try@^2.0.0:
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+pako@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.4.tgz#6cebc4bbb0b6c73b0d5b8d7e8476e2b2fbea576d"
+ integrity sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==
+
param-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"