archematics/src/giveAwrl.civet

195 lines
8.3 KiB
Plaintext

import ./deps/jquery.js
{convert} from ./deps/vrml1to97/index.js
import type {ConfigType} from ./adapptypes.ts
configPromise := browser.storage.local.get(['vrmlview', 'vrml97'])
knownExtensions := /[.](?:wrl|x3d|gltf|glb|obj|stl|ply)$/
certainlyHandled :=
knownExtensions.source.slice(0, -2).split('wrl|')[1].split '|'
function makeBrowser(url: string, width: string, height: string,
config: ConfigType)
x_ite_rel := 'deps/x_ite/x_ite.mjs'
x_ite_url .= './' + x_ite_rel
unless typeof browser is 'undefined'
if browser?.runtime?.getURL
x_ite_url = browser.runtime.getURL x_ite_rel
const { default: X3D } = await import x_ite_url
canvas := X3D.createBrowser()
// Fix up css: smaller browser, but we can see the world info
$(canvas).css {width, height, overflow: 'visible', 'vertical-align': 'top'}
x_ite_shadow := canvas.shadowRoot
if x_ite_shadow
x_ite_style := x_ite_shadow.querySelector 'link'
if x_ite_style
$(x_ite_style).after '<style type="text/css">
.x_ite-private-world-info-overlay {
inset: unset;
width: 300px;
height: 300px;
}</style>'
x_ite_browser := x_ite_shadow.querySelector '.x_ite-private-browser'
if x_ite_browser
$(x_ite_browser).css overflow: 'visible'
// Now get the browser and load the requested VRML, converting if need be
browser3D := X3D.getBrowser canvas
browser3D.setBrowserOption 'StraightenHorizon', false
if certainlyHandled.some((ext) => url.includes ext)
canvas.setAttribute 'src', url
else if url.includes '.wrl'
// Need to obtain the text and check what level it is
response := await fetch url
text .= await response.text()
if /#\s*VRML\s*V?1[.]/i.test text
text = convert text
maybeDebug text, config
browser3D.baseURL = url
scene := await browser3D.createX3DFromString text
browser3D.replaceWorld scene
{canvas, browser3D}
configPromise.then((config) =>
// Put eye icons after all of the eligible links
links := $('a').filter -> knownExtensions.test @.getAttribute('href') ?? ''
links.after ->
unless config.vrmlview return ''
newSpan := $('<span>👁</span>')
newSpan.css 'overflow', 'visible'
floatLike := this.lastElementChild as HTMLElement
float .= ''
if floatLike
float = (floatLike.getAttribute('align') ?? '')
or floatLike.style.getPropertyValue 'float'
or window.getComputedStyle(floatLike).getPropertyValue 'float'
switch float
/left/i
float = 'left'
newSpan.css {float, position: 'relative'}
/right/i
float = 'right'
newSpan.css {float, position: 'relative'}
else float = ''
newSpan.hover
(-> $(@).css 'background-color', 'lightblue'),
(-> $(@).css 'background-color', 'inherit')
newSpan.on 'click', @,
(e) =>
eye := e.target
state .= eye.getAttribute 'data'
unless state
state = 'off'
url := e.data.getAttribute('href') ?? ''
overImg := floatLike and floatLike.tagName is 'IMG'
width := overImg ? ($(floatLike).width() + 'px') : '150px'
height := overImg ? ($(floatLike).height() + 'px') : '150px'
{canvas} := await makeBrowser url, width, height, config
if float
canvas.style.float = float
if overImg
canvas.style.position = 'absolute'
imgSty := window.getComputedStyle floatLike
canvas.style.marginTop =
imgSty.getPropertyValue 'margin-top'
canvas.style.marginLeft =
imgSty.getPropertyValue 'margin-left'
canvas.style.marginRight =
imgSty.getPropertyValue 'margin-right'
if float is 'right'
canvas.style.left = $(eye).width() + 'px'
else if float is 'left'
canvas.style.right = $(eye).width() + 'px'
else canvas.style.left = floatLike.offsetLeft
$(eye).append canvas
if state is 'off'
eye.setAttribute 'data', 'on'
$(eye).css 'text-decoration', 'line-through 3px'
$(eye.lastElementChild as Element).show()
else
eye.setAttribute 'data', 'off'
$(eye).css 'text-decoration', 'none'
$(eye.lastElementChild as Element).hide()
let conwayBrowser: any
madeConway .= false
// See if we are on George Hart's Conway-notation generator page
inputs := $('input[type="button"][value="Generate"][onclick="viewVRML()"]')
if config.vrmlview and inputs.length is 1
// Seems so, fix the generator
// Note that modifying the onclick prop is not the recommended way to
// change button click functionality, but we need to clear out the old
// behavior so I wasn't sure how else to do it
inputs.prop 'onclick', (i, val) => () =>
import(browser.runtime.getURL('conway.js')).then (conway) =>
notation := $('input[name="notation"]').val()
unless notation then return
vrml := conway.generateVRML notation.toString()
maybeDebug vrml, config
unless madeConway
{canvas, browser3D} :=
await makeBrowser '', '250px', '250px', config
conwayBrowser = browser3D
canvas.style.float = 'left'
canvas.style.marginRight = '1em'
$('form[name="input"]').first().before canvas
madeConway = true
scene := await conwayBrowser.createX3DFromString vrml
conwayBrowser.replaceWorld scene
// See if we are on George Hart's prism generator page
panelFrame := $('frame[name="panel"][src="prism-maker-subpanel.html"]')
if config.vrmlview and panelFrame.length is 1
// Seems so, fix the generator
panelFrame.on "load", =>
panelDoc := frames[1].document
vrmlDoc := frames[0].document
vrmlBody := $('body', vrmlDoc)
// Grab the initial text while it is still easy to get
textNode := vrmlBody.contents()[0]
initialVrml1: string := textNode.textContent or ''
// Now build up the vrml frame as we want it
viewerDiv := $('<div></div>')
$('head').after $('<body></body>')
$('body').append viewerDiv
// We are presuming here that the body just contains a single
// text node. That should stay true unless GWH changes the page.
initialVrml97 := convert initialVrml1
{canvas, browser3D: prismBrowser} :=
await makeBrowser '', '300px', '300px', config
viewerDiv.append canvas
initialScene := await prismBrowser.createX3DFromString initialVrml97
prismBrowser.replaceWorld initialScene
$(textNode).remove()
$('frame[name="vrml"]').remove()
// OK, finally have the layout cleaned up. Now we can set up our
// replacement generator:
prismBtn :=
$('input[type="button"][value="View"][onclick="ViewVRML()"]',
panelDoc)
unless prismBtn.length is 1 return
prismBtn.prop 'onclick', (i, val) => =>
import(browser.runtime.getURL('prism.js')).then (prism) =>
numerator := parseInt(
$('input[name="numerator"]', panelDoc).val() as string)
denominator := parseInt(
$('input[name="denominator"]', panelDoc).val() as string)
checks: boolean[] := []
$('input[name="what"]', panelDoc).each ->
checks.push (@ as HTMLInputElement).checked
return
{vrml, err} := prism.generateVRML numerator, denominator, checks
maybeDebug vrml, config
if err then alert err
if vrml
scene := await prismBrowser.createX3DFromString vrml
prismBrowser.replaceWorld scene
) // end of then for configPromise
function maybeDebug(vrml: string, config: ConfigType)
if config.vrml97 then console.log 'Generated VRML97', vrml