Skip to content
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

PLJ-785 CodeMirror Eject to TextArea - Reload from TextArea in Offline HTML export #805

Merged
merged 9 commits into from
Jan 23, 2021
32 changes: 27 additions & 5 deletions frontend/common/OfflineHTMLExport.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ export const offline_html = async ({ pluto_version, body, head }) => {
}

try {
const oldBody = body
body = body.cloneNode(true)

for (let sizer of body.querySelectorAll(".CodeMirror-sizer")) {
sizer.style.minHeight = "23px"
}

const oldBodyCMs = oldBody.querySelectorAll("pluto-input .CodeMirror")
body.querySelectorAll("pluto-input .CodeMirror").forEach((cm, i) => {
const oldCM = oldBodyCMs[i].CodeMirror
oldCM.save()
cm.outerHTML = `<textarea class="init-cm">${oldCM.getTextArea().value}</textarea>`
})
for (let iframe of body.querySelectorAll("iframe")) {
if (iframe.dataset.datauri) {
iframe.src = iframe.dataset.datauri
Expand Down Expand Up @@ -52,13 +54,33 @@ export const offline_html = async ({ pluto_version, body, head }) => {
<link rel="stylesheet" href="${CDNified(pluto_version, "treeview.css")}" type="text/css" />
<link rel="stylesheet" href="${CDNified(pluto_version, "hide-ui.css")}" type="text/css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/lib/codemirror.min.css" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/codemirror.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/mode/julia/julia.min.js" defer></script>

${head.querySelector("style#MJX-SVG-styles").outerHTML}
</head>
<body>
${body.querySelector("main").outerHTML}
${body.querySelector("svg#MJX-SVG-global-cache").outerHTML}
</body>
<script>
const cmOptions = {
lineNumbers: true,
mode: "julia",
lineWrapping: true,
viewportMargin: Infinity,
placeholder: "Enter cell code...",
indentWithTabs: true,
indentUnit: 4,
cursorBlinkRate: -1,
readOnly: false,
}
document.addEventListener("DOMContentLoaded", () =>
document.querySelectorAll(".init-cm").forEach(textArea => {
CodeMirror.fromTextArea(textArea, cmOptions)
})
)
</script>
</html>
`
} catch (error) {
Expand Down
53 changes: 25 additions & 28 deletions frontend/components/CellInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const CellInput = ({
let pluto_actions = useContext(PlutoContext)

const cm_ref = useRef(null)
const text_area_ref = useRef(null)
const dom_node_ref = useRef(/** @type {HTMLElement} */ (null))
const remote_code_ref = useRef(null)
const change_handler_ref = useRef(null)
Expand All @@ -79,36 +80,31 @@ export const CellInput = ({
}, [remote_code])

useLayoutEffect(() => {
const cm = (cm_ref.current = CodeMirror(
(el) => {
dom_node_ref.current.appendChild(el)
},
{
value: local_code,
lineNumbers: true,
mode: "julia",
lineWrapping: true,
viewportMargin: Infinity,
placeholder: "Enter cell code...",
indentWithTabs: true,
indentUnit: 4,
hintOptions: {
hint: juliahints,
pluto_actions: pluto_actions,
notebook_id: notebook_id,
on_update_doc_query: on_update_doc_query,
extraKeys: {
".": (cm, { pick }) => {
pick()
cm.replaceSelection(".")
cm.showHint()
},
// "(": (cm, { pick }) => pick(),
const cm = (cm_ref.current = CodeMirror.fromTextArea(text_area_ref.current, {
value: local_code,
lineNumbers: true,
mode: "julia",
lineWrapping: true,
viewportMargin: Infinity,
placeholder: "Enter cell code...",
indentWithTabs: true,
indentUnit: 4,
hintOptions: {
hint: juliahints,
pluto_actions: pluto_actions,
notebook_id: notebook_id,
on_update_doc_query: on_update_doc_query,
extraKeys: {
".": (cm, { pick }) => {
pick()
cm.replaceSelection(".")
cm.showHint()
},
// "(": (cm, { pick }) => pick(),
},
matchBrackets: true,
}
))
},
matchBrackets: true,
}))

const keys = {}

Expand Down Expand Up @@ -475,6 +471,7 @@ export const CellInput = ({
return html`
<pluto-input ref=${dom_node_ref}>
<button onClick=${on_delete} class="delete_cell" title="Delete cell"><span></span></button>
<textarea ref=${text_area_ref}></textarea>
</pluto-input>
`
}
Expand Down
6 changes: 3 additions & 3 deletions test/frontend/helpers/pluto.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const getPlutoUrl = () => `http://localhost:${process.env.PLUTO_PORT}`
export const prewarmPluto = async (page) => {
await page.goto(getPlutoUrl(), { waitUntil: 'networkidle0' })
await createNewNotebook(page)
const cellInputSelector = 'pluto-input textarea'
const cellInputSelector = 'pluto-input .CodeMirror textarea'
await page.waitForSelector(cellInputSelector, { visible: true })
await writeSingleLineInPlutoInput(page, 'pluto-input', '21*2')

Expand Down Expand Up @@ -54,7 +54,7 @@ export const waitForCellOutputToChange = (page, cellId, currentOutput) => {
}

export const writeSingleLineInPlutoInput = async (page, plutoInputSelector, text) => {
await page.type(`${plutoInputSelector} textarea`, text)
await page.type(`${plutoInputSelector} .CodeMirror textarea`, text)
// Wait for CodeMirror to process the input and display the text
return page.waitFor((plutoInputSelector, text) => {
const codeMirrorLine = document.querySelector(`${plutoInputSelector} .CodeMirror-line`)
Expand All @@ -64,7 +64,7 @@ export const writeSingleLineInPlutoInput = async (page, plutoInputSelector, text

export const keyboardPressInPlutoInput = async (page, plutoInputSelector, key) => {
const currentLineText = await getTextContent(`${plutoInputSelector} .CodeMirror-line`)
await page.focus(`${plutoInputSelector} textarea`)
await page.focus(`${plutoInputSelector} .CodeMirror textarea`)
await page.waitFor(500)
await page.keyboard.press(key)
await page.waitFor(500)
Expand Down