ライティング環境を見直す2021春夏

※ 2023年に思い出しながら書いてます。

Google Driveベースの作業が多くなってきたので環境を見直したい

問題意識:OmniGraffle起点だけだと弱い

  • 2019年に重い腰をあげて PlantUML を使い始めたが、概念図を描くにはやはり OmniGraffle であーでもないこーでもないするのが便利
  • 一方で OmniGraffle スタートだと画像とドキュメントを取り出してドキュメント化するのが手間で、ついそのまま PDF にしちゃいがち
  • ただ見せるだけならそれでもいいけど、再利用性は間違いなく落ちるし、OmniGraffle が必要なほど複雑でない図で伝えたいだけの場合も増えてきた

手法:まずVS CodeのMarkdown拡張を知る

文書を起点にするならそういう記法を使うのもアリか。もう少しこれまでよりも自然言語ライティング自体を加速させるような取り組みをしたい。1

Markdown Preview Enhanced - Visual Studio Marketplace

  • Google Drive だけでなく日記の更新や薄い本みたいなある程度の分量のドキュメントを書きやすくはしておきたい
  • Markdown Preview Enhancement という拡張を知る
    • PlantUML も拡張でレンダーできる
    • esa などでも Markdown の中に埋め込めるのは知っていたけど、esa 限定だと面白くないと思っていた
  • Markdown はそんなに記述力ない(割と簡単に HTML 生書きに陥る)のがネックけど、内容によっては割と耐えられるかも?

課題:Google Drive へどうやって持っていくか

書くだけなら Google Drive よりまともなエディタで書ける方がありがたい。一方で Google Docs は Markdown エディタではないので、Markdown で書いたものをどうにかして Google Docs の形式に変換しないとそのままでは普通の人には見慣れない記号にまみれた無愛想なドキュメントになってしまう。

ネック

  • 画像。PlantUML で描いたとしてそれをラスタ画像として取り出せないと Google Docs へ添付できない
  • Google Docs は Markdown 記法に直接対応はしていないのでなんらかの変換が必要

変換方法

とりあえず見つけた方法。

※ ご存知の通り無駄が多いです。

  1. Asciidoc ← Markdown ( kramdoc / kramdown の機能 )
  2. DocBook ← Asciidoc ( asciidoctor の機能 )
  3. bocx ←DocBook ( Pandoc の機能 )
  4. Google Docs ← docx ( Google Drive の機能 )

PlantUML を書いて PlantUML をそのまま変換して画像を出力できる方法は知っていたが、一連の流れの中で書けると嬉しいと思い、試行錯誤してみる。この過程で気づきがいろいろある。

Markdown Preview Enhancement の中で Pandoc を呼べるが、Markdown + PlantUML → Pandoc → docx を直接実行すると PlantUML 画像内の日本語が化けるなど、拡張内の各ツールの設定が練れていない。

一方で Asciidoctor は面白い。

Asciidoctorよいかも

Asciidoc も名前だけは以前から知っていたが、特段 Asciidoc を使うメリットは感じていなかった。表現力は Markdown より上なんだろうけど、やはり Markdown は利用できるシーンが非常に多いため、あえて普段使いに Asciidoc を使う理由を見つけるのは難しい。

そんななか、上の docx 生成で Pandoc に繋ぐ際に asciidoc を経由する方法もあるなと思い、手を出してみたら思いのほか手応えを感じる。

AsciiDoc - Visual Studio Marketplace

  • 拡張が Asciidoctor2 本家からリリースされていて安心
  • Markdown ではサポートされていない画像埋め込みの機能が記法自体にある
  • asciidoctor + asciidoctor-diagram で変換するとそのまま画像を取り出すことができる
  • Pandoc で直接処理するよりも Asciidoctor 経由で処理した方が docx 変換もスムーズ
  • asciidoctor 自体で ePub や PDF 生成の機能を持っており、最初から AsciiDoc で書いておけば HTML 以外に出力にも向いている

docx 変換については以下の sh スクリプトを用意した。

asciidoctorとasciidoctor-diagramとpandocを使ってasciidocからdocxを作る

OOXML の template を作るのはある程度コツが要る割に期待した仕上がりまで持っていくのはかなり大変なので、ある程度までになってます…。

今のところ微妙?

Markdown で書き始めるのはよいが、その後ラスタ画像を作るのはやはり億劫。それでも画像作成の機会と Markdown スタートでの環境の書きやすさのどちらがマシかというとやはり後者の方に軍配が上がる。

面倒は面倒。特に PNG 出力が思ったより解像度が悪いので、いったん SVG にしてから PNG に変換する部分でかなりの手間を要する。

もう一つ、docx ( OOXML ) 変換向けのテンプレートを頑張って作ったが、これなら Google Docs のデフォルトスタイルに合わせつつ margin とか文字サイズの設定だけすればだいたい満足なのでは?という感じがしている。

すると asciidoctor + asciidoctor-diagram は画像の取り出しのためだけに使う、みたいな感じになっていて手間の割に嬉しみが少ない。

図のない Google Docs を Markdown から一手間(行頭の記号の入力に応じて変換が走るので)掛けて作る、みたいな運用がほとんどになっている。

  1. これまではコード、仕様、設計が主で日本語ドキュメントはスライドが中心と思いねぇ 

  2. Asciidoctor は Asciidoc 処理系の一つで恐らく最もアクティブに開発されている。 

Google Apps Script開発にstaging環境を用意してContinuous Deployment

※ 2023年夏時点で Script API はサービスアカウントで利用することができないため、安全に安定的に CD を実現するのは難しく、そこまでするメリットが薄いのではないかと考えています。

Introduction  |  Apps Script  |  Google for Developers

Apps Script API はサービス アカウントでは動作しません。

Script API 登場以降、ずっとこの話題はありましたが、2021年に結論リポジトリができています。

Apps Scripts API

背景

  • Google Apps Script 開発もモダンになっており、Git + GitHub + CI/CD な構成は実現できることが分かった
  • でもやはり master ブランチ以外は staging 環境の方へ deploy したい
  • しかし gas-manager などによる Google Drive API を利用した deploy の際には、deploy 先となるプロジェクトの Drive ID が必要になるので、Drive ID の切り替えが必要。しかもこの ID などの情報は JSON ファイル で保存されているのが前提

対処方法の基本的な考え方

  • deploy 前に (gas-managerで言う)gas-project.json や必要となる Spreadsheet の ID を差し替える仕組みを動かす ( preprocess )
  • 実行時に必要なパラメータは実行時にスイッチする仕組みを入れてもよいが、どうせ書き換えが必要な ID があるし、実行時の if スイッチが増えるのはバグが増えるのと同義なので、build 時に書き換えができるようにすればよい

具体的な方法

  1. パラメータの詰まった JSON を用意する
  2. gas-project.json などはこの 1 の JSON と template をもとに upload 前に生成する
  3. Browserify で実行コードを生成する際に、1 で用意した JSON から必要な環境の分だけを抽出した JSON を生成し、これを require する

これで実行時に必要なパラメータは実行時にコードの中に詰まっている状態になる。秘密情報でなければこの方法で埋め込んでしまうのがリーズナブルな解決方法だと思う。

gas-project.json の template は以下のような感じ。{{mustache}}

gas-project.json.mjs

{
  "src": {
    "fileId": "",
    "files": {
      "<scriptname>": {
        "path": "src/code.js",
        "type": "server_js"
      }
    }
  }
}

パラメータの詰まった JSON はこんな感じ。

gas-components.json

{
  "production": {
    "fileId": "",
    "targetBook": ""
  },
  "staging": {
    "fileId": "",
    "targetBook": ""
  }
}

全体像を図にすると以下のような感じ。

GASプロジェクトにpreprocessを入れてstaging環境への切り替えを実現する

jQuery.deferredを経由しつつES2015に入ったPromiseの雰囲気を味わう

Promiseを受け取るコードの練習が狙い

今回のコードは裏では動作の確認はしてるけど全体的には雰囲気を味わうものです。Promise がなんだかよく分からないので適当に sleep して返事を返すだけのサーバをでっち上げて、これまた普段使っていないのになぜか jQuery.deferred から試してみてます。既存の道具からのステップを小さくしておくことで理解しやすくなることを狙います。

また Promise そのものや Promsie を作る部分は注目してません。あくまで Promise を利用するのはそんなに難しくないな、という雰囲気を知るためのものです。

Node.js に詳しい人は 2015年リリースの v4 から使えるので、いちいち遠回りする必要はないと思いますし、すでに動いているコードを今回のように書き換える意味はないと思います。

jQuery.deferred

jQuery.Deferred() | jQuery API Documentation

まずは jQuery.deferred で実験。

実は jQuery はかなり古い 1.5 の時代から Deferred という機能を持っていて、ajax() や getJSON() などはこの Deferred オブジェクトを返しています。そしてこの Deferred オブジェクトが Promise とよく似た動作をします。ただし fail() は jQuery 用語で、ES2015 だと catch() になります。

1) 単純な成否

$.getJSON('/api1')
  .then(function() {
     // success
  })
  .fail(function() {
    // failure
  });

これだけだと if then else のように動く。

2) エラーをまとめて拾う

$.getJSON('/api1')
  .then(function() {
    return $.getJSON('/api2');
  })
  .fail(function() {
    // failure for api1 and api2
  });

then() の中で非同期処理を実行して「Promiseを返せば」どちらで失敗しても同じ fail() を通過する。

3) 異なるPromiseのをエラーを別々に拾う

$.getJSON('/api1')
  .then(function() {
    $.getJSON('/api2')
      .then(function() {
        // success
      })
      .fail(function() {
        // failure for api2
      });
    })
  .fail(function() {
    // failure for api1
  });

非同期ではあるけど if then の入れ子のような感じで書ける。中の fail() でエラーを拾っておけば外の fail() まで伝播することはない。

Promise ( ES2015 )

今度は jQuery のように使えて jQuery より小さいけど、Deferred を持っていない UmbrellaJS を使ったうえで、Promise の部分だけ ES2015 で補います。

※ IE 対応が必要な場合はトランスパイラや Polyfill が要ります。

まずはjQuery の $.getJSON() とほぼ同じ動きをして Promise を返す wrapper 関数 u.getJSON() を定義します。1ES2015 の Promise は jQuery.deferred と違って失敗時は catch() で拾います。

※ くりかえしますが、実際のプロダクトではこんなコードは必要ないです。

Umbrella JS

wrapper

u.getJSON = function(url) {
  return new Promise(function(resolve, reject) {
    u.ajax(url,
           {method: 'GET'},
           function(err, data) {
             if ( err ) {
               reject(err);
             } else {
               resolve(data);
             }
           }
          );
  });
}

1) 単純な成否

u.getJSON('/api1')
  .then(function(data) {
    // success
  })
  .catch(function(e) {
    // failure
    console.log(e + ' : api failed.');
  });

2) エラーをまとめて拾う

u.getJSON('/api1')
  .then(function() {
    // success
    return u.getJSON('/api2');
  })
  .catch(function() {
    // failure for api1 and api2
  });

3) 異なるPromiseのエラーを別々に拾う

u.getJSON('/api1')
  .then(function() {
    u.getJSON('/api2')
      .then(function() {
        // success
      })
      .catch(function() {
        // failure for api2
      });
    })
  .catch(function() {
    // failure for api1
  });

参考

応用編

  1. ちなみに u.ajax() は特に指定しなくても JSON string だったら自動的に parse してくれる謎機能が付いてます。 

今日のブログチャート

「アクセス」がそれなりの数あるということなのか Lv 36 にはなったけど、「評価」がグッと下がった。次は「話題度」が下がるかな? 話題になんかなってないよ。

ただ急激に増減することのない購読数の 144やクリップ数の 376は自分で思っていたよりは多い。塵も積もればこれくらいにはなるんだなー。

Ajax でアサマシブログ支援

時代は RSS リーダーとアフィリエイトなのに、どうも書いているときはそういうことはあまり意識していないのでとりあえずそのまま書いちゃって、公開し終わってふーっと一息ついたあとに慌てて amazon のアフィリエイトを引っ張り出してきてるオレがいるorz

こんなんじゃうまいこと誘導できっこねーよなぁ。明らかにあとから amazon へのリンクが増えてるんだもの。 RSS の更新を監視してればすぐにどういう意図をもって記事を修正しているかバレる。もっとこう、書いてる最中から文章を解析してそれっぽい商品を検索しまくって教えてくれる機能とか tDiary にあればいいのに。あれですよ、Ajax ですよ。書いてる裏で検索して textarea の隣とかにバババっと商品が出てくるの。そんでよーしこれとこれ買わせちゃれ、ってポチポチしていくとそいつらが文章の中にうまいこと埋め込まれていくの。

もちろんこれらのリクエストは「よーしパパあさましエントリ書いちゃうぞー」って意思表示したときだけね。なんかそういう checkbox があるの。そこチェックするとバババって出てくるの。普段からそんなリクエスト飛ばしまくってるとうざいからね。意思表示したときだけね。

出ないかなぁ、そういうの。

「それ以前に影響力のあるblogじゃないじゃん」ていうツッコミはなしね。単に楽したいってだけの話だから。あと、サイドバーとかタイトルのすぐあととか、エントリの切れ目とかに自動的に入るやつにすれば?ってのも却下。あれは自分が読むときうざいだけだから。あくまでうまいことエントリに馴染んでないとダメなの。そういうのが美しいと思うから。

BEATWASH と汚れのようなもの

日立 水をためない洗濯機 (@2ch.net)

229 :目のつけ所が名無しさん :2005/04/14(木) 19:57:02
    節水できる、に釣られて買ったビートウォッシュ。
    黒い綿シャツが綿埃と糸くずで白っぽくなるし、
    これまで何度も洗ってたタオルがTシャツに色移り。
    (衣類を擦り合わせるかららしいが……)
    一週間で返品、他機種に交換しました。
265 :目のつけ所が名無しさん :2005/06/09(木) 09:43:16
    ビートウォッシュ使ってますが、ノーマルモードでは糸くず(綿埃のようなもの)が
    衣服に残るので注水すすぎなどを使って回避しています。節水の意味がないな。

大量の水にくぐらせないので糸くず系の汚れが落ちないという話。

洗濯する前に手で取れるような汚れは落としておけってことだよな、逆に言うと。考えたら洗濯の基本というか。

クレジットカードの国際化の歴史の一部

Re:非常に素朴な質問。 (MasterCardなどのカード情報4000万枚分が大量流出@/.-j)

なるへそ。この von_yosukeyan 氏は以前からスラド日記でたくさん金融系の話を書かれていてすげーなぁとは思っていたんだけど、今後もちょこちょこ勉強させてもらいます。

ついに Orca が 100番台に

Orca 198位

乗っちゃったのですが…。うなぎのぼりなんですよ最近。なんか以前より平均ストローク上がってるし。頑張りすぎですか。別に Orca 目的で余計なことしてるわけじゃないんですけどね。まーよくやった、おれ。頑張れ、おれ。頑張りすぎるな、おれ。

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm