Markdown Table Generator

The script included below creates a markdown table in a Safari web page that supports markdown (typically a forum). The first row of the table is a header and is not included in the number of rows specified by the user. The second row of the table allows the user to specify whether the column is left-aligned (:—), center-aligned (:—:), or right-aligned (—:). The number of dashes have no significance, although there should be at least three of them.

The following is an example of a simple table. The table itself is left aligned, and there’s no easy way to change this.

First Name Last Name Status
Peavine Peabody member
Nigel Garvey moderator
Shane Stanley developer

The script:

--revised 2024.07.29

display dialog "Enter the number of columns, a space, and the number of rows. Then select whether the columns should be left or center aligned." buttons {"Cancel", "Center", "Left"} with title "Markdown Table Generator" default button 3 default answer "3 3"
set {columnAlignment, columnAndRowCount} to {button returned, text returned} of result

set text item delimiters to {" "}
try
	set columnCount to (text item 1 of columnAndRowCount) as integer
	set rowCount to (text item 2 of columnAndRowCount) as integer
on error
	display dialog "The entered data could not be processed" buttons {"OK"} cancel button 1 default button 1
end try
set text item delimiters to {""}

set {dataRow, formatRow} to {"|", "|"}
if columnAlignment is "Left" then
	repeat columnCount times
		set dataRow to dataRow & "  |"
		set formatRow to formatRow & " :--- |"
	end repeat
else
	repeat columnCount times
		set dataRow to dataRow & "  |"
		set formatRow to formatRow & " :---: |"
	end repeat
end if

set dataRows to ""
repeat rowCount times
	set dataRows to dataRows & dataRow & linefeed
end repeat

set theTable to dataRow & linefeed & formatRow & linefeed & dataRows
set the clipboard to theTable

tell application "System Events" to tell process "Safari"
	try
		set frontmost to true
		delay 0.3 --may not be needed
		click menu item "Paste" of menu "Edit" of menu bar 1
	end try
end tell
3 Likes

Pretty handy.

I don’t use markdown tables very often but sometimes I do when capturing part of a wikipedia page in devonthink… typically to lay out one of the information boxes, or occasionally when capturing some sports statistics.

I often forget the syntax as I do that infrequently so this should help.

As an aside, while it doesn’t seem to work on this site, you can add CSS styles to markdown and that includes centering a table.

Putting this at the top of a devonthink markdown document would cause any table to be centred horizontally on the page. It should work in most (non-online) markdown environments.

<style>
table {
	margin-left: auto;
	margin-right: auto;
}
</style>

1 Like

Nice one, @peavine. :sunglasses:

Here for my own amusement on a Sunday morning — and in the spirit of Code Exchange, of course :wink: — is some tinkering with your code. Apart from a slight tightening up of the input checks, I wouldn’t claim it to be any better than your original.

set {text returned:columnsAndRows, button returned:theAlignment} to ¬
	(display dialog "Enter the number of columns, a space, and the number of rows. Then select whether the columns should be left or center aligned." buttons {"Cancel", "Center", "Left"} with title "Markdown Table Generator" default button 3 default answer "3 3")
set {astid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {space}}
set {columnsAndRows, AppleScript's text item delimiters} to {columnsAndRows's text items, astid}
try
	set {columnCount, rowCount} to columnsAndRows
	if (((count columnsAndRows) > 2) or (1 > columnCount) or (0 > rowCount)) then error
on error
	display dialog "The entered data could not be processed" buttons {"OK"} cancel button 1 default button 1
end try

set rowTemplate to {"|"}
repeat columnCount times
	set rowTemplate's end to "|"
end repeat

set aHeaderOrRow to join(rowTemplate, "  ")
set theFormatter to join(rowTemplate, {" :---: ", " :--- "}'s item (((theAlignment is "Left") as integer) + 1))

set theRows to {aHeaderOrRow, theFormatter}
repeat rowCount times
	set theRows's end to aHeaderOrRow
end repeat

set theTable to join(theRows, linefeed)
set the clipboard to theTable

tell application "System Events" to tell process "Safari"
	try
		set frontmost to true
		delay 0.3 --may not be needed
		click menu item "Paste" of menu "Edit" of menu bar 1
	end try
end tell

on join(lst, delim)
	set {astid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, delim}
	set {txt, AppleScript's text item delimiters} to {lst as text, astid}
	return txt
end join
1 Like

Here is an extension of @peavine’s script.

If you feed it some tabular data, then it should output the final table.

As it basically just pipes the data into the field spots, it must have the requisite number of tabs, even if there isn’t any data for a particular record/field. There are probably ways to deal with this gracefully but this version of the script doesn’t attempt that.

I included two examples of data. Uncomment the second one to test it out. For actual use, I’ll probably set it up to get the data from the clipboard and then calculate the row and column count from that.

use scripting additions
display dialog "Enter the number of columns, a space, and the number of rows. Then select whether the columns should be left or center aligned." buttons {"Cancel", "Center", "Left"} with title "Markdown Table Generator" default button 3 default answer "2 5"
set {columnAlignment, columnAndRowCount} to {button returned, text returned} of result

set text item delimiters to {" "}
try
	set columnCount to (text item 1 of columnAndRowCount) as integer
	set rowCount to (text item 2 of columnAndRowCount) as integer
on error
	display dialog "The entered data could not be processed" buttons {"OK"} cancel button 1 default button 1
end try
set text item delimiters to {""}

set {dataRow, formatRow} to {"|", "|"}
set {centr, lef} to {" :---: |", " :--- |"}

-- set default alignment
if columnAlignment is "Left" then
	set colAlign to lef
else -- is centred
	set colAlign to centr
end if

-- use '•' as a field token
repeat columnCount times
	set dataRow to dataRow & " • |"
	set formatRow to formatRow & colAlign
end repeat

-- append rows
set dataRows to ""
repeat rowCount times
	set dataRows to dataRows & dataRow & linefeed
end repeat

set theTable to dataRow & linefeed & formatRow & linefeed & dataRows -- prepend headings
-- set the clipboard to theTable
set tableTop to dataRow & linefeed & formatRow -- headings and alignment rows
set tableStructure to dataRows -- data rows

-- data examples, tab-separated
-- example 1: '2 5'
set tabData to "Case Opinions	
Majority	Powell, joined by Burger
	Stewart, Blackmun, Stevens
Concurrence	Burger
Dissent	White, joined by Brennan, Marshall
Dissent	Rehnquist"

-- example 2: '6 10'
(*
set tabData to "Rk	Player	Tm	Car	Yds	TD
1	Derrick Henry*	TEN	280	1167	12
2	Christian McCaffrey*+	SFO	272	1459	14
3	Rachaad White	TAM	272	990	6
4	Travis Etienne	JAX	267	1008	11
5	Joe Mixon	CIN	257	1034	9
6	Najee Harris	PIT	255	1035	8
7	Tony Pollard	DAL	252	1005	6
8	Saquon Barkley	NYG	247	962	6
9	Chuba Hubbard	CAR	238	902	5
10	James Cook*	BUF	237	1122	2"
*)

-- separate heading from data
set text item delimiters to linefeed
set headData to paragraph 1 of tabData
set bodyData to rest of paragraphs of tabData as text

-- split into lists of field data
set text item delimiters to {linefeed, tab}
set bd to text items of bodyData
set hd to text items of headData

set text item delimiters to "•"
set blocks to ""
set heads to ""

-- replace bullets with field data
set tsd to text items of tableStructure
repeat with di from 1 to ((count of tsd) - 1)
	set blocks to blocks & item di of tsd & item di of bd
end repeat
set blocks to blocks & " |"

set ttd to text items of tableTop
repeat with hi from 1 to ((count of ttd) - 1)
	set heads to heads & item hi of ttd & item hi of hd
end repeat

-- stitch parts together and output
set finalTable to heads & last item of ttd & linefeed & blocks
set the clipboard to finalTable

finalTable

The two outputs should like something like these:

Case Opinions
Majority Powell, joined by Burger
Stewart, Blackmun, Stevens
Concurrence Burger
Dissent White, joined by Brennan, Marshall
Dissent Rehnquist
Rk Player Tm Car Yds TD
1 Derrick Henry* TEN 280 1167 12
2 Christian McCaffrey*+ SFO 272 1459 14
3 Rachaad White TAM 272 990 6
4 Travis Etienne JAX 267 1008 11
5 Joe Mixon CIN 257 1034 9
6 Najee Harris PIT 255 1035 8
7 Tony Pollard DAL 252 1005 6
8 Saquon Barkley NYG 247 962 6
9 Chuba Hubbard CAR 238 902 5
10 James Cook* BUF 237 1122 2
1 Like