First public release
This commit is contained in:
parent
963cae3756
commit
64333fdb4a
14 changed files with 1580 additions and 0 deletions
507
static/js/app.js
Normal file
507
static/js/app.js
Normal file
|
@ -0,0 +1,507 @@
|
|||
import { h, Component, render } from '/js/preact.module.js';
|
||||
import htm from '/js/htm.module.js';
|
||||
|
||||
// Initialize htm with Preact
|
||||
const html = htm.bind(h);
|
||||
window.mitty = mitt()
|
||||
|
||||
const SVG_BATTERY_LEVEL = html`<svg style="enable-background:new 0 0 16 16" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M15 4H0v8h15V9h1V7h-1V4zm-1 3v4H1V5h13v2z"/><rect class="battery-bar-4" height="4" width="2" x="11" y="6"/><rect class="battery-bar-3" height="4" width="2" x="8" y="6"/><rect class="battery-bar-2" height="4" width="2" x="5" y="6"/><rect class="battery-bar-1" height="4" width="2" x="2" y="6"/></svg>`
|
||||
|
||||
const BATTERY_LEVEL = {
|
||||
4: 'full',
|
||||
3: 'medium',
|
||||
2: 'low',
|
||||
1: 'critical',
|
||||
0: 'critical',
|
||||
}
|
||||
|
||||
const PairingMethod = {
|
||||
DEFAULT: 'default',
|
||||
FAST: 'fast'
|
||||
}
|
||||
|
||||
const WsCommand = {
|
||||
GET_JOYCON_LIST: 'get_joycon_list',
|
||||
CONNECT_JOYCON: 'connect_joycon',
|
||||
DISCONNECT_JOYCON: 'disconnect_joycon',
|
||||
UPDATE_JOYCON_STATE: 'update_joycon_state',
|
||||
}
|
||||
|
||||
const PairingState = {
|
||||
IDLE: 0,
|
||||
GETTING_TOKEN: 1,
|
||||
PAIRING: 2,
|
||||
CONNECTING: 3,
|
||||
CONNECTED: 4,
|
||||
DISCONNECTING: 5,
|
||||
DISCONNECTED: 10,
|
||||
|
||||
ERROR_JOYCON: 101,
|
||||
ERROR_CONNECTION: 102,
|
||||
ERROR_INVALID_PAIRING_CODE: 103,
|
||||
ERROR_PUNCH_PAIRING: 104,
|
||||
ERROR_HOLE_PUNCHING: 105,
|
||||
ERROR_CONSOLE_CONNECTION: 106,
|
||||
}
|
||||
|
||||
const PairingStateMessage = {
|
||||
[PairingState.IDLE]: 'Idle',
|
||||
[PairingState.GETTING_TOKEN]: 'Getting auth token...',
|
||||
[PairingState.PAIRING]: 'Sending pairing code...',
|
||||
[PairingState.CONNECTING]: 'Connecting with console...',
|
||||
[PairingState.CONNECTED]: 'Connected!',
|
||||
[PairingState.DISCONNECTED]: 'Disconnected',
|
||||
|
||||
[PairingState.ERROR_JOYCON]: 'Joy-Con problem!',
|
||||
[PairingState.ERROR_CONNECTION]: 'Couldn\'t get auth token!',
|
||||
[PairingState.ERROR_INVALID_PAIRING_CODE]: 'Invalid pairing code!',
|
||||
[PairingState.ERROR_PUNCH_PAIRING]: 'Couldn\'t punch pairing!',
|
||||
[PairingState.ERROR_HOLE_PUNCHING]: 'Couldn\'t connect with console!',
|
||||
[PairingState.ERROR_CONSOLE_CONNECTION]: 'Couldn\'t connect with console!',
|
||||
}
|
||||
|
||||
class PairingMethodPicker extends Component {
|
||||
constructor(props) {
|
||||
super()
|
||||
this.state = {
|
||||
pairing_method: props.pairing_method,
|
||||
}
|
||||
|
||||
this.onChange = this.onChange.bind(this)
|
||||
}
|
||||
|
||||
onChange(e) {
|
||||
const pairing_method = e.target.value
|
||||
this.setState({
|
||||
pairing_method: pairing_method,
|
||||
})
|
||||
|
||||
window.mitty.emit('update_method', pairing_method)
|
||||
}
|
||||
|
||||
render(props) {
|
||||
return html`
|
||||
<label for="stacked-state">Pairing Method</label>
|
||||
<select id="stacked-state" onChange=${this.onChange} value=${props.pairing_method}>
|
||||
<option value="${PairingMethod.DEFAULT}">Default: All platforms (incl. Xbox Series/Stadia)</option>
|
||||
<option value="${PairingMethod.FAST}">Fast: Xbox One/PlayStation/Nintendo Switch</option>
|
||||
</select>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
class PrivateIpAddress extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
let lock_host = false
|
||||
let host_ip_addr = props.host_ip_addr
|
||||
let console_ip_addr = props.console_ip_addr
|
||||
|
||||
let hostname = window.location.hostname
|
||||
if (hostname.startsWith('192.168.')) {
|
||||
host_ip_addr = hostname
|
||||
lock_host = true
|
||||
}
|
||||
|
||||
this.state = {
|
||||
host_ip_addr: host_ip_addr,
|
||||
console_ip_addr: console_ip_addr,
|
||||
lock_host: lock_host,
|
||||
}
|
||||
|
||||
this.onKeyPress = this.onKeyPress.bind(this)
|
||||
this.onChange = this.onChange.bind(this)
|
||||
}
|
||||
|
||||
onChange(e) {
|
||||
const key = this.props.pairing_method == PairingMethod.DEFAULT ? 'host_ip_addr' : 'console_ip_addr'
|
||||
const value = e.target.value
|
||||
this.setState({
|
||||
[key]: value,
|
||||
})
|
||||
|
||||
window.mitty.emit('update_addr', value)
|
||||
}
|
||||
|
||||
onKeyPress(e) {
|
||||
if (!/[0-9\.]/.test(e.key)) {
|
||||
e.preventDefault()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.mitty.emit('update_addr', this.state.host_ip_addr)
|
||||
}
|
||||
|
||||
render(props, state) {
|
||||
const pairing_method = props.pairing_method
|
||||
const addr = pairing_method == PairingMethod.DEFAULT ? state.host_ip_addr : state.console_ip_addr
|
||||
return html`
|
||||
<label>
|
||||
${pairing_method == PairingMethod.DEFAULT && html`Host's Private IP Address`}
|
||||
${pairing_method == PairingMethod.FAST && html`Console's Private IP Address`}
|
||||
</label>
|
||||
|
||||
${pairing_method == PairingMethod.DEFAULT && state.lock_host && html`
|
||||
<input readonly required id="ipAddr" type="text" size="15" placeholder="${addr}" />
|
||||
`}
|
||||
|
||||
${(pairing_method == PairingMethod.FAST || !state.lock_host) && html`
|
||||
<input required id="ipAddr" type="text" inputmode="decimal" size="15" maxlength="15" placeholder="192.168.x.x" pattern="^192\\.168\\.((\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.)(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])$" value=${addr} onKeyPress=${this.onKeyPress} onChange="${this.onChange}" />
|
||||
`}
|
||||
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
class PairingCode extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
pairing_code: props.pairing_code,
|
||||
}
|
||||
|
||||
this.onChange = this.onChange.bind(this)
|
||||
}
|
||||
|
||||
onChange(e) {
|
||||
const value = e.target.value
|
||||
this.setState({
|
||||
pairing_code: value,
|
||||
})
|
||||
|
||||
window.mitty.emit('update_code', value)
|
||||
}
|
||||
|
||||
render(props, state) {
|
||||
return html`
|
||||
<label>Pairing Code</label>
|
||||
${props.pairing_method == PairingMethod.DEFAULT && html`
|
||||
<input required id="pairingCode" type="text" inputmode="decimal" value=${state.pairing_code} placeholder="000000" maxlength="6" size="6" pattern="[0-9]{6}" onKeyPress=${(e) => !/[0-9]/.test(e.key) && e.preventDefault()} onChange=${this.onChange} />
|
||||
`}
|
||||
${props.pairing_method == PairingMethod.FAST && html`
|
||||
<input type="text" id="pairingCode" value="" readonly placeholder="Not Required" size="12" />
|
||||
`}
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
class JoyCon extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.connect = this.connect.bind(this)
|
||||
this.disconnect = this.disconnect.bind(this)
|
||||
this.onStateUpdated = this.onStateUpdated.bind(this)
|
||||
|
||||
this.state = {
|
||||
...props.joycon,
|
||||
}
|
||||
|
||||
window.mitty.on('resp_' + WsCommand.DISCONNECT_JOYCON, this.onDisconnected)
|
||||
window.mitty.on('resp_' + WsCommand.UPDATE_JOYCON_STATE, this.onStateUpdated)
|
||||
}
|
||||
|
||||
connect() {
|
||||
window.mitty.emit('req_' + WsCommand.CONNECT_JOYCON, this.props.joycon.serial)
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
window.mitty.emit('req_' + WsCommand.DISCONNECT_JOYCON, this.props.joycon.serial)
|
||||
}
|
||||
|
||||
onStateUpdated(data) {
|
||||
if (data['serial'] != this.props.joycon.serial) {
|
||||
return
|
||||
}
|
||||
|
||||
const state = data['state']
|
||||
if (PairingStateMessage.hasOwnProperty(state)) {
|
||||
this.setState({
|
||||
...data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render(props, { name, state, pairing_code, is_left, color, battery_level }) {
|
||||
const joyconState = state
|
||||
const stateMessage = PairingStateMessage[joyconState]
|
||||
let showButton = true
|
||||
if ([PairingState.GETTING_TOKEN, PairingState.PAIRING, PairingState.CONNECTING].indexOf(joyconState) > -1) {
|
||||
showButton = false
|
||||
}
|
||||
|
||||
let joyconSvg
|
||||
if (is_left) {
|
||||
joyconSvg = html`<svg class="joycon-color" viewBox="0 0 171 453" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd"><path d="M219.594 33.518v412.688c0 1.023-.506 1.797-1.797 1.797h-49.64c-51.68 0-85.075-45.698-85.075-85.075V114.987c0-57.885 56.764-84.719 84.719-84.719h48.79c2.486 0 3.003 1.368 3.003 3.25zm-32.123 105.087c0 17.589-14.474 32.062-32.063 32.062-17.589 0-32.062-14.473-32.062-32.062s14.473-32.063 32.062-32.063 32.063 14.474 32.063 32.063z" style="fill:${color};stroke:#000;stroke-width:8.33px" transform="translate(-65.902 -13.089)"/></svg>`
|
||||
} else {
|
||||
joyconSvg = html`<svg class="joycon-color" viewBox="0 0 171 453" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd"><path d="M324.763 40.363v412.688c0 1.023.506 1.797 1.797 1.797h49.64c51.68 0 85.075-45.698 85.075-85.075V121.832c0-6.774-.777-13.123-2.195-19.054-10.696-44.744-57.841-65.665-82.524-65.665h-48.79c-2.486 0-3.003 1.368-3.003 3.25zm96 218.094c0 17.589-14.473 32.063-32.062 32.063s-32.063-14.474-32.063-32.063c0-17.589 14.474-32.062 32.063-32.062 17.589 0 32.062 14.473 32.062 32.062z" style="fill:${color};fill-rule:nonzero;stroke:#000;stroke-width:8.33px" transform="translate(-307.583 -19.934)"/></svg>`
|
||||
}
|
||||
|
||||
const batteryLevel = BATTERY_LEVEL[battery_level]
|
||||
|
||||
return html`
|
||||
<li>
|
||||
<div class="pure-g">
|
||||
|
||||
<div class="pure-u-2-24 flex">${joyconSvg}</div>
|
||||
<div class="pure-u-12-24 joycon-info">
|
||||
<div class="flex">
|
||||
<span class="joycon-name">${name}</span>
|
||||
<span class="battery-level ${batteryLevel}">${SVG_BATTERY_LEVEL}</span>
|
||||
</div>
|
||||
<span class="joycon-state">${stateMessage}</span>
|
||||
</div>
|
||||
<div class="pure-u-4-24 flex">
|
||||
${pairing_code && html`
|
||||
<span class="pairing-code">${pairing_code}</span>
|
||||
`}
|
||||
</div>
|
||||
<div class="pure-u-6-24">
|
||||
${showButton && joyconState == PairingState.CONNECTED && html`
|
||||
<button type="button" onClick=${this.disconnect} class="pure-button pure-button-error">Disconnect</button>
|
||||
`}
|
||||
${showButton && joyconState != PairingState.CONNECTED && html`
|
||||
<button type="button" onClick=${this.connect} class="pure-button pure-button-primary">Connect</button>
|
||||
`}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
class JoyCons extends Component {
|
||||
constructor() {
|
||||
super()
|
||||
this.state = {
|
||||
isRefreshing: false,
|
||||
}
|
||||
|
||||
this.refreshJoyconList = this.refreshJoyconList.bind(this)
|
||||
}
|
||||
|
||||
refreshJoyconList() {
|
||||
this.setState({
|
||||
isRefreshing: false,
|
||||
})
|
||||
window.mitty.emit('req_' + WsCommand.GET_JOYCON_LIST)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
}
|
||||
|
||||
render(props, state) {
|
||||
return html`
|
||||
<div class="pure-g">
|
||||
<h2 class="pure-u-18-24">Joy-Cons</h2>
|
||||
${state.isRefreshing && html`
|
||||
<button type="button" disabled class="pure-button btn-refresh pure-u-6-24">Refresh</a>
|
||||
`}
|
||||
${!state.isRefreshing && html`
|
||||
<button type="button" class="pure-button btn-refresh pure-u-6-24" onClick=${this.refreshJoyconList}>Refresh</button>
|
||||
`}
|
||||
</div>
|
||||
<div class="joycons-wrapper">
|
||||
${props.joycons.length == 0 && html`
|
||||
<p class="empty">No Joy-Cons found!</p>
|
||||
`}
|
||||
|
||||
|
||||
${props.joycons.length > 0 && html`
|
||||
<ul class="joycons-list">
|
||||
${props.joycons.map(item => (
|
||||
html`<${JoyCon} joycon=${item} key=${item.serial} />`
|
||||
))}
|
||||
</ul>
|
||||
`}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
super()
|
||||
|
||||
this.state = {
|
||||
pairing_method: window.CONFIG.pairing_method,
|
||||
host_ip_addr: window.CONFIG.host_ip_addr,
|
||||
console_ip_addr: window.CONFIG.console_ip_addr,
|
||||
pairing_code: window.CONFIG.pairing_code,
|
||||
joycons: [],
|
||||
}
|
||||
|
||||
this.connectWs = this.connectWs.bind(this)
|
||||
this.sendRequest = this.sendRequest.bind(this)
|
||||
this.requestGetJoyconList = this.requestGetJoyconList.bind(this)
|
||||
this.requestConnectJoycon = this.requestConnectJoycon.bind(this)
|
||||
this.requestDisconnectJoycon = this.requestDisconnectJoycon.bind(this)
|
||||
this.handleMethodChange = this.handleMethodChange.bind(this)
|
||||
this.handleAddrChange = this.handleAddrChange.bind(this)
|
||||
this.handleCodeChange = this.handleCodeChange.bind(this)
|
||||
|
||||
window.mitty.on('req_' + WsCommand.GET_JOYCON_LIST, this.requestGetJoyconList)
|
||||
window.mitty.on('req_' + WsCommand.CONNECT_JOYCON, this.requestConnectJoycon)
|
||||
window.mitty.on('req_' + WsCommand.DISCONNECT_JOYCON, this.requestDisconnectJoycon)
|
||||
window.mitty.on('update_method', this.handleMethodChange)
|
||||
window.mitty.on('update_addr', this.handleAddrChange)
|
||||
window.mitty.on('update_code', this.handleCodeChange)
|
||||
}
|
||||
|
||||
sendRequest(cmd, data) {
|
||||
if (!data) {
|
||||
data = {}
|
||||
}
|
||||
const msg = {
|
||||
cmd: cmd,
|
||||
data: data,
|
||||
}
|
||||
console.log('send', msg)
|
||||
this.socket.send(JSON.stringify(msg))
|
||||
}
|
||||
|
||||
requestGetJoyconList() {
|
||||
this.sendRequest(WsCommand.GET_JOYCON_LIST);
|
||||
}
|
||||
|
||||
requestConnectJoycon(serial) {
|
||||
const state = this.state
|
||||
const pairing_method = state.pairing_method
|
||||
let addr = pairing_method == PairingMethod.DEFAULT ? state.host_ip_addr : state.console_ip_addr
|
||||
if (!addr.match(/^192\.168\.((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.)(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/)) {
|
||||
alert('ERROR: Invalid IP address!')
|
||||
document.getElementById('ipAddr').focus()
|
||||
return
|
||||
}
|
||||
|
||||
if (pairing_method == PairingMethod.DEFAULT) {
|
||||
const pairing_code = state.pairing_code
|
||||
if (!pairing_code.match(/^\d{6}$/)) {
|
||||
alert('ERROR: Invalid pairing code!')
|
||||
document.getElementById('pairingCode').focus()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.sendRequest(WsCommand.CONNECT_JOYCON, {
|
||||
pairing_method: state.pairing_method,
|
||||
host_ip_addr: state.host_ip_addr,
|
||||
console_ip_addr: state.console_ip_addr,
|
||||
pairing_code: state.pairing_code,
|
||||
joycon_serial: serial,
|
||||
})
|
||||
}
|
||||
|
||||
requestDisconnectJoycon(serial) {
|
||||
this.sendRequest(WsCommand.DISCONNECT_JOYCON, {
|
||||
joycon_serial: serial,
|
||||
})
|
||||
}
|
||||
|
||||
connectWs() {
|
||||
const that = this
|
||||
this.socket = new WebSocket('ws://' + window.location.host + '/ws')
|
||||
|
||||
this.socket.onopen = function(e) {
|
||||
console.log('[open] Connection established')
|
||||
that.requestGetJoyconList()
|
||||
}
|
||||
|
||||
this.socket.onmessage = function(event) {
|
||||
const msg = JSON.parse(event.data)
|
||||
console.log(msg)
|
||||
const cmd = msg['cmd']
|
||||
const shortCmd = msg['cmd'].slice(5) // Remove "resp_" prefix
|
||||
|
||||
switch (shortCmd) {
|
||||
case WsCommand.GET_JOYCON_LIST:
|
||||
that.setState({
|
||||
joycons: msg['data'],
|
||||
})
|
||||
break
|
||||
|
||||
default:
|
||||
window.mitty.emit(cmd, msg['data'])
|
||||
}
|
||||
}
|
||||
|
||||
this.socket.onclose = function(event) {
|
||||
if (event.wasClean) {
|
||||
console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
|
||||
} else {
|
||||
console.log('[close] Connection died');
|
||||
}
|
||||
}
|
||||
|
||||
this.socket.onerror = function(error) {
|
||||
console.log(`[error] ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
handleMethodChange(pairing_method) {
|
||||
this.setState({
|
||||
pairing_method: pairing_method,
|
||||
})
|
||||
}
|
||||
|
||||
handleAddrChange(addr) {
|
||||
const key = this.state.pairing_method == PairingMethod.DEFAULT ? 'host_ip_addr' : 'console_ip_addr'
|
||||
this.setState({
|
||||
[key]: addr,
|
||||
})
|
||||
}
|
||||
|
||||
handleCodeChange(pairing_code) {
|
||||
this.setState({
|
||||
pairing_code: pairing_code,
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.connectWs()
|
||||
}
|
||||
|
||||
render(props, state) {
|
||||
return html`
|
||||
<div class="container">
|
||||
<div class="ascii">
|
||||
<pre> ░░ ░░░░░░ ░░ ░░ ░░░░░░ ░░░░░ ░░░ ░░ ░░░░░░ ░░░░░░░
|
||||
▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒▒▒ ▒▒ ▒▒ ▒▒
|
||||
▒▒ ▒▒ ▒▒ ▒▒▒▒ ▒▒ ▒▒ ▒▒▒▒▒▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒▒▒▒
|
||||
▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓
|
||||
█████ ██████ ██ ██████ ██ ██ ██ ████ ██████ ███████
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<form class="pure-form pure-form-stacked">
|
||||
<fieldset>
|
||||
<div class="pure-g">
|
||||
<h2 class="pure-u-1">Config</h2>
|
||||
<div class="pure-u-1">
|
||||
<${PairingMethodPicker} pairing_method=${state.pairing_method}/>
|
||||
</div>
|
||||
<div class="pure-u-1-2">
|
||||
<${PrivateIpAddress} pairing_method=${state.pairing_method} host_ip_addr=${state.host_ip_addr} console_ip_addr=${state.console_ip_addr} />
|
||||
</div>
|
||||
<div class="pure-u-1-2">
|
||||
<${PairingCode} pairing_method=${state.pairing_method} pairing_code=${state.pairing_code} />
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<div class="pure-u-1 joycons">
|
||||
<${JoyCons} pairing_method=${state.pairing_method} joycons=${state.joycons} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<a href="https://github.com/redphx/joydance" target="_blank">${window.VERSION}</a>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
render(html`<${App} />`, document.body)
|
1
static/js/htm.module.js
Normal file
1
static/js/htm.module.js
Normal file
|
@ -0,0 +1 @@
|
|||
var n = function (t, s, r, e) {var u;s[0] = 0;for (var h = 1; h < s.length; h++) {var p = s[h++],a = s[h] ? (s[0] |= p ? 1 : 2, r[s[h++]]) : s[++h];3 === p ? e[0] = a : 4 === p ? e[1] = Object.assign(e[1] || {}, a) : 5 === p ? (e[1] = e[1] || {})[s[++h]] = a : 6 === p ? e[1][s[++h]] += a + "" : p ? (u = t.apply(a, n(t, a, r, ["", null])), e.push(u), a[0] ? s[0] |= 2 : (s[h - 2] = 0, s[h] = u)) : e.push(a);}return e;},t = new Map();export default function (s) {var r = t.get(this);return r || (r = new Map(), t.set(this, r)), (r = n(this, r.get(s) || (r.set(s, r = function (n) {for (var t, s, r = 1, e = "", u = "", h = [0], p = function (n) {1 === r && (n || (e = e.replace(/^\s*\n\s*|\s*\n\s*$/g, ""))) ? h.push(0, n, e) : 3 === r && (n || e) ? (h.push(3, n, e), r = 2) : 2 === r && "..." === e && n ? h.push(4, n, 0) : 2 === r && e && !n ? h.push(5, 0, !0, e) : r >= 5 && ((e || !n && 5 === r) && (h.push(r, 0, e, s), r = 6), n && (h.push(r, n, 0, s), r = 6)), e = "";}, a = 0; a < n.length; a++) {a && (1 === r && p(), p(a));for (var l = 0; l < n[a].length; l++) t = n[a][l], 1 === r ? "<" === t ? (p(), h = [h], r = 3) : e += t : 4 === r ? "--" === e && ">" === t ? (r = 1, e = "") : e = t + e[0] : u ? t === u ? u = "" : e += t : '"' === t || "'" === t ? u = t : ">" === t ? (p(), r = 1) : r && ("=" === t ? (r = 5, s = e, e = "") : "/" === t && (r < 5 || ">" === n[a][l + 1]) ? (p(), 3 === r && (h = h[0]), r = h, (h = h[0]).push(2, 0, r), r = 0) : " " === t || "\t" === t || "\n" === t || "\r" === t ? (p(), r = 2) : e += t), 3 === r && "!--" === e && (r = 4, h = h[0]);}return p(), h;}(s)), r), arguments, [])).length > 1 ? r : r[0];}
|
1
static/js/mitt.umd.js
Normal file
1
static/js/mitt.umd.js
Normal file
|
@ -0,0 +1 @@
|
|||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).mitt=n()}(this,function(){return function(e){return{all:e=e||new Map,on:function(n,t){var f=e.get(n);f?f.push(t):e.set(n,[t])},off:function(n,t){var f=e.get(n);f&&(t?f.splice(f.indexOf(t)>>>0,1):e.set(n,[]))},emit:function(n,t){var f=e.get(n);f&&f.slice().map(function(e){e(t)}),(f=e.get("*"))&&f.slice().map(function(e){e(n,t)})}}}});
|
1
static/js/preact.module.js
Normal file
1
static/js/preact.module.js
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue