138 lines
3.3 KiB
JavaScript
138 lines
3.3 KiB
JavaScript
function cleanText(value) {
|
|
return String(value || '')
|
|
.replace(/\s+/g, ' ')
|
|
.replace(/\u200b/g, '')
|
|
.trim();
|
|
}
|
|
|
|
function bodyText() {
|
|
const body = document.body;
|
|
return cleanText(body && (body.innerText || body.textContent || ''));
|
|
}
|
|
|
|
function isLoginBlocked(url, text) {
|
|
return /\/signin\b|\/signup\b/.test(url) ||
|
|
/登录|注册|验证码|安全验证|验证后继续|请先登录/.test(text);
|
|
}
|
|
|
|
function hasEditorSignals() {
|
|
return !!document.querySelector(
|
|
"textarea[placeholder*='标题'], input[placeholder*='标题'], div[contenteditable='true'][role='textbox']"
|
|
);
|
|
}
|
|
|
|
function isVisible(node) {
|
|
if (!node) {
|
|
return false;
|
|
}
|
|
const rect = typeof node.getBoundingClientRect === 'function' ? node.getBoundingClientRect() : null;
|
|
return !rect || rect.width > 0 || rect.height > 0;
|
|
}
|
|
|
|
function isWriteEntryText(text) {
|
|
return !!text && (text.includes('写文章') || text.includes('发文章'));
|
|
}
|
|
|
|
function extractHref(node) {
|
|
if (!node) {
|
|
return '';
|
|
}
|
|
if (typeof node.href === 'string' && node.href) {
|
|
return node.href;
|
|
}
|
|
if (typeof node.getAttribute === 'function') {
|
|
return node.getAttribute('href') || '';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function findClickableAncestor(node) {
|
|
let current = node;
|
|
while (current) {
|
|
const tagName = String(current.tagName || '').toUpperCase();
|
|
const role = typeof current.getAttribute === 'function' ? cleanText(current.getAttribute('role')) : '';
|
|
const tabindex = typeof current.getAttribute === 'function' ? current.getAttribute('tabindex') : null;
|
|
const href = extractHref(current);
|
|
if (
|
|
tagName === 'A' ||
|
|
tagName === 'BUTTON' ||
|
|
role === 'button' ||
|
|
href ||
|
|
(tabindex !== null && tabindex !== '')
|
|
) {
|
|
return current;
|
|
}
|
|
current = current.parentElement || null;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function findWriteEntry() {
|
|
const directCandidates = Array.from(
|
|
document.querySelectorAll("a[href], button, [role='button']")
|
|
);
|
|
const directMatch = directCandidates.find((node) => {
|
|
const text = cleanText(node.textContent);
|
|
if (!isWriteEntryText(text)) {
|
|
return false;
|
|
}
|
|
return isVisible(node);
|
|
});
|
|
if (directMatch) {
|
|
return directMatch;
|
|
}
|
|
|
|
const textNodes = Array.from(
|
|
document.querySelectorAll("div, span, [tabindex]")
|
|
);
|
|
for (const node of textNodes) {
|
|
if (!isVisible(node)) {
|
|
continue;
|
|
}
|
|
const text = cleanText(node.textContent);
|
|
if (!isWriteEntryText(text)) {
|
|
continue;
|
|
}
|
|
const clickableAncestor = findClickableAncestor(node);
|
|
if (clickableAncestor && isVisible(clickableAncestor)) {
|
|
return clickableAncestor;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
const currentUrl = location.href;
|
|
const text = bodyText();
|
|
|
|
if (isLoginBlocked(currentUrl, text)) {
|
|
return {
|
|
status: 'login_required',
|
|
current_url: currentUrl,
|
|
};
|
|
}
|
|
|
|
if (hasEditorSignals()) {
|
|
return {
|
|
status: 'editor_ready',
|
|
current_url: currentUrl,
|
|
};
|
|
}
|
|
|
|
const writeEntry = findWriteEntry();
|
|
if (writeEntry) {
|
|
writeEntry.click();
|
|
const href = extractHref(writeEntry);
|
|
return {
|
|
status: 'creator_entry_clicked',
|
|
current_url: currentUrl,
|
|
next_url: href || undefined,
|
|
};
|
|
}
|
|
|
|
return {
|
|
status: 'creator_home',
|
|
current_url: currentUrl,
|
|
desired_target: String(args.desired_target || 'creator_home'),
|
|
};
|