feat: add initial skill authoring workspace
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
137
skills/zhihu-navigate/scripts/open_creator_entry.js
Normal file
137
skills/zhihu-navigate/scripts/open_creator_entry.js
Normal file
@@ -0,0 +1,137 @@
|
||||
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'),
|
||||
};
|
||||
Reference in New Issue
Block a user