Help us understand the problem. What is going on with this article?

小説執筆補助ツール「novel-builder」README

More than 1 year has passed since last update.

※この記事は、私がnpmおよびGitHubに公開しているnode.js製の小説執筆補助ツール「novel-builder」のREADMEをそのまま転載したものです。
解説は「恋に落ちるコード.js」の絵子と樹里です。
(2018/11/18 v0.4.0の内容に修正)


novel-builder.js

篠宮樹里「絵子よ、Web小説の執筆を補助するツールをNode.jsで作ってみたぞ」
瀬尾絵子「何でもJavaScriptでやりたいんだねー……」

Description

このツールは、次のような方々を主なターゲットとして開発しています。

  • 小説もNode.jsプロジェクトとして執筆(開発)したい!
  • 開発で使い慣れたエディタ(VSCode等)を執筆にも使いたい!
  • 原稿はMarkdown形式で書きたい!
  • node.jsやnpmに抵抗がない。むしろ好き!

下記のような執筆補助機能を提供してします。

  • 小説の原稿を各種小説投稿サイト向けの原稿に変換する機能
  • 電書協 EPUB 3 制作ガイドに準拠したEPUBを作成する機能
  • 小説をPNG画像で出力する機能
  • 行頭に全角スペースを挿入する等の校正機能
  • レポート出力機能

また、本ツールは開発途中のため、予告なく仕様の変更が行われることがあります。
それでもよろしければ、続きをお読みください。

Demo

このツールを組み込んだWeb小説をGitHubに公開しています。ご参考までに。

Installation

樹里「ではさっそく、このツールの使い方……というか、まずはNode.jsプロジェクトとして小説を執筆する方法について解説していこう」
絵子「お願いします」

準備

Node.jsをインストールする

樹里「まず最初にやるべき事は、Node.jsのインストールだ」
絵子「そりゃ、これがないと動かないからねー」

Node.jsプロジェクトを作成する

樹里「次に、Node.jsプロジェクトを作成しよう」
絵子「お、難しそうだね」
樹里「そんな事はない。ディレクトリをひとつ作るだけだ」
絵子「それだけ?」
樹里「ああ。その代わり、ディレクトリ名は半角英数字、ハイフン、アンダーバーのみを使用したほうがいい」
絵子「日本語は使わないほうがいいのね」
樹里「ちなみに、私達の活躍を書いたWeb小説『恋に落ちるコード.js』の
プロジェクト名はjk-meets-jsだ」
絵子「あ、そんな名前だったんだ」

package.jsonを作成する

樹里「続いて、このディレクトリがNode.jsプロジェクトであることを宣言するためのファイル、package.jsonを作成しよう」
絵子「ここをNode.jsプロジェクトとする!」
樹里「ちゃんと専用のコマンドが用意されている。ターミナルで作成したディレクトリに移動し、次のコマンドを入力しよう」

npm init

絵子「英文が表示されたね」
樹里「必要なプロパティを対話形式で入力していくのだが、とりあえずエンターキーを押していけば完了する」
絵子「それでいいの?」
樹里「もちろん、それぞれの意味は理解しておいたほうがいい。特にライセンスの部分などはな。だが、最初はそれでいいだろう」
絵子「はーい」

ツールをインストールする

樹里「さて、プロジェクトが作成できたところで、いよいよ主役の登場だ」
絵子「いよっ、待ってました!」
樹里「本ツール『novel-builder』をインストールするためのコマンドがこれだ」

npm install novel-builder --save

樹里「ちなみに--saveオプションをつけることでpackage.jsonに必要な情報を追記してくれる」
絵子「なるほど」

package.jsonを編集する(scriptsプロパティ)

樹里「では、出来上がったpackage.jsonを開いてみよう」
絵子「おーぷん!」
樹里「先程npm initで指定した各種設定がJSON形式で記述されている」
絵子「ほんとだ。nameとかversionとか書いてあるね」
樹里「ちなみにインストールしたnovel-builderの情報はdependenciesに書かれている」
絵子「おー、あるある」
樹里「このpackage.jsonの任意の場所に、下記の情報を手動で追加する必要がある」

  "scripts": {
    "novel-build": "novel-build",
    "novel-build-hameln": "novel-build-hameln",
    "novel-build-kakuyomu": "novel-build-kakuyomu",
    "novel-build-narou": "novel-build-narou",
    "novel-build-note": "novel-build-note",
    "novel-build-novelabo": "novel-build-novelabo",
    "novel-png": "novel-png",
    "novel-png-square": "novel-png-square",
    "novel-png-paperback": "novel-png-paperback",
    "novel-png-note-header": "novel-png-note-header",
    "novel-png-twitter-header": "novel-png-twitter-header",
    "novel-proofread": "novel-proofread",
    "novel-publish": "novel-publish",
    "novel-publish-horizontal": "novel-publish-horizontal",
    "novel-publish-vertical": "novel-publish-vertical",
    "novel-report": "novel-report"
  },

絵子「なんだこりゃ」
樹里「このscriptsプロパティは、コマンド名と実行されるコマンドとを対比したものだ」
絵子「えーと、つまり、novel-buildとコマンド入力したらnovel-buildが実行されますよ、ということ?」
樹里「その通り。詳しい内容は順番に説明する」
絵子「はーい」

必要なツールを追加インストールする

樹里「さて、準備の仕上げとして、次のコマンドで必要なツールを追加インストールしよう」

npm install

樹里「node_modulesディレクトリ内に、動作に必要なパッケージ群が追加インストールされる」
絵子「ほんとだ。サブディレクトリがたくさんできてる」
樹里「これで環境は整った。次は……」

原稿を書く

絵子「ま、これが一番大事だよね。当たり前だけど」
樹里「そうなんだが、原稿の書き方にはいくつかルールがある」

  • すべての原稿は、episodesディレクトリ内に保存します。
  • 原稿はMarkdown形式で記述し、ファイル名は「001.md」「002.md」…のように連番となるよう保存します。
  • ルビの記法は青空文庫注記形式とします。
  • 傍点で表示したい箇所は**または__で囲みます。
  • 英数字は基本的に半角で記述します。

Usage

樹里「さて、ここからが本ツールの機能説明だ」
絵子「長い前置きだったねー」
樹里「ところで、原稿は書けたか?」
絵子「書けたよー。いやー、苦労した」
樹里「ご苦労。なお、とりあえず機能を試してみたいという方は、GitHubの『恋に落ちるコード.js』の
リポジトリをgit cloneで取得してみよう。ディレクトリ構成やpackage.jsonの記述の参考になるだろう」
絵子「それを先に言いなさいよ」

校正機能を使用する(novel-proofread

樹里「では、まずは校正機能を使ってみよう」

npm run novel-proofread

樹里「上記コマンドを入力すると、原稿を自動で校正する」
絵子「おー、すごい」
樹里「ちなみに、このnovel-proofreadの部分が、先程追記したpackage.jsonscriptsプロパティの記述と対応している。つまり……」

"p": "novel-proofread"

樹里「……と書けば、npm run pと入力するだけでnovel-proofreadコマンドが実行されるわけだ」
絵子「ま、proofreadなんて英単語、覚えにくいもんね。短いほうがいいや」
樹里「ただし、他のnpmをインストールしている場合、コマンド名が競合する可能性もあるのでそこは注意を」
絵子「ふむふむ」
樹里「では、実際にどう校正されるのか説明しよう」

novel-proofread

樹里「下記のような、一般的な小説のルールに基づいて文書を修正し、上書き保存する」

  • 行頭に全角スペースを挿入します。ただし、下記と一致する行を除きます。
    • 開き鉤括弧(「『)で始まる行
    • Markdownの見出し記号(#)で始まる行
    • 既に全角スペースが挿入されている行
    • 空行
  • 全角の感嘆符(!)、疑問符(?)のあとに全角スペースを挿入します。ただし、下記と一致する場合を除きます。
    • 直後が感嘆符、疑問符、閉じ鉤括弧(」』)、半角スペースの場合
    • 既に全角スペースが挿入されている場合
  • 閉じ鉤括弧(」』)直前の全角スペースおよび句読点(、。)を削除します。
  • 三点リーダー(…)の連続回数が奇数だった場合、もう一つ追加します。
  • ダッシュ(―)の連続回数が奇数だった場合、もう一つ追加します。
  • 鉤括弧の開きと閉じの書式が異なる場合、開きの鉤括弧の書式に統一します。
    • 「〜』という文が合った場合、「〜」に変換します。

樹里「つまり、」

「樹里!貴女はなんて素敵なの!?それにひきかえ私は…」
絵子の表情が曇る。

樹里「これが」

「樹里! 貴女はなんて素敵なの!? それにひきかえ私は……」
 絵子の表情が曇る。

樹里「というように校正されるわけだ」
絵子「……何なのよこの例文」


ファイル変換機能を使用する(novel-build

樹里「次は、原稿を変換して出力する機能だ」

npm run novel-build

樹里「コマンドを入力すると、distディレクトリが作成され、変換された原稿が出力される」
絵子「おー、すごい」
樹里「これも同じく……」

"b": "novel-build"

樹里「……と書けば、npm run bnovel-buildコマンドが実行される」
絵子「短いコマンドは正義だね」
樹里「それで、そもそもこのコマンドは何のためにあるかと言うとだな。投稿先のサイトによって、レイアウトや仕様の違いがあるわけだ」
絵子「横書きとか、縦書きとか?」
樹里「そう。あとは、ルビ文字の記法とかな。それらの違いに合わせて別々の原稿を作成するのが面倒なので、一つの原稿をそれぞれのサイトの仕様に合わせて変換しよう……というのがこの機能だ」
絵子「らいとわんす、らんえにーうぇあってやつだね」
樹里「このコマンドは、投稿先のサイトの特性に合わせて既定の変換ルールが設定されている。縦書きレイアウトなら英数字を全角に変換する、など。しかし、コマンドの引数によって別のルールを適用することもできるぞ」
絵子「へー」
樹里「それでは、一つ一つ説明しよう。まずはサイト毎の既定の変換ルール、次に引数(起動オプション)の説明だ」

novel-build

下記全てのファイルを一度に出力します。

novel-build-hameln

dist/hamelnディレクトリに、ハーメルン向けの原稿をプレーンテキストで出力します。

既定の変換ルール:

  • ルビ記法: そのまま出力します。
  • 強調記号: 傍点記法に変換します(emphasis=bracket)。
  • 半角英字: そのまま出力します。
  • 半角数字: そのまま出力します。

novel-build-kakuyomu

dist/kakuyomuディレクトリに、カクヨム向けの原稿をプレーンテキストで出力します。

既定の変換ルール:

  • ルビ記法: そのまま出力します。
  • 強調記号: 傍点記法に変換します(emphasis=bracket)。
  • 半角英字: そのまま出力します。
  • 半角数字: そのまま出力します。

novel-build-narou

dist/narouディレクトリに、小説家になろう向けの原稿をプレーンテキストで出力します。
エブリスタNOVEL DAYSにも対応しています。

既定の変換ルール:

  • ルビ記法: そのまま出力します。
  • 強調記号: 削除します(emphasis=none)。
  • 半角英字: そのまま出力します。
  • 半角数字: そのまま出力します。

novel-build-note

dist/noteディレクトリに、note向けの原稿をプレーンテキストで出力します。

既定の変換ルール:

  • ルビ記法: 括弧書きに変換します(ruby=paren)。
  • 強調記号: 削除します(emphasis=none)。
  • 半角英字: そのまま出力します。
  • 半角数字: そのまま出力します。

novel-build-novelabo

dist/novelaboディレクトリに、ノベラボ向けの原稿をプレーンテキストで出力します。

既定の変換ルール:

  • ルビ記法: そのまま出力します。
  • 強調記号: 削除します(emphasis=none)。
  • 半角英字: 全角英字に変換します(alphabet=full)。
  • 半角数字: 全角数字に変換します(number=full)。

引数(起動オプション)

コマンド実行時に引数(起動オプション)を指定することで、変換ルールを細かく指定することができます。
引数は、npm run novel-build -- number=tcyというように、コマンドの末尾に--とスペースに続けて記述します。
複数の引数を指定することもできます。その場合は、number=tcy ruby=htmlというようにスペースで区切って指定します。

ruby=html

ルビ記法をHTMLに変換します。
「|絵子《えこ》」は「<ruby>絵子<rt>えこ</rt></ruby>」に変換されます。

ruby=paren

ルビ記法を括弧書きに変換します。括弧は全角括弧です。
「|絵子《えこ》」は「絵子(えこ)」に変換されます。

ruby=none

ルビ文字を除去します。
「|絵子《えこ》」は「絵子」に変換されます。

emphasis=bracket

強調記号を傍点記法に変換します。
「**樹里**」は「《《樹里》》」に変換されます。

emphasis=sesame

強調記号を傍点(ゴマ点)で表示するHTMLに変換します。
※実際には、<span class="em-sesame">樹里</span>というHTMLに変換されるだけなので、傍点で表示させるCSSは別途指定する必要があります。
電書協 EPUB 3 制作ガイドでは、下記のCSSが適用されています。

-webkit-text-emphasis-style: filled sesame;
-epub-text-emphasis-style: filled sesame;

emphasis=none

強調記号を除去します。
「**樹里**」は「樹里」に変換されます。

alphabet=full

半角英字、アンド記号(&)、カンマ(,)、ピリオド(.)を全角に変換します。

number=tcy

半角数字を、3桁以下は縦中横で表示するHTMLに、4桁以上は全角数字に変換します。
※実際には、<span class="tcy">123</span>というHTMLに変換されるだけなので、縦中横で表示させるCSSは別途指定する必要があります。
電書協 EPUB 3 制作ガイドでは、下記のCSSが適用されています。

-webkit-text-combine: horizontal;
-webkit-text-combine-upright: all;
text-combine-upright: all;
-epub-text-combine: horizontal;

number=kan

半角数字を漢数字に変換します。

number=full

半角数字を全角数字に変換します。

symbol=[\W+]

指定された記号(非単語構成文字)を全角に変換します。
例えば、「#」「$」「%」の記号を全角に変換したい場合はsymbol=#$%と入力します。


EPUB出力機能を使用する(novel-publish

樹里「次は、EPUBを出力する機能だ」
絵子「EPUBって、電子書籍のフォーマットだよね。そんなのもできるんだねー」
樹里「それも、電書協 EPUB 3 制作ガイドに準拠したEPUBが……」

npm run novel-publish

樹里「のコマンド一つで出来上がる」
絵子「ほえー。こりゃ便利だ」
樹里「また、novel-buildコマンドの時と同じ引数(起動オプション)も指定できるぞ」

novel-publish

下記全てのファイルを一度に出力します。

novel-publish-horizontal

distディレクトリに、横書きレイアウトのEPUBファイルを出力します。ファイル名は『(パッケージ名)-h.epub』となります。

既定の変換ルール:

  • ルビ記法: そのまま出力します。
  • 強調記号: 傍点(ゴマ点)で表示するHTMLに変換します(emphasis=sesame)。
  • 半角英字: そのまま出力します。
  • 半角数字: そのまま出力します。

novel-publish-vertical

distディレクトリに、縦書きレイアウトEPUBファイルを出力します。ファイル名は『(パッケージ名)-v.epub』となります。

既定の変換ルール:

  • ルビ記法: そのまま出力します。
  • 強調記号: 傍点(ゴマ点)で表示するHTMLに変換します(emphasis=sesame)。
  • 半角英字: 全角英字に変換します(alphabet=full)。
  • 半角数字: 全角数字に変換します(number=full)。

必要なファイル

樹里「EPUBファイルを作成するためには、原稿以外にいくつかのファイルを準備する必要がある」
絵子「一冊の本を作るわけだからね。準備は大事だね」
樹里「すべてのファイルは、プロジェクトディレクトリ直下にepubというディレクトリを作り、そこに保存する」
絵子「おっけー」

cover.jpg (表紙画像)
樹里「表紙に使用する画像ファイルを、cover.jpgというファイル名でepubディレクトリに保存する」
絵子「ちなみに、Amazon KDPだと、
縦2,560 x 横1,600 ピクセルというサイズが推奨されているよ」

fmatter.md (前付)
樹里「書籍の前付にあたる文章をMarkdown形式で記述し、fmatter.mdというファイル名でepubディレクトリに保存する」
絵子「目次より前に書いてある、序文とか謝辞とかのことだね。『支えてくれた妻と娘に捧げる。』とか書いてあるやつ」
樹里「なお、このファイルがない場合、前付部分は作成しない」

titlepage.md (本扉ページ)
樹里「書籍の本扉にあたる文章をMarkdown形式で記述する」
絵子「タイトルや著者名が書いてあるページだね」
樹里「これも、ファイルがない場合は作成しない」

caution.md (注意書きページ)
樹里「書籍の注意書きにあたる文章をMarkdown形式で記述する」
絵子「無断転載はダメだぞ!とか」
樹里「これも同じく、ファイルがなければ作成しない」

colophon.md (奥付ページ)
樹里「書籍の奥付にあたる文章をMarkdown形式で記述する」
絵子「最後の部分だね。出版社名とか発行日とか書いてあるページ」
樹里「これもファイルがない場合は作成しないぞ」

package.jsonを編集する(configプロパティ)

樹里「それから、package.jsonconfigプロパティを作成し、必要な項目を追加する必要がある」

  "config": {
    "epub_title": "恋に落ちるコード.js",
    "epub_title_file_as": "こいにおちるこーどどっとじぇいえす",
    "epub_author": "足羽川永都",
    "epub_author_file_as": "あすわがわえいと",
    "epub_publisher": "8novels",
    "epub_publisher_file_as": "えいとのべるず"
  },

絵子「こんな感じで書いてね!」

epub_title
書籍のタイトルを記述します。

epub_title_file_as
書籍のタイトルの読みがなを記述します。

epub_author
著者名を記述します。

epub_author_file_as
著者名の読みがなを記述します。

epub_publisher
出版社名を記述します。

epub_publisher_file_as
出版社名の読みがなを記述します。


PNG出力機能を使用する(novel-png

樹里「小説をPNG画像として出力する機能もあるぞ」
絵子「どういう時に使うの?」
樹里「例えば、Instagramなどに掌編小説を公開したい時に使う」
絵子「あー、なるほど」

npm run novel-png

樹里「というコマンドで、dist/pngディレクトリに画像を出力できるぞ」

novel-png

PNG画像を出力します。高さは1,080px固定で、幅は文章の長さによって変わります。

novel-png-square

正方形のPNG画像を出力します。
幅・高さともに1,080pxとなります。はみ出した文章は表示されません(以下同じ)。

novel-png-paperback

文庫本と同じ比率のPNG画像を出力します。
幅が766px、高さが1,080pxとなります。

novel-png-note-header

noteのヘッダに適したPNG画像を出力します。
幅が1,280px、高さが670pxとなります。

novel-png-twitter-header

Twitterのヘッダに適したPNG画像を出力します。
幅が1,500px、高さが500pxとなります。

引数(起動オプション)

novel-buildコマンド実行時と同じ引数を指定できます。

スタイルシートを適用する

樹里「プロジェクトディレクトリ直下にpngというディレクトリを作り、その中にpng.cssという名前でスタイルシートを保存すれば、独自のスタイルを適用させることもできる」
絵子「どんな風に書いたらいいのかな?」
樹里「既定のスタイルは300文字前後の掌編を出力するのに適しているが、それより長い文章の場合はfont-sizeを調整したほうが読みやすい。高さ1,080pxの場合、大体20〜21pxくらいで1行40文字くらいになる」
絵子「へー」
樹里「あとは、行間(line-height)、文字間(letter-spacing)、余白(padding)、背景色(background-color)あたりだな、調整するとしたら。もちろん、背景画像を指定したり、フォントを指定したり、他にも色々調整できるぞ」


レポート機能を使用する(novel-report

樹里「最後に、原稿を分析してレポートを出力する機能だ」
絵子「そんな機能まで付けたんだ。至れり尽くせりだね」

npm run novel-report

樹里「コマンドを入力すると、report.htmlファイルに分析した内容が出力される」
絵子「ほー」

novel-report

レポートを出力します。下記の統計情報が出力されます。

  • 原稿の文字数(全体・章別)
    • 半角スペース・改行を除いた文字数
    • さらに全角スペースを除いた文字数
    • さらにルビ文字を除いた文字数
    • さらに章タイトルを除いた文字数
  • 原稿用紙に換算した場合の枚数(全体・章別)
  • 原稿の行数
    • 台詞(鉤括弧で始まる行)の行数・割合
    • 地の文(全角スペースで始まる行)の行数・割合
    • その他の文字で始まる行(章タイトル等)の行数・割合
    • 空行の行数・割合
  • novel-buildコマンドで変換対象となる文字の一覧
    • ルビ文字
    • 半角数字
    • 半角英字

GitHubに公開する

樹里「では最後に、執筆した原稿をリモートリポジトリとしてGitHubに公開する際の注意点を説明しておこう」
絵子「GitHubに公開するの?」
樹里「別に必須ではないが、リモートリポジトリを作成しておくと、外出先で執筆できたり、共同執筆が出来たりとなかなか便利だ。他人に見られたくない場合はプライベートリポジトリにすればいい」
絵子「ふーん」

.gitignoreについて

樹里「.gitignoreとは、Gitの管理下から除外するファイルを指定するための設定ファイルだ」
絵子「アップロードしたくないファイルを指定するんだね。node_modulesディレクトリとか」
絵子「GitHubのリモートリポジトリで.gitignoreというファイルを新規作成すると、テンプレートを選択できるので、Node用を指定すればいい。これが一番手っ取り早い」

ライセンスについて

樹里「さて、リポジトリをパブリックとして公開する場合は、ライセンスの表記を真面目に考える必要がある」
絵子「ライセンスってどこかで指定してたっけ?」
樹里「最初にpackage.jsonを作成した時に指定したはずだ」
絵子「あ、そうだった。そのままエンターキーを押したからISCになってる」
樹里「そのように、自分の意図とは異なるライセンスが適用されていないかどうか、公開前には十分に配慮しよう。ま、package.jsonからlicenseプロパティを除外しておくのが最も無難だな」


樹里「以上で説明は終了だ。わずらわしい事はすべてプログラムに任せ、執筆に集中しようじゃないか」
絵子「よーし、やるぞー!」

Requirement

このツールは、下記のライブラリを使用しています。

Todo

  • 対応する形式を増やす(ハーメルン、アルファポリス、etc)
  • EPUB変換時に全角スペースが消失する問題の対応
  • 自動フォーマット機能(全角インデント挿入等)の実装
  • 画像出力機能の実装
  • READMEに「package.jsonに記述するライセンス表記について」を追記
  • READMEに「.gitignoreの書き方」を追記
  • 縦書き原稿への変換時、数字を漢数字や縦中横に変換できるオプションを追加

Author

8amjp

このツールは Xubuntu 18.04 上で Visual Studio Code で開発しています。
Windows、OS X等での動作確認は行っておりません。ご了承ください。

8amjp
福井市に住むSE・プログラマ。Kindleストアで技術系異世界ファンタジー小説「Redmineで始める異世界人心掌握術」販売中。JavaScript学園コメディ「恋に落ちるコード.js」電子書籍化準備中。
https://8am.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした