InDesignからHTML、CSSに書き出すツール

[前回のIllustrator版](http://qiita.com/onebitious/items/18e402948ef6f64c4aa6)に続きInDesign版を作ってみました。

InDesignにはHTMLへの書き出し機能は既存ですが、自分なりにカスタマイズしてみました。

段落スタイル名をHTMLタグと見立てコーディングしCSSを生成します。
操作、取得するプロパティは以下。

| InDesign文字属性       |       JS property |    CSS property    |
|:----------------:|:------------------:|:------------------:|
| 段落スタイル名             |              name |        -        |
| サイズ           |            pointSize |       font-size       |
| フォントファミリー             |              appliedFont.name |        font-family        |
| フォントウェイト               |                appliedFont.fontStyleName |         font-weight         |
| カラー             |             fillColor.colorValue |       color       |
| 行揃え          |           justification |      text-align       |
| 行送り          |           leading |      line-height       |

Illustratorとは一部異なり、例えばカラー値取得を、

```JavaScript:getColorValue.jsx
var myDoc = app.activeDocument; //ドキュメント
var mySel = myDoc.selection;//選択

var myColor=mySel[0].fillColor.colorValue;//カラー値
alert(myColor);
```

とすると、下図のように配列で取得されます。
![03.JPG](https://qiita-image-store.s3.amazonaws.com/0/122812/543db82e-c94a-217b-3050-ce0bccb3d28d.jpeg)
番地を指定してRGBの各数値を取得する必要があります。
※複数の段落スタイルからの取得になるので、多次元配列で処理できそうでしたが、技術的に追いついておらず、各数値を取得するようにしました。

おまけに段落スタイルの行送り値は環境設定 -> 単位と増減値 -> 他の単位 のテキストサイズの単位で換算されるらしく、文字パネルとは異なった表示になります。

![04.JPG](https://qiita-image-store.s3.amazonaws.com/0/122812/b7051d43-6cc9-1ab8-4ed8-c245a70d780d.jpeg)
▲組版：ポイント、テキストサイズ：級 で試してみます。

![05.JPG](https://qiita-image-store.s3.amazonaws.com/0/122812/af2ab5a3-0761-886c-2eeb-5de2eca727a6.jpeg)
▲文字パネルでの行送り値は環境設定の組版の単位通り表示されます。

![06.JPG](https://qiita-image-store.s3.amazonaws.com/0/122812/8ce9ea4c-5731-d962-d47b-8d7f19d92bb6.jpeg)
▲段落スタイルの行送り値は環境設定のテキストサイズの単位で換算され表示されます。

![07.JPG](https://qiita-image-store.s3.amazonaws.com/0/122812/6e5f0e39-5169-76cc-be0e-504c90dd2c50.jpeg)
▲ところが同じ段落スタイルでも一般のスタイル設定では組版の単位で表示されます。

仕様？　バグ？　かなり紛らわしいですね。。。

行送りの取得には単位の組み合わせによって換算する実装が必要かと思い散々苦労しましたが、下図のようにInDesignにはHTMLの単位がポイントしかないのです。
![01.JPG](https://qiita-image-store.s3.amazonaws.com/0/122812/5479ed98-87b6-8fb2-b39f-68326eeb1fc9.jpeg)
※定規の単位にはピクセルが存在します。
　確かCS 5や5.5には組版、テキストサイズにもピクセルがあったはず。。。

だったら一度、環境設定の単位をポイントに変更し、そこから文字サイズ、行送り値を取得した後に元の単位に戻せばいいのだと思いました。
※72dpi、96dpi、さらにレティナディスプレイなど画面解像度によって大きさは変化しますが、とりあえずは置いておきます。。。

行送り値は自動だったらジャスティフィケーションの自動行送り値を1/100にして取得するようにし、自動でなかったら値をポイントで取得するようにしました。
例
自動行送り値：175%の場合、xxx{line-height:1.75;}のようにします。
単位がないとfont-sizeの175%という結果になります。


ソースコードは以下です。

```JavaScript:InDesign2HTML.jsx
/*////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
変数定義とエラー処理
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
var myDoc = app.activeDocument; //ドキュメント
var mySel = myDoc.selection; //選択しているテキストフレーム

MAIN: {
    try { //エラー処理
        if (mySel.length == 0 || mySel[0].constructor.name != "TextFrame") {
            alert("テキストフレームを選択してください。");
            break MAIN;
        }
    } catch (e) {
        break MAIN;
    }

    var myCont = mySel[0].contents; //コンテンツ 確認用
    var myPara = mySel[0].paragraphs; //段落
    var myParaStyle = myDoc.paragraphStyles; //ドキュメントの段落スタイル

    /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    配列定義
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
    var myHTMLArray = []; //HTMLタグ用配列
    var myCSSArray = []; //CSS用配列
    var myPropArray = []; //CSSプロパティ用配列
    var mySizeArray = []; //サイズ用配列
    var myFontFamilyArray = []; //フォントファミリー用配列
    var myFontWeightArray = []; //フォントウェイト用配列
    var myColorArray = []; //カラー用配列
    var myLeadingArray = []; //行送り用配列
    var myJustificationArray = []; //行揃え用配列

    /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    関数定義
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
    //▼ゼロパディング
    function zeroPad(myNum) {
        var myNum = ('00' + myNum).slice(-2);
        return myNum;
    }

    //▼四捨五入
    function myRound(number, n) { //
        var myPow = Math.pow(10, n);
        return Math.round(number * myPow) / myPow;
    }

    /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    単位取得
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
    //▼環境設定
    var myTypoMeasUni = myDoc.viewPreferences.typographicMeasurementUnits; //環境設定 -> 単位と増減値 -> 組版
    var myTextSizeMeasUni = myDoc.viewPreferences.textSizeMeasurementUnits; //環境設定 -> 単位と増減値 -> テキストサイズ

    //▼環境設定 -> 単位と増減値 -> 組版 に設定されている単位を変数に格納
    switch (myTypoMeasUni) {
    case 2054188905:
        myTypoMeasUni = 2054188905; //ポイント
        break;
    case 1516790048:
        myTypoMeasUni = 1516790048; //歯
        break;
    case 1514238068:
        myTypoMeasUni = 1514238068; //アメリカ式ポイント
        break;
    case 2051691808:
        myTypoMeasUni = 1514238068; //U
        break;
    case 2051170665:
        myTypoMeasUni = 2051170665; //Bai
        break;
    case 2051893612:
        myTypoMeasUni = 2051170665; //Mils
        break;
    }

    //▼環境設定 -> 単位と増減値 -> テキストサイズ に設定されている単位を変数に格納
    switch (myTextSizeMeasUni) {
    case 2054188905:
        myTextSizeMeasUni = 2054188905; //ポイント
        break;
    case 2054255973:
        myTextSizeMeasUni = 2054255973; //級
        break;
    case 1514238068:
        myTextSizeMeasUni = 1514238068; //アメリカ式ポイント
    }

    /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    InDesign2HTML
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
    //▼一度、単位をポイントに変更
    myDoc.viewPreferences.typographicMeasurementUnits = 2054188905; //環境設定 -> 単位と増減値 -> 組版 をポイントに変更
    myDoc.viewPreferences.textSizeMeasurementUnits = 2054188905; //環境設定 -> 単位と増減値 -> テキストサイズ をポイントに変更

    for (var i = 0, myParaLen = myPara.length; myParaLen > i; i++) {
        var myPraContents = myPara[i].contents; //段落ごとのコンテンツ
        var myParaTagName = myPara[i].appliedParagraphStyle.name; //段落ごとの段落スタイル名
        var myStarTag = "<" + myParaTagName + ">"; //開始タグ
        var myEndTag = "</" + myParaTagName + ">"; //終了タグ
        var myHTMLSentence = myStarTag + myPraContents + myEndTag; //開始タグ＋コンテンツ＋終了タグ
        myHTMLArray.push(myHTMLSentence); //配列に追加
    }

    for (var j = 2, myParaStyleLen = myParaStyle.length; myParaStyleLen > j; j++) {
        var myParaStyleName = myParaStyle[j].name; //段落スタイル名
        myCSSArray.push(myParaStyleName);

        var myFontSize = myParaStyle[j].pointSize; //サイズ
        var myLeading = myParaStyle[j].leading; //行送り
        var myAutoLeading = myParaStyle[j].autoLeading; //自動行送り

        if (myLeading == 1635019116) { //行送りが自動の場合
            var myLeadingResult = "line-height: " + myRound(myAutoLeading, 2) / 100 + ";";
        } else {
            var myLeadingResult = "line-height: " + myRound(myLeading, 3) + "pt;"; //単位はポイントに固定
        }
        myLeadingArray.push(myLeadingResult); //配列に追加

        var myFontSizeResult = "font-size: " + myRound(myFontSize, 3) + "pt;"; //単位はポイントに固定
        mySizeArray.push(myFontSizeResult); //配列に追加   

        var myFontFamily = myParaStyle[j].appliedFont.name //フォントファミリー
        var myFontFamily = "font-family: " + myFontFamily + ";";
        myFontFamilyArray.push(myFontFamily); //配列に追加

        var myFontWeight = myParaStyle[j].appliedFont.fontStyleName //フォントウェイト
        var myFontWeight = "font-weight: " + myFontWeight + ";";
        myFontWeightArray.push(myFontWeight); //配列に追加

        var myColor = myParaStyle[j].fillColor.colorValue; //カラー
        var myColorRed = myColor[0].toString(16).toUpperCase(); //red値を取得（大文字のHEX値）
        var myColorRed = zeroPad(myColorRed); //ゼロパディング関数実行
        var myColorGreen = myColor[1].toString(16).toUpperCase(); //green値を取得（大文字のHEX値）
        var myColorGreen = zeroPad(myColorGreen); //ゼロパディング関数実行
        var myColorBlue = myColor[2].toString(16).toUpperCase(); //blue値を取得（大文字のHEX値）
        var myColorBlue = zeroPad(myColorBlue); //ゼロパディング関数実行
        var myColor = "color: #" + myColorRed + myColorGreen + myColorBlue + ";"; //rgb値として取得
        myColorArray.push(myColor); //配列に追加

        var myJustification = myParaStyle[j].justification; //行揃え
        switch (myJustification) {
        case Justification.LEFT_ALIGN:
            myJustification = "text-align: left;";
            break;
        case Justification.CENTER_ALIGN:
            myJustification = "text-align: center;";
            break;
        case Justification.RIGHT_ALIGN:
            myJustification = "text-align: right;";
            break;
        case Justification.LEFT_JUSTIFIED:
            myJustification = "text-align: justify;";
            break;
        }
        myJustificationArray.push(myJustification); //配列に追加
        //alert(myJustification);//確認用
    }
    for (var k = 0, myCSSArrayLen = myCSSArray.length; k < myCSSArrayLen; k++) {
        var myCSSResult = myCSSArray[k] + "{" + mySizeArray[k] + myFontFamilyArray[k] + myFontWeightArray[k] + myColorArray[k] + myLeadingArray[k] + myJustificationArray[k] + "margin: 0;" + "}"; //CSS生成
        myPropArray.push(myCSSResult); //配列に追加
        //alert(myPropArray);//確認用
    }

    var myHTMLArray = myHTMLArray.toString(); //HTMLタグ用配列を文字列に変換　※変数上書き
    var myHTMLArray = myHTMLArray.replace(/,/g, ""); //文字列化したCSVのカンマを削除
    var myPropArray = myPropArray.toString(); //CSS用配列を文字列に変換　※変数上書き
    var myPropArray = myPropArray.replace(/,/g, ""); //文字列化したCSVのカンマを削除

    var MyHTMLRessult = '<!DOCTYPE html><html lang="ja"><head><meta charset="UTF-8"><title>Document</title><style>' + myPropArray + '</style></head><body>' + myHTMLArray + '</body></html>'; //HTML生成

    //▼単位を元に戻す
    myDoc.viewPreferences.typographicMeasurementUnits = myTypoMeasUni; //環境設定 -> 単位と増減値 -> 組版 をポイントに変更
    myDoc.viewPreferences.textSizeMeasurementUnits = myTextSizeMeasUni; //環境設定 -> 単位と増減値 -> テキストサイズ をポイントに変更

    /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ファイル保存
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
    (function () { //無名関数を定義し実行
        var inputFileName = File.saveDialog("保存先とファイル名を指定して下さい");
        if (inputFileName == null) { //キャンセル処理
            alert("キャンセルしました。");
            return;
        }

        var inputFileName = inputFileName.toString(); //ファイル名に拡張子がないときの処理
        var myNewText = inputFileName.match(/.html/); //拡張子".txt"を付与
        if (myNewText) {
            var inputFileName = inputFileName; //入力したファイル名に拡張子が含まれる場合はそのまま
        } else {
            var inputFileName = inputFileName + ".html"; //入力したファイル名に拡張子が含まれない場合は付与
        }

        var fileObj = new File(inputFileName); //ファイル名を入力して保存
        var inputFileName = fileObj.open("w");
        if (inputFileName == true) {
            fileObj.encoding = "UTF-8"; //UTF-8を指定。これを入れないと異体字依存で書き出されない場合がある。
            fileObj.writeln(MyHTMLRessult); //書き出すテキストを連結
            fileObj.close();
            alert("処理が終わりました。");
        }
    })();
}
```

各段落スタイルの設定は以下。
サイズ、行送りの括弧内の数値は環境設定の組版を歯に、テキストサイズを級にしたときの数値。
h1
フォント：A-OTF UD新丸ゴ Pr6N
スタイル：DB
サイズ：21.26pt(30 Q)
行送り：37.333 pt(52.682 H)
揃え：中央揃え
カラー：R:255,G:0,B:0(HEX値:#FF0000)

h2
フォント：A-OTF 見出ゴMB31 Pr6N
スタイル：MB31
サイズ：14.173 pt(20 Q)
行送り：25.633 pt(36.17 H)
揃え：均等配置（最終行左 / 上揃え）
カラー：R:98,G:55,B:195(HEX値:#6237C3)

h3
フォント：A-OTF 太ゴB101 Pr6N
スタイル：Bold
サイズ：10.63 pt(15 Q)
行送り：20.964 pt(29.582 H)
揃え：右揃え
カラー：R:229,G:174,B:74(HEX値:#E5AE4A)

p
フォント：A-OTF 中ゴシックBBB Pr6N
スタイル：Med
サイズ：9.213pt(13 Q)
行送り：17.633 pt(24.882 H)
揃え：均等配置（最終行左 / 上揃え）
カラー：R:0,G:0,B:0(HEX値:#000000)

実行後Bracketsで開きBeautifyでコードフォーマット

```HTML:I_am_a_cat.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        h1 {
            font-size: 21.26pt;
            font-family: A-OTF UD新丸ゴ Pr6N DB;
            font-weight: DB;
            color: #FF0000;
            line-height: 37.333pt;
            text-align: center;
            margin: 0;
        }
        
        h2 {
            font-size: 14.173pt;
            font-family: A-OTF 見出ゴMB31 Pr6N MB31;
            font-weight: MB31;
            color: #6237C3;
            line-height: 25.633pt;
            text-align: justify;
            margin: 0;
        }
        
        h3 {
            font-size: 10.63pt;
            font-family: A-OTF 太ゴB101 Pr6N Bold;
            font-weight: Bold;
            color: #E5AE4A;
            line-height: 20.964pt;
            text-align: right;
            margin: 0;
        }
        
        p {
            font-size: 9.213pt;
            font-family: A-OTF 中ゴシックBBB Pr6N Medium;
            font-weight: Medium;
            color: #000000;
            line-height: 17.633pt;
            text-align: justify;
            margin: 0;
        }
    </style>
</head>

<body>
    <h1>青空文庫：吾輩は猫である　夏目漱石
</h1>
    <h2>吾輩は猫である
</h2>
    <h3>夏目漱石
</h3>
    <p>吾輩は猫である。名前はまだ無い。
    </p>
    <p>どこで生れたかとんと見当がつかぬ。
    </p>
    <p>何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。</p>
</body>
</html>
```


![image](https://qiita-image-store.s3.amazonaws.com/0/122812/3b2a9b3a-2125-3a97-d8a1-2f6df34e6d76.png)
▲Chromeでの表示結果。
一応、意図した通りに書き出してくれましたが、さすがに font-weight:DB; とかだと無効になります。。。
なかなか一筋縄ではいきませんな。。。

※検証はWindows10　Google Chromeでしか行っておりません。