Feat: parse page title when paste a link (#1344)

This commit is contained in:
Ran Luo 2019-09-17 16:15:33 +08:00 committed by GitHub
parent d26f509209
commit 141d25d896
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 6 deletions

View File

@ -1,6 +1,6 @@
import { PARAGRAPH_TYPES, PREVIEW_DOMPURIFY_CONFIG, HAS_TEXT_BLOCK_REG, IMAGE_EXT_REG } from '../config'
import { sanitize, getUniqueId, getImageInfo as getImageSrc } from '../utils'
import { sanitize, getUniqueId, getImageInfo as getImageSrc, getPageTitle } from '../utils'
import { getImageInfo } from '../utils/getImageInfo'
const LIST_REG = /ul|ol/
@ -53,7 +53,7 @@ const pasteCtrl = ContentState => {
return type
}
ContentState.prototype.standardizeHTML = function (html) {
ContentState.prototype.standardizeHTML = async function (html) {
// Only extract the `body.innerHTML` when the `html` is a full HTML Document.
if (/<body>[\s\S]*<\/body>/.test(html)) {
const match = /<body>([\s\S]*)<\/body>/.exec(html)
@ -99,9 +99,15 @@ const pasteCtrl = ContentState => {
const text = link.textContent
if (href === text) {
const span = document.createElement('span')
span.innerHTML = text
link.replaceWith(span)
const title = await getPageTitle(href)
if (title) {
link.textContent = title
} else {
const span = document.createElement('span')
span.innerHTML = text
link.replaceWith(span)
}
}
}
@ -216,7 +222,7 @@ const pasteCtrl = ContentState => {
const text = rawText || event.clipboardData.getData('text/plain')
let html = rawHtml || event.clipboardData.getData('text/html')
html = this.standardizeHTML(html)
html = await this.standardizeHTML(html)
const copyType = this.checkCopyType(html, text)
const { start, end } = this.cursor
const startBlock = this.getBlock(start.key)

View File

@ -5,6 +5,8 @@ import { isInElectron, URL_REG } from '../config'
const ID_PREFIX = 'ag-'
let id = 0
const TIMEOUT = 1500
export const getUniqueId = () => `${ID_PREFIX}${id++}`
export const getLongUniqueId = () => `${getUniqueId()}-${(+new Date()).toString(32)}`
@ -155,6 +157,61 @@ export const loadImage = async (url, detectContentType = false) => {
})
}
export const isOnline = () => {
return navigator.onLine === true
}
export const getPageTitle = url => {
// No need to request the title when it's not url.
if (!url.startsWith('http')) {
return ''
}
// No need to request the title when off line.
if (!isOnline()) {
return ''
}
const req = new XMLHttpRequest()
let settle
const promise = new Promise((resolve, reject) => {
settle = resolve
})
const handler = () => {
if (req.readyState === XMLHttpRequest.DONE) {
if (req.status === 200) {
const contentType = req.getResponseHeader('Content-Type')
if (/text\/html/.test(contentType)) {
const { response } = req
if (typeof response === 'string') {
const match = response.match(/<title>(.*)<\/title>/)
return match[1] ? settle(match[1]) : settle('')
}
return settle('')
}
return settle('')
} else {
return settle('')
}
}
}
const handleError = (e) => {
settle('')
}
req.open('GET', url)
req.onreadystatechange = handler
req.onerror = handleError
req.send()
// Resolve empty string when `TIMEOUT` passed.
const timer = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('')
}, TIMEOUT)
})
return Promise.race([promise, timer])
}
export const checkImageContentType = url => {
const req = new XMLHttpRequest()
let settle