Bookmarklets

Bookmarklets

19 bookmarks
Custom sorting
Create a bookmarklet to remove highlighting on a page | Shared Grok Conversation [remhi:]
Create a bookmarklet to remove highlighting on a page | Shared Grok Conversation [remhi:]
  • How to create a bookmarklet, tell an AI (grok.com, gemini.com, chatgpt.ai) what you want to do.
  • You will find generated code in inner window and a copy link. If you want further modifications, contin to as in the san chat. The chat is private to share with someone use the link icon at end of what you have so far.
  • Create a bookmark for any page or sort not already bookmarked, then change the title: to what you want, replace the url:/link: with your new javascript code.
  • To move/place bookmarklet into a bookmark folder you will have use the bookmarks manager. To find your bookmarklet.you can search on important words in your new bookmark's title to find it.
  • If you want further modifications, continue in the same chat. The chat is private to share with someone ues the link icon at end of what you have so far. Any changes made to a shared link become your own new chat with modifications.

See https://dmcritchie.mvps.org/dolphin/lesson_from_newtab.htm

·grok.com·
Create a bookmarklet to remove highlighting on a page | Shared Grok Conversation [remhi:]
Bookmarklet to convert HTML selection to Markdown - Tips - DEVONtechnologies Community
Bookmarklet to convert HTML selection to Markdown - Tips - DEVONtechnologies Community

javascript:/HTML to Markdown/(() => { const script = document.createElement("script"); script.type = "text/javascript"; script.src = "https://unpkg.com/turndown/dist/turndown.js"; script.async = false; script.defer = false; document.head.appendChild(script); script.addEventListener('load', () => { const sel = window.getSelection(); const range = sel.getRangeAt(0); const turndownService = new TurndownService(); const dummy = document.createElement('div'); dummy.appendChild(range.cloneContents()); const markdown = turndownService.turndown(dummy.innerHTML); navigator.clipboard.writeText(markdown); }) })() /* https://discourse.devontechnologies.com/t/bookmarklet-to-convert-html-selection-to-markdown/62170 */

·discourse.devontechnologies.com·
Bookmarklet to convert HTML selection to Markdown - Tips - DEVONtechnologies Community
unicode: unicode coding into clipboard for selected character --- bookmarklet
unicode: unicode coding into clipboard for selected character --- bookmarklet
javascript:(function(){let input=prompt("Paste or type the Unicode character:","");if(!input||input.trim()===""){alert("No character entered.");return}let s=input.trim().charAt(0);if(!s){alert("Could not read character.");return}let c=s.codePointAt(0);let hex=c.toString(16).toUpperCase().padStart(4,'0');let dec=c;let entity=`&#x${hex};%60;let%20alt=%60alt+${dec}%60;alert(%60${s}\t${entity}\t${alt}\n\n%E2%9C%85%20Copied:%20${entity}%60);navigator.clipboard.writeText(entity).catch(()=%3E{});})();
·grok.com·
unicode: unicode coding into clipboard for selected character --- bookmarklet
tjs: bookmarklet toggle javascript on off
tjs: bookmarklet toggle javascript on off
javascript:(function(){if(document.body.contentEditable='false'||document.body.contentEditable='inherit'){document.body.contentEditable='true';document.designMode='on';}else{document.body.contentEditable='false';document.designMode='off';alert('JavaScript OFF ');}})();
·google.com·
tjs: bookmarklet toggle javascript on off
More precise titlecase?
More precise titlecase?
Title case additionally upper-cases the first letters of each additional word, then lower cases some short word, then re-upper-cases them again if they are the first or last words. Those words are: "a", "an", "and", "at", "but", "by", "for", "in", "nor", "of", "on", "or", "so", "the", "to", "up", and "yet". Stock symbols, acronyms, initials.
·talk.tiddlywiki.org·
More precise titlecase?
cud:a CopyURLdesc ANCHOR YouTube time w/o server mods 2025-05-25
cud:a CopyURLdesc ANCHOR YouTube time w/o server mods 2025-05-25

Note: Please fix syntax in following bookmarklet code: javascript:(function() {

/* Get page details */ const title = document.title || '(undefined)'; const url = window.location.href; const isYouTube = (url.includes('youtube.com') || url.includes('youtu.be')) && (url.includes('/watch?v=') || url.includes('/v/') || url.includes('/shorts')); const descMeta = document.querySelector('meta[name="description"]') || document.querySelector('meta[property="og:description"]'); let description = descMeta ? descMeta.content : '(undefined)'; const timestamp = new Date().toISOString();

/* Truncate description to 410 characters with ellipsis if needed */ if (description !== '(undefined)' && description.length > 410) { description = description.substring(0, 406) + '...'; }

/* Format title with duration for YouTube */ let formattedTitle = title; if (isYouTube) { const videoDuration = document.querySelector('meta[itemprop="duration"]')?.content || 'PT0M0S'; let days = 0, hours = 0, minutes = 0, seconds = 0; const daysMatch = videoDuration.match(/(\d+)D/); const hoursMatch = videoDuration.match(/(\d+)H/); const minutesMatch = videoDuration.match(/(\d+)M/); const secondsMatch = videoDuration.match(/(\d+)S/); if (daysMatch) days = parseInt(daysMatch[1]); if (hoursMatch) hours = parseInt(hoursMatch[1]); if (minutesMatch) minutes = parseInt(minutesMatch[1]); if (secondsMatch) seconds = parseInt(secondsMatch[1]); let durationStr = ''; if (days > 0) durationStr += ${days.toString().padStart(2, '0')}D ;

if (hours > 0 || days > 0) durationStr += `${hours.toString().padStart(2, '0')}:`;
durationStr += `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
formattedTitle = `${title} [${durationStr}]`;

}

/* Truncate URL */ let formattedUrl = url; if (isYouTube) { formattedUrl = url.split('&')[0]; } else { formattedUrl = url.split('?')[0]; }

/* Create prompt parts */ const displayPart = `${formattedTitle}\r\n\r\n%20%20%20%20%20(Ready too copy to clipboard last update: '+document.lastModified+' \r\n\r\n'+

${description}\r\n\r\n${formattedUrl}; const copyPart = ${formattedTitle}\r\n${description !== '(undefined)' ? description + '\r\n'}${formattedUrl}`;

const anchorPart = <a target=%22_blank%22 href=%22' + ${formattedUrl}+'%22 + ${description !== '(undefined)' ? title=%22${description}%22'>${formattedTitle}</a>;

prompt(displayPart, copyPart);

Alert('anchor: ' + anchorPart);

prompt(anchorPart, anchorPart);

})();

3 / 3

Here's the corrected bookmarklet code with fixed syntax errors:

javascript

Copy javascript:(function() { /* Get page details */ const title = document.title || '(undefined)'; const url = window.location.href; const isYouTube = (url.includes('youtube.com') || url.includes('youtu.be')) && (url.includes('/watch?v=') || url.includes('/v/') || url.includes('/shorts')); const descMeta = document.querySelector('meta[name="description"]') || document.querySelector('meta[property="og:description"]'); let description = descMeta ? descMeta.content : '(undefined)'; const timestamp = new Date().toISOString();

/* Truncate description to 410 characters with ellipsis if needed */ if (description !== '(undefined)' && description.length > 410) { description = description.substring(0, 406) + '...'; }

/* Format title with duration for YouTube */ let formattedTitle = title; if (isYouTube) { const videoDuration = document.querySelector('meta[itemprop="duration"]')?.content || 'PT0M0S'; let days = 0, hours = 0, minutes = 0, seconds = 0; const daysMatch = videoDuration.match(/(\d+)D/); const hoursMatch = videoDuration.match(/(\d+)H/); const minutesMatch = videoDuration.match(/(\d+)M/); const secondsMatch = videoDuration.match(/(\d+)S/); if (daysMatch) days = parseInt(daysMatch[1]); if (hoursMatch) hours = parseInt(hoursMatch[1]); if (minutesMatch) minutes = parseInt(minutesMatch[1]); if (secondsMatch) seconds = parseInt(secondsMatch[1]); let durationStr = ''; if (days > 0) durationStr += ${days.toString().padStart(2, '0')}D ; if (hours > 0 || days > 0) durationStr += ${hours.toString().padStart(2, '0')}:; durationStr += ${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}; formattedTitle = ${title} [${durationStr}]; }

/* Truncate URL */ let formattedUrl = url; if (isYouTube) { formattedUrl = url.split('&')[0]; } else { formattedUrl = url.split('?')[0]; }

/* Create prompt parts */ const displayPart = ${formattedTitle}\r\n\r\n (Ready to copy to clipboard last update: ${document.lastModified})\r\n\r\n${description}\r\n\r\n${formattedUrl}; const copyPart = ${formattedTitle}\r\n${description !== '(undefined)' ? description + '\r\n' : ''}${formattedUrl}; const anchorPart = <a target="_blank" href="${formattedUrl}" ${description !== '(undefined)' ? title="${description}" : ''}>${formattedTitle}</a>;

prompt(displayPart, copyPart); alert('anchor: ' + anchorPart); prompt(anchorPart, anchorPart); })(); The main fixes include:

Fixed string concatenation in displayPart by removing incorrect quotes and plus signs Fixed conditional expression in copyPart by adding proper string concatenation Completely reformatted anchorPart to use proper string template literals and correct HTML attribute syntax Changed Alert to lowercase alert (JavaScript is case-sensitive) Fixed spacing and formatting for better readability Removed stray plus signs and incorrect string concatenation in anchorPart Properly escaped quotes in the HTML attributes The bookmarklet should now work as intended, creating prompts with the formatted title, description, and URL, and showing an alert with the HTML anchor tag.

When I paste text from the prompt line into Gmail the \r\n is not forcing newline on Android pasting into Gmail. I want to use my bookmarklets on both Windows and Android and other systems if I had them as well.

The issue you're encountering is due to how Gmail on Android handles pasted text, particularly with newline characters (\r\n). Gmail's Android app often normalizes or strips certain formatting, including newline characters, which can break the expected behavior of your bookmarklet. This is a known challenge with cross-platform compatibility, as different systems and applications handle newlines differently (\n for Unix-like systems, \r\n for Windows, and sometimes \r for older Mac systems). Additionally, Gmail's editor may not respect raw \r\n sequences when pasting, especially in plain text mode. Below, I'll provide solutions to make your bookmarklet work consistently across Windows, Android, and other platforms when pasting into Gmail.

Problem Analysis Newline Handling: Gmail on Android may ignore \r\n or convert it to a single space or no break at all, especially when pasting into the compose window. This is because Gmail's editor processes pasted text and may not render raw control characters as expected. Cross-Platform Compatibility: Your bookmarklet uses \r\n (Windows-style newlines), but Android and Gmail may expect \n or handle newlines differently. For universal compatibility, you need to ensure the output is robust across platforms. Gmail's Plain Text vs. HTML Mode: Gmail's compose window operates in HTML mode by default, but pasting plain text with control characters like \r\n may not translate to visible line breaks unless properly formatted. Bookmarklet Constraints: Bookmarklets are single-line JavaScript URLs, so newlines in the code must be encoded or handled carefully to avoid breaking the script or output. Solutions Here are several approaches to fix the newline issue and ensure cross-platform compatibility when pasting into Gmail:

  1. Use URL-Encoded Newlines in the Bookmarklet Output Instead of relying on literal \r\n in the prompt output, encode newlines using %0A (URL-encoded \n) or %0D%0A (URL-encoded \r\n) to ensure compatibility. When the user copies the text from the prompt, these encoded characters can be decoded by Gmail or other applications as proper line breaks.

Modified Code: Update the displayPart and copyPart in your bookmarklet to use encoded newlines:

javascript

Copy javascript:(function() { /* Get page details */ const title = document.title || '(undefined)'; const url = window.location.href; const isYouTube = (url.includes('youtube.com') || url.includes('youtu.be')) && (url.includes('/watch?v=') || url.includes('/v/') || url.includes('/shorts')); const descMeta = document.querySelector('meta[name="description"]') || document.querySelector('meta[property="og:description"]'); let description = descMeta ? descMeta.content : '(undefined)'; const timestamp = new Date().toISOString();

/* Truncate description to 410 characterswith ellipsis if needed */ if (description !== '(undefined)' && description.length > 410) { description = description.substring(0, 406) + '...'; }

/* Format title with duration for YouTube */ let formattedTitle = title; if (isYouTube) { const videoDuration = document.querySelector('meta[itemprop="duration"]')?.content || 'PT0M0S'; let days = 0, hours = 0, minutes = 0, seconds = 0; const daysMatch = videoDuration.match(/(\d+)D/); const hoursMatch = videoDuration.match(/(\d+)H/); const minutesMatch = videoDuration.match(/(\d+)M/); const secondsMatch = videoDuration.match(/(\d+)S/); if (daysMatch) days = parseInt(daysMatch[1]); if (hoursMatch) hours = parseInt(hoursMatch[1]); if (minutesMatch) minutes = parseInt(minutesMatch[1]); if (secondsMatch) seconds = parseInt(secondsMatch[1]); let durationStr = ''; if (days > 0) durationStr += ${days.toString().padStart(2, '0')}D ; if (hours > 0 || days > 0) durationStr += ${hours.toString().padStart(2, '0')}:; durationStr += `

·grok.com·
cud:a CopyURLdesc ANCHOR YouTube time w/o server mods 2025-05-25
titlecase: convert selected text to title case
titlecase: convert selected text to title case

javascript:(function(){ var selectedText = (window.getSelection && window.getSelection().toString()) || (document.selection && document.selection.createRange().text); if (selectedText) { var titleCased = selectedText.toLowerCase().split(' ').map(function(word) { return word. alert(titleCased); } })();

·example.com·
titlecase: convert selected text to title case
FxT: fix table -- https://grok.com/share/bGVnYWN5_718276d3-8217-4d95-8372-8ec217d63717
FxT: fix table -- https://grok.com/share/bGVnYWN5_718276d3-8217-4d95-8372-8ec217d63717

javascript:(function() { document.body.contentEditable = 'true'; document.designMode = 'on'; var elements = document.getElementsByTagName(''); for (var i = 0; i < elements.length; i++) { var element = elements[i]; if (element.childNodes.length > 0) { for (var j = 0; j < element.childNodes.length; j++) { var node = element.childNodes[j]; if (node.nodeType === 3) { node.nodeValue = node.nodeValue.replace(/�/g, ' '); } } } } document.body.contentEditable = 'false'; document.designMode = 'off'; })(); / https://grok.com/share/bGVnYWN5_718276d3-8217-4d95-8372-8ec217d63717 */

·dmcritchie.mvps.org·
FxT: fix table -- https://grok.com/share/bGVnYWN5_718276d3-8217-4d95-8372-8ec217d63717
cud: CopyURLdesc Title/Description/Url on separate text lines oOo
cud: CopyURLdesc Title/Description/Url on separate text lines oOo
javascript:/copyurldesc/(function()%7Bvar%20a%20=%20(document.title);var%20b%20=%20(document.location.href);var%20c%20=%20document.getElementsByTagName('meta');var%20description%20=%20'(no%20description)';for%20(var%20x=0,y=c.length;%20x%3Cy;%20x++)%20%7Bif%20(c[x].name.toLowerCase()%20==%20'description')%20%7Bdescription%20=%20c[x];%20break;break;%20%7D%7Dwindow.prompt(a+'\n\nReady%20to%20copy%20to%20clipboard%20(last%20update:%20'%20+%20document.lastModified%20+%20')\r\n'+description.content+'\r\n'+b,a+',%20\r\n//'+description.content+'%20\r\n'+b);%7D)()
·example.com·
cud: CopyURLdesc Title/Description/Url on separate text lines oOo
TTT: Copy Title use if Title messed up in Raindrop oOo bookmark
TTT: Copy Title use if Title messed up in Raindrop oOo bookmark

javascript:/TTT: based on copyurldesc/(function()%7Bvar%20a%20=%20(document.title);var%20b%20=%20(document.location.href);var%20c%20=%20document.getElementsByTagName('meta');var%20description%20=%20'(no%20description)';for%20(var%20x=0,y=c.length;%20x%3Cy;%20x++)%20%7Bif%20(c[x].name.toLowerCase()%20==%20'description')%20%7Bdescription%20=%20c[x];%20break;break;%20%7D%7Dwindow.prompt(a+'\n\nReady%20to%20copy&20TITLE%20to%20clipboard%20(last%20update:%20'%20+%20document.lastModified%20+%20')\n\n'+description.content+'\n\n'+b,a);%7D)()

·example.com·
TTT: Copy Title use if Title messed up in Raindrop oOo bookmark
DDD: use if DESCRIPTION is missing or messed up in Raindrop oOo bookmark
DDD: use if DESCRIPTION is missing or messed up in Raindrop oOo bookmark
javascript:/DDD: from copyurldesc/(function()%7Bvar%20a%20=%20(document.title);var%20b%20=%20(document.location.href);var%20c%20=%20document.getElementsByTagName('meta');var%20description%20=%20'(no%20description)';for%20(var%20x=0,y=c.length;%20x%3Cy;%20x++)%20%7Bif%20(c[x].name.toLowerCase()%20==%20'description')%20%7Bdescription%20=%20c[x];%20break;break;%20%7D%7Dwindow.prompt(a+'\n\nReady%20to%20copy&20DESCRIPTION%20to%20clipboard%20(last%20update:%20'%20+%20document.lastModified%20+%20')\n\n'+description.content+'\n\n'+b,description.content);%7D)()
·example.com·
DDD: use if DESCRIPTION is missing or messed up in Raindrop oOo bookmark
RDr: bookmarklet to add current page to app.raindrop.io (your own raindrop.io)
RDr: bookmarklet to add current page to app.raindrop.io (your own raindrop.io)
·grok.com·
RDr: bookmarklet to add current page to app.raindrop.io (your own raindrop.io)
[Title] Create a bookmarklet that will put information into the clipboard and create a prompt The prompt is to include the title of the current web page the description of the current web page in the URL of the current web page the formatting for the prompt is the title and if it is a YouTube the title is to have appended to it a left bracket square bracket the hours two digits a colon and two digits for minutes and they close square bracket at the end, skip two lines put in the time stamp that the webpage was created, skip two lines. Put in the description however if his description is empty put a left paren the word undefined then close paren. Skip two lines to place the URL. I want the URL to be truncated at a question mark if it is not a YouTube and if it is a YouTube to be truncated at the ampersand. For a single prompt line I want it to include the title as previously described w...
[Title] Create a bookmarklet that will put information into the clipboard and create a prompt The prompt is to include the title of the current web page the description of the current web page in the URL of the current web page the formatting for the prompt is the title and if it is a YouTube the title is to have appended to it a left bracket square bracket the hours two digits a colon and two digits for minutes and they close square bracket at the end, skip two lines put in the time stamp that the webpage was created, skip two lines. Put in the description however if his description is empty put a left paren the word undefined then close paren. Skip two lines to place the URL. I want the URL to be truncated at a question mark if it is not a YouTube and if it is a YouTube to be truncated at the ampersand. For a single prompt line I want it to include the title as previously described w...

Note:

Bookmarklet for Web Page Info Clipping Create a https://grok.com/chat/596674b4-f8f6-4f88-964a-7e0cd618222e https://grok.com/share/bGVnYWN5_469b9bdd-85f1-41f7-adf6-d03d4a072e88 2025-05-03 Create a bookmarklet that will put information into the clipboard and create a prompt The prompt is to include the title of the current web page the description of the current web page in the URL of the current web page the formatting for the prompt is the title and if it is a YouTube the title is to have appended to it a left bracket square bracket the hours two digits a colon and two digits for minutes and they close square bracket at the end, skip two lines put in the time stamp that the webpagee was created, skip two lines. Put in the description however if his description is empty put a left paren the word undefined then close paren. Skip two lines to place the URL. I want the URL to be truncated at a question mark if it is not a YouTube and if it is a YouTube to be truncated at the ampersand. For a single prompt line I want it to include the title as previously described with the carriage return line feed with the description if there is one and if there is one to be followed by the carriage return line feed and then the URL as previously described.

bookmarklet.js javascript Show inline

Bookmarklets cannot contain //comments they must be /* */

bookmarklet.js javascript Show inline

The /n/n will not work on Android or Windows from the clipboard . I must be able to paste from the clipboard to both Android and Windows. There are several forms for YouTube URLs. In the US we see YouTube.com and YouTu.be after which /v/, /watch?v=, /shorts

To ensure compatibility with Android and Windows clipboards, I'll replace \n\n with \r\n\r\n for consistent line breaks. I'll also update the YouTube URL detection to handle various forms (youtube.com, youtu.be, /v/, /watch?v=, /shorts). The bookmarklet will use /* */ comments as required.

bookmarklet.js javascript Show inline

Missing top portion of prompt in non YouTube video. I want title, description (if present), shortened useable URL in both top and bottom of prompt, for YouTube videos the duration must be included after title in both to and bottom of prompt.

To address the issue, I'll modify the bookmarklet to ensure both the full prompt and single-line prompt include the title, description (if present), and shortened usable URL for all pages. For YouTube videos, the duration will be appended to the title in both prompts. I'll also ensure the YouTube URL detection handles youtube.com, youtu.be, /v/, /watch?v=, and /shorts, and use \r\n\r\n for consistent line breaks across Android and Windows. The bookmarklet will use /* */ comments and maintain the same artifact ID for continuity.

bookmarklet.js javascript Show inline

Tested YouTube video was https://m.youtube.com/watch?v=RIYv8LP3Iu8 and non YouTube was https://dmcritchie.mvps.org/dolphin/dolphin_newtab.htm duration of YouTube reported as [00:33] should be [33:55] video could longer do minutes could be extended or days and hours placed in front. Limit description to 320 chars and if truncated include ellipsis at end. YouTube failed to copy to clipboard. /

Thank you for the detailed feedback and test cases. I'll address the issues:

YouTube Duration Error: The duration calculation was incorrect ([00:33] instead of [33:55]). The code will now properly parse the ISO 8601 duration format (PT33M55S) from YouTube's meta[itemprop="duration"] and handle extended durations (including hours and days). Description Truncation: The description will be limited to 320 characters, with an ellipsis (...) appended if truncated. Clipboard Copy Failure: The clipboard copy failure on YouTube will be handled by ensuring compatibility and providing a fallback alert with the full prompt text if the clipboard API fails. YouTube URL Detection: The YouTube URL detection already handles m.youtube.com, youtube.com, youtu.be, /v/, /watch?v=, and /shorts, but I'll ensure it remains robust for the test case (https://m.youtube.com/watch?v=RIYv8LP3Iu8). Non-YouTube URL: The non-YouTube test case (https://dmcritchie.mvps.org/dolphin/dolphin_newtab.htm) will be processed correctly, with the URL truncated at ? and no duration appended. Prompt Structure: Both the full prompt and single-line prompt will include title, description (if present, truncated to 320 chars), and shortened URL. For YouTube, the title will include the duration. The full prompt will repeat this structure after the timestamp. The bookmarklet will continue using /* */ comments and \r\n\r\n for consistent line breaks across Android and Windows.

bookmarklet.js javascript Show inline

25 web pages

The first part should go into default text of prompt(text default text) and the second part should go into text of the prompt. Want file updated to show as (Updated: yyyy-mm-dd hh:mm ET) to show as 24hour local time as i am in ET time zone.

Based on your request, I'll update the bookmarklet to:

Prompt Structure: The first part (title, description, URL) will be set as the default text of the first prompt dialog using prompt('Copied to clipboard! Full prompt:', firstPart). The second part (timestamp, title, description, URL) will be set as the text of the second prompt dialog using prompt('Second part:', secondPart). The full prompt (both parts combined) will still be copied to the clipboard. File Update Timestamp: Add (Updated: yyyy-mm-dd hh:mm ET) to the bookmarklet code, using the current local time in the Eastern Time (ET) zone, formatted in 24-hour format. Existing Functionality: Maintain YouTube URL detection (youtube.com, youtu.be, /v/, /watch?v=, /shorts). Handle YouTube duration correctly (parsing ISO 8601 format, e.g., PT33M55S for [00:33:55]). Truncate description to 320 characters with ellipsis if needed. Truncate URLs (& for YouTube, ? for non-YouTube). Use \r\n\r\n for consistent line breaks across Android and Windows. Use /* */ comments. Keep robust clipboard handling with fallback. The current date is May 02, 2025, and I'll calculate the local ET time for the update timestamp.

bookmarklet.js javascript Show inline

This is what the 2nd parameter in my Prompt looks like, I want an anchor statement with same information the description if present going into Title= of the anchor, I want the title to the right of the href= and immediately before the href= the _blank signal to create a new tab

const copyPart = ${formattedTitle}\r\n${description !== '(undefined)' ? description + '\r\n' : ''}${formattedUrl};

Why is there a colon in the above

Thank you for the clarification. I'll address your requirements and explain the issue with the colon in the provided code snippet.

Addressing the Requirements Second Parameter in Prompt (Anchor Statement): You want the second parameter of the prompt (previously the secondPart) to be an HTML anchor (<a>) statement with: The formattedUrl as the href attribute. The formattedTitle as the text content of the anchor (to the right of href=). _blank as the target attribute to open the link in a new tab. The description (if present, truncated to 320 characters with ellipsis) as the title attribute of the anchor. This anchor statement will replace the previous secondPart content in the second prompt dialog. Prompt Structure: The first prompt will show the firstPart (title, description, URL) as the default text. The second prompt will show the anchor statement as the text. The third prompt will show the singleLinePrompt (title, description if present, URL). The full prompt (first part + second part) will be copied to the clipboard. Existing Functionality: Maintain YouTube URL detection (youtube.com, youtu.be, /v/, /watch?v=, /shorts). Handle YouTube duration correctly (parsing ISO 8601 format, e.g., PT33M55S for [00:33:55]). Truncate description to 320 characters with ellipsis if needed. Truncate URLs (& for YouTube, ? for non-YouTube). Use \r\n\r\n for consistent line breaks across Android and Windows. Use /* */ comments. Keep robust clipboard handling with fallback. Include the update timestamp in ET 24-hour format. File Update Timestamp: Update the timestamp to reflect the current time in Eastern Time (ET), formatted as (Updated: yyyy-mm-dd hh:mm ET) in 24-hour format. Explaining the Colon Issue The code snippet you provided (const copyPart = ...) is from your message, but it doesn't appear in the previous bookmarklet code I generated. Instead, the relevant line in the prior artifact was:

javascript

Copy const singleLinePrompt = ${formattedTitle}\r\n${description !== '(undefined)' ? description + '\r\n' : ''}${formattedUrl}; There is no colon in this line. However, I suspect you might be referring to:

A misunderstanding of the ternary operator (?:) in the expression description !== '(undefined)' ? description + '\r\n' : '', which uses a colon as part of JavaScript syntax, not as a literal character in the output. Or, possibly, you're seeing a colon in the output (e.g., in the duration like [00:33:55]) or elsewhere, which is intentional for YouTube durations. To clarify:

The ternary operator checks if description !== '(undefined)'. If true, it includes description + '\r\n'; if false, it includes an empty string (''). No literal colon is added to the singleLinePrompt output unless it's part of the formattedTitle (e.g., YouTube duration) or description. If you meant a specific colon appearing in the output, please confirm where it appears (e.g., in the clipboard, prompt, or anchor), and I'll address it. For now, I'll assume the ternary operator syntax caused confusion, and I'll ensure the anchor statement output is clean.

𝍤 Updated Bookmarklet I'll generate the bookmarklet with the anchor statement for the second prompt, using the structure from your copyPart snippet as a guide for content but formatted as an HTML anchor. The update timestamp will reflect the current time in ET (assuming now is May

·grok.com·
[Title] Create a bookmarklet that will put information into the clipboard and create a prompt The prompt is to include the title of the current web page the description of the current web page in the URL of the current web page the formatting for the prompt is the title and if it is a YouTube the title is to have appended to it a left bracket square bracket the hours two digits a colon and two digits for minutes and they close square bracket at the end, skip two lines put in the time stamp that the webpage was created, skip two lines. Put in the description however if his description is empty put a left paren the word undefined then close paren. Skip two lines to place the URL. I want the URL to be truncated at a question mark if it is not a YouTube and if it is a YouTube to be truncated at the ampersand. For a single prompt line I want it to include the title as previously described w...
Bookmarklet -- cud:nova copyurldesc updated/YouTube/url-cleanse
Bookmarklet -- cud:nova copyurldesc updated/YouTube/url-cleanse

javascript:(function() { /* Get page details */ const title = document.title || '';

const lastModified = new Date(document.lastModified).getTime(); const systemTime = new Date().getTime(); const diff = Math.abs((systemTime - lastModified) / 1000); /* seconds difference */ let b = 'Ready to copy to clipboard'; if (diff < 3) { b += (served at ${document.lastModified})\n\n; } else { b += (last updated ${document.lastModified})\n\n; }

const url = window.location.href; const isYouTube = (url.includes('youtube.com') || url.includes('youtu.be')) && (url.includes('/watch?v=') || url.includes('/v/') || url.includes('/shorts')); const descMeta = document.querySelector('meta[name="description"]') || document.querySelector('meta[property="og:description"]'); let description = descMeta ? descMeta.content : '';

/* Truncate description */ if (description && description.length > 320) { description = description.substring(0, 317) + '...'; }

/* Format title with duration for YouTube */ let formattedTitle = title; if (isYouTube) { const videoDuration = document.querySelector('meta[itemprop="duration"]')?.content || 'PT0M0S'; let days = 0, hours = 0, minutes = 0, seconds = 0; const daysMatch = videoDuration.match(/(\d+)D/); const hoursMatch = videoDuration.match(/(\d+)H/); const minutesMatch = videoDuration.match(/(\d+)M/); const secondsMatch = videoDuration.match(/(\d+)S/); if (daysMatch) days = parseInt(daysMatch[1]); if (hoursMatch) hours = parseInt(hoursMatch[1]); if (minutesMatch) minutes = parseInt(minutesMatch[1]); if (secondsMatch) seconds = parseInt(secondsMatch[1]); let durationStr = ''; if (days > 0) durationStr += ${days.toString().padStart(2, '0')}D ; if (hours > 0) durationStr += ${hours.toString().padStart(2, '0')}:; durationStr += ${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}; formattedTitle = ${title} [${durationStr}]; }

/* Truncate URL */ let formattedUrl = url; if (isYouTube) { formattedUrl = url.split('&')[0]; } else { formattedUrl = url.split('?')[0]; }

/* Create prompt parts */ const firstPart = b +${formattedTitle}\n\n${description ? '//'+description+ '\n\n' : ''}${formattedUrl}; const secondPart = ${formattedTitle}\n\n${description ? '//'+description+ '\n\n' : ''}${formattedUrl}; prompt(firstPart,secondPart);

/* Create output */ const output = ${formattedTitle}\n\n${description ? '//' + description + '\n\n' : ''}${formattedUrl};

})();f

·example.com·
Bookmarklet -- cud:nova copyurldesc updated/YouTube/url-cleanse
New cud: CopyURLdesc
New cud: CopyURLdesc

javascript:(function() { /* Get page details */ const title = document.title || '(undefined)'; const url = window.location.href; const isYouTube = url.includes('youtube.com') || url.includes('youtu.be') && (url.includes('/watch?v=') || url.includes('/v/') || url.includes('/shorts')); const descMeta = document.querySelector('meta[name="description"]') || document.querySelector('meta[property="og:description"]'); const description = descMeta ? descMeta.content : '(undefined)'; const timestamp = new Date().toISOString();

/* Format title for YouTube */ let formattedTitle = title; if (isYouTube) { const videoDuration = document.querySelector('meta[itemprop="duration"]')?.content || 'PT0H0M'; const hours = String(videoDuration.match(/(\d+)H/)?.[1] || '0').padStart(2, '0'); const minutes = String(videoDuration.match(/(\d+)M/)?.[1] || '0').padStart(2, '0'); formattedTitle = ${title} [${hours}:${minutes}]; }

/* Truncate URL */ let formattedUrl = url; if (isYouTube) { formattedUrl = url.split('&')[0]; } else { formattedUrl = url.split('?')[0]; }

/* Create full prompt */ const fullPrompt = ${formattedTitle}\r\n\r\n${timestamp}\r\n\r\n${description}\r\n\r\n${formattedUrl};

/* Create single-line prompt */ const singleLinePrompt = ${formattedTitle}\r\n${description !== '(undefined)' ? description + '\r\n' : ''}${formattedUrl};

/* Copy to clipboard / navigator.clipboard.writeText(fullPrompt).then(() => { / Show prompt with both formats */ prompt('Copied to clipboard! Full prompt:', fullPrompt); prompt('Single-line prompt:', singleLinePrompt); }).catch(err => { console.error('Clipboard copy failed:', err); alert('Failed to copy to clipboard. Full prompt:\r\n\r\n' + fullPrompt + '\r\n\r\nSingle-line prompt:\r\n\r\n' + singleLinePrompt); }); })();

·grok.com·
New cud: CopyURLdesc
User:JesseW/ BookmarkletsUniversal
User:JesseW/ BookmarkletsUniversal
211 Javascript categorized bookmarklets with text code/references, no Keywords, not as bookmarklets links
·en.wikipedia.org·
User:JesseW/ BookmarkletsUniversal
What are some common uses for bookmarklets? - Quora
What are some common uses for bookmarklets? - Quora
Answer (1 of 2): Bookmarklets are written in JavaScript, stored and used as bookmarks generally to change the appearance of a webpage, or extract information from a page. A bookmarklet does not change actual content, a page refresh reloads page without any changes. Bookmarklets generally run in a...
·quora.com·
What are some common uses for bookmarklets? - Quora
Emailthis:
Emailthis:
Bookmarklets are small pieces of JavaScript that run in your web browser. They appear to be bookmarks/favorites, and are just as clickable, but instead of opening a webpage when selected, they execute the JavaScript code they’re programmed to run. JavaScript snippets like you’ll see below expand the functionality of your browser without requiring any additional
·online-tech-tips.com·
Emailthis: