Any success moving from Joplin?

That at least can be scripted. See below

Same

That doesn’t work, as explained in the documentation:

Linking: You can reference local images, scripts, and other resources using item links, downward-relative (traveling subgroups; it’s not possible to travel up with ‘..’ as documents can have multiple parents) or absolute (start with a forward slash) paths.

Script to move some front matter stuff into DT metadata

This JavaScript script works on the current selection. Modification to make it work as a smart rule script is left to the reader.

(() => {
  const app = Application("DEVONthink 3");
  const selection = app.selectedRecords();
  /* Use only markdown records from current selection and loop over them */
  selection.filter(r => r.type() === "markdown").forEach(r => {
    /* Get the text of the record */
    const txt = r.plainText();
    /* Get the frontmatter of the record, each "entry" as an element in the array "frontmatter" */
    const frontmatter = txt.split(/^---/m)[1].split(/^(?=\S)/m).filter(l => !/^$/.test(l));
    /* Loop over all frontmatter entries */
    frontmatter.forEach(f => {
      /* We're only interested in 'created', 'updated' and 'tags' */
      const linetype = f.match(/(updated|created|tags):\s+(.*)/s);
      if (linetype) {
        if (linetype[1] === 'updated' || linetype[1] === 'created'){
          /* Set the creation or modification date */
          const dateString = linetype[2];
          /* Joplin's date format is non-standard: 
          replace the space with a "T" and remove the trailing newline */
          const date = new Date(dateString.replace(" ","T").replace("\n",""));
          if (linetype[1] === 'updated') {
            r.modificationDate = date;
          } else {
            r.creationDate = date;
          }
        } else {
          /* Tags: Split everything pertaining to this entry into its own array */
          const tags = linetype[2].split(/-\s*/ms);
          /* merge the current tags of the crecord with the ones found in the note */
          r.tags = r.tags().concat(tags);
        }
      }
    })
  })
})()

Some explanations:

  • selection is an Array. As such, it provides the method filter which returns a new Array, containing only those entries matching a criterion. Here, type() === "markdown", so that the result of applying filter to selection is an Array containing only markdown records.
  • forEach is another Array method that applies the function passed in as a parameter on every element of the Array.
  • The record’s plainText property is stored in txt which is then passed through several split calls. The first one (split(/^---/m) returns an Array consisting of an empty element, the front matter, and the rest of the markdown element: ^/---/ uses lines beginning with three dashes as text separator. Then [1] extracts the 2nd element of the Array, which is the front matter, and applies split(/^(?=\S)/m) to it. That separates the front matter into single lines (as Array elements) beginning with anything that is not a space character (\S). This ensures that tags: ... is kept together with the following lines, i.e. the tag names, in a single Array element. The expression (?=\S) is “zero-width”, which means that it is used to separate the lines, but the character(s) are not gobbled up. Using simply \S instead would result in lines like reated: ... and ags: ...
  • The final call to filter removes all empty lines from the array.
  • Inside the frontmatter.forEach loop, the f.match matches only those front matter lines we’re interested in, which are beginning with updated, created, or tags, | being the alternation operator. The string is saved in a first capturing group, the rest of the line in the second one.

Note: Joplin stores dates in UTC, whereas DT displays them in local time. So, 9:00 in Joplin becomes 11:00 in DT when your computer’s time zone is CEST.

1 Like