Advertisement
rccharles

asc adjust clipboard June, 11th 2019

Jun 11th, 2019
1,045
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (*
  2.  
  3.   This applescript converts clipboard input into a format suited for pasting into an ASC
  4.   reply.  I observed that my copies into an ASC reply were not formated that well.  
  5.   I observed that copies from a web browser were formated much better.  I went about
  6.    adjusting the clipboard copy to the format expected by a web browser for best results.
  7.  
  8.  This applescript accepts the clipboard in either
  9.  -- plain text upon which the text is converted to HTML.  Conversion is limitted to inserting paragraph tags for blank lines and inserting links where http or https text appears. The page title is substituted for the link.  
  10.  -- HTML source code identified by text containing HTML markup.  
  11.          Caveat emptor.  
  12.  
  13. run with copy from Waterfox. List of main routines.
  14.   --- run ---
  15.   --- common ---
  16.   --- adjustCharacters ---
  17.   --- adjustBrowserHTML ---
  18.   --- adjustURLs ---
  19.   --- adustDuplicateAnchorURLs ---
  20.   --- adjustToAscHtml ---
  21.   --- adjustLF ---
  22.   --- convertToHTML ---
  23.  
  24. run with HTML as text from TextWrangler. List of main routines.
  25.   --- run ---
  26.   --- common ---
  27.   --- adjustCharacters() ---
  28.   --- adjustBrowserHTML ---
  29.   --- adjustURLs ---
  30.   --- adustDuplicateAnchorURLs ---
  31.   --- adjustToAscHtml ---
  32.   --- adjustLF ---
  33.   --- adjustLF ---
  34.   --- adjustLF() ---
  35.   --- convertToHTML
  36.  
  37. run with plain text from TextWrangler. List of main routines
  38.   --- run ---
  39.   --- common ---
  40.   --- adjustCharacters ---
  41.   --- adjustURLs ---
  42.   --- addParagraphs ---
  43.   --- convertToHTML ---
  44.  
  45.  to use:
  46.  1) copy command + c what data you want to convert
  47.  2) run this applascript by double clicking on the app.
  48.  3) paste command + V into an ASC reply
  49.  
  50.  I have tested in Waterfox 56.2.9 in Yosemite.  I assume the process will work with other web browsers and other versions of macOS.
  51.  
  52.  Save as an Application Bundle.  Don't check any of the boxes.
  53.  
  54. Should you experience a problem, run in the Script Editor.
  55.    Shows how to debug via on run path. Shows items added to folder. Shows log statement.
  56.    It is easier to diagnose problems with debug information. I suggest adding log statements to your script to see what is going on.  Here is an example.  
  57.    
  58.   For testing, run in the Script Editor.
  59.          1) Click on the Event Log tab to see the output from the log statement
  60.       2) Click on Run
  61.    
  62. change log
  63. may 1, 2019   -- skip 403 forbidding title
  64. may 2, 2019   -- convert \" to ".  the \" mysteriously appears in HTML source code input.  Probably some TextEdit artifact.
  65.                 copy to TextEdit copy out of TextEdit.
  66. may 7, 2019   -- regressed May 2nd update.  Applescript was inserting \" for display purposes into output.
  67. may 8, 2019   -- special processing for html class on clipboard
  68.                          https://pastebin.com/raw/Yg138YqT
  69. may 16,2019  -- fixed hexDumpFormatOne bugs and improved output
  70. may 16,2019  -- added hexDumpFormatZero
  71. may 19,2019  -- eliminate line breaks outside the <pre>...</pre> tags in HTML. ASC intrepreting line
  72.                          breaks as meaningful <br>
  73.                          instead of white space.simplified line break code.
  74.                        https://pastebin.com/raw/Nq08cFYH
  75. may 23, 2019 -- squash leading blanks in a line. #4
  76. may 27, 2019 -- Horizontal Ellipsis. #7
  77.                          8230   U+2026  E2 80 A6    … Horizontal Ellipsis
  78.                  https://www.charset.org/utf-8/9
  79. may 28, 2019 -- decide what to do with tabs. #6
  80. may 29, 2019 -- filter titles. #1
  81.                          https://pastebin.com/raw/3xRYMXtd
  82. june 1, 2019   -- automate debugging
  83. June 8, 2019   -- Substitute title for duplicate links
  84.  
  85.  
  86.          
  87.  
  88. enhancements:
  89.   -- get pdf title
  90.  
  91.  
  92. Author: rccharles
  93.  
  94.  Copyright 2019 rccharles  
  95.      
  96.        Permission is hereby granted, free of charge, to any person obtaining a copy  
  97.        of this software and associated documentation files (the "Software"), to deal  
  98.        in the Software without restriction, including without limitation the rights  
  99.        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
  100.        copies of the Software, and to permit persons to whom the Software is  
  101.        furnished to do so, subject to the following conditions:  
  102.        
  103.        The above copyright notice and this permission notice shall be included in all  
  104.        copies or substantial portions of the Software.  
  105.        
  106.        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
  107.        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
  108.        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
  109.        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
  110.        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
  111.        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
  112.        SOFTWARE.   
  113.  
  114.  *)
  115.  
  116.  
  117. -- Gets invoked here when you run in AppleScript editor or double click on the app icon.
  118. on run
  119.     global debug
  120.     global squashRedundentURL
  121.     global droppedFileName
  122.    
  123.     -- Write a message into the event log.
  124.     log "  --- Starting on " & ((current date) as string) & " --- "
  125.    
  126.     -- 3 and 6 are good to use
  127.     set debug to 0
  128.     -- 0 no debugging
  129.     -- 1 displays input and output to this routine
  130.     -- 2 moderate
  131.     -- 3 display important "on" blocks
  132.     -- 4 display end of important "on" blocks
  133.     -- 5 display minor "on" blocks
  134.     -- 6 intense
  135.     -- 7 routines the spew lots of data
  136.    
  137.     -- how do we process the <a> tag?
  138.     set squashRedundentURL to true
  139.     -- true -- get title for anchor
  140.     -- false -- let title of anchor be the same as the link
  141.    
  142.     -- debugging
  143.     set droppedFileName to "::: from clipboard :::"
  144.    
  145.     set lf to character id 10
  146.    
  147.     if debug ≥ 3 then log "in --- run ---"
  148.    
  149.     --set the clipboard to wrapupClipboardDataSelector()
  150.    
  151.     set theList to clipboard info
  152.     if debug ≥ 2 then printClipboardInfo(theList)
  153.    
  154.     set cbInfo to get (clipboard info) as string
  155.    
  156.     -- Most likely, if we have HTML data in the clipboard it will be from a web browser or Word.
  157.     if cbInfo contains "HTML" then
  158.        
  159.         if debug ≥ 2 then log "Working with HTML Class data from clipboard."
  160.         set theBoard to the clipboard as «class HTML»
  161.        
  162.         set normalHtml to do shell script "osascript -e 'try' -e 'get the clipboard as «class HTML»' -e 'end try' | awk '{sub(/«data HTML/, \"\") sub(/»/, \"\")} {print}' | xxd -r -p "
  163.         if debug ≥ 1 then
  164.             log "...Print out plain text version of inputed HTML data from the clipboard..." & return & normalHtml
  165.             hexDumpFormatOne("after converting to printable, normalHtml", normalHtml)
  166.         end if
  167.        
  168.         set normalHtml to adjustCharacters(normalHtml)
  169.        
  170.         set returnedData to adjustBrowserHTML(normalHtml)
  171.         if debug ≥ 2 then
  172.             log "...Print out plain text version of adjusted HTML data ..." & return & returnedData
  173.             log "...just printed plain text version"
  174.             log "printed in hex"
  175.             hexDumpFormatOne("returnedData", returnedData)
  176.         end if
  177.        
  178.         set returnedData to convertToHTML(returnedData)
  179.         try
  180.             if debug ≥ 2 then log "returnedData is " & returnedData
  181.         on error errStr number errorNumber
  182.             log "===> We didn't find HTML data.   errStr is " & errStr & " errorNumber is " & errorNumber
  183.             return 1
  184.         end try
  185.     else
  186.         -- will work with a plain html or plain text.
  187.         try
  188.             if debug ≥ 2 then log "Working with plain html or plain text"
  189.             set clipboardData to (the clipboard as text)
  190.             if debug ≥ 2 then
  191.                 log "class clipboardData is " & class of clipboardData
  192.                 log "continuing plain html or plain text"
  193.             end if
  194.            
  195.             if debug ≥ 1 then
  196.                 log "inputted clipboardData is " & clipboardData
  197.                 hexDumpFormatOne("inputted clipboardData", clipboardData)
  198.             end if
  199.         on error errStr number errorNumber
  200.             log "===> We didn't find data on the clipboard.   errStr is " & errStr & " errorNumber is " & errorNumber
  201.             display dialog "We didn't find HTML source code nor plain text on the clipboard." & return & "Please copy from a different source." giving up after 15
  202.             return 1
  203.         end try
  204.         if debug ≥ 2 then log "calling common"
  205.         set returnedData to common(clipboardData)
  206.     end if
  207.     if debug ≥ 2 then log "place on the clipboard returnedData is " & returnedData
  208.     postToCLipboard(returnedData)
  209.     -- return code
  210.     return 0
  211.    
  212. end run
  213.  
  214. -- Folder actions.
  215. -- Gets invoked here when something is dropped on the folder that this script is monitoring.
  216. -- Right click on the folder to be monitored. services > Folder Action Settup...
  217. on adding folder items to this_folder after receiving added_items
  218.     -- Write a message into the event log.
  219.     log "  --- Starting on " & ((current date) as string) & " --- "
  220.     display dialog "TBD, some assembly required."
  221. end adding folder items to
  222.  
  223.  
  224.  
  225. -- Gets invoked here when something is dropped on this AppleScript icon
  226. on open dropped_items
  227.     global debug
  228.     global squashRedundentURL
  229.     global droppedFileName
  230.    
  231.     -- see on run for details
  232.     set debug to 0
  233.    
  234.     -- how do we process the <a> tag?
  235.     set squashRedundentURL to true
  236.     -- true -- get title for anchor
  237.     -- false -- let title of anchor be the same as the link
  238.    
  239.     -- debugging
  240.     set droppedFileName to ""
  241.    
  242.     -- debuging for this module.  Puts out timed display dialogs.
  243.     set localDebug to false
  244.     -- true displayed timed dialogs
  245.     -- false skip debuging
  246.    
  247.     set debugSeparator to true
  248.     -- true place a separator between the output of dropped files
  249.     -- false nothing is added
  250.    
  251.    
  252.     -- Write a message into the event log.
  253.     log "  --- Starting on " & ((current date) as string) & " --- "
  254.     if debug ≥ 3 then log "in --- open ---"
  255.    
  256.    
  257.     (*
  258.     -- Debug code.
  259.       set fileName to choose file with prompt "get file"
  260.       set dropped_items to {fileName}
  261.     *)
  262.     if debug ≥ 2 then log "class of dropped_items is " & class of dropped_items
  263.     if (count of dropped_items) is 1 then
  264.         set substitueString to (count of dropped_items) & " item."
  265.     else
  266.         set substitueString to (count of dropped_items) & " items."
  267.     end if
  268.     display dialog "You dropped " & substitueString & return & "  Caveat emptor. You have been warned." giving up after 6
  269.    
  270.     set totalFileData to ""
  271.     repeat with droppedItem in dropped_items
  272.         set droppedFileName to droppedItem as string
  273.         if debug ≥ 2 then
  274.             log "The droppedItem is "
  275.             if localDebug then display dialog "processing file " & (droppedItem as string) giving up after 3
  276.             log droppedItem
  277.             log "class = " & class of droppedItem
  278.         end if
  279.         set extIs to findExtension(droppedItem)
  280.         set extIsU to makeCaseUpper(extIs)
  281.         if extIsU is "HTML" or extIsU is "HTM" or extIsU is "TEXT" or extIsU is "TXT" then
  282.             try
  283.                
  284.                 set theFileString to droppedItem as string
  285.                 if localDebug is true and debug is 0 then display dialog "theFileString " & return & theFileString giving up after 3
  286.                 set theFile to open for access file theFileString
  287.                 set allOfFile to read theFile
  288.                 close access theFile
  289.             on error theErrorMessage number theErrorNumber
  290.                 log "==> " & theErrorMessage & "error number " & theErrorNumber
  291.                 close access theFile
  292.             end try
  293.             if debug ≥ 2 then printHeader("read from file ( allOfFile )", allOfFile)
  294.            
  295.             --if localDebug then display dialog "processing " giving up after 3
  296.             if debugSeparator then
  297.                 -- get just the filename and extension
  298.                 set justTheName to last item of textToList(theFileString, ":")
  299.                 -- prevent your web broswer from acting on html like text
  300.                 set justTheName to alterString(justTheName, "&", "&amp;")
  301.                 set justTheName to alterString(justTheName, "<", "&lt;")
  302.                 set totalFileData to totalFileData & convertToHTML("<p><pre>&nbsp;&nbsp;--&gt;&nbsp;" & justTheName & "&nbsp&lt;--</pre></p>")
  303.                 if localDebug then display dialog "length and data of totalFileData   " & (length of totalFileData) & return & totalFileData giving up after 3
  304.             end if
  305.            
  306.             -- returns data converted to clipboard html
  307.             set totalFileData to totalFileData & common(allOfFile)
  308.             if localDebug then display dialog "after length and data of totalFileData   " & (length of totalFileData) & return & totalFileData giving up after 3
  309.         else
  310.             -- we do not support this extension
  311.             if localDebug then display dialog "We only support files with extenstion of html, htm, text or txt in either case. Your file had a " & extIs & " extention. Skipping" giving up after 10
  312.         end if
  313.     end repeat
  314.    
  315.     postToCLipboard(totalFileData)
  316.     if localDebug then display dialog "posted to clipboard length and data " & (length of totalFileData) & return & totalFileData giving up after 20
  317.     -- return code
  318.     return 0
  319.    
  320. end open
  321.  
  322.  
  323. -- ------------------------------------------------------
  324. on common(clipboardData)
  325.     global debug
  326.     if debug ≥ 3 then log "in --- common ---"
  327.     set ht to character id 9
  328.     set lf to character id 10
  329.     set cbInfo to get (clipboard info) as string
  330.    
  331.     set clipboardData to adjustCharacters(clipboardData)
  332.     (*
  333.     -- for some crazy reason, I found hex "090a" (HT LF) in a html file.
  334.     set clipboardData to alterString(clipboardData, ht & lf, lf)
  335.     -- don't let Windoze confuse us. convert Return LineFeed to lf
  336.     set clipboardData to alterString(clipboardData, return & lf, lf)
  337.     -- might as will convert classic macOS return to lf. We will have to look for less things.
  338.     set clipboardData to alterString(clipboardData, return, lf)
  339.     if debug ≥ 2 then hexDumpFormatOne("change various line ends to a LF. clipboardData", clipboardData)
  340.     *)
  341.    
  342.     -- figure out what type of data we have: plain text or html source code text.
  343.     set paraCount to count of textToList(clipboardData, "<p")
  344.     set endparaCount to count of textToList(clipboardData, "</p>")
  345.     set titleCount to count of textToList(clipboardData, "<title")
  346.     set endTitleCount to count of textToList(clipboardData, "</title>")
  347.     set aLinkCount to count of textToList(clipboardData, "href=\"http")
  348.     -- mangled href="http
  349.     set mangledLinkCount to count of textToList(clipboardData, "href=\\\"http")
  350.     set brCount to count of textToList(clipboardData, "<br>")
  351.     if debug ≥ 2 then
  352.         log "Values used to distinguis HTML source code from plain text."
  353.         log "paraCount  is " & paraCount
  354.         log "endparaCount is " & endparaCount
  355.         log "titleCount is " & titleCount
  356.         log "endTitleCount is " & endTitleCount
  357.         log "aLinkCount is " & aLinkCount
  358.         log "brCount is " & brCount
  359.         log "mangledLinkCount is " & mangledLinkCount
  360.     end if
  361.    
  362.     -- note, textToList returns a count one greater than the actual because item one is the data before the first found entry.
  363.     if paraCount ≥ 4 and endparaCount ≥ 3 or brCount ≥ 4 or ((titleCount is endTitleCount) and titleCount ≥ 2) or aLinkCount ≥ 3 or mangledLinkCount ≥ 3 then
  364.         -- ASC tends to convert line-ends to either <p></p> or <p><br></p>. Isn't desireable for HTML input
  365.         if debug ≥ 2 then log "... found HTML input ... (in plain text format )."
  366.         set clipboardData to adjustBrowserHTML(clipboardData)
  367.        
  368.     else
  369.         if debug ≥ 2 then log "... found plain Text input ..."
  370.         set clipboardData to typeText(clipboardData)
  371.     end if
  372.     set readyData to convertToHTML(clipboardData)
  373.     if debug ≥ 4 then log "bye from  -.- common -.-"
  374.     return readyData
  375. end common
  376.  
  377. -- ------------------------------------------------------  
  378. (* add paragraphs *)
  379. on addParagraphs(theOutputBuffer)
  380.     global debug
  381.     if debug ≥ 3 then log "in --- addParagraphs ---"
  382.     set lf to character id 10
  383.    
  384.     -- start the theOutputBuffer with a paragraph tag.  We are taking a simple approach at this time.
  385.     set theOutputBuffer to "<p>" & theOutputBuffer
  386.     --  LF
  387.     -- Remember CRLF was changed to LF above and CR was chanaged to LF above.
  388.     -- we don't want no Windoze problems
  389.     set theOutputBuffer to alterString(theOutputBuffer, lf & lf, "</p><p> </p><p>")
  390.    
  391.     -- Does the string end with a dangling paragraph?  
  392.     if debug ≥ 5 then
  393.         log "length of theOutputBuffer is " & length of theOutputBuffer
  394.     end if
  395.     if (length of theOutputBuffer) > (length of "</p>") then
  396.         if text ((length of theOutputBuffer) - 2) thru (length of theOutputBuffer) of theOutputBuffer is "<p>" then
  397.             set theOutputBuffer to text 1 thru ((length of theOutputBuffer) - 3) of theOutputBuffer
  398.         else if text ((length of theOutputBuffer) - 2) thru (length of theOutputBuffer) of theOutputBuffer is not "</p>" then
  399.             set theOutputBuffer to theOutputBuffer & "</p>"
  400.         end if
  401.     end if
  402.     if debug ≥ 4 then log "bye from  -.- addParagraphs -.-"
  403.     return theOutputBuffer
  404. end addParagraphs
  405.  
  406. -- ------------------------------------------------------
  407. (*
  408.   We received HTML class data on the clipboard.  This is the manager.
  409.   At this point, we expect only LFs in the text.
  410.  *)
  411. on adjustBrowserHTML(normalHtml)
  412.     global debug
  413.     if debug ≥ 3 then log "in --- adjustBrowserHTML ---"
  414.     set lf to character id 10
  415.    
  416.     set alteredHTML to adjustURLs(normalHtml)
  417.     set alteredHTML to adjustToAscHTML(alteredHTML)
  418.     if debug ≥ 4 then log "bye from  -.- adjustBrowserHTML -.-"
  419.     return alteredHTML
  420. end adjustBrowserHTML
  421.  
  422. -- ------------------------------------------------------
  423. (*
  424.     Symbol  Meaning                 Hex     Used
  425.         CR      Carriage Return         0d      classic Macintosh
  426.         LF      Line Feed                       0a      UNIX
  427.         CR/LF   Carriage Return/Line Feed   0d0a    MS-DOS, Windows, OS/2
  428.        
  429.     8230    U+2026  E2 80 A6    … Horizontal Ellipsis
  430.         https://www.charset.org/utf-8/9
  431.        &hellip;
  432.         https://www.toptal.com/designers/htmlarrows/punctuation/horizontal-ellipsis/
  433.  
  434.     *)
  435. on adjustCharacters(normalHtml)
  436.     global debug
  437.     set ht to character id 9 -- horizontal tab
  438.     set lf to character id 10
  439.     set ellipsis1 to character id 226
  440.     set ellipsis2 to character id 128
  441.     set ellipsis3 to character id 166
  442.    
  443.     if debug ≥ 3 then log "in --- adjustCharacters() ---"
  444.    
  445.     -- for some reason web broswers are having difficulty with utf-8 E2 80 A6
  446.     -- so convert to a HTML entity.  does work in <pre>
  447.     set normalHtml to alterString(normalHtml, ellipsis1 & ellipsis2 & ellipsis3, "&hellip;")
  448.    
  449.     -- don't let Windoze confuse us. convert Return LineFeed to lf
  450.     set normalHtml to alterString(normalHtml, return & lf, lf)
  451.     -- might as will convert classic macOS return to lf. We will have to look for less things.
  452.     set normalHtml to alterString(normalHtml, return, lf)
  453.     if debug ≥ 3 then hexDumpFormatOne("after altering characters normalHtml", normalHtml)
  454.     return normalHtml
  455. end adjustCharacters
  456.  
  457. -- ------------------------------------------------------
  458. (*
  459.    Is the displayed title the same as the href URL?
  460.    <a href="https://support.apple.com/en-ca/HT204759">https://support.apple.com/en-ca/HT204759</a>
  461. *)
  462. on adustDuplicateAnchorURLs(anchorTagInput)
  463.     global debug
  464.     global squashRedundentURL
  465.     set lf to character id 10
  466.    
  467.     if debug ≥ 3 then log "in --- adustDuplicateAnchorURLs ---"
  468.    
  469.     -- reduce LFs in title
  470.     set anchorTagString to alterString(anchorTagInput, lf, " ")
  471.     if debug ≥ 2 then hexDumpFormatOne("  adustDuplicateAnchorURLs: anchorTagString", anchorTagString)
  472.    
  473.     -- Does the user want us to get the title for duplicate URLs?
  474.     if squashRedundentURL is false then
  475.         return anchorTagString -- --------- ignore duplicates ---------->
  476.     end if
  477.    
  478.     if debug ≥ 2 then log "  adustDuplicateAnchorURLs: anchorTagString is " & anchorTagString
  479.     set splitList to textToList(anchorTagString, "href=")
  480.     if debug ≥ 4 then printList("adustDuplicateAnchorURLs: splitList", splitList)
  481.     set hrefURL to tagContent(item 2 of splitList, "\"", "\"")
  482.     if debug ≥ 2 then log "  adustDuplicateAnchorURLs: hrefURL is " & hrefURL
  483.     set titleURL to tagContent(item 2 of splitList, ">", "<")
  484.     if hrefURL is not titleURL then
  485.         return anchorTagString -- --------- assume we have the title ---------->
  486.     end if
  487.    
  488.     -- They are the same
  489.     if debug ≥ 2 then log "  adustDuplicateAnchorURLs: href and title are the same."
  490.     set gotTitle to getTitle(hrefURL)
  491.     if debug ≥ 2 then log "  adustDuplicateAnchorURLs: gotTitle is " & gotTitle
  492.    
  493.     -- build anchor tag.
  494.     set anchorTrailer to textToList(item 2 of splitList, ">")
  495.     if debug ≥ 4 then printList("adustDuplicateAnchorURLs: anchorTrailer", anchorTrailer)
  496.     set anchorTagOutput to (item 1 of splitList) & " href=" & item 1 of anchorTrailer & ">" & gotTitle & "</a>"
  497.     if debug ≥ 2 then log "  adustDuplicateAnchorURLs: anchorTagOutout is " & anchorTagOutput
  498.     return anchorTagOutput
  499.    
  500.    
  501. end adustDuplicateAnchorURLs
  502.  
  503. -- ------------------------------------------------------
  504. -- called for HTML processing
  505. on adjustLF(theBuffer)
  506.     global debug
  507.     set ht to character id 9
  508.     set lf to character id 10
  509.     if debug ≥ 3 then log "in --- adjustLF() ---"
  510.     if debug ≥ 2 then hexDumpFormatOne("  adjustLF: input from theBuffer", theBuffer)
  511.     set numberOfLf to 1 -- for debuggin so we can display loop count
  512.    
  513.     set inputLfBuffer to theBuffer -- now, input data
  514.     set outputBuildLf to "" -- output data
  515.     -- copy & change
  516.     -- ditch leading LFs
  517.     repeat while length of inputLfBuffer ≥ 2 and text 1 thru 1 of inputLfBuffer is lf
  518.         if debug ≥ 2 then log "  adjustLF: found leading lf. current length of inputLfBuffer is " & getIntegerAndHex(length of inputLfBuffer)
  519.         -- just lob off LF
  520.         set inputLfBuffer to text 2 thru -1 of inputLfBuffer
  521.        
  522.         log "  adjustLF: next text character is " & text 1 thru 1 of inputLfBuffer
  523.     end repeat
  524.     -- for some crazy reason, I found hex "090a" (HT LF) in a html file.
  525.     set inputLfBuffer to alterString(inputLfBuffer, ht & lf, lf)
  526.     repeat until inputLfBuffer is ""
  527.        
  528.         set whereLfOffset to offset of lf in inputLfBuffer
  529.         if debug ≥ 2 then log "  adjustLF: whereLfOffset is " & whereLfOffset & " in hex " & integerToHex(whereLfOffset)
  530.        
  531.         -- get before and after characters if present.
  532.         if whereLfOffset ≥ 2 then
  533.             set priorCharacter to (text (whereLfOffset - 1) thru (whereLfOffset - 1) in inputLfBuffer)
  534.         else
  535.             set priorCharacter to ""
  536.         end if
  537.         if whereLfOffset ≥ (length of inputLfBuffer) then
  538.             -- no following character
  539.             set followingCharacter to ""
  540.         else
  541.             set followingCharacter to (text (whereLfOffset + 1) thru (whereLfOffset + 1) in inputLfBuffer)
  542.         end if
  543.         if debug ≥ 2 then log "  adjustLF: priorCharacter is >" & priorCharacter & "< followingCharacter is >" & followingCharacter & "<"
  544.        
  545.         -- process the LF. 
  546.         if (whereLfOffset is 1) and ((length of inputLfBuffer)2) then
  547.             set inputLfBuffer to text 2 thru -1 of inputLfBuffer
  548.             if debug ≥ 2 then log "  adjustLF: leading lf.  Got rid of it."
  549.             -- nothing to move to outputBuildLf            
  550.         else if (whereLfOffset is 1) and ((length of inputLfBuffer) is 1) then
  551.             -- we have found all theLFs to find.
  552.             set inputLfBuffer to ""
  553.             if debug ≥ 2 then log "  adjustLF: only one character left.  Got rid of it."
  554.         else if followingCharacter is "" then
  555.             if debug ≥ 2 then log "null"
  556.             -- didn't we just check this? Yes, but we need to iterate somehow.
  557.             set {inputLfBuffer, outputBuildLf} to trimOneChar(inputLfBuffer, outputBuildLf, whereLfOffset, " ")
  558.             -- just skip it, so we don't have to put anything on outputBuildLf
  559.         else if priorCharacter is not ">" and priorCharacter is not " " and followingCharacter is lf then
  560.             -- reduce a series of LFs to one blank
  561.             -- the next time around the next LF will be comparing to the prior character
  562.             -- as a blank
  563.             if debug ≥ 2 then log "  adjustLF: series of LFs"
  564.             set {inputLfBuffer, outputBuildLf} to trimOneChar(inputLfBuffer, outputBuildLf, whereLfOffset, " ")
  565.         else if priorCharacter is " " and followingCharacter is tab then
  566.             -- reduce a series of LFs to one blank
  567.             -- the next time around the next LF will be comparing to the prior character
  568.             -- as a blank
  569.             if debug ≥ 2 then log "  adjustLF: series of LFs"
  570.             set {inputLfBuffer, outputBuildLf} to trimOneChar(inputLfBuffer, outputBuildLf, whereLfOffset, "")
  571.             set {inputLfBuffer, outputBuildLf} to trimCharacters(inputLfBuffer, outputBuildLf, tab)
  572.         else if priorCharacter is ">" and followingCharacter is not " " then
  573.             --  LF after HTML tag. no real need for lf here.  asc tends to make these into <p></p>
  574.             if debug ≥ 2 then log "  adjustLF: found a tag"
  575.             -- copy prior stuff
  576.             set {inputLfBuffer, outputBuildLf} to trimOneChar(inputLfBuffer, outputBuildLf, whereLfOffset, "")
  577.         else if followingCharacter is lf then
  578.             -- prevent double LFs.
  579.             if debug ≥ 2 then log "  adjustLF: prevent double LFs at" & getIntegerAndHex(whereLfOffset)
  580.             set {inputLfBuffer, outputBuildLf} to trimOneChar(inputLfBuffer, outputBuildLf, whereLfOffset, "")
  581.             -- middle of text
  582.         else if (whereLfOffset < (length of inputLfBuffer)) and followingCharacter is " " then
  583.             -- we need to avoid double blanks
  584.             -- purge
  585.             if debug ≥ 2 then log "  adjustLF: getting rid of lf at " & getIntegerAndHex(whereLfOffset)
  586.             -- skip lf.
  587.             set {inputLfBuffer, outputBuildLf} to trimOneChar(inputLfBuffer, outputBuildLf, whereLfOffset, " ")
  588.             -- get read of leading spaces.  That is the spaces after the lf
  589.             set {inputLfBuffer, outputBuildLf} to trimCharacters(inputLfBuffer, outputBuildLf, " ")
  590.         else
  591.             -- assume there are character before and after the LF.
  592.             if debug ≥ 2 then log "  adjustLF: punt."
  593.             -- replace with blank
  594.             set {inputLfBuffer, outputBuildLf} to trimOneChar(inputLfBuffer, outputBuildLf, whereLfOffset, " ")
  595.         end if
  596.        
  597.         if debug ≥ 2 then
  598.             hexDumpFormatOne("  adjustLF: outputBuildLf of " & numberOfLf, outputBuildLf)
  599.             hexDumpFormatOne("  adjustLF: inputLfBuffer of " & numberOfLf, inputLfBuffer)
  600.         end if
  601.         -- next pass will be
  602.         set numberOfLf to numberOfLf + 1
  603.     end repeat
  604.     if debug ≥ 4 then log "bye from  -.- adjustLF() -.-"
  605.     return outputBuildLf
  606. end adjustLF
  607.  
  608. -- ------------------------------------------------------
  609. (* ASC likes to insert lots of white space into a page.
  610.   This routine attempt to fix up the html to avoid
  611.   all the extra white-space.
  612.  
  613.    Minimize the amount of white space inserted.
  614.  *)
  615.  
  616. on adjustToAscHTML(ascHtml)
  617.     global debug
  618.     if debug ≥ 3 then log "in --- adjustToAscHtml ---"
  619.     set lf to character id 10
  620.     set numberOfPres to 1
  621.     -- In the context of HTML, LF should mostly be insignificant.
  622.     -- Would be bad to change a LF inside the <pre>  tag.
  623.     --skip changing lf in "<pre>.  
  624.     set buildHtml to "" -- will contain the output
  625.     if debug ≥ 2 then log "find <pre>s"
  626.     -- copy & change
  627.     if (offset of "</pre>" in ascHtml) is not 0 then
  628.         repeat while (offset of "</pre>" in ascHtml) is not 0
  629.             -- get text before "<pre" tag
  630.             set splitString to item 1 of splitTextToList(ascHtml, "<pre")
  631.             if debug ≥ 2 then
  632.                 log "splitString is " & splitString
  633.                 hexDumpFormatOne("buildHtml *before* adjustLF()", buildHtml)
  634.             end if
  635.             set buildHtml to buildHtml & adjustLF(splitString)
  636.             hexDumpFormatOne("buildHtml after adjustLF()", buildHtml)
  637.            
  638.             -- lob off header text we processed
  639.             -- while we found the text before "<pre", we still need to get it out
  640.             -- of ascHtml
  641.             --  & gets rid of the token ("<pre"), so fix
  642.             set ascHtml to "<pre" & chompLeftAndTag(ascHtml, "<pre")
  643.            
  644.             -- any more <pre> tags?
  645.             if ascHtml is "" then
  646.                 display dialog "HTML missing </pre> tag. possible logic error." giving up after 10
  647.                 -- none. We have already adjusted buildHtml
  648.                 exit repeat -- ------ done processing ascHtml ------>
  649.             end if
  650.             if debug ≥ 2 then hexDumpFormatOne("remaining ascHtml is ", ascHtml)
  651.            
  652.             -- tack on the unaltered <pre>..</pre> stuff
  653.             set buildHtml to buildHtml & (item 1 of splitTextToList(ascHtml, "</pre>")) & "</pre>"
  654.             if debug ≥ 2 then hexDumpFormatOne("buildHtml after finding </pre>", buildHtml)
  655.            
  656.             set ascHtml to chompLeftAndTag(ascHtml, "</pre>")
  657.             if debug ≥ 2 then hexDumpFormatOne("ascHtml end of " & numberOfPres & " pass", ascHtml)
  658.             set numberOfPres to numberOfPres + 1
  659.            
  660.         end repeat
  661.         -- remainder
  662.         set buildHtml to buildHtml & adjustLF(ascHtml)
  663.         set ascHtml to ""
  664.     else
  665.         -- lf's are only signigicant in <pre>...</pre>
  666.         if debug ≥ 2 then log "didn't find a <pre>"
  667.         -- all others are white space.
  668.         set buildHtml to adjustLF(ascHtml)
  669.         set ascHtml to "" -- input text processed
  670.     end if
  671.    
  672.    
  673.     (*
  674.     Hack about to fix ASC interpretation of HTML.
  675.    
  676.     ASC alters the definition of a paragraph to have not space before or after the paragraph.
  677.     A paragraph like <p></p> works like a <br>.
  678.    
  679.     Consequently, ASC converts <p> </p> to <p><br></p>, that is a
  680.     space only paragraph to a paragraph with a <br> in it.
  681.    
  682.     the code converts one tag on a line to a line of tags.
  683.     </ol>
  684.     </p>
  685.     <p>
  686.     converted form
  687.     </ol></p><p>
  688.    
  689.     so that means a change on </ol></p><p> converts both the multi-lines form and the single line form.
  690.    
  691.     *)
  692.     set buildHtml to alterString(buildHtml, "<br> ", "<br>")
  693.     -------------------- failure???
  694.     --set buildHtml to alterString(buildHtml, "<p> ", "<p>")
  695.    
  696.     -- asc paragraphs don't generate space before and after the paragraph.
  697.     set buildHtml to alterString(buildHtml, "</p><p></p><p></p>", "</p><p> </p><p></p>")
  698.    
  699.     set buildHtml to alterString(buildHtml, "</p><p></p><p></p>", "</p><p> </p><p></p>")
  700.    
  701.     set buildHtml to alterString(buildHtml, "</ol></p><p>", "</ol><p> </p></p><p>")
  702.     (*
  703.     surprisingly ASC converts <p> </p> to <p><br></p>, that is a
  704.     space only paragraph to a paragraph with a <br> in it.
  705.    
  706.     the code converts one tag on a line to a line of tags.
  707.     </ol>
  708.     </p>
  709.     <p>
  710.     converted form
  711.     </ol></p><p>
  712.    
  713.     so that means a change on </ol></p><p> converts both the multi-lines form and the single line form.
  714.    
  715.     *)
  716.     --set buildHtml to alterString(buildHtml, "<p> </p>", "<p></p>")
  717.     if debug ≥ 2 then hexDumpFormatOne("complete buildHtml ", buildHtml)
  718.     if debug ≥ 4 then log "bye from  -.- adjustToAscHTML -.-"
  719.     return buildHtml
  720. end adjustToAscHTML
  721.  
  722. -- ------------------------------------------------------
  723. (*
  724. example:
  725.   Free version of Parallels for individual use:</p><p><br></p>
  726.   <p>https://itunes.apple.com/us/app/parallels-desktop-lite/id1085114709?mt=12</p>
  727.   <p><br></p>
  728.   <p>Full version</p><p><a href="http://www.parallels.com/en/products/desktop/" target="_blank">
  729.      http://www.parallels.com/en/products/desktop/</a>
  730.      
  731. If asc find a URL outside of an a tag, it will place blank lines around the URL. No, it will not go the
  732. full nine yards and place an a tag around the url.
  733.  
  734. *)
  735. on adjustURLs(theOriginalInputBuffer)
  736.     global debug
  737.     if debug ≥ 3 then log "in --- adjustURLs ---"
  738.     set alteredBuffer to false
  739.     set lf to character id 10
  740.     set theInputBuffer to theOriginalInputBuffer
  741.     if debug ≥ 2 then hexDumpFormatOne("  adjustURLs: theInputBuffer", theInputBuffer)
  742.    
  743.     -- we end up in a lot of grief when the buffer ends without
  744.     -- a line-end
  745.     if text (length of theInputBuffer) thru (length of theInputBuffer) of theInputBuffer is not lf then
  746.         -- tack LF at the end
  747.         set alteredBuffer to true
  748.         set theInputBuffer to theInputBuffer & lf
  749.         if debug ≥ 2 then hexDumpFormatOne("  adjustURLs: theInputBuffer", theInputBuffer)
  750.     end if
  751.    
  752.     set buildHtml to ""
  753.     if debug ≥ 5 then log "  adjustURLs: buildHTML [ should be empty string ] is " & buildHtml
  754.     set countI to 1 -- variable is used for debuging.
  755.     -- do until we have processed theInputBuffer
  756.     repeat until theInputBuffer is ""
  757.         if debug ≥ 2 then log "  adjustURLs: at the top of theInputBuffer ........."
  758.        
  759.         set foundWhere to {}
  760.         repeat with lookCharacters in {"https://", "http://", "<a "}
  761.             copy (offset of lookCharacters in theInputBuffer) to the end of the foundWhere
  762.             try
  763.                 set tempLoc to (offset of lookCharacters in theInputBuffer)
  764.                 if debug ≥ 2 then log "  adjustURLs: searching for " & lookCharacters & " found at offset  " & tempLoc & " contains " & text tempLoc thru (tempLoc + ((length of lookCharacters) - 1)) of theInputBuffer
  765.             end try
  766.         end repeat
  767.         if debug ≥ 2 then log foundWhere
  768.         set foundMarkerOffset to (minimumPositiveNumber from foundWhere)
  769.         -- figure out what type of marker we got?
  770.        
  771.         -- None.  Reached the end of the data without finding one.
  772.         if foundMarkerOffset ≤ 0 then
  773.             -- we are done
  774.             if debug ≥ 2 then log "  adjustURLs: Found all links."
  775.             set buildHtml to buildHtml & theInputBuffer
  776.             if debug ≥ 2 then printHeader("  adjustURLs: buildHTML", buildHtml)
  777.             set theInputBuffer to ""
  778.             exit repeat -- ------ done processing theInputBuffer ------>
  779.         end if
  780.        
  781.         -- find which of three markers we found.
  782.         if (text foundMarkerOffset thru (foundMarkerOffset + 2) of theInputBuffer) is "<a " then
  783.             set actualMarker to "<a "
  784.         else if text foundMarkerOffset thru (foundMarkerOffset + 6) of theInputBuffer is "http://" then
  785.             set actualMarker to "http://"
  786.         else
  787.             -- just assume it's the remaining "https://" since we looked for just three.
  788.             set actualMarker to "https://"
  789.         end if
  790.         set actualMarkerOffsetLength to ((length of actualMarker) - 1)
  791.         if debug ≥ 2 then
  792.             log "  adjustURLs: actualMarker is " & actualMarker & " actualMarkerOffsetLength is " & actualMarkerOffsetLength
  793.             log "  adjustURLs: foundMarkerOffset is " & getIntegerAndHex(foundMarkerOffset) & "  verify marker text is " & text foundMarkerOffset thru (foundMarkerOffset + actualMarkerOffsetLength) of theInputBuffer
  794.         end if
  795.        
  796.        
  797.         if foundMarkerOffset ≥ 2 then
  798.             -- collect and strip off characters that are before the marker.
  799.             if debug ≥ 2 then
  800.                 log "  adjustURLs: buildHTML is " & buildHtml & " length is " & getIntegerAndHex(length of buildHtml)
  801.                 hexDumpFormatOne("  adjustURLs: theInputBuffer", theInputBuffer)
  802.                 log "  adjustURLs:  (foundMarkerOffset - 1) is " & getIntegerAndHex((foundMarkerOffset - 1))
  803.             end if
  804.             -- get the proceding text
  805.             set buildHtml to buildHtml & text 1 thru (foundMarkerOffset - 1) of theInputBuffer
  806.             if debug ≥ 2 then
  807.                 log "  adjustURLs: buildHTML is " & buildHtml
  808.                 hexDumpFormatOne("  adjustURLs: buildHTML", buildHtml)
  809.             end if
  810.            
  811.             -- https://apple.stackexchange.com/a/20135/44531
  812.            
  813.             set theInputBuffer to text foundMarkerOffset thru -1 of theInputBuffer --trim off character before what we found
  814.             if debug ≥ 2 then
  815.                 printHeader("  adjustURLs: theInputBuffer", theInputBuffer)
  816.                 hexDumpFormatOne("  adjustURLs: theInputBuffer", theInputBuffer)
  817.             end if
  818.         else
  819.             log "  adjustURLs: ==> no proceeding data."
  820.         end if
  821.        
  822.         repeat 1 times -- interate loop
  823.            
  824.             -- example" the url is also the display text
  825.             -- <a href="https://discussions.apple.com/docs/DOC-8841" target="_blank">https://discussions.apple.com/docs/DOC-8841</a>
  826.             if debug ≥ 2 then hexDumpFormatOne("  adjustURLs: theInputBuffer", theInputBuffer)
  827.            
  828.             -- check for the <a> tag
  829.             if text 1 thru (length of "<a ") of theInputBuffer is "<a " then
  830.                 -- found <a> tag
  831.                 if debug ≥ 2 then log "  adjustURLs: processing <a> tag"
  832.                 -- ASC consider a line-end as a <br> when when firefox considers it a blank
  833.                 -- change a possible line-end before an <a> tag to a " "
  834.                 if debug ≥ 2 then hexDumpFormatOne("  adjustURLs: before lf check buildHTML", buildHtml)
  835.                 if text (length of buildHtml) thru (length of buildHtml) of buildHtml is lf then
  836.                     if debug ≥ 2 then log "  adjustURLs: we need to delete a line-end before the <a> tag"
  837.                     set buildHtml to text 1 thru ((length of buildHtml) - 1) of buildHtml
  838.                     set buildHtml to buildHtml & " "
  839.                     if debug ≥ 2 then hexDumpFormatOne("  adjustURLs: after lf deletion buildHTML", buildHtml)
  840.                 end if
  841.                 -- find ending </a> tag
  842.                 set whereEnds to offset of "</a>" in theInputBuffer
  843.                 if whereEnds ≤ 0 then
  844.                     if debug ≥ 2 then log "  adjustURLs: ==> found an error in the HTML.  no ending </a>"
  845.                     set buildHtml to buildHtml & theInputBuffer
  846.                     printHeader("  adjustURLs: buildHTML", buildHtml)
  847.                     set theInputBuffer to ""
  848.                     display dialog "  adjustURLs: Found an error in the HTML.  No ending </a>.  Will skip." giving up after 10
  849.                     exit repeat -- ------ next ------>
  850.                 end if
  851.                 set lastOffsetLength to ((length of "</a>") - 1)
  852.                 if debug ≥ 2 then log "  adjustURLs: lastOffsetLength is " & lastOffsetLength
  853.                 set lastCharacterOffset to whereEnds + lastOffsetLength
  854.                 if debug ≥ 2 then log "  adjustURLs: lastCharacterOffset is " & getIntegerAndHex(lastCharacterOffset)
  855.                 -- needs to copy the ending ">"
  856.                 set anchorString to text 1 thru lastCharacterOffset of theInputBuffer
  857.                 -- don't let Windoze confuse us. convert Return LineFeed to lf
  858.                 -- Correct absure ASC bug where there is a line-end in the <a> text.
  859.                 if debug ≥ 2 then hexDumpFormatOne("  adjustURLs: before adjusting anchorString", anchorString)
  860.                 set anchorString to alterString(anchorString, lf, " ")
  861.                 if debug ≥ 2 then hexDumpFormatOne("  adjustURLs: anchorString", anchorString)
  862.                 set anchorString to adustDuplicateAnchorURLs(anchorString, lf, " ")
  863.                 --
  864.                 -- fix up mangled url
  865.                 -- be a nice guy for RW -???-
  866.                 -- Waterfox fixes up!
  867.                 --  
  868.                 set buildHtml to buildHtml & anchorString
  869.                 if debug ≥ 2 then hexDumpFormatOne("  adjustURLs: buildHTML", buildHtml)
  870.                 -- https://apple.stackexchange.com/a/20135/44531
  871.                 -- We want first character of the "next" portion of theInputBuffer so add one
  872.                 set theInputBuffer to text (lastCharacterOffset + 1) thru -1 of theInputBuffer --trim out <a>
  873.                 if debug ≥ 2 then hexDumpFormatOne("  adjustURLs: theInputBuffer", theInputBuffer)
  874.                 -- Web Browsers like Firefox convert a line-end in text to a space.
  875.                 if text 1 thru 1 of theInputBuffer is lf then
  876.                     if (length of theInputBuffer) is 1 then
  877.                         set theInputBuffer to " "
  878.                     else
  879.                         set theInputBuffer to " " & (text 2 thru (length of theInputBuffer) of theInputBuffer)
  880.                         if debug ≥ 2 then hexDumpFormatOne("  adjustURLs: after lf deletion; theInputBuffer", theInputBuffer)
  881.                     end if
  882.                 end if
  883.                 exit repeat -- ------ next ------>
  884.             end if
  885.            
  886.             -- find the end of the HTML URL by splitting on blank or return
  887.             -- unsafe characters  <blank> " < > # % { } | \ ^ ~ [ ] `
  888.             -- and line-end
  889.             -- while # is listed as unsafe, it does appear in a url as a marker of some sort.
  890.             -- leave it out as an ending character.
  891.             -- https://perishablepress.com/stop-using-unsafe-characters-in-urls/
  892.             -- the end of the clipboard string my end after the url, hence no " ", LF or CR
  893.             -- Rember, CRLF was converted to LF above
  894.             set endsWhere to {}
  895.             -- the end of the url ends with one of the not allowed characters + line-end
  896.             repeat with unsafeCharacter in {" ", "\"", lf, "<", ">", "%", "{", "}", "|", "\\", "^", "~", "[", "]"}
  897.                 copy (offset of unsafeCharacter in theInputBuffer) to the end of the endsWhere
  898.             end repeat
  899.             if debug ≥ 2 then log endsWhere
  900.             set endOfURL to (minimumPositiveNumber from endsWhere) - 1
  901.            
  902.             if debug ≥ 2 then log "  adjustURLs: endOfURL is " & endOfURL
  903.            
  904.             if endOfURL ≤ 0 then
  905.                 -- We have reached the end of the input
  906.                 set theURL to theInputBuffer
  907.                 set theInputBuffer to ""
  908.             else
  909.                 set theURL to text 1 thru endOfURL of theInputBuffer
  910.                 if debug ≥ 2 then log "  adjustURLs: from middle theURL is " & theURL
  911.                
  912.                 set theInputBuffer to text (endOfURL + 1) thru -1 of theInputBuffer -- trim off url in front.
  913.             end if
  914.             if debug ≥ 2 then printHeader("  adjustURLs: printHeader", theInputBuffer)
  915.            
  916.             set actualTagData to getTitle(theURL)
  917.            
  918.             -- why the _blank in the <a>?
  919.             set assembled to "<a href=\"" & theURL & "\" target=\"_blank\">" & actualTagData & "</a>"
  920.             if debug ≥ 2 then log "  adjustURLs: assembled  is " & assembled
  921.            
  922.             if (length of theInputBuffer)0 then
  923.                 -- We have reached the end of the input
  924.                 if debug ≥ 2 then log "  adjustURLs: we have reached the end of the input."
  925.                 set buildHtml to buildHtml & assembled
  926.             else
  927.                 if debug ≥ 2 then log "  adjustURLs: more input to process"
  928.                 set buildHtml to buildHtml & assembled
  929.             end if
  930.            
  931.             -- wrap up
  932.             --log "transformed text from buildHTML is  " & return & buildHTML
  933.             if debug ≥ 2 then log "  adjustURLs: #" & countI & " transformed text from buildHTML is  " & return & buildHtml
  934.             -- number of links found
  935.             set countI to countI + 1
  936.            
  937.         end repeat -- used to interate
  938.     end repeat -- processing links in the input text
  939.     if alteredBuffer is true then
  940.         -- chop off the lf we added above.
  941.         set buildHtml to text 1 thru ((length of buildHtml) - 1) of buildHtml
  942.         set alteredBuffer to false -- somewhat redundant
  943.     end if
  944.     if debug ≥ 4 then log "bye from  -.- adjustURLs -.-"
  945.     return the buildHtml
  946.    
  947. end adjustURLs
  948.  
  949. -- ------------------------------------------------------
  950. (*
  951. alterString
  952.   thisText is the input string to change
  953.   delim is what string to change.  It doesn't have to be a single character.
  954.   replacement is the new string
  955.  
  956.   returns the changed string.
  957. *)
  958.  
  959. on alterString(thisText, delim, replacement)
  960.     global debug
  961.     if debug ≥ 5 then log "in ~~~ alterString ~~~"
  962.     set resultList to {}
  963.     set {tid, my text item delimiters} to {my text item delimiters, delim}
  964.     try
  965.         set resultList to every text item of thisText
  966.         set text item delimiters to replacement
  967.         set resultString to resultList as string
  968.         set my text item delimiters to tid
  969.     on error
  970.         set my text item delimiters to tid
  971.     end try
  972.     return resultString
  973. end alterString
  974.  
  975. -- ------------------------------------------------------
  976. (*
  977.   Return the text to the right of theToken.
  978. *)
  979. on answerAndChomp(theString, theToken)
  980.     global debug
  981.     if debug ≥ 5 then log "in ~~~ answerAndChomp ~~~"
  982.     set debugging to false
  983.     set theOffset to offset of theToken in theString
  984.     if debug ≥ 7 then log "theOffset is " & theOffset
  985.     set theLength to length of theString
  986.     if theOffset > 0 then
  987.         set beginningPart to text 1 thru (theOffset - 1) of theString
  988.         if debug ≥ 7 then log "beginningPart is " & beginningPart
  989.        
  990.         set chompped to text theOffset thru theLength of theString
  991.         if debug ≥ 7 then log "chompped is " & chompped
  992.         return {chompped, beginningPart}
  993.     else
  994.         set beginningPart to ""
  995.         return {theString, beginningPart}
  996.     end if
  997.    
  998. end answerAndChomp
  999.  
  1000. -- ------------------------------------------------------
  1001. (*
  1002.   Delete the leading part of the string until and including theToken.
  1003. *)
  1004. on chompLeftAndTag(theString, theToken)
  1005.     global debug
  1006.     if debug ≥ 5 then log "in --- chompLeftAndTag ---"
  1007.     if debug ≥ 7 then
  1008.         log "chompLeftAndTag: theToken is " & theToken
  1009.         hexDumpFormatOne("chompLeftAndTag: theString", theString)
  1010.     end if
  1011.     set theOffset to offset of theToken in theString
  1012.     if debug ≥ 7 then log "chompLeftAndTag: theOffset is " & theOffset & " in hex is " & integerToHex(theOffset)
  1013.     set theLength to length of theString
  1014.     if debug ≥ 7 then log "chompLeftAndTag: theLength is " & theLength & " in hex is " & integerToHex(theLength)
  1015.    
  1016.     if theOffset > 0 then
  1017.         -- Do we have any more of the string to return?
  1018.         if (theOffset + (length of theToken)) ≤ length of theString then
  1019.             set chompped to text (theOffset + (length of theToken)) thru theLength of theString
  1020.         else
  1021.             set chompped to ""
  1022.         end if
  1023.         if debug ≥ 7 then log "chompLeftAndTag: length of chompped is " & integerToHex(length of chompped) & "; chompped is " & chompped
  1024.         return chompped
  1025.     else
  1026.         return ""
  1027.     end if
  1028. end chompLeftAndTag
  1029.  
  1030. -- ------------------------------------------------------
  1031. on convertToHTML(theData)
  1032.     global debug
  1033.     if debug ≥ 3 then log "in --- convertToHTML ---" & return & "  Try to send back HTML. the processed data in variable theData is " & theData
  1034.     try
  1035.         set clipboardDataQuoted to quoted form of theData
  1036.        
  1037.         if debug ≥ 1 then
  1038.             log "  convertToHTMLz: .... data soon to be returned ...." & return & "clipboardDataQuoted is " & return & clipboardDataQuoted
  1039.             hexDumpFormatOne("clipboardDataQuoted", clipboardDataQuoted)
  1040.         end if
  1041.         -- make hex string as required for HTML data on the clipboard
  1042.         set toUnix to "/bin/echo -n " & clipboardDataQuoted & " | hexdump -ve '1/1 \"%.2x\"'"
  1043.         if debug ≥ 5 then printHeader("  convertToHTMLz: toUnix to convert to hex", toUnix)
  1044.         set fromUnix to do shell script toUnix
  1045.        
  1046.         if debug ≥ 5 then printHeader("  convertToHTMLz: fromUnix", fromUnix)
  1047.        
  1048.         if debug ≥ 5 then
  1049.             log "  convertToHTMLz: displaying original string -- so we can tell if it converted successfully. "
  1050.             --hexDumpFormatOne("fromUnix", fromUnix)
  1051.         end if
  1052.     on error errMsg number n
  1053.         log "  convertToHTMLz: ==> convert to hex string failed. " & errMsg & " with number " & n
  1054.         set fromUnix to ""
  1055.     end try
  1056.     if debug ≥ 4 then log "bye from  -.- convertToHTML -.-"
  1057.     return fromUnix
  1058. end convertToHTML
  1059.  
  1060. -- ------------------------------------------------------  
  1061. (*
  1062. Yvan Koenig
  1063. https://macscripter.net/viewtopic.php?id=43133
  1064. *)
  1065. on findExtension(inputFileName)
  1066.     global debug
  1067.     if debug ≥ 5 then log "in ~~~ findExtension ~~~"
  1068.     set fileName to inputFileName as string
  1069.     set saveTID to AppleScript's text item delimiters
  1070.     set AppleScript's text item delimiters to {"."}
  1071.     set theExt to last text item of fileName
  1072.     set AppleScript's text item delimiters to saveTID
  1073.     --log "theExt is " & theExt
  1074.     if theExt ends with ":" then set theExt to text 1 thru -2 of theExt
  1075.     if debug ≥ 5 then log "theExt is " & theExt
  1076.     return theExt
  1077. end findExtension
  1078.  
  1079. -- ------------------------------------------------------
  1080. (*
  1081. length of inputLfBuffer & " in hex " & integerToHex(length of inputLfBuffer)
  1082. *)
  1083. on getIntegerAndHex(aNumber)
  1084.     global debug
  1085.     if debug ≥ 5 then log "in ~~~ getIntegerAndHex ~~~"
  1086.    
  1087.     return aNumber & " in Hex " & integerToHex(aNumber)
  1088. end getIntegerAndHex
  1089.  
  1090. -- ------------------------------------------------------
  1091. (*
  1092.   find the html title in the given web page.
  1093.  
  1094.   retrieve the file pointed to by the URL so we can
  1095.             get the title. Note: <title> can have attributes.  Example:
  1096.                
  1097.             <title data-test-page-title="Parallels Desktop Lite on the Mac App Store"
  1098.             >‎Parallels Desktop Lite on the Mac App Store</title>
  1099.  
  1100. *)
  1101. on getTitle(theURL)
  1102.     global debug
  1103.     global droppedFileName
  1104.     set lf to character id 10
  1105.    
  1106.     if debug ≥ 5 then log "in ~~~ getTitle ~~~"
  1107.     if debug ≥ 1 then log "  getTitle: ----------------------- " & theURL & " -----------------------"
  1108.     if (text 1 thru (length of "http:") of theURL is "http:") or (text 1 thru (length of "https:") of theURL is "https:") then
  1109.         -- found url we can process
  1110.         if debug ≥ 5 then log "getTitle: We can process this URL since it begins with http or https." & return & "  " & theURL
  1111.     else
  1112.         log "==> getTitle: we cannot process this url" & theURL & return & "  we will return what re received."
  1113.         return theURL --------------------------------->
  1114.     end if
  1115.    
  1116.     -- Example:
  1117.     -- curl --silent --location --max-time 10 <URL>
  1118.     set toUnix to "curl --silent --location --max-time 10 " & quoted form of theURL
  1119.     if debug ≥ 2 then log "  getTitle: what we will use to retrieve the Url. toUnix  is " & return & "  " & toUnix
  1120.     try
  1121.         if debug ≥ 2 then log "  getTitle: reading link file to get title"
  1122.         set fromUnix to do shell script toUnix
  1123.         --log "fromUnix:"
  1124.         if debug ≥ 2 then
  1125.             printHeader("  getTitle: fromUnix", fromUnix)
  1126.             -- may not be working with an HTLM document, so thefound title may be too long or confused.
  1127.             log "  getTitle: how far?..."
  1128.         end if
  1129.         -- there could be some bagage with the <title
  1130.         set actualTagData to tagContent(fromUnix, "<title", "</title>")
  1131.         -- Find what we will actually display in the title.
  1132.         -- Fix up gotchas.             
  1133.         if debug ≥ 2 then log "  getTitle: actualTagData  is " & printHeader("actualTagData", actualTagData)
  1134.         if actualTagData is "" then
  1135.             set actualTagData to theURL
  1136.         else if length of actualTagData > 140 then
  1137.             if debug ≥ 2 then log "  getTitle: length of actualTagData is " & length of actualTagData & "which is too long.  Truncated."
  1138.             set actualTagData to theURL
  1139.             -- curl https://appleid.apple.com returns <title>403 Forbidden</title>
  1140.             -- which is misleading.
  1141.         else if actualTagData contains "403" and actualTagData contains "Forbidden" then
  1142.             log "  getTitle:  found 403 web page."
  1143.             set actualTagData to theURL
  1144.         else
  1145.             -- there could be some attributes within the <title> tag.
  1146.             -- or there could not be
  1147.             -- an attribute could have a > in it. ignoring that for now.
  1148.             try
  1149.                 -- find where <title ends
  1150.                 set whereToEnd to (offset of ">" in actualTagData)
  1151.                 if debug ≥ 2 then log "  getTitle: whereToEnd is " & whereToEnd
  1152.                 set whereToBegin to whereToEnd + (length of ">")
  1153.                 if debug ≥ 2 then log "  getTitle: whereToBegin is " & whereToBegin
  1154.                 hexDumpFormatOne("  getTitle: actualTagData", actualTagData)
  1155.                 set actualTagData to text whereToBegin thru (length of actualTagData) of actualTagData
  1156.                 if debug ≥ 2 then log "  getTitle: actualTagData is " & actualTagData
  1157.             on error theErrorMessage number theErrorNumber
  1158.                 log "  getTitle: ==>No ending greater than (>) for title. Badly contructed html." & return & "message is " & theErrorMessage & "error number " & theErrorNumber
  1159.                 set actualTagData to actualTagData
  1160.                 -- no need to repair.  It's not our page.
  1161.             end try
  1162.            
  1163.             -- found line-end in title.  caused confustion.
  1164.             -- note: this is new data and the multiple line-ends have not been
  1165.             -- filtered out.
  1166.             -- some joker had a line-end in the title!
  1167.             if debug ≥ 3 then
  1168.                 log "  getTitle: actualTagData (title) has been chanaged which is  " & actualTagData
  1169.                 hexDumpFormatOne("  getTitle: actualTagData (title)", actualTagData)
  1170.             end if
  1171.             set actualTagData to alterString(actualTagData, return & lf, lf)
  1172.             set actualTagData to alterString(actualTagData, return, lf)
  1173.             set actualTagData to adjustLF(actualTagData)
  1174.             if debug ≥ 2 then
  1175.                 log "  getTitle: actualTagData (title) has been chanaged which is  " & actualTagData
  1176.                 hexDumpFormatOne("  getTitle: actualTagData (title)", actualTagData)
  1177.             end if
  1178.            
  1179.         end if
  1180.     on error errMsg number n
  1181.         display dialog "  getTitle: ==> Error occured when looking for title. " & errMsg & " with number " & n & return & "  " & droppedFileName & return & "  " & theURL giving up after 10
  1182.         log "  getTitle: ==> Error occured when looking for title. " & errMsg & " with number " & n
  1183.         set actualTagData to theURL
  1184.     end try
  1185.     return actualTagData
  1186. end getTitle
  1187. -- ------------------------------------------------------
  1188. (*
  1189.   http://krypted.com/mac-os-x/to-hex-and-back/
  1190.                0    2    4    6    8    a    c    e     0 2 4 6 8 a c e
  1191. 0000000:   3c 703e 5369 6d70 6c65 2070 7574 2c20   <p>Simple put,
  1192.             *)
  1193. on hexDumpFormatOne(textMessage, hex)
  1194.     global debug
  1195.    
  1196.     set aNul to character id 1
  1197.    
  1198.     if debug ≥ 5 then log "in ~~~ hexDumpFormatOne ~~~"
  1199.     if debug ≥ 7 then log "    hexDumpFormatOne: input string is " & return & hex
  1200.    
  1201.     -- -r -p
  1202.     set displayValue to aNul & hex
  1203.     set toUnix to "/bin/echo -n " & (quoted form of displayValue) & " | xxd  "
  1204.     if debug ≥ 7 then log "    hexDumpFormatOne: toUnix is " & toUnix
  1205.    
  1206.     try
  1207.         set fromUnix to do shell script toUnix
  1208.        
  1209.         -- two hex digits
  1210.         set displayText to replaceCharacter(fromUnix, 10, "  ")
  1211.         if debug ≥ 7 then
  1212.             log "    hexDumpFormatOne: " & return & displayText
  1213.             log "    hexDumpFormatOne: length of displayText is " & length of displayText
  1214.         end if
  1215.         -- one character
  1216.         set displayText to replaceCharacter(displayText, 51, " ")
  1217.         if debug ≥ 7 then
  1218.             log "    hexDumpFormatOne: " & return & displayText
  1219.             log "    hexDumpFormatOne: almost there ..... length of displayText is " & length of displayText
  1220.         end if
  1221.         log "variable " & textMessage & " in hex is " & return & "         0    2    4    6    8    a    c    e     0 2 4 6 8 a c e" & return & displayText
  1222.     on error errMsg number n
  1223.         log "    hexDumpFormatOne: ==> convert hex string to string failed. " & errMsg & " with number " & n
  1224.     end try
  1225.     if debug ≥ 7 then
  1226.         log "leaving ~.~ hexDumpFormatOne ~.~"
  1227.     end if
  1228. end hexDumpFormatOne
  1229.  
  1230. -- ------------------------------------------------------
  1231. on hexDumpFormatZero(textMessage, hex)
  1232.     global debug
  1233.     if debug ≥ 5 then log "in ~~~ hexDumpFormatZero ~~~"
  1234.     if debug ≥ 5 then log "input string is " & hex
  1235.     -- -r -p
  1236.     set toUnix to "/bin/echo -n " & (quoted form of hex) & " | xxd  "
  1237.     if debug ≥ 5 then log "toUnix is " & toUnix
  1238.     try
  1239.         set displayText to do shell script toUnix
  1240.        
  1241.         log "variable " & textMessage & " in hex is " & return & "         0    2    4    6    8    a    c    e     0 2 4 6 8 a c e" & return & displayText
  1242.     on error errMsg number n
  1243.         log "==> convert hex string to string failed. " & errMsg & " with number " & n
  1244.     end try
  1245. end hexDumpFormatZero
  1246.  
  1247. -- ------------------------------------------------------
  1248. (*
  1249. https://macscripter.net/viewtopic.php?id=43713
  1250.   *)
  1251. on integerToHex(nDec)
  1252.     global debug
  1253.     if debug ≥ 5 then log "in ~~~ integerToHex ~~~"
  1254.     try
  1255.         set nHex to do shell script "perl -e 'printf(\"%X\", " & nDec & ")'" --> "F0"
  1256.     on error errMsg number n
  1257.         log "==> convert integer to hex. " & errMsg & " with number " & n
  1258.         set nHex to ""
  1259.     end try
  1260.     return nHex
  1261. end integerToHex
  1262.  
  1263. -- ------------------------------------------------------
  1264. (*
  1265.  
  1266. https://stackoverflow.com/questions/55838252/minimum-value-that-not-zero
  1267.        set m to get minimumPositiveNumber from {10, 2, 0, 2, 4}
  1268.     log "m is " & m
  1269.     set m to minimumPositiveNumber from {0, 0, 0}
  1270.     log "m is " & m
  1271. *)
  1272. on minimumPositiveNumber from L
  1273.     global debug
  1274.     if debug ≥ 5 then log "in ~~~ minimumPositiveNumber ~~~"
  1275.     local L
  1276.    
  1277.     if L = {} then return null
  1278.    
  1279.     set |ξ| to 0
  1280.    
  1281.     repeat with x in L
  1282.         set x to x's contents
  1283.         if (x < |ξ| and x ≠ 0) ¬
  1284.             or |ξ| = 0 then ¬
  1285.             set |ξ| to x
  1286.     end repeat
  1287.    
  1288.     |ξ|
  1289. end minimumPositiveNumber
  1290.  
  1291. -- ------------------------------------------------------
  1292. (*
  1293.   makeCaseUpper("Now is the time, perhaps, for all good men")
  1294. *)
  1295. on makeCaseUpper(theString)
  1296.     global debug
  1297.     if debug ≥ 5 then log "in ~~~ makeCaseUpper ~~~"
  1298.     set UC to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  1299.     set LC to "abcdefghijklmnopqrstuvwxyz"
  1300.     set C to characters of theString
  1301.     repeat with ch in C
  1302.         if ch is in LC then set contents of ch to item (offset of ch in LC) of UC
  1303.     end repeat
  1304.     return C as string
  1305. end makeCaseUpper
  1306.  
  1307. -- ------------------------------------------------------
  1308. on postToCLipboard(pleasePost)
  1309.     global debug
  1310.     if debug ≥ 5 then log "in ~~~ postToCLipboard ~~~"
  1311.     try
  1312.         -- osascript -e "set the clipboard to «data HTML${hex}»"     
  1313.         set toUnixSet to "osascript -e \"set the clipboard to «data HTML" & pleasePost & \""
  1314.         if debug ≥ 5 then log "  postToCLipboard: toUnixSet is " & printHeader("toUnixSet", toUnixSet)
  1315.        
  1316.         set fromUnixSet to do shell script toUnixSet
  1317.         if debug ≥ 5 then log "  postToCLipboard: fromUnixSet is " & fromUnixSet
  1318.        
  1319.     on error errMsg number n
  1320.         log "  postToCLipboard: ==> We tried to send back HTML data, but failed. " & errMsg & " with number " & n
  1321.     end try
  1322.     -- see what ended up on the clipboard
  1323.     set theList2 to clipboard info
  1324.     if debug ≥ 2 then printClipboardInfo(theList2)
  1325. end postToCLipboard
  1326.  
  1327. -- ------------------------------------------------------
  1328. on printClipboardInfo(theList)
  1329.     global debug
  1330.     if debug ≥ 5 then log "in ~~~ printClipboardInfo ~~~"
  1331.     log (clipboard info)
  1332.     log class of theList
  1333.     log "Data types on the clipboard ... "
  1334.     printList("", theList)
  1335.     log "... "
  1336. end printClipboardInfo
  1337.  
  1338. -- ------------------------------------------------------
  1339. (* Pump out the beginning of theString *)
  1340. on printHeader(theName, theString)
  1341.     global debug
  1342.     if debug ≥ 5 then
  1343.         log "in ~~~ printHeader ~~~"
  1344.         log "theName is " & theName
  1345.         -- let's not culter the log
  1346.         if debug ≥ 7 then log theString
  1347.         log "length of theString is " & length of theString
  1348.     end if
  1349.     if length of theString ≤ 0 then
  1350.         log "==> no string to print"
  1351.     else
  1352.         log theName & " is " & return & text 1 thru (minimumPositiveNumber from {400, length of theString}) of theString & "<+++++++++"
  1353.     end if
  1354. end printHeader
  1355.  
  1356. -- ------------------------------------------------------
  1357. (*
  1358. print out the items in a list
  1359.  
  1360. *)
  1361.  
  1362. on printList(theName, splits)
  1363.     global debug
  1364.     if debug ≥ 5 then log "in ~~~ printList ~~~"
  1365.     try
  1366.         set theCount to 1
  1367.         repeat with theEntry in splits
  1368.             --log "class of theEntry is " & class of theEntry
  1369.             set classDisplay to class of theEntry as text
  1370.             --log "classDisplay is " & classDisplay as text
  1371.             --log "class of classDisplay is " & class of classDisplay
  1372.             if classDisplay is "list" then
  1373.                 log "    " & theName & " # " & theCount & " is " & item 1 of theEntry & "; " & item 2 of theEntry
  1374.             else
  1375.                 log "    " & theName & " # " & theCount & " is " & theEntry
  1376.             end if
  1377.             set theCount to theCount + 1
  1378.         end repeat
  1379.     on error errMsg number n
  1380.         log "==> No go in printList. " & errMsg & " with number " & n
  1381.     end try
  1382. end printList
  1383.  
  1384. -- ------------------------------------------------------
  1385. (*
  1386. StefanK in https://macscripter.net/viewtopic.php?id=43852
  1387. Replaces one or more characters based on the length of theCharacter.
  1388.  
  1389.   Big Warning!!!
  1390.   ==============
  1391.     This on block is called by hexDumpFormatOne().  
  1392.     Therefor, you may not call hexDumpFormatOne() from this on block.
  1393.     If you so so, you get yourself into an endless loop.
  1394.     Use hexDumpFormatZero() instead.
  1395.    
  1396.     script -k <output file name>
  1397.     osascript /Applications/applescriptFiles/workwithclipboardV13-HTML.app
  1398.     use Activity Monito to stop osascript
  1399.    
  1400. *)
  1401.  
  1402. on replaceCharacter(theText, theOffset, theCharacter)
  1403.     global debug
  1404.     if debug ≥ 7 then log "in ~~~ replaceCharacter ~~~"
  1405.     if debug ≥ 7 then
  1406.         log "  theOffset is " & getIntegerAndHex(theOffset) & " with theCharacter >" & theCharacter & "<  length of theText is " & getIntegerAndHex(length of theText)
  1407.         log "theText is " & theText
  1408.     end if
  1409.    
  1410.     set theOutput to theText -- ready to return if need be.
  1411.     repeat 1 times
  1412.         -- sanity checks
  1413.         if theOffset ≤ 0 then
  1414.             display dialog "No character to replace at " & theOffset & " with character " & theCharacter & " in " & theText giving up after 10
  1415.             log "==> Adjust theOffset to be wihin the string."
  1416.             exit repeat -------------- return ---------->                  
  1417.         end if
  1418.         if (theOffset - (length of theCharacter))0 then
  1419.             display dialog "Too near the front of the buffer.  " & theOffset & " with character " & theCharacter & " in " & theText giving up after 10
  1420.             log "==> Too near the front of the buffer. "
  1421.             exit repeat -------------- return ---------->
  1422.         end if
  1423.         if (theOffset + (length of theCharacter) - 1) > (length of theText) then
  1424.             display dialog "To near the end of the buffer. " & theOffset & " with character " & theCharacter & " in " & theText giving up after 10
  1425.             log "==> Too near the end of the buffer. "
  1426.             log "  " & "theOffset is " & theOffset & " with theCharacter >" & theCharacter & "<  in " & theText
  1427.             log "length of buffer is " & getIntegerAndHex(length of theText)
  1428.             exit repeat -------------- return ---------->                  
  1429.         end if
  1430.        
  1431.         if debug ≥ 7 then
  1432.             log "theOffset is " & getIntegerAndHex(theOffset)
  1433.             log "theCharacter is " & theCharacter
  1434.         end if
  1435.        
  1436.         try
  1437.             -- what if we are at the end of the buffer.  We cannot get any remainder text.
  1438.             if theOffset ≥ (length of theText) then
  1439.                 set theOutput to (text 1 thru (theOffset - 1) of theText) & theCharacter
  1440.             else
  1441.                 set theOutput to (text 1 thru (theOffset - 1) of theText) & theCharacter & (text (theOffset + (length of theCharacter)) thru -1 of theText)
  1442.             end if
  1443.         on error errMsg number n
  1444.             log "==> No go. " & errMsg & " with number " & n
  1445.             exit repeat -------------- return ---------->
  1446.         end try
  1447.     end repeat
  1448.     return theOutput
  1449. end replaceCharacter
  1450.  
  1451. -- ------------------------------------------------------
  1452. (*
  1453. splitTextToList seems to be what you are trying to do
  1454.   thisText is the input string
  1455.   delim is what to split on
  1456.  
  1457.   results returned in a list
  1458.  
  1459.   Total hack. We know splitTextToList strips of delim so add it back.
  1460. *)
  1461.  
  1462. on splitTextToList(thisText, delim)
  1463.     global debug
  1464.     if debug ≥ 5 then log "in ~~~ splitTextToList ~~~"
  1465.    
  1466.     set returnedList to textToList(thisText, delim)
  1467.     set resultArray to {}
  1468.     copy item 1 of returnedList to the end of the resultArray
  1469.    
  1470.     repeat with i from 2 to (count of returnedList) in returnedList
  1471.         set newElement to delim & item i of returnedList
  1472.         copy newElement to the end of the resultArray
  1473.     end repeat
  1474.    
  1475.     return resultArray
  1476. end splitTextToList
  1477.  
  1478. -- ------------------------------------------------------
  1479. (*
  1480.   Retrieved data between "begin" and "end" tag. Whatever is between the strings.
  1481. *)
  1482. on tagContent(theString, startTag, endTag)
  1483.     global debug
  1484.     if debug ≥ 5 then log "in ~~~ tagContent ~~~"
  1485.     try
  1486.         if debug ≥ 5 then log "in tabContent. " & return & "    startTag is " & startTag & " endTag is " & endTag
  1487.         set beginningOfTag to chompLeftAndTag(theString, startTag)
  1488.         if length of beginningOfTag ≤ 0 then
  1489.             set middleText to ""
  1490.         else
  1491.             printHeader("beginningOfTag", beginningOfTag)
  1492.             set endingOffset to (offset of endTag in beginningOfTag)
  1493.            
  1494.             if endingOffset ≤ (length of endTag) then
  1495.                 set middleText to ""
  1496.             else
  1497.                 set middleText to text 1 thru (endingOffset - 1) of beginningOfTag
  1498.                 printHeader("middleText is ", middleText)
  1499.             end if
  1500.         end if
  1501.     on error errMsg number n
  1502.         log "==> finding contained text failed. " & errMsg & " with number " & n
  1503.         set middleText to ""
  1504.     end try
  1505.     if debug ≥ 5 then log "returning with middleText is " & middleText
  1506.     return middleText
  1507. end tagContent
  1508. -- ------------------------------------------------------
  1509. (*
  1510. textToList seems to be what you are trying to do
  1511.   thisText is the input string
  1512.   delim is what to split on
  1513.  
  1514.   returns a list of strings.  
  1515.  
  1516. - textToList was found here:
  1517. - http://macscripter.net/viewtopic.php?id=15423
  1518.  
  1519. *)
  1520.  
  1521. on textToList(thisText, delim)
  1522.     global debug
  1523.     if debug ≥ 5 then log "in ~~~ textToList ~~~"
  1524.     set resultList to {}
  1525.     set {tid, my text item delimiters} to {my text item delimiters, delim}
  1526.    
  1527.     try
  1528.         set resultList to every text item of thisText
  1529.         set my text item delimiters to tid
  1530.     on error
  1531.         set my text item delimiters to tid
  1532.     end try
  1533.     return resultList
  1534. end textToList
  1535.  
  1536. -- ------------------------------------------------------
  1537. on trimCharacters(inputTrim, outputTrim, reduce)
  1538.     global debug
  1539.     if debug ≥ 3 then
  1540.         log "in ~~~ trimCharacters ~~~"
  1541.         log "  trimCharacters: length of inputTrim is" & getIntegerAndHex(length of inputTrim)
  1542.         hexDumpFormatOne("  trimCharacters: inputTrim", inputTrim)
  1543.         log "  trimCharacters: length of outputTrim is " & getIntegerAndHex(length of outputTrim)
  1544.         hexDumpFormatOne("  trimCharacters: outputTrim", outputTrim)
  1545.         log "  trimCharacters: with reduce >" & reduce & "<  "
  1546.     end if
  1547.     set repCount to 1
  1548.    
  1549.     repeat while length of inputTrim ≥ 1 and text 1 thru 1 of inputTrim is " "
  1550.         set {inputTrim, outputTrim} to trimOneChar(inputTrim, outputTrim, 1, "")
  1551.         if debug ≥ 6 then
  1552.             log "  trimCharacters: repCount is " & repCount
  1553.             set repCount to repCount + 1
  1554.             log "  trimCharacters: length of inputTrim is" & getIntegerAndHex(length of inputTrim)
  1555.             hexDumpFormatOne("  trimCharacters: cycling inputTrim", inputTrim)
  1556.             log "  trimCharacters: length of outputTrim is " & getIntegerAndHex(length of outputTrim)
  1557.             hexDumpFormatOne("  trimCharacters: cycling outputTrim", outputTrim)
  1558.            
  1559.         end if
  1560.     end repeat
  1561.    
  1562.     if debug ≥ 3 then
  1563.         log "  trimCharacters: length of inputTrim is" & getIntegerAndHex(length of inputTrim)
  1564.         hexDumpFormatOne("  trimCharacters: completed inputTrim", inputTrim)
  1565.         log "  trimCharacters: length of outputTrim is " & getIntegerAndHex(length of outputTrim)
  1566.         hexDumpFormatOne("  trimCharacters: completed outputTrim", outputTrim)
  1567.         log "bye from  ~.~ trimCharacters ~.~"
  1568.     end if
  1569.     return {inputTrim, outputTrim}
  1570. end trimCharacters
  1571.  
  1572. -- ------------------------------------------------------
  1573. on trimOneChar(inputLf, outputTrimmed, theLfOffset, substitueCharacter)
  1574.     global debug
  1575.    
  1576.     if debug ≥ 3 then
  1577.         log "in ~~~ trimOneChar ~~~"
  1578.         hexDumpFormatOne("inputLf", inputLf)
  1579.         hexDumpFormatOne("outputTrimmed", outputTrimmed)
  1580.         log "theLfOffset, is " & getIntegerAndHex(theLfOffset)
  1581.         log "with substitueCharacter >" & substitueCharacter & "<  "
  1582.     end if
  1583.    
  1584.     -- check boundaries
  1585.     if theLfOffset ≤ 0 or (theLfOffset > (length of inputLf)) then
  1586.         -- We are almost done.
  1587.         log "no LF found."
  1588.         -- tack on any trialing stuff
  1589.         set outputTrimmed to outputTrimmed & inputLf
  1590.         set inputLf to ""
  1591.         if debug ≥ 3 then
  1592.             hexDumpFormatOne("inputLf", inputLf)
  1593.             hexDumpFormatOne("outputTrimmed", outputTrimmed)
  1594.         end if
  1595.         return {inputLf, outputTrimmed} ------------ return ------------>
  1596.     end if
  1597.    
  1598.     -- We need to deal with output first, so we haven't trimmed the input we need.
  1599.     if theLfOffset ≥ 2 then
  1600.         if debug ≥ 6 then log "  theLfOffset ≥ 2"
  1601.         set outputTrimmed to outputTrimmed & (text 1 thru (theLfOffset - 1) of inputLf) & substitueCharacter
  1602.     else if theLfOffset = 1 then
  1603.         if debug ≥ 6 then log "  theLfOffset = 1"
  1604.         -- no stuff before the lf
  1605.         set outputTrimmed to outputTrimmed & substitueCharacter
  1606.     end if
  1607.    
  1608.     -- deal with inputLf.
  1609.     if theLfOffset < (length of inputLf) then
  1610.         if debug ≥ 6 then log "  theLfOffset < (length of inputLf) "
  1611.         -- trailing stuff
  1612.         set inputLf to text (theLfOffset + 1) thru -1 of inputLf
  1613.     else if theLfOffset is (length of inputLf) then
  1614.         if debug ≥ 6 then log "  theLfOffset is (length of inputLf) "
  1615.         set inputLf to ""
  1616.     end if
  1617.    
  1618.     if debug ≥ 3 then
  1619.         hexDumpFormatOne("inputLf", inputLf)
  1620.         hexDumpFormatOne("outputTrimmed", outputTrimmed)
  1621.     end if
  1622.     if debug ≥ 4 then log "bye from  ~.~ trimOneChar ~.~"
  1623.     return {inputLf, outputTrimmed}
  1624.    
  1625. end trimOneChar
  1626.  
  1627. -- ------------------------------------------------------
  1628. (*
  1629.          Unix-like systems      LF      0A      \n
  1630.             (Linux, macOS)
  1631.                Microsoft Windows    CRLF    0D 0A   \r\n
  1632.                classic Mac OS       CR      0D          \r   Applescript return
  1633.   *)
  1634. on typeText(theData)
  1635.    
  1636.     global debug
  1637.     if debug ≥ 5 then log "in ~~~ typeText ~~~"
  1638.     set lf to character id 1
  1639.    
  1640.     if debug ≥ 2 then printHeader("the input  ( theData )", theData)
  1641.     -- Example: -- https://discussions.apple.com/docs/DOC-8841
  1642.     -- locate links
  1643.    
  1644.     set theOutputBuffer to adjustURLs(theData)
  1645.    
  1646.     -- add paragraphs
  1647.     set theOutputBuffer to addParagraphs(theOutputBuffer)
  1648.    
  1649.     if debug ≥ 2 then log "theOutputBuffer is " & return & theOutputBuffer
  1650.     if debug ≥ 4 then log "bye from  -.- typeText -.-"
  1651.     return theOutputBuffer
  1652. end typeText
  1653.  
  1654. -- ------------------------------------------------------
  1655. (* 
  1656.  place debuging data on cipboard
  1657.  has a big side effect.  
  1658. *)
  1659. on wrapupClipboardDataSelector()
  1660.     return "<html><head>
  1661. <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">
  1662. <title>asc insert title in &lt;a>.html</title>
  1663. </head>
  1664. <body>
  1665. <p></p>
  1666. <p>\"Avoid phishing scams\"
  1667. <a href=\"https://support.apple.com/en-ca/HT204759\">https://support.apple.com/en-ca/HT204759</a>
  1668. </p>
  1669. <p>Lets pad the <a> tag.</p>
  1670. <p>
  1671. <a title=\"Go to W3Schools HTML section\" href=\"https://support.apple.com/en-ca/HT204759\" target=\"_blank\">https://support.apple.com/en-ca/HT204759</a>
  1672. </p>
  1673. <p>That's all folks.</p><p></p>
  1674. </body>
  1675. <html>"
  1676.    
  1677.    
  1678. end wrapupClipboardDataSelector
  1679. (*
  1680.    
  1681.        
  1682.     "Global Lyme Alliance Reveals Several Drugs and Drug Combinations That Show Success in Treating Lyme Disease
  1683. https://globallymealliance.org/press-releases/global-lyme-alliance-reveals-several-drugs-drug-combinations-show-success-treating-lyme-disease/?utm_source=Newsletter&utm_campaign=220eebaf84-EMAIL_CAMPAIGN_2019_04_18_03_43&utm_medium=email&utm_term=0_2eb359dd6a-220eebaf84-37014111
  1684.  
  1685. https://www.omf.ngo/community-symposium-2/
  1686. Saturday, September 7, 2019
  1687. Live streamed
  1688. https://www.omf.ngo/community-symposium-2/
  1689.  
  1690.  
  1691. New OMF-funded Research Publication: A Nanoelectronics-blood-based diagnostic biomarker for ME/CFS
  1692.  
  1693. Dr. Ron Davis, OMF Scientific Advisory Board Director, explains the PNAS publication on the nanoneedle (April 29, 2019)
  1694.  
  1695. A paper describing the nanoneedle was published in the Proceedings of the National Academy of Sciences. Ronald W. Davis, PhD, is the senior author. Rahim Esfandyarpour, PhD, is the lead author. The nanoneedle is a test that measures changes in immune cells with their blood plasma as a result of salt stress. Inside the nanoneedle, the immune cells interfere with a small electric current. The change in electrical activity is directly correlated with the health of the sample. The test, which is still in a pilot phase, is based on how a person’s immune cells respond to stress. With blood samples from 40 people — 20 with ME/CFS and 20 without — the test yielded precise results, accurately flagging all patients and none of the healthy individuals.
  1696.  
  1697.  
  1698. https://www.youtube.com/watch?v=6Qn0fIV8SbE&feature=youtu.be"
  1699.    
  1700.     return "<p> </p><p> </p><p>If you are unable to set up \"two-factor authentication,\" you should set up \"2-step.\"
  1701.    
  1702.    
  1703.  
  1704.  
  1705. Run etrecheck.  The
  1706. first five runs are free.</p> "
  1707. *)
  1708.  
  1709. (* 
  1710. set the clipboard to "<html><p>As you are using a non-Apple app to access your email or other  facilities, you are now required to use an 'app-specific' password in place of your normal iCloud password. In order to do this you need to set up two-factor authentication for your Apple ID, and for this you need to have either a Mac running El Capitan or above, or an iOS device running iOS9 or above.</p><p> </p><p><a href=\"https://support.apple.com/HT204915\" target=\"_blank\">Two-factor authentication for Apple ID - Apple Support</a></p><p> </p><p><a href=\"https://support.apple.com/HT204397\" target=\"_blank\">Using app-specific passwords - Apple Support</a></p><p> </p><p>If you are unable to set up \"two-factor authentication,\" you should set up \"2-step.\"
  1711.    
  1712.    
  1713.  
  1714.  
  1715. Run etrecheck.  The
  1716. first five runs are free. Provided a report on your
  1717. machines hardware and software.  Great for diagnosing your system.  Click on the download
  1718. link at the bottom of the screen.
  1719. <a href=\"http://etrecheck.com/\" target=\"_blank\">EtreCheck</a></p><p></p>
  1720. <p></p><p>
  1721. <ol>
  1722. <li>point 1</li>
  1723. <li>point 2</li>
  1724. <li>point 3</li>
  1725. </ol>
  1726. </p>
  1727. <p>the end</p>
  1728.  
  1729. </ol></p><p>
  1730. "
  1731. *)
  1732. (*
  1733. https://www.oreilly.com/library/view/applescript-the-definitive/0596102119/re89.html
  1734.  
  1735. https://stackoverflow.com/questions/11085654/apple-script-how-can-i-copy-html-content-to-the-clipboard
  1736.  
  1737. -- user has copied a file's icon in the Finder
  1738. clipboard info
  1739. -- {{string, 20}, {«class ut16», 44}, {«class hfs », 80}, {«class
  1740.  utf8», 20}, {Unicode text, 42}, {picture, 2616}, {«class icns», 43336},
  1741. {«class furl», 62}}
  1742.  
  1743. textutil -convert html foo.rtf
  1744.  
  1745. if ((clipboard info) as string) contains "«class furl»" then
  1746.         log "the clipboard contains a file named " & (the clipboard as string)
  1747.     else
  1748.         log "the clipboard does not contain a file"
  1749.     end if
  1750.    
  1751. the clipboard       required
  1752. as  class   optional
  1753.  
  1754. tell application "Script Editor"
  1755.         activate
  1756.     end tell
  1757.    
  1758. textutil has a simplistic text to html conversion
  1759.     set clipboardDataQuoted to quoted form of theData
  1760.     log "quoted form is " & clipboardDataQuoted
  1761.    
  1762.     set toUnix to "/bin/echo -n " & clipboardDataQuoted
  1763.     set toUnix to toUnix & " | textutil -convert html -noload -nostore -stdin -stdout "
  1764.     log "toUnix is " & toUnix
  1765.     set fromUnix to do shell script toUnix
  1766.     log "fromUnix  is " & fromUnix
  1767.    
  1768.    
  1769. set s to "Today is my birthday"
  1770. log text 1 thru ((offset of "my" in s) - 1) of s
  1771. --> "Today is "
  1772.             -- text 1 thru ((offset of "my" in s) - 1) of s
  1773.             -- -1 since offset return the first character "m" position count
  1774.            
  1775. log "beginningOfTag is " & text 1 thru (minimumPositiveNumber from {200, length of beginningOfTag}) of beginningOfTag & "<+++++++++++++++++++++++"
  1776.  
  1777. https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_cmds.html
  1778.  
  1779. *)
  1780.  
  1781. --mac $ hex=`echo -n "<p>your html code here</>" | hexdump -ve '1/1 "%.2x"'`
  1782. --mac $ echo $hex
  1783. --3c703e796f75722068746d6c20636f646520686572653c2f3e
  1784. --mac $ osascript -e "set the clipboard to «data HTML${hex}»"
  1785. --mac $
  1786. (*  
  1787. A sub-routine for encoding ASCII characters.  
  1788.  
  1789. encode_char("$")  
  1790. --> returns: "%24"  
  1791.  
  1792. based on:  
  1793. https://www.macosxautomation.com/applescript/sbrt/sbrt-08.html  
  1794.  
  1795. *)
  1796. (*
  1797. Lowest Numeric Value in a List
  1798.  
  1799. This sub-routine will return the lowest numeric value in a list of items. The passed list can contain non-numeric data as well as lists within lists. For example:
  1800.  
  1801. lowest_number({-3.25, 23, 2345, "sid", 3, 67})
  1802. --> returns: -3.25
  1803. lowest_number({-3.25, 23, {-22, 78695, "bob"}, 2345, true, "sid", 3, 67})
  1804. --> returns: -22
  1805.  
  1806. If there is no numeric data in the passed list, the sub-routine will return a null string ("")
  1807.  
  1808. lowest_number({"this", "list", "contains", "only", "text"})
  1809. --> returns: ""
  1810.  
  1811. https://macosxautomation.com/applescript/sbrt/sbrt-03.html
  1812.  
  1813. Here's the sub-routine:
  1814.  
  1815. *)
  1816. (*
  1817. on lowestNumber(values_list)
  1818.     set the low_amount to ""
  1819.     repeat with i from 1 to the count of the values_list
  1820.         set this_item to item i of the values_list
  1821.         set the item_class to the class of this_item
  1822.         if the item_class is in {integer, real} then
  1823.             if the low_amount is "" then
  1824.                 set the low_amount to this_item
  1825.             else if this_item is less than the low_amount then
  1826.                 set the low_amount to item i of the values_list
  1827.             end if
  1828.         else if the item_class is list then
  1829.             set the low_value to lowest_number(this_item)
  1830.             if the the low_value is less than the low_amount then ¬
  1831.                 set the low_amount to the low_value
  1832.         end if
  1833.     end repeat
  1834.     return the low_amount
  1835. end lowestNumber
  1836.  
  1837. https://lists.apple.com/archives/applescript-users/2010/Sep/msg00139.html
  1838. set list_of_values to {10, 20, 30, 40, 50, 60, 2000, 9, 3000, 4}
  1839.  
  1840. set minimum to 9.9999999999E+12
  1841. set maximum to 0
  1842. repeat with ref_to_value in list_of_values
  1843.     set the_value to contents of ref_to_value
  1844.     if the_value > maximum then set maximum to the_value
  1845.     if the_value < minimum then set minimum to the_value
  1846. end repeat
  1847.  
  1848. {minimum, maximum}
  1849.  
  1850. may do the trick.
  1851.  
  1852. Yvan KOENIG (VALLAURIS, France) lundi 13 septembre 2010 22:32:41
  1853. *)
  1854. (* https://lists.apple.com/archives/applescript-users/2010/Sep/msg00139.html
  1855. set list_of_values to {10, 20, 30, 40, 50, 60, 2000, 9, 3000, 4}
  1856.  
  1857. set minimum to 9.9999999999E+12
  1858.  
  1859. assume it's limited to positive values
  1860.  
  1861.  
  1862. on maxValue(list_of_values)
  1863.     global debug
  1864.     if debug ≥ 5 then log "in maxValue " & return & list_of_values
  1865.     set maximum to 0
  1866.     repeat with ref_to_value in list_of_values
  1867.         set the_value to contents of ref_to_value
  1868.         if the_value > maximum then set maximum to the_value
  1869.     end repeat
  1870.     if debug ≥ 5 then log maximum
  1871.     return maximum
  1872. end maxValue
  1873. *)
  1874. -- ------------------------------------------------------
  1875. (*
  1876. http://harvey.nu/applescript_url_encode_routine.html
  1877.  
  1878. on urlencode(theText)
  1879.     set theTextEnc to ""
  1880.     repeat with eachChar in characters of theText
  1881.         set useChar to eachChar
  1882.         set eachCharNum to ASCII number of eachChar
  1883.         if eachCharNum = 32 then
  1884.             set useChar to "+"
  1885.         else if (eachCharNum ≠ 42) and (eachCharNum ≠ 95) and (eachCharNum < 45 or eachCharNum > 46) and (eachCharNum < 48 or eachCharNum > 57) and (eachCharNum < 65 or eachCharNum > 90) and (eachCharNum < 97 or eachCharNum > 122) then
  1886.             set firstDig to round (eachCharNum / 16) rounding down
  1887.             set secondDig to eachCharNum mod 16
  1888.             if firstDig > 9 then
  1889.                 set aNum to firstDig + 55
  1890.                 set firstDig to ASCII character aNum
  1891.             end if
  1892.             if secondDig > 9 then
  1893.                 set aNum to secondDig + 55
  1894.                 set secondDig to ASCII character aNum
  1895.             end if
  1896.             set numHex to ("%" & (firstDig as string) & (secondDig as string)) as string
  1897.             set useChar to numHex
  1898.         end if
  1899.         set theTextEnc to theTextEnc & useChar as string
  1900.     end repeat
  1901.     return theTextEnc
  1902. end urlencode
  1903.  
  1904. Clipboard classes after a copy from the application.
  1905. from waterfox
  1906. (*«class HTML», 13876, «class utf8», 505, «class ut16», 1012, string, 505, Unicode text, 1010*)
  1907.  
  1908. from chrome
  1909. (*«class HTML», 748, «class utf8», 204, «class ut16», 410, string, 204, Unicode text, 408*)
  1910.  
  1911. from safari
  1912. (*«class weba», 120785, «class RTF », 70255, «class HTML», 122811, «class utf8», 3370, «class ut16», 6772, uniform styles, 47132, string, 3385, scrap styles, 8122, Unicode text, 6732, uniform styles, 47132, scrap styles, 8122*)
  1913.  
  1914. iCab
  1915. (*«class weba», 1665, «class RTF », 763, «class utf8», 121, «class ut16», 244, uniform styles, 376, string, 121, scrap styles, 62, Unicode text, 242, uniform styles, 376, scrap styles, 62*)
  1916.  
  1917. Opera
  1918. (*«class HTML», 5767, «class utf8», 150, «class ut16», 302, string, 150, Unicode text, 300*)
  1919.  
  1920. Textedit
  1921. (*«class RTF », 1136, «class utf8», 138, «class ut16», 278, uniform styles, 148, string, 138, scrap styles, 22, Unicode text, 276, uniform styles, 148, scrap styles, 22*)
  1922.  
  1923. Word
  1924. (*«class DSIG», 4, «class DOBJ», 56, «class OBJD», 244, «class RTF », 30573, «class HTML», 21160, scrap styles, 22, uniform styles, 136, string, 210, Unicode text, 420, «class PDF », 13197, picture, 154058, «class EMBS», 33280, «class LNKS», 909, «class LKSD», 244, «class OJLK», 93, «class HLNK», 1387, «class OFSC», 232, «class ut16», 422, «class DSIG», 4, «class DOBJ», 56, «class OBJD», 244, scrap styles, 22, uniform styles, 136, «class EMBS», 33280, «class LNKS», 909, «class LKSD», 244, «class OJLK», 93, «class HLNK», 1387, «class OFSC», 232*)
  1925.  
  1926. TextWrangler
  1927. (*«class utf8», 185, «class BBLM», 4, «class ut16», 372, string, 185, Unicode text, 370, «class BBLM», 4*)
  1928.  
  1929. *)
  1930.  
  1931.  
  1932.  
  1933. (*
  1934.     set the clipboard to "<html><p>As you are using a non-Apple app to access your email or other  facilities, you are now required to use an 'app-specific' password in place of your normal iCloud password. In order to do this you need to set up two-factor authentication for your Apple ID, and for this you need to have either a Mac running El Capitan or above, or an iOS device running iOS9 or above.</p><p> </p><p><a href=\"https://support.apple.com/HT204915\" target=\"_blank\">Two-factor authentication for Apple ID - Apple Support</a></p><p> </p><p><a href=\"https://support.apple.com/HT204397\" target=\"_blank\">Using app-specific passwords - Apple Support</a></p><p> </p><p>If you are unable to set up two-factor authentication you should set up 2-step \"
  1935.    
  1936.    
  1937.  
  1938.  
  1939. Run etrecheck.  The
  1940. first five runs are free. Provided a report on your
  1941. machines hardware and software.  Great for diagnosing your system.  Click on the download
  1942. link at the bottom of the screen.
  1943. <a href=\"http://etrecheck.com/\" target=\"_blank\">EtreCheck</a></p><p></p>
  1944. <p></p><p>
  1945. <ol>
  1946. <li>point 1</li>
  1947. <li>point 2</li>
  1948. <li>point 3</li>
  1949. </ol>
  1950.  </p>
  1951. <p>the end</p>
  1952. "
  1953.     *)
  1954. (*  set the clipboard to "<p>Simple put, Apple attempts
  1955. to provide all the
  1956. malware detection and removal you need in Mac OS X.</p>
  1957. <p></p><p></p><p></p>
  1958. <p>\"Effective defenses against malware and other threats\" by John Galt
  1959. <a href=\"https://discussions.apple.com/docs/DOC-8841\" target=\"_blank\">Effective
  1960. defenses against malware and ot… - Apple Community</a>
  1961. </p><pre>
  1962. code line #a
  1963. code line #b
  1964. code line #c
  1965. </pre><p> </p><p>\"Avoid phishing emails, fake 'virus' alerts, phony support calls, and other scams\"
  1966. <a href=\"https://support.apple.com/en-ca/HT204759\">Avoid phishing emails, fake
  1967. 'virus' alerts, phony support calls, and other scams - Apple Support</a>
  1968. <pre>
  1969. code line #1
  1970. code line #2
  1971. code line #3
  1972. </pre>"
  1973. *)
  1974. (*
  1975.     set the clipboard to "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
  1976. <html>
  1977.   <head>
  1978.  
  1979.     <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">
  1980.     <title>asc roger's help text</title>
  1981.   </head>
  1982.   <body>
  1983.     <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">
  1984.     <span style=\"font-weight: bold; font-family: Lucida Grande;\">App-Specific
  1985.       passwords</span> (copy direct,
  1986.     clean up returns)<br>
  1987.     <br>
  1988.     There are apps in the Play Store to sync calendars and contacts -
  1989.     search on
  1990.     Smoothsync for two of the best. <br>
  1991.     <br>
  1992.     iCloud mail is standard IMAP and you
  1993.     can access it in the mail application using the settings here:<br>
  1994.     <br>
  1995.     <a href=\"https://support.apple.com/HT202304\">https://support.apple.com/HT202304</a><br>
  1996.     <br>
  1997.     As you are using a non-Apple app to access your email or other&nbsp;
  1998.     facilities, you are now required to use an 'app-specific' password
  1999.     in
  2000.     place of your normal iCloud password. In order to do this you need
  2001.     to
  2002.     set up two-factor authentication for your Apple ID, and for this you
  2003.     need to have either a Mac running El Capitan or above, or an iOS
  2004.     device
  2005.     running iOS9 or above.<br>
  2006.     <br>
  2007.     <a href=\"https://support.apple.com/HT204915\">https://support.apple.com/HT204915</a><br>
  2008.     <br>
  2009.     <a href=\"https://support.apple.com/HT204397\">https://support.apple.com/HT204397</a><br>
  2010.     <br>
  2011.     If you are unable to set up two-factor authentication you should set
  2012.     up
  2013.     2-step verification and use that to create an app-specific password
  2014.     (see link below) . Then go
  2015.     to https://appleid.apple.com , select 'Password and Security'; click
  2016.     'Generate an App-Specific
  2017.     Password' and follow the instructions. Once you have the password,
  2018.     copy
  2019.     it and paste it into the password field in the application instead
  2020.     of
  2021.     your usual iCloud password. You should also keep a note of it
  2022.     (though
  2023.     you can generate a new one if required).<br>
  2024.     <br>
  2025.     <a href=\"https://support.apple.com/kb/HT204152\">https://support.apple.com/kb/HT204152</a><br>
  2026.     <br>
  2027.     You will need to nominate a 'trusted device' - any phone capable of
  2028.     receiving SMS messages. There will be a 2-day wait before you can
  2029.     complete the process.<br>
  2030.     (A particular caveat (about 2-step only) - you will be issued with a
  2031.     'Recovery Key' in case you lose your 'trusted device'. Make sure to
  2032.     write this down and keep it in a safe place; if you lose both it and
  2033.     your trusted device you will be permanently locked out of your ID.
  2034.     You'd be surprised at the number of people who've posted here that
  2035.     they've got themselves into just that position.)<br>
  2036.     <br>
  2037.     Incidentally, Mail on Snow Leopard and earlier is not recognized as
  2038.     an
  2039.     Apple application because it's pre-iCloud and doesn't have the
  2040.     necessary facilities, so it will be necessary to obtain an
  2041.     app-specific
  2042.     password for that.
  2043.   </body>
  2044. </html>
  2045.  
  2046. <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
  2047. <html>
  2048.   <head>
  2049.  
  2050.     <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">
  2051.     <title>asc roger's help text</title>
  2052.   </head>
  2053.   <body>
  2054.     <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">
  2055.     <span style=\"font-weight: bold; font-family: Lucida Grande;\">App-Specific
  2056.       passwords</span> (copy direct,
  2057.     clean up returns)<br>
  2058.     <br>
  2059.     There are apps in the Play Store to sync calendars and contacts -
  2060.     search on
  2061.     Smoothsync for two of the best. <br>
  2062.     <br>
  2063.     iCloud mail is standard IMAP and you
  2064.     can access it in the mail application using the settings here:<br>
  2065.     <br>
  2066.     <a href=\"https://support.apple.com/HT202304\">https://support.apple.com/HT202304</a><br>
  2067.     <br>
  2068.     As you are using a non-Apple app to access your email or other&nbsp;
  2069.     facilities, you are now required to use an 'app-specific' password
  2070.     in
  2071.     place of your normal iCloud password. In order to do this you need
  2072.     to
  2073.     set up two-factor authentication for your Apple ID, and for this you
  2074.     need to have either a Mac running El Capitan or above, or an iOS
  2075.     device
  2076.     running iOS9 or above.<br>
  2077.     <br>
  2078.     <a href=\"https://support.apple.com/HT204915\">https://support.apple.com/HT204915</a><br>
  2079.     <br>
  2080.     <a href=\"https://support.apple.com/HT204397\">https://support.apple.com/HT204397</a><br>
  2081.     <br>
  2082.     If you are unable to set up two-factor authentication you should set
  2083.     up
  2084.     2-step verification and use that to create an app-specific password
  2085.     (see link below) . Then go
  2086.     to https://appleid.apple.com , select 'Password and Security'; click
  2087.     'Generate an App-Specific
  2088.     Password' and follow the instructions. Once you have the password,
  2089.     copy
  2090.     it and paste it into the password field in the application instead
  2091.     of
  2092.     your usual iCloud password. You should also keep a note of it
  2093.     (though
  2094.     you can generate a new one if required).<br>
  2095.     <br>
  2096.     <a href=\"https://support.apple.com/kb/HT204152\">https://support.apple.com/kb/HT204152</a><br>
  2097.     <br>
  2098.     You will need to nominate a 'trusted device' - any phone capable of
  2099.     receiving SMS messages. There will be a 2-day wait before you can
  2100.     complete the process.<br>
  2101.     (A particular caveat (about 2-step only) - you will be issued with a
  2102.     'Recovery Key' in case you lose your 'trusted device'. Make sure to
  2103.     write this down and keep it in a safe place; if you lose both it and
  2104.     your trusted device you will be permanently locked out of your ID.
  2105.     You'd be surprised at the number of people who've posted here that
  2106.     they've got themselves into just that position.)<br>
  2107.     <br>
  2108.     Incidentally, Mail on Snow Leopard and earlier is not recognized as
  2109.     an
  2110.     Apple application because it's pre-iCloud and doesn't have the
  2111.     necessary facilities, so it will be necessary to obtain an
  2112.     app-specific
  2113.     password for that.
  2114.   </body>
  2115. </html>
  2116. "
  2117.  
  2118. adustDuplicateAnchorURLs("<a href=\"https://support.apple.com/en-ca/HT204759\">https://support.apple.com/en-ca/HT204759</a>")
  2119.  
  2120. adustDuplicateAnchorURLs("<a title=\"Go to W3Schools HTML section\" href=\"https://support.apple.com/en-ca/HT204759\" target=\"_blank\">https://support.apple.com/en-ca/HT204759</a>")
  2121.    
  2122. return
  2123.    
  2124. *)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement