This commit is contained in:
Hongbo Wu 2022-11-29 15:40:22 +08:00
parent 8ee19a98fa
commit f8e0efad05

View file

@ -6,30 +6,29 @@ export class StackOverflowHandler extends ContentHandler {
this.name = 'stackoverflow'
}
parseVotes(element: Element, dom: Document, title: string) {
const votes = element.querySelector(`div[itemprop='upvoteCount']`)
if (votes) {
const newVotes = dom.createElement('div')
newVotes.innerHTML = `<h3>${title}: ${votes.innerHTML}vote(s)</h3>`
element.prepend(newVotes)
parseText(element: Element, title: string) {
const newText = element.ownerDocument.createElement('div')
const text = element.querySelector(`div[itemprop='text']`)
if (text) {
const votes = element.querySelector(`div[itemprop='upvoteCount']`)
if (votes) {
newText.innerHTML = `<h2>${title}:${votes.innerHTML}vote(s)</h2><div>${text.innerHTML}</div>`
}
}
return newText
}
parseComments(element: Element, dom: Document) {
parseComments(element: Element) {
const dom = element.ownerDocument
const newComments = dom.createElement('div')
// comments
const commentsDiv = element.querySelector(`.comments`)
if (commentsDiv) {
const comments = commentsDiv.querySelectorAll(`.comment`)
if (comments.length > 0) {
// const count = element.querySelector(
// `span[itemprop='commentCount']`
// )?.textContent
const newComments = dom.createElement('div')
newComments.innerHTML = `<h4>Comments</h4>`
// newComments.innerHTML = `<h4>${
// count ? count + ' Comments' : 'Comment'
// }</h4>`
newComments.innerHTML = `<h3>Comments</h3>`
comments.forEach((comment) => {
const author = comment.querySelector(`.comment-user`)
@ -38,36 +37,41 @@ export class StackOverflowHandler extends ContentHandler {
const date = comment.querySelector(`.relativetime-clean`)?.textContent
if (author && text && authorHref && date) {
const newComment = dom.createElement('p')
newComment.innerHTML = `<a href="${authorHref}">${author.innerHTML}</a>: ${text} - ${date}`
newComment.innerHTML = `<a href="${authorHref}"><b>${author.innerHTML}</b></a>: ${text} - ${date}`
newComments.appendChild(newComment)
}
})
commentsDiv.parentNode?.replaceChild(newComments, commentsDiv)
}
}
// remove comment count
element.querySelector(`span[itemprop='commentCount']`)?.remove()
return newComments
}
parseUser(element: Element, dom: Document) {
const users = element.querySelectorAll(`.post-signature`)
users.forEach((user) => {
const name = user.querySelector(`.user-details a`)?.textContent
const link = user.querySelector(`.user-details a`)?.getAttribute('href')
const reputation = user.querySelector(`.reputation-score`)?.textContent
const badges = Array.from(user.querySelectorAll(`span[title*='badges']`))
parseAuthors(element: Element) {
const dom = element.ownerDocument
const newAuthors = dom.createElement('div')
const authors = element.querySelectorAll(`.post-signature`)
authors.forEach((author) => {
const name = author.querySelector(`.user-details a`)?.textContent
const link = author.querySelector(`.user-details a`)?.getAttribute('href')
const reputation = author.querySelector(`.reputation-score`)?.textContent
const badges = Array.from(
author.querySelectorAll(`span[title*='badges']`)
)
.map((badge) => badge.getAttribute('title'))
.join(', ')
const date = user.querySelector(`.user-action-time`)?.textContent
const date = author.querySelector(`.user-action-time`)?.textContent
if (name && link && reputation && date) {
const newUser = dom.createElement('p')
newUser.innerHTML = `By <a href="${link}">${name}</a> - ${reputation} reputation - ${
const newAuthor = dom.createElement('p')
newAuthor.innerHTML = `<a href="${link}"><b>${name}</b></a> - ${reputation} reputation - ${
badges || 'no badge'
} - ${date}`
element.replaceChild(newUser, user)
newAuthors.appendChild(newAuthor)
}
})
return newAuthors
}
shouldPreParse(url: string, dom: Document): boolean {
@ -77,36 +81,28 @@ export class StackOverflowHandler extends ContentHandler {
async preParse(url: string, dom: Document): Promise<Document> {
const mainEntity = dom.querySelector(`div[itemprop='mainEntity']`)
if (mainEntity) {
const newMainEntity = dom.createElement('div')
const question = mainEntity.querySelector('.question')
if (question) {
this.parseVotes(question, dom, 'Question')
this.parseComments(question, dom)
this.parseUser(question, dom)
newMainEntity.appendChild(this.parseText(question, 'Question'))
newMainEntity.appendChild(this.parseAuthors(question))
newMainEntity.appendChild(this.parseComments(question))
}
const answersDiv = mainEntity.querySelector('#answers')
if (answersDiv) {
// const count = mainEntity.querySelector(
// `span[itemprop='answerCount']`
// )?.textContent
const newAnswers = dom.createElement('div')
newAnswers.innerHTML = `<h2>Answers</h2>`
// newAnswers.innerHTML = `<h2>${
// count ? count + ' Answers' : 'Answer'
// }</h2>`
const answers = answersDiv.querySelectorAll(`.answer`)
answers.forEach((answer) => {
const title = answer.classList.contains('accepted-answer')
? 'Accepted Answer'
: 'Answer'
this.parseVotes(answer, dom, title)
this.parseComments(answer, dom)
this.parseUser(answer, dom)
newAnswers.appendChild(answer)
newMainEntity.appendChild(this.parseText(answer, title))
newMainEntity.appendChild(this.parseAuthors(answer))
newMainEntity.appendChild(this.parseComments(answer))
})
answersDiv.replaceChildren(newAnswers)
}
dom.body.replaceChildren(newMainEntity)
}
return Promise.resolve(dom)