-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add comment in index.html.tmpl #750
base: refactor/extract-scripting-api
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import * as log from 'loglevel'; | ||
import ExternalInterface, {ExternalInterfaceCtx} from './util/ExternalInterface'; | ||
import Vienna from './folding/Vienna'; | ||
import Vienna2 from './folding/Vienna2'; | ||
import NuPACK from './folding/NuPACK'; | ||
import Contrafold from './folding/Contrafold'; | ||
import EternaFold from './folding/Eternafold'; | ||
import EternaFoldThreshknot from './folding/EternafoldThreshknot'; | ||
import RNAFoldBasic from './folding/RNAFoldBasic'; | ||
import FolderManager from './folding/FolderManager'; | ||
import LinearFoldC from './folding/LinearFoldC'; | ||
import LinearFoldE from './folding/LinearFoldE'; | ||
import LinearFoldV from './folding/LinearFoldV'; | ||
import Folder from './folding/Folder'; | ||
import FoldingAPI from './eternaScript/FoldingAPI'; | ||
import addSelectFolderAPIToInterface from './eternaScript/SelectFolderAPI'; | ||
|
||
interface FoldingAppParams { | ||
containerID?: string; | ||
folderName?: string; | ||
} | ||
|
||
interface ProcessedFoldingAppParams { | ||
containerID: string; | ||
folderName: string; | ||
} | ||
|
||
export class WasmNotSupportedError extends Error {} | ||
|
||
export class ContainerElementNotFound extends Error {} | ||
|
||
/** | ||
* Entry point for the folding API provider. | ||
* | ||
* This is an alternate version of EternaJS, only exposing the API needed for scripts to work | ||
* (e.g. `Lib.fold` via `document.getElementById("maingame").fold`). | ||
* */ | ||
export default class FoldingAPIApp { | ||
constructor(params: FoldingAppParams) { | ||
// Default param values | ||
params.containerID = params.containerID || 'maingame'; | ||
params.folderName = 'vienna'; | ||
|
||
this._params = {containerID: params.containerID, folderName: params.folderName}; | ||
|
||
const appContainer: HTMLElement | null = document.getElementById(params.containerID); | ||
if (!appContainer) { | ||
throw new ContainerElementNotFound(`Could not find HTML element with ID ${params.containerID}`); | ||
} | ||
this._appContainer = appContainer; | ||
|
||
ExternalInterface.init(appContainer); | ||
} | ||
|
||
private static isWebAssemblySupported() { | ||
return typeof WebAssembly === 'object'; | ||
} | ||
|
||
public async run(): Promise<void> { | ||
if (!FoldingAPIApp.isWebAssemblySupported()) { | ||
throw new WasmNotSupportedError( | ||
"Can't initialize the folding API app, since the browser doesn't support WASM" | ||
); | ||
} | ||
|
||
await this.initFoldingEngines(); | ||
this.initScriptInterface(); | ||
} | ||
|
||
public disposeNow(): void { | ||
this._appContainer.innerHTML = ''; | ||
|
||
FolderManager.dispose(); | ||
ExternalInterface.dispose(); | ||
} | ||
|
||
private async initFoldingEngines(): Promise<void> { | ||
log.info('Initializing folding engines...'); | ||
const folders: (Folder | null)[] = await Promise.all([ | ||
Vienna.create(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Folders duplication with |
||
Vienna2.create(), | ||
NuPACK.create(), | ||
LinearFoldC.create(), | ||
LinearFoldE.create(), | ||
LinearFoldV.create(), | ||
Contrafold.create(), | ||
EternaFold.create(), | ||
EternaFoldThreshknot.create(), | ||
RNAFoldBasic.create()]); | ||
|
||
log.info('Folding engines intialized'); | ||
for (const folder of folders) { | ||
if (folder !== null) { | ||
FolderManager.instance.addFolder(folder); | ||
} | ||
} | ||
|
||
const folder = FolderManager.instance.getFolder(this._params.folderName); | ||
if (folder === null) { | ||
log.warn(`No such folder '${this._params.folderName}'`); | ||
} else { | ||
this._folder = folder; | ||
} | ||
} | ||
|
||
private trySelectFolder(folderName: string): boolean { | ||
const folder = FolderManager.instance.getFolder(folderName); | ||
if (folder === null) { | ||
log.warn(`No such folder '${this._params.folderName}'`); | ||
return false; | ||
} else { | ||
return true; | ||
} | ||
} | ||
|
||
private initScriptInterface(): void { | ||
new FoldingAPI({ | ||
getFolder: () => this._folder, | ||
getIsPseudoknot: () => false | ||
}).registerToScriptInterface(this._scriptInterface); | ||
addSelectFolderAPIToInterface({ | ||
selectFolder: (folderName) => this.trySelectFolder(folderName), | ||
scriptInterface: this._scriptInterface | ||
}); | ||
|
||
ExternalInterface.pushContext(this._scriptInterface); | ||
} | ||
|
||
private readonly _params: ProcessedFoldingAppParams; | ||
private readonly _scriptInterface: ExternalInterfaceCtx = new ExternalInterfaceCtx(); | ||
private readonly _appContainer: HTMLElement; | ||
private _folder: Folder; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import * as log from 'loglevel'; | ||
import EternaApp from 'eterna/EternaApp'; | ||
import FoldingAPIApp from 'eterna/FoldingAPIApp'; | ||
import * as PIXI from 'pixi.js'; | ||
|
||
const isProduction = process.env.NODE_ENV === 'production'; | ||
|
@@ -8,9 +9,11 @@ log.setLevel(isProduction ? 'info' : 'trace'); | |
declare global { | ||
interface Window { | ||
EternaApp: typeof EternaApp; | ||
FoldingAPIApp: typeof FoldingAPIApp; | ||
app: EternaApp; // this syntax is used in index.html.tmpl, at least... | ||
__PIXI_APP__?: PIXI.Application; | ||
} | ||
} | ||
|
||
window.EternaApp = EternaApp; | ||
window.FoldingAPIApp = FoldingAPIApp; | ||
Comment on lines
+12
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally I'd use a different |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<!DOCTYPE html> | ||
<html style="height: 100%;"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> | ||
<title>EternaJS</title> | ||
|
||
<!-- | ||
These scripts are all grabbed from https://github.com/EteRNAgame/website/tree/master/frontend | ||
--> | ||
|
||
<link type="text/css" rel="stylesheet" media="all" href="./frontend/themes/css/eterna.css" /> | ||
|
||
<script> | ||
// The Coffeescript code exposes a Comment object, which clobbers a browser global, which we do not use, | ||
// but the browser global is used by DOMPurify | ||
__comment_bak = Comment; | ||
</script> | ||
|
||
<script src="./frontend/jscripts/jquery/jquery-1.7.2.min.js"></script> | ||
<script src="./frontend/jscripts/jquery/jquery-unselectable.js"></script> | ||
<script src="./frontend/jscripts/jquery-ui/jquery-ui-1.8.7.custom.min.js"></script> | ||
<script src="./frontend/jscripts/json/json2.js"></script> | ||
|
||
<script src="./frontend/jscripts/application.js"></script> | ||
<script src="./frontend/jscripts/utils.js"></script> | ||
<script src="./frontend/jscripts/ajaxmanager.js"></script> | ||
<script src="./frontend/jscripts/datamanager.js"></script> | ||
<script src="./frontend/jscripts/usermanager.js"></script> | ||
|
||
<script src="./frontend/jscripts/eterna/eterna-application.js"></script> | ||
<script src="./frontend/jscripts/eterna/eterna-utils.js"></script> | ||
<script src="./frontend/jscripts/eterna/script-library.js"></script> | ||
<script src="./frontend/jscripts/eterna/script-interface.js"></script> | ||
<script src="./frontend/jscripts/eterna/presenter.js"></script> | ||
Comment on lines
+20
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure which of these is necessary - I would rather not have all of them in the script editor |
||
|
||
<script> | ||
// The Coffeescript code exposes a Comment object, which clobbers a browser global, which we do not use, | ||
// but the browser global is used by DOMPurify | ||
Comment = __comment_bak; | ||
</script> | ||
</head> | ||
<body style="margin: 0; padding: 0; height: 100%; display: flex; flex-direction: column;"> | ||
|
||
<!-- Scripts expect that an element with "maingame" will exist, so this name shouldn't be changed --> | ||
<div id="maingame"></div> | ||
|
||
<!-- Load our webpack bundles --> | ||
<%= htmlWebpackPlugin.tags.bodyTags %> | ||
|
||
<script> | ||
// Wrapping the code in a function to prevent variables from leaking into the global scope. | ||
(() => { | ||
Application.GET_URI = "<%= htmlWebpackPlugin.options.process.env.APP_SERVER_URL %>/get/"; | ||
Application.POST_URI = "<%= htmlWebpackPlugin.options.process.env.APP_SERVER_URL %>/post/"; | ||
|
||
const params = new URLSearchParams(window.location.search); | ||
const containerID = "maingame"; | ||
|
||
const app = new FoldingAPIApp({ | ||
containerID: containerID, | ||
folderName: params.get("folder"), | ||
}) | ||
|
||
app.run(); | ||
|
||
window.stopApp = () => { | ||
app.disposeNow(); | ||
} | ||
})(); | ||
</script> | ||
</body> | ||
</html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided to leave handling this error to the Vue app trying to import it. Does it make sense?
Currently it wouldn't propagate to the vue app because of how I used it in
folding-api.html.tmpl