使用命令行脚本从 OmniGraffle 导出

2018 年 8 月 21 日

我经常在 OmniGraffle 中绘制大量图表,然后需要将它们全部转换为可以在网页中显示的格式。如果我只有一两个,那么每次都这样做是可以的。但是,如果我有十几个或更多,那么我发现使用脚本更容易。这样,我就可以在需要时安全地导出所有图表。

幸运的是,OmniGraffle 通过提供一个自动化接口使这成为可能,该接口允许我通过 AppleScript 与其进行通信。它在这些年里发生了变化,我今天早上花了几小时才让它工作。所以我想我会记下我的笔记,以防其他人想这样做。

最终可能会有更好的方法来做到这一点。Omni Group 正在构建一个更丰富的自动化环境,该环境将 可以从 JavaScript 调用。当我写这篇文章时,从 JavaScript 无法访问导出功能,所以我改为依赖 AppleScript 路线。

我不熟悉 AppleScript,而且当我使用它时并不喜欢它。因此,我喜欢将 AppleScript 中的任何代码保持在最低限度。我做了通常的谷歌搜索,并拼凑了一个小脚本,它导出当前的前端文档。它假设文件中只有一个画布,这对我正在使用的文件来说是正确的。

omni2png.scpt…

  on convertGraffleFile(outputFile)
    tell application "OmniGraffle"
      export front document scope "all graphics" as "SVG" to file outputFile
      close front document
    end tell
  end convertGraffleFile
  
  on run argv
     convertGraffleFile(item 1 of argv)
  end run

我想对特定文件夹中匹配特定名称模式的所有文件执行所有这些操作。我想要用一种熟悉的语言来实现大部分逻辑,而 ruby 是我用于此类脚本的语言。

omni.rb…

  module Omni
    def self.convert_file folder, name
      input = folder + (name + ".graffle")
      return unless input.exist?
      output = folder + (name + ".svg")
      return if FileUtils::uptodate?(output.to_s, [input.to_s])
      system "open #{input}"
      call_conversion(macpath(output))
    end
  
    def self.convert_rgram folder
      convert_file folder, "rgram2"
    end
  
    def self.call_conversion output
      cmd = "osascript lib/omni2png.scpt #{output}"
      result = system cmd
      puts "error processing #{output}" unless result
    end
  
    def self.convert_all_rgrams
      Pathname('catalog').children
        .select {|p| p.directory?}
        .each {|p| convert_rgram p }
    end
  
    def self.macpath arg
      return arg.expand_path.to_s.tr("/", ":")[1..-1]
    end
  end

此代码查看 catalog 的所有子目录,对于每个包含 ggram.graffle 的目录,都会导出到一个类似命名的 png 文件中。它只在日期表明 png 文件需要被重写时才会这样做。

你可能会觉得奇怪,我使用命令行调用(system)打开文件,而不是在 AppleScript 脚本中打开文件。我这样做是因为有时我会在 AppleScript 中打开 OmniGraffle 文档时遇到令人讨厌的错误(它说存在权限错误,但如果我手动或通过命令行打开它,则没有问题)。


重大修订

2018 年 8 月 21 日:更新为 OmniGraffle 更改了其导出方法,使用新的“导出”动词(而不是使用保存)。

2017 年 10 月 31 日:原始帖子