Importieren und umwandeln von Dokuwiki TXT-Dateien

Hi zusammen,

versuche gerade mehrere hundert TXT-Dateien aus einem Dokuwiki in DT3 zu importieren. Dabei möchte ich die Dateien u. den Inhalt im Markdown-Format ablegen.

Folgende Herausforderungen gibt es dabei zu bewältigen:

  • Umwandlung Dateiinhalt der Dokuwiki Syntax in Markdown: Die Überschriften sind in den TXT-Dateien mit mehreren “=”-Zeichen deklariert. Hier müsste ich z.B. “=====”-Zeichen für eine Überschrift Ebene 1 in Markdown-Format “#” ersetzen

  • die Tags aus der TXT-Datei würde ich natürlich auch gerne direkt übernehmen. Die sind in der Dokuwiki-Syntax nach dem Schema {{tag>tag1 tag2 tag3 tag4 usw.}} aufgebaut

Bekommt man das irgendwie mit Bordmitteln hin oder hat jemand einen Tipp für eine andere Software?

Vielen Dank

Das funktioniert auf jeden Fall mit Bordmitteln, denn DEVONthink ist skriptbar, mit AppleScript oder mit JavaScript.

Sie sollten mal eine Beispieldatei hier posten, damit der exakte Aufbau klar ist (z. B. befinden sich die tags immer in einem bestimmten Absatz?).

Auch wichtig: Was soll mit den tags passieren? Sollen sie in macOS/iOS-tags umgewandelt werden? Oder in hashtags? In beides? Und sollen die tags in der Dokuwiki-Syntax erhalten werden (vermutlich nicht)?

Eine andere Frage: Sollen jetzt nur einmalig die mehreren hundert Dateien umgewandelt werden oder soll das regelmäßig und automatisiert geschehen (das geht problemlos, solange die Dateien des Dokuwiki nicht in einer Datenbank versteckt sind, sondern offen zugänglich im Dateisystem).

Super, das geht ja schnell hier :astonished:

Hier eine Beispieldatei:

welcome.txt.zip (1.0 KB)

Die Tags aus der Datei sollen als Tag der Markdown Datei in Devonthink zugeordnet werden. Als macOS-tag brauche ich die Information eigentlich nicht. Anschließend können sie aus der Datei gelöscht werden bzw. brauchen erst gar nicht mitgenommen werden…

Eigentlich ist das ganze eine einmalige Geschichte. Nichtsdestotrotz würde mich sehr interessieren wie es automatisiert ginge.

Vielen Dank schon mal für die Infos!

Für das Konvertieren von Dokuwiki in Markdown würde ich Perl nehmen. Das geht sicherlich auch anders, z.B. mit JavaScript oder AppleScript. So oder so: reguläre Ausdrücke sind dafür sinnvoll, in Perl etwa so

s/^=+([^=]+)=+$/# $1/

(in Perl, anderswo sieht es ähnlich aus. Klartext: Suche nach den Zeilen, die mit mindestens einem = (^=+) anfangen, gefolgt von beliebig vielen anderen Zeichen ([^=]+), und am Ende wieder mindestens ein = (=+$). Ersetze das durch "# " gefolgt von dem “beliebig vielen anderen Zeichen” ($1).
Das würde ich im Dateisystem erledigen, einfacher und schneller. In der Datei, die Du gepostet hast, sehe ich keine Tags. Die könnte man allerdings nur mit DT selbst vernünftig dort eintragen. Also entweder per Apple/JavaScript in osascript oder innerhalb von DT.

Hier kommt nun ein Skript. Ich muss vorab gestehen, dass ich kein AppleScript-Experte bin und es deshalb bestimmt eine bessere Lösung gibt (mit Regulären Ausdrücken z. B.). Aber es funktioniert!

on performSmartRule(theRecords)
	tell application id "DNtp"
		
		repeat with theRecord in theRecords
			
			set thePlainText to the plain text of theRecord
			set theParagraphs to paragraphs of thePlainText
			
			-- Dept. Tags:
			
			set theDokuwikitagLine to my findDokuwikitags(theParagraphs)
			
			if (theDokuwikitagLine is not 0) then
				set theDokuwikitags to item theDokuwikitagLine of theParagraphs as string
				set theDokuwikitags to characters 7 thru ((length of theDokuwikitags) - 3) of theDokuwikitags as string
				set theTags to my splitText(theDokuwikitags as string, " ")
				
				set tags of theRecord to theTags
				
			end if
			
			set theParagraphs to my polishUpTheParagraphs(theParagraphs, theDokuwikitagLine)
			
			set theInterimPlaintext to ""
			repeat with p from 1 to count of theParagraphs
				set theInterimPlaintext to theInterimPlaintext & item p of theParagraphs
			end repeat
			set thePlainText to theInterimPlaintext
			
			-- Dept. Headings:
			
			set theDokuwikiHeadings to {"======", "=====", "====", "===", "==", "="}
			set theMarkdownHeadings to {"#", "##", "###", "####", "#####", "######"}
			
			repeat with h from 1 to 6
				set thePlainText to my findAndReplaceInText(thePlainText, item h of theDokuwikiHeadings, item h of theMarkdownHeadings)
			end repeat
			
			set plain text of theRecord to thePlainText
			
		end repeat
		
	end tell
end performSmartRule



on findDokuwikitags(theParagraphs)
	repeat with p from (count of theParagraphs) to 1 by -1
		if (length of item p of theParagraphs > 6) then
			if (characters 1 thru 6 of item p of theParagraphs as string is "{{tag>") then return p
		end if
	end repeat
	return 0
end findDokuwikitags



on splitText(theText, theDelimiter)
	set AppleScript's text item delimiters to theDelimiter
	set theTextItems to every text item of theText
	set AppleScript's text item delimiters to ""
	return theTextItems
end splitText



on polishUpTheParagraphs(theParagraphs, theDokuwikitagLine)
	set theInterimParagraphs to {}
	repeat with p from 1 to count of theParagraphs
		if ((p is not theDokuwikitagLine) and (item p of theParagraphs is not "")) then set theInterimParagraphs to theInterimParagraphs & item p of theParagraphs & return & return
	end repeat
	return theInterimParagraphs
end polishUpTheParagraphs



on findAndReplaceInText(theText, theSearchString, theReplacementString)
	set AppleScript's text item delimiters to theSearchString
	set theTextItems to every text item of theText
	set AppleScript's text item delimiters to theReplacementString
	set theText to theTextItems as string
	set AppleScript's text item delimiters to ""
	return theText
end findAndReplaceInText

Dieses Skript ist für eine Smart Rule geschrieben und muss daher auch durch eine solche ausgelöst werden (es ließe sich aber auch leicht umschreiben, um es direkt aus dem Skript-Menü aufzurufen).

Was also zu tun ist: Dieses Skript muss, am besten mit dem Skripteditor im Unterordner “Smart Rules” des Skripte-Ordner von DEVONthink abgespeichert werden. Um an den zu gelangen, in DT oben auf das Skript-Symbol in der Menüleiste klicken und den Menüpunkt “Skriptordner öffnen” (oder so ähnlich – ich verwende DT mit englischer Benutzeroberfläche) wählen.

Dann lässt sich es sich in so einer einfachen Smart Rule aufrufen:

Bildschirmfoto 2021-03-18 um 24.50.22

“Process Dokuwiki Test” ist der Name meines Skriptes, Ihres kann natürlich anders heißen. Wenn man “External” wählt, werden alle Skripte im erwähnten Smart-Rule-Ordner angezeigt.

“On Demand” ist die manuelle Auslösung eines Skriptes. Sollte man beim Testen immer so machen. Die Smart Rule könnte aber auch, ausgelöst durch einen Trigger, die Dokuwiki-Dateien z. B. aus einem externen Ordner in DEVONthink bewegen und sie dann umwandeln.

Wenn die ersten Testergebnisse zur Ihrer Zufriedenheit ausfallen – Kopien Ihrer Dokuwiki-Dateien sollten Sie auf jeden Fall haben, trauen Sie mir nicht, ich traue mir auch nicht! –, können Sie die Smart Rule auch auf viele Dateien in einem Rutsch anwenden, einfach markieren und Regel anwerfen.

Aufgabe also gelöst, alles super?

Leider nein. Ich sehe zwei Probleme:

  1. Die Umwandlung von txt in md
    a. Konvertieren von txt in md: Wenn man die Smart Rule zusätzlich noch konvertieren lässt, dann werden sämtliche Zeichen, die Markdown-Markup bedeuten könnten, mit einem Backslash versehen, damit sie eben kein Markup sind. So funktioniert das Konvertieren in Markup seit Kurzem. Aber das will man ja nicht unbedingt.
    b. Umbenennen der Datei in Name.md: Ebenfalls tricky, denn DEVONthink verhält sich dann seltsam: Die Datei wird im Inspektor als Text und nicht als Markdown angezeigt, aber sie wird gerendert, ist also doch Markdown. Und die Smart Rule erfasst sie auch nicht mehr, was ebenfalls heißt: Sie ist Markdown. Keine Ahnung, was das noch für Folgen haben kann.
    Eine Umbenennung vorab und außerhalb von DEVONthink von .txt in .md wäre eine Möglichkeit. Aber da haben andere, die sich besser auskennen, bestimmt auch eine bessere Idee.

  2. In Ihrer Beispieldatei stecken viele, viele Links, die innerhalb Ihres Wikis funktioniert haben. Aber funktionieren sie auch in DEVONthink? Bzw.: Ließen auch die sich automatisiert umwandeln, damit sie funktionieren? Ich weiß es nicht. Das sieht weit komplizierter aus als das, was mein Skript macht.