Jump to content

User:Nihiltres/Click-to-ImageMap

From Wikipedia, the free encyclopedia

User:Nihiltres/Nav ImageMap is a useful MediaWiki extension that allows images to be clickable using nice, clean code. Since this extension hasn't always been active on the Wikimedia servers, we have a workaround template widely in use, {{click}}, which uses a nifty little hack to superimpose an invisible link over an image. This workaround doesn't work right in all contexts, making it a usability problem. It is still useful in some cases, however, since ImageMap does not support templates or template parameters. We should therefore convert all instances of {{click}} that can be converted.


I wrote a couple of scripts in AppleScript that take {{click}} input and output some virtually equivalent ImageMap code. They require three things to work: A computer running Mac OS X, the included application TextEdit, and a third-party scripting extension called TextCommands, freely available online. The scripts follow. The older, deprecated script is in a very messy state - I coded it and debugged it very quickly, more as a proof-of-concept than anything else, though it is functional. The second script is vastly preferable.

Older, deprecated prototype version parsing only single {{click}}s
on run
	----whatever works here... just get the input of one {{click}} to parameter *click*
	set click to (display dialog "Give an input of a {{click}}" default answer "" default button 2)'s text returned
	tell application "TextCommands"
		set click to (search click for "| " replacing with "|")
		set click to (search click for " |" replacing with "|")
		set click to (search click for "}}" replacing with "|}}")
	end tell
	----
	set imagepar to getparameter(click, "image")
	set widthpar to getparameter(click, "width")
	set heightpar to getparameter(click, "height")
	------dimensions parser
	if heightpar is not "" then
		tell application "TextCommands"
			set widthpar to (search widthpar for "p" replacing with "")
		end tell
		set dimensions to (widthpar & heightpar)
	else
		set dimensions to widthpar
	end if
	------
	------create the image line
	set imagebit to ("Image:" & imagepar & "|" & dimensions)
	set titlepar to getparameter(click, "title")
	if titlepar is not equal to "" then set imagebit to (imagebit & "|" & titlepar)
	------
	set linkpar to getparameter(click, "link")
	------link line parser
	if titlepar is not equal to "" then
		set linkbit to ("default [[" & linkpar & "|" & titlepar & "]]")
	else
		set linkbit to ("default [[" & linkpar & "]]")
	end if
	------
	--create as text in TextEdit
	tell application "TextEdit"
		activate
		make new document with properties {text:"<imagemap> 
" & imagebit & "
" & linkbit & "
desc none 
</imagemap>"}
	end tell
	--
	----warn if noncompliant
	------check for template bits
	if (imagebit & "|" & linkbit) contains "{{" then display dialog "This ImageMap syntax appears to contain templates or parameters, which is not supported by either the ImageMap extension or this conversion script." with icon caution buttons {"OK"} default button 1
	------check for empty critical parameters
	if (linkpar = "") or (imagepar = "") then display dialog "This ImageMap syntax appears to be missing either an image or a destination link, both of which are required." with icon caution buttons {"OK"} default button 1
	----
end run


----
on getcontentfrom(content, container)
	--This command requires *container* to be a list of two strings and *content* to be some text. 
	tell application "TextCommands"
		if ((search content for ((escape pattern (item 1 of container)) & ".*?" & (escape pattern (item 2 of container))) with regex) as Unicode text) as Unicode text is not equal to "" then
			set getcontentfrom_result to ¬
				(text (((count (item 1 of container)) + 1) as number) through (((count ((search content for ((escape pattern (item 1 of container)) & ".*?" & (escape pattern (item 2 of container))) with regex) as Unicode text) as Unicode text)) - (count (item 2 of container)) as number) of ((search content for ((escape pattern (item 1 of container)) & ".*?" & (escape pattern (item 2 of container))) with regex) as Unicode text) as Unicode text)
		else
			set getcontentfrom_result to ""
		end if
		return getcontentfrom_result
	end tell
end getcontentfrom
----

----
on getparameter(sometext, parameter)
	if (getcontentfrom(sometext, {(parameter & "="), "|"})) is not equal to "" then
		set theparamvalue to (getcontentfrom(sometext, {(parameter & "="), "|"}))
	else
		tell application "TextCommands"
			if sometext contains (parameter & "=") then
				if ((split sometext using (parameter & "=")) as string) is not equal to "" then
					set theparamvalue to item 2 of (split sometext using (parameter & "="))
				else
					set theparamvalue to ""
					display dialog (parameter & " failed.")
				end if
			else
				set theparamvalue to ""
			end if
		end tell
	end if
	return theparamvalue
end getparameter
----

I recently decided to recode the tool to let it parse a whole page for all the {{click}}s at once. This version is somewhat cleaner, but it runs quite slowly - a limitation of the simplicity of AppleScript, though improved somewhat by simplification of some of the more inefficient commands. Feel free to suggest improvements to me. It also could use a better interface - pasting an entire page worth of wikicode into a single short line in a dialog box is unwieldy for all that it is workable. I may write a bot framework and get it to make edits semi-automatically, though for now it works fine just as an easy method, or a shortcut for pages with dozens of {{click}}s.

Newer version parsing whole page for all {{click}}s simultaneously
on run
	--
	set parseList to {}
	set imageparreceived to false
	set linkparreceived to false
	set widthparreceived to false
	set heightparreceived to false
	set titleparreceived to false
	set output to ""
	----empty and normalize the starting values for each run...
	--
	set theText to (display dialog "Give me text" default answer "" default button 2)'s text returned
	----doesn't matter how you get the text, just get it and make sure the method handles it properly as Unicode text.
	--
	tell application "TextCommands"
		set midList to (split theText using "{{")
		repeat with m from 1 to (count midList)
			if item m of midList contains "}}" then
				set subList to (split (item m of midList) using "}}")
				repeat with n from 1 to (count subList)
					set end of parseList to (item n of subList)
				end repeat
			else
				set end of parseList to (item m of midList)
			end if
		end repeat
		repeat with o from 1 to (count parseList)
			if ((-1) ^ o) > 0 then
				if (check (strip item o of parseList) matches "^(c|C)lick.*") is true then
					set midList to (split item o of parseList using "|")
					if (count midList) > 2 then
						if (text 1 of (item (o + 1) of parseList)) is not "{" then
							repeat with p from 2 to count midList
								if (item p of midList) contains "=" then
									set explodedParameter to (split item p of midList using "=" splitting first 1)
									repeat with q from 1 to 2
										set (item q of explodedParameter) to (strip (item q of explodedParameter))
									end repeat
									--below is a bouncing script to evaluate it if it's a valid parameter.
									if (lowercase (item 1 of explodedParameter)) is equal to "image" then
										if imageparreceived is false then
											set imagepar to (item 2 of explodedParameter)
											set imageparreceived to true
										end if
									else if (lowercase (item 1 of explodedParameter)) is equal to "link" then
										if linkparreceived is false then
											set linkpar to (decode HTML (item 2 of explodedParameter))
											set linkparreceived to true
										end if
									else if (lowercase (item 1 of explodedParameter)) is equal to "width" then
										if widthparreceived is false then
											set widthpar to (item 2 of explodedParameter)
											set widthparreceived to true
										end if
									else if (lowercase (item 1 of explodedParameter)) is equal to "height" then
										if heightparreceived is false then
											set heightpar to (item 2 of explodedParameter)
											set heightparreceived to true
										end if
									else if (lowercase (item 1 of explodedParameter)) is equal to "title" then
										if titleparreceived is false then
											set titlepar to (item 2 of explodedParameter)
											set titleparreceived to true
										end if
									else
										--should return some sort of error
									end if
								end if
							end repeat --of p
							
							--------HERE WE HAVE PARAMETERS: ASSEMBLE THEM!
							if (widthparreceived is true) and (linkparreceived is true) and (imageparreceived is true) then
								--
								if heightparreceived is true then
									set dimensionsbit to (join {(strip widthpar removing "p" from throughout),heightpar})
								else
									set dimensionsbit to widthpar
								end if
								--
								set imagebit to (join {"Image:", imagepar, "|", dimensionsbit})
								if titleparreceived is true then
									set imagebit to (join {imagebit, "|", titlepar})
									set linkbit to (join {"default [[", linkpar, "|", titlepar, "]]"})
								else
									set linkbit to (join {"default [[", linkpar, "]]"})
								end if
								--
								set theimagemap to (join {"<imagemap>
", imagebit, "
", linkbit, "
desc none
</imagemap>"})
								set output to (join {(strip output from right end removing "{"),theimagemap})
								--------
							else
								--should return some sort of error
							end if --of enough-parameters check
						else
							--should return some sort of error
						end if --of "includes {{{}}}?" check						
					else
						--should return some sort of error
					end if --of "is midlist count > 2?" check
				else --of "is this a {{click}}" check
					if o < (count parseList) then
						set output to (join {output, item o of parseList, "}}"})
					end if
				end if --of "is this a {{click}}" check
			else --of "is o even?" check
				if o < (count parseList) then
					set output to (join {output, item o of parseList, "{{"})
				else
					set output to (join {output, item o of parseList})
				end if
			end if --of "is o even?" check
			set imageparreceived to false
			set linkparreceived to false
			set widthparreceived to false
			set heightparreceived to false
			set titleparreceived to false
			--reset the receivers for the next ImageMap on the page
			----
			
		end repeat -- of o
	end tell
	--
	tell application "TextEdit"
		activate
		make new document with properties {text:output}
	end tell
	--doesn't matter how you return it, as long as you do...
	--
end run