fix: support GitHub turbo

This commit is contained in:
EnixCoda 2022-06-28 16:59:20 +08:00
parent 98ee885254
commit 05507abbcb
5 changed files with 79 additions and 7 deletions

View file

@ -63,7 +63,7 @@ export function SideBar() {
: intelligentToggle,
)
const shouldShow = $shouldShow.value
React.useEffect(() => {
const toggleBodyIndent = React.useCallback(() => {
if (sidebarToggleMode === 'persistent') {
DOMHelper.setBodyIndent(shouldShow)
} else {
@ -75,6 +75,12 @@ export function SideBar() {
}
}, [shouldShow, sidebarToggleMode])
React.useEffect(() => {
toggleBodyIndent()
}, [toggleBodyIndent])
useOnPJAXDone(toggleBodyIndent)
// Save expand state on toggle if auto expand is off
React.useEffect(() => {
if (intelligentToggle !== null) {

View file

@ -4,6 +4,11 @@ import { addMiddleware } from 'driver/connect'
import { platform } from 'platforms'
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import {
insertLogoMountPoint,
insertSideBarMountPoint,
persistGitakoElements
} from 'utils/DOMHelper'
import './content.scss'
if (platform.resolvePartialMetaData()) {
@ -18,8 +23,9 @@ if (platform.resolvePartialMetaData()) {
async function init() {
await injectStyles(browser.runtime.getURL('content.css'))
const SideBarElement = document.createElement('div')
document.body.appendChild(SideBarElement)
const SideBarElement = insertSideBarMountPoint()
const logoElement = insertLogoMountPoint()
persistGitakoElements(SideBarElement, logoElement)
ReactDOM.render(<Gitako />, SideBarElement)
}

View file

@ -112,6 +112,7 @@ const pathSHAMap = new Map<string, string>()
const pjaxContainerSelector = ['#repo-content-pjax-container', '#js-repo-pjax-container'].find(
selector => document.querySelector(selector),
)
const turboContainerId = 'repo-content-turbo-frame'
export const GitHub: Platform = {
isEnterprise,
@ -213,6 +214,7 @@ export const GitHub: Platform = {
if (configRef.pjaxMode === 'native' && (!options?.node || options.node.type === 'blob'))
return {
'data-pjax': pjaxContainerSelector,
'data-turbo-frame': turboContainerId,
onClick() {
/* Overwriting default onClick */
},

View file

@ -36,17 +36,17 @@ export function setBodyIndent(shouldShowGitako: boolean) {
}
export function $(selector: string): HTMLElement | null
export function $<T1>(selector: string, existCallback: (element: HTMLElement) => T1): T1
export function $<T1>(selector: string, existCallback: (element: HTMLElement) => T1): T1 | null
export function $<T1, T2>(
selector: string,
existCallback: (element: HTMLElement) => T1,
otherwise: () => T2,
): T1 | T2
): T1 | T2 | null
export function $<T2>(
selector: string,
existCallback: undefined | null,
otherwise: () => T2,
): HTMLElement | null | T2
): HTMLElement | T2
export function $(selector: string, existCallback?: any, otherwise?: any) {
const element = document.querySelector(selector)
if (element) {
@ -55,6 +55,15 @@ export function $(selector: string, existCallback?: any, otherwise?: any) {
return otherwise ? otherwise() : null
}
export function insertSideBarMountPoint() {
const mountPointID = 'gitako-mount-point-wrapper'
const sideBarElement = document.createElement('div')
sideBarElement.setAttribute('data-turbo-permanent', '')
sideBarElement.setAttribute('id', mountPointID)
document.body.appendChild(sideBarElement)
return sideBarElement
}
/**
* add the logo element into DOM
*/
@ -64,6 +73,7 @@ export function insertLogoMountPoint() {
return $(logoSelector, undefined, function createLogoMountPoint() {
const logoMountElement = document.createElement('div')
logoMountElement.setAttribute('id', logoID)
logoMountElement.setAttribute('data-turbo-permanent', '')
document.body.appendChild(logoMountElement)
return logoMountElement
})
@ -142,3 +152,46 @@ export function setCSSVariable(name: string, value: string | undefined, element:
if (value === undefined) element.style.removeProperty(name)
else element.style.setProperty(name, value)
}
/**
* Unlike the good-old-PJAX-time, now GitHub replaces whole body element after redirecting using turbo.
* If move Gitako mount point from `body` to `html`, Gitako style would break because it inherits style from GitHub body.
* The temporary solution is recovery Gitako elements once the body is removed.
*/
export function persistGitakoElements(SideBarElement: HTMLElement, logoElement: HTMLElement) {
const observer = new MutationObserver(mutations => {
for (const { addedNodes, removedNodes } of mutations) {
const [addedBody, removedBody] = [addedNodes, removedNodes].map(findBodyElement)
if (addedBody && removedBody) {
// hard-coded list due to limited time
// TODO: refactor in a better practice
// migrate gitako attributes, e.g. class
const propertiesNeedToMigrate = ['--gitako-width']
for (const property of propertiesNeedToMigrate) {
const oldValue = removedBody.style.getPropertyValue(property)
if (oldValue) addedBody.style.setProperty(property, oldValue)
}
const cssClassesNeedToMigrate = ['with-gitako-spacing']
for (const cssClass of cssClassesNeedToMigrate) {
if (removedBody.classList.contains(cssClass)) addedBody.classList.add(cssClass)
}
// move gitako elements
if (!addedBody.contains(SideBarElement)) addedBody.appendChild(SideBarElement)
if (removedBody.contains(SideBarElement)) removedBody.removeChild(SideBarElement)
if (!addedBody.contains(logoElement)) addedBody.appendChild(logoElement)
if (removedBody.contains(logoElement)) removedBody.removeChild(logoElement)
}
}
function findBodyElement(addedNodes: NodeList) {
return Array.from(addedNodes).find(addedNode => addedNode instanceof HTMLBodyElement) as
| HTMLBodyElement
| undefined
}
})
observer.observe(document.documentElement, {
childList: true,
})
}

View file

@ -4,6 +4,8 @@ import { platform } from 'platforms'
import * as React from 'react'
import { useEvent } from 'react-use'
// TODO: rename PJAX
const config: Config = {
areas: [
// github
@ -53,7 +55,10 @@ export const loadWithPJAX = (url: string, element: HTMLElement) => {
}
export function useOnPJAXDone(callback: () => void) {
useEvent('pjax:end', callback, document)
useEvent('pjax:end', callback, document) // legacy support
// 'turbo:render' should be the best timing but GitHub has attached a mutation observer on body to block that
// TODO: fire at turbo:render
useEvent('turbo:load', callback, document)
}
export function useRedirectedEvents(