-
-
Save JoeIsHere/f843d625dd75eb9ee5fb5f8cfa29a5c9 to your computer and use it in GitHub Desktop.
Drafts Action - Blog YAML with links
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| let options = { | |
| timeZone: 'America/Los_Angeles', | |
| year: 'numeric', | |
| month: '2-digit', | |
| day: '2-digit', | |
| hour: '2-digit', | |
| minute: '2-digit', | |
| second: '2-digit', | |
| hour12: false | |
| }; | |
| let now = new Date(); | |
| // Round to the nearest 5-minute interval | |
| let minutes = now.getMinutes(); | |
| let remainder = minutes % 5; | |
| if (remainder < 3) { | |
| now.setMinutes(minutes - remainder); | |
| } else { | |
| now.setMinutes(minutes + (5 - remainder)); | |
| } | |
| now.setSeconds(0, 0); // Reset seconds and milliseconds | |
| // NOTE: This uses the old toLocaleString() logic from earlier | |
| let date = now.toLocaleString('sv-SE', options).replace(/:[0-9]{2}$/, ':00'); | |
| let title = draft.title; | |
| console.log(draft.title); | |
| let body = draft.content; | |
| let paragraphs = body.split('\n\n'); | |
| let yamlLines = paragraphs[0]; | |
| let yamlTitle = null; | |
| let yamlDate = null; | |
| let yamlAuthor = null; | |
| let yamlCategory = null; | |
| let yamlLink = null; | |
| let yamlImage = null; | |
| let nonYamlLines = []; | |
| let continueLink = null; | |
| let urlTitle = null; | |
| let newBody = null; | |
| let introParagraphs = null; | |
| // ------------------------------------------------------------------- | |
| // 1. CHECK EXISTING YAML | |
| // ------------------------------------------------------------------- | |
| // Checks if the input string matches the format YYYY-MM-DD HH:mm:ss. | |
| function isValidCustomDateFormat(line) { | |
| // 1. Strip the "Date: " prefix | |
| let dateString = line.replace(/^Date:\s*/i, "").trim(); | |
| // 2. Regular Expression for YYYY-MM-DD HH:mm:ss | |
| // \d{4} = 4 digits (year) | |
| // \d{2} = 2 digits (month, day, hour, minute, second) | |
| let regex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/; | |
| if (regex.test(dateString)) { | |
| // If the format matches, return the clean date string | |
| return trimmedLine; | |
| } else { | |
| // Format does not match | |
| return null; | |
| } | |
| } | |
| if (title.startsWith('Title:')) { | |
| title = title.replace('Title:', ''); | |
| title = title.trim(); | |
| } | |
| for (let i = 0; i < yamlLines.length; i++) { | |
| // We trim the line for checks, but save the original line for nonYamlLines | |
| let line = yamlLines[i]; | |
| let trimmedLine = line.trim(); | |
| let count = 1; | |
| // --- YAML FIELD CHECKS (consume the line if it starts with a key) --- | |
| if (trimmedLine.startsWith('Title: ' && count === 1)) { | |
| yamlTitle = trimmedLine; | |
| count = count - 1; | |
| } else if (trimmedLine.startsWith('Date: ' && count === 1)) { | |
| // Line is consumed/discarded from the body regardless of validity. | |
| yamlDate = isValidCustomDateFormat(trimmedLine); | |
| count = count - 1; | |
| } | |
| else if (trimmedLine.startsWith('Author: ' && count === 1)) { | |
| yamlAuthor = trimmedLine; | |
| count = count - 1; | |
| } | |
| else if (trimmedLine.startsWith('Category: ' && count === 1)) { | |
| yamlCategory = trimmedLine; | |
| count = count - 1; | |
| } | |
| else if (trimmedLine.startsWith('Link: ' && count === 1)) { | |
| yamlLink = trimmedLine; | |
| count = count - 1; | |
| } | |
| else if (trimmedLine.startsWith('Image: ' && count === 1)) { | |
| yamlImage = trimmedLine; | |
| count = count - 1; | |
| } | |
| else { | |
| // --- NON-YAML LINE: PUSH TO BODY --- | |
| // If the line is NOT any of the above YAML fields, it MUST be body content | |
| // or a line break we want to preserve. | |
| //nonYamlLines.push(line); | |
| } | |
| } | |
| // ------------------------------------------------------------------- | |
| // 1. PROCESS CLIPBOARD AND FETCH URL DATA | |
| // ------------------------------------------------------------------- | |
| let clipboardContent = app.getClipboard(); | |
| let clipboardText = String(clipboardContent || ""); | |
| // Set yamlLink and continueLink based on clipboard content | |
| if (clipboardText.indexOf("http") === 0 && yamlLink === null) { | |
| yamlLink = `Link: ${clipboardText}`; | |
| } | |
| if (clipboardText.indexOf("https://sixcolors.com") === 0) { | |
| continueLink = `[Continue reading on Six Colors ►](${clipboardText})`; | |
| } | |
| let url = app.getClipboard(); // Using clipboard content as the URL | |
| let http = HTTP.create(); | |
| let response = http.request({ | |
| "url": url, | |
| "method": "GET" | |
| }); | |
| if (response.success) { | |
| let htmlContent = response.responseText; | |
| let pageTitle = null; | |
| let formattedDateString = null; | |
| let introParagraphs = null; // New variable to store the extracted intro content | |
| // --- NEW: INTRO CONTENT EXTRACTION --- | |
| // This regex attempts to capture all content (including paragraphs and line breaks) | |
| // between the closing </h1> tag and the opening <h2> tag. | |
| // The 's' flag at the end (for singleline mode) is CRITICAL here, as it allows '.' to match newlines. | |
| let contentRegex = /<\/h1>(.*?)<h2>/is; | |
| let contentMatchResult = htmlContent.match(contentRegex); | |
| if (contentMatchResult && contentMatchResult.length > 1) { | |
| introParagraphs = contentMatchResult[1].trim(); | |
| // Remove any residual tags like <p> and </p> to get clean text | |
| // This is a common step when pulling content for a plaintext/markdown post | |
| introParagraphs = introParagraphs.replace(/<\/?p>/g, "").trim(); | |
| // console.log("Extracted Intro:\n" + introParagraphs.substring(0, 100) + "..."); | |
| } else { | |
| console.log("Could not find Six Colors content between </h1> and <h2>."); | |
| } | |
| // --- TITLE EXTRACTION --- | |
| let titleMatch = htmlContent.match(/<title>(.*?)<\/title>/i); | |
| let patternToRemove = /\s*– Six Colors/i; | |
| if (titleMatch && titleMatch.length > 1) { | |
| pageTitle = titleMatch[1].trim(); | |
| pageTitle = pageTitle.replace(patternToRemove, "").trim(); | |
| // Set yamlTitle variable for later use in construction | |
| urlTitle = `Title: ${pageTitle}`; // Using urlTitle to hold the extracted title | |
| } else { | |
| console.log("Could not find a title tag."); | |
| } | |
| // --- DATE EXTRACTION --- | |
| let dateMatchResult = htmlContent.match(/<p class="dateline">(.*?)<\/p>/i); | |
| if (dateMatchResult && dateMatchResult.length > 1) { | |
| let rawDateString = dateMatchResult[1].trim(); | |
| // CRITICAL: Replace 'PT' with 'PDT' to help the Date constructor parse the timezone. | |
| let dateToParse = rawDateString.replace(" PT", " PDT"); | |
| let dateObject = new Date(dateToParse); | |
| if (isNaN(dateObject.getTime())) { | |
| console.log("Error: Could not parse date string from Six Colors: " + rawDateString); | |
| } else { | |
| // Manual Formatting with Standard JS Methods | |
| let year = dateObject.getFullYear(); | |
| let month = dateObject.getMonth() + 1; | |
| let day = dateObject.getDate(); | |
| let hour = dateObject.getHours(); | |
| let minute = dateObject.getMinutes(); | |
| let second = dateObject.getSeconds(); // Include seconds for full consistency | |
| let pad = (n) => n < 10 ? '0' + n : n; | |
| // Assemble the formatted string YYYY-MM-DD HH:mm:ss | |
| formattedDateString = `${year}-${pad(month)}-${pad(day)} ${pad(hour)}:${pad(minute)}:${pad(second)}`; | |
| console.log("Raw Date: " + rawDateString); | |
| console.log("Formatted Date: " + formattedDateString); | |
| if (yamlDate === null) { | |
| yamlDate = `Date: ${formattedDateString}`; | |
| } | |
| } | |
| } else { | |
| console.log("Could not find dateline element in the Six Colors HTML."); | |
| } | |
| } else { | |
| // Handle error (e.g., website down, bad URL) | |
| console.log(`HTTP Request failed for ${url}: ${response.statusCode}`); | |
| } | |
| // ------------------------------------------------------------------- | |
| // 3. CONSTRUCT DRAFT | |
| // ------------------------------------------------------------------- | |
| let newYaml = []; | |
| // Determine Title | |
| if (yamlTitle === null) { | |
| if (urlTitle) { | |
| newYaml.push(urlTitle); // Use the extracted URL title if available | |
| } else { | |
| newYaml.push(`Title: ${title}`); | |
| } | |
| } else { | |
| newYaml.push(yamlTitle); | |
| // Fallback to the draft's title | |
| } | |
| // Determine Date | |
| console.log(`YAML DATE: ${yamlDate}`); | |
| if (yamlDate === null) { | |
| newYaml.push(`Date: ${date}`); | |
| } else { | |
| newYaml.push(yamlDate); | |
| } | |
| // Author and Category (always fall back to defaults if not found in existing YAML) | |
| if (yamlAuthor) { | |
| newYaml.push(yamlAuthor); | |
| } else { | |
| newYaml.push(`Author: joe-steel`); | |
| } | |
| if (yamlCategory) { | |
| newYaml.push(yamlCategory); | |
| } else { | |
| newYaml.push(`Category: text`); | |
| } | |
| // Link and Image (only push if a value was found) | |
| if(yamlLink){ | |
| newYaml.push(yamlLink); | |
| } | |
| if(yamlImage){ | |
| newYaml.push(yamlImage); | |
| } | |
| // Start with YAML, followed by two blank lines | |
| newBody = newYaml.join('\n') //+ '\n\n'; | |
| // Insert the extracted content if available | |
| if (introParagraphs) { | |
| newBody += introParagraphs + '\n\n'; | |
| } | |
| // Append any existing non-YAML content from the original draft | |
| newBody += nonYamlLines.join('\n'); | |
| // Append the continue link if it exists | |
| if (continueLink) { | |
| newBody += `\n\n${continueLink}`; | |
| } | |
| if (paragraphs[1]) { | |
| newBody += '\n\n' + paragraphs.slice(1).join('\n\n'); | |
| } | |
| draft.content = newBody; | |
| draft.update(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment