MD files and automatic insertions (CSS-linkage, TOC-strings) – possible?

hello community + everyone,

sorry if this has been discussed somewhere (I have checked forum and didn´t find precedence); and sorry if it meshes two things that might have somewhat different status (for the ‘naíve me’ this appears as one issue-context).

I would like to
1 - style all MD-files w/in a folder and/or DB with help of a specific CSS. it seems to me
a) this can not be done per se;
b) would be doable if there is a way to automate the inclusion of the css-instruction at the top of any MD-file located in ‘X’

2 - insert a TOC ({{TOC}} ) in the same way at the top of given MD-files (in location ‘X’) – either on Top, or – even better – by default after the first h1-tag.
(just in case you wonder: TOC does not only produce the TOC where I´d want it instead of the DT-pane for content-structure (right side-pane), but also a cleaner version for my purposes… which is, why I need it :smiley: )

questions:
– can this be done? (if so can you point me a way? :slight_smile: )
– has this already been done (is there a resource for that), or have I overlooked an obvious resource for this within DT?

thx already for any help!

You can define a css file in the preferences. I’m sure it’s described in more detail in the documentation And md styling with css has been discussed in the forum, too.

Another possibility might be to create one or more templates which link to the desired stylesheet, include {{TOC}} and a dummy header.

1 Like

If you select a global stylesheet in the Preferences > Media > Markdown, it will apply to all Markdown files. This may - or may not - be what you want to do.

If not, it is possible to script something. Here is a teaching edition example - noting you’ll have to replace the item link with the link of the stylesheet you want to use…

property stylesheet : "<link rel=\"stylesheet\" href=\"x-devonthink-item://6C8A682B-8B28-4DDB-84AC-D78C26577019\" />" -- The item link is from the CSS file. This is one approach but allows for some flexibility in where the stylesheet is located.

set ot to AppleScript's text item delimiters -- Cache the default AppleScript text item delimiters

tell application id "DNtp"
	repeat with thisRecord in (selected records) -- Process any selected records
		
		if (type of thisRecord as string = "markdown") or (type of thisRecord as string = "text") then  -- Check the file type
			set src to plain text of thisRecord -- Get the plain text of the file to process
			
			repeat with incr from 1 to (count paragraphs of src) -- Process the paragraphs looking for the first Markdown header
				if paragraph incr of src begins with "# " then
					
					-- The section here is required in this case as empty paragraphs, i.e., returns, aren't preserved when converted to strings
					set AppleScript's text item delimiters to return -- Change the delimiters to a return
					
					set bef to (paragraphs 1 thru incr) of src -- Get the current line and the ones preceding it
					set bef to text items of bef as string
					
					set aft to (paragraphs (incr + 1) thru -1) of src -- Get the next line and the ones following it
					set aft to (text items of aft as string)

		-- Stringing the text of the file back together and replacing the text.
		set plain text of thisRecord to (stylesheet & return & return & bef & return & return & "{{TOC}}  " & return & return & aft)

					exit repeat -- Stop looping as we only want to introduce the {{TOC}} once.
					
				end if
			end repeat			
		end if
	end repeat
			set AppleScript's text item delimiters to ot -- Reset the delimiters to the original state

end tell

The script can be saved in the ~/Library/Application Scripts/com.devon-technologies.think3/Menu directory for use as needed.

1 Like

thx a load for these swift and helpful comments to all!

@chrillek: thx for reaction. I was indeed aware of the global setting, and was asking for more granular options (– as for rationale: I would like to treat my text + write up sketches differently than, say, my archived diary and journal entries)

@cgrunenberg: that is a helpful hint in general. in my case, I am dealing with MD-files regularly imported (indexed) from another app

@BLUEFROG: thx for that amazing shoot. I´ll try to dive into it, being not too script-literate. but I am always reminded that one can just do amazing things w/ scripting. so, appreciate the lead and will try to wander off into the wilderness… :slight_smile:

… will also try to extend this to a solution on {{TOC}}-insertion. meanwhile any additional hints on this one by the more initiated still welcome + appreciated!

so, thx to all!

The script I posted does the TOC insertion after the first detected H1 header.
And you’re welcome.

1 Like

Thx for extra-flagging!
plain lovely! appreciate the detail + attention in a teaching edition! :smiley:

You’re welcome.

PS: I made a small modification the the script posed above. Recopy it use it as it’s now written.

hey Jon,

unfortunately this didn´t work for me :-/

I tried several routes (and restarts):
1 - via script-menu, triggering it on the (test-)MD-file as well as its parent folder
2 - same via smart rule (including the ‘on performSmartRule(…) – end performSmartRule’ bracketing

in both case… well… nothing happened. no error message. no indication of processing. but also no result (neither TOC-insert, nor the stylesheet-referencing)

I do not want to take up free time of anyone.
so I comforted myself w/ going back to the global CSS-toggle-option and making my peace with it. (as to TOC … I can/will insert it by hand, when really needed)

– just thought to leave a feedback / trace here. for others.
… and for documentation of my so-so-relation to scripts :smiley:

thx again!

  • What does the test Markdown file look like?
  • What kind is it?

hey Jim,

thx for revisiting + follwing. appreciated.

I am no Markdown-expert. but it seems a ‘simple’(?) MD file generated as output from Diarly. it uses
a) very basic /standard markup (as far as I can tell; i.e. headings, italics/bold, highlight, img; links, hr… not more)
b) the only remarkable thing seems ‘******’ for ‘hr’; and that it uses for attachments… but that also is standard, I think
c) …actually I was checking with minimal versions, only containing some h1 and h2 lines … still same problem

also: the smart rule I constructed also found some MD-files from earlier ‘Notebooks’-exports (the software by Alfons Schmid). very basic entries - here: same problem. nothing happens. neither w/ menu script nor w/ smart rule…

Stupid question: Did you adjust the link to the style sheet at the top of the script to the one you want to use? 2nd question: Did anything appear in DT’s log window?

@chrillek: no question is stupid in cases where someone interacts ‘stupidly’ w/ scripting, as is the case for me :slight_smile: so good + thx for double checking!

answer #1: yes! I did. meanwhile I have some feeling for what to look out for / attend to – even if it´s not very well-founded in real scripting-knowledge.

answer #2: example of me being somewhat stupid nevertheless. of course log-files is something I should have thought of! – result: no entry whatsoever; just checked again. then it gives a log-entry for my smart rule… probably done something wrong there… but then, it seems the script it self is not working anyways…

    on performSmartRule(theRecords)
	property stylesheet : "<link rel=\"stylesheet\" href=\"x-devonthink-item://6C8A682B-8B28-4DDB-84AC-D78C26577019\" />" -- The item link is from the CSS file. This is one approach but allows for some flexibility in where the stylesheet is located.

set ot to AppleScript's text item delimiters -- Cache the default AppleScript text item delimiters

tell application id "DNtp"
	repeat with thisRecord in (selected records) -- Process any selected records
		
		if (type of thisRecord as string = "markdown") or (type of thisRecord as string = "text") then  -- Check the file type
			set src to plain text of thisRecord -- Get the plain text of the file to process
			
			repeat with incr from 1 to (count paragraphs of src) -- Process the paragraphs looking for the first Markdown header
				if paragraph incr of src begins with "# " then
					
					-- The section here is required in this case as empty paragraphs, i.e., returns, aren't preserved when converted to strings
					set AppleScript's text item delimiters to return -- Change the delimiters to a return
					
					set bef to (paragraphs 1 thru incr) of src -- Get the current line and the ones preceding it
					set bef to text items of bef as string
					
					set aft to (paragraphs (incr + 1) thru -1) of src -- Get the next line and the ones following it
					set aft to (text items of aft as string)

		-- Stringing the text of the file back together and replacing the text.
		set plain text of thisRecord to (stylesheet & return & return & bef & return & return & "{{TOC}}  " & return & return & aft)

					exit repeat -- Stop looping as we only want to introduce the {{TOC}} once.
					
				end if
			end repeat			
		end if
	end repeat
			set AppleScript's text item delimiters to ot -- Reset the delimiters to the original state

end tell
end performSmartRule

The property line shouldn’t be inside the Smart Rule handler. Move it one line up

In addition to what @pete31 said, I’d leave out the whole smartrule thingy. That’s a bit pointless here, I think.
To ease debugging, you might want to run the script in ScriptEditor and check the output that’s generated there.

I have the impression that the plain text of a markdown file has no paragraphs. At least not in the MD file I’m experimenting with (which is long-ish and certainly does have paragraphs).

I propose an alternate version of the script written in JavaScript.

(() => {
/* self executing function */
let app = Application("DEVONthink 3");
let stylesheet = `<link rel="stylesheet" href="x-devonthink-item://0841105D-70B7-4518-8E2C-68E25CF8FC38" />`;  
  app.selectedRecords().forEach(r => {
    let src = r.plainText();
	let toc = "";
    if (new RegExp("^# ","m").test(src)) {
  	    toc = "{{TOC}} ";
    }
  r.plainText = `${stylesheet}\n\n\n\n${toc}\n\n${src}`
  })
})()

What it does (here, with one example file): Add the <link…> to the CSS at the top line, add four blank lines after that, adds {{TOC}} on a line by itself, two more blank lines. The original MD file follows.

thx everyone!

I am ‘blushed’ by the brain-/scriptpowers going into this, and being shared.
I will have to put myself deeper into all this, getting hands dirty. for now this finds me w/ a lack of technical understanding and currently low bandwith. so,

@Pete31: I tried this; but didn´t work either

@chrillek: thx a lot! I have also seen the other debates/hints on using JS. but in the end, I can´t even make this ‘fire’ trigger (I have tried putting it into the folder, one time as .scpt-file; one time as .js-file. the first desnt´t do anything; the js doesn´t appear at all; and trying reconstructing the smart rule way also led me nowhere…)

I guess, I will have to return later with some more breath.
but meanwhile big ‘thank you all!’ – and I hope this als might give others ideas / hints…

best!

ps: meanwhile I´ll settle w/ glbal css-toggle. there are worse work-arounds :smiley:

Whatever that means. You can copy& paste it into script editor (selecting JavaScript in the tool bar), select a record in DT am then run the script in script editor. If it does what you want, save it (from script editor) in DT’s script location, whatever subfolder seems appropriate.
Then you can select the records to modify in DT and run the script from the script menu in DT. From your post, I have no idea what you were doing at all.
Beware though: in this form, it can’t be used in a smart rule!

1 Like

Can you zip and post an example Markdown file you’re trying the script with?

1 Like