本稿の目的
どうも、フロントエンドエンジニアです。
(たまにバックもやります)
さて、HTML コーダーなどをやっていると
「テキストでコーディングしてください!」という依頼を受けることがたまにあります。
以下のような RichText ですが、普通は画像化したほうが早いです。
sample_ja.psd
とはいえ、お客様のご要望であればテキスト化します。
これを HTML と CSS で表現すると、以下のようなコードになります。
<p class="text1"><span>100本<small>の</small>解説動画</span>と<span>6つ<small>の</small>豪華特典</span>、<br>
さらに講師が<span>あなた<small>を</small><strong>徹底</strong>サポート!</span></p>
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@700&display=swap');
.text1 {
color: #242424;
font-family: 'Noto Sans JP';
font-size: 40px;
line-height: 60px;
}
.text1 span {
color: #d92367;
font-size: 50px;
}
.text1 small {
font-size: 40px;
}
.text1 strong {
color: #ff9900;
font-weight: bold;
text-decoration: underline;
}
</style>
(自分なら)軽く2-3分はかかる作業です。
スニペット化したら幾分、高速化できそうですが
それでも時間はかかりますし、数が少ないならまだしも
ランディングページともなると、RichText が至る所に存在します。
これを一瞬で作ることができたなら・・・という記事です。
(実際のスクリプトは後編へ)
試してみたこと
1) Photoshop Script - TextExportToCSV
テキストレイヤーからテキストと、最初の文字のスタイルを CSV に書き出してくれます。
ただ、後続の RichText に対しては何もしてくれません。
全部は試してませんが、Photoshop Script だとこれが限界かも?
2) Node.js - psd
PSD ファイルを食わせると中身をパースしてくれる優れものです。
が、今回の記事では残念ながら不採用となりました。
一応、以下の手順を Windows で試してみました。
(ちなみに 2021/10/26 現在、最新版の psd.js@3.3.0 はバグのため fromFile ないよと言われて続行不可。3.2.0 へダウングレードしてます)
- Node.js をインストール
mkdir %USERPROFILE%¥Desktop¥sample
cd %USERPROFILE%¥Desktop¥sample
npm install psd@3.2.0
- 以下の index.js を sample フォルダに保存
let psd = require('psd').fromFile('sample.psd');
psd.parse();
let data = psd.tree().export();
console.dir(data, {depth: null});
- PSD ファイルを sample フォルダに突っ込む
node index.js
{
children: [
{
type: 'layer',
visible: true,
opacity: 1,
blendingMode: 'normal',
name: 'text1',
left: 20,
right: 779,
top: 25,
bottom: 164,
height: 139,
width: 759,
mask: {},
text: {
value: '100本の解説動画と6つの豪華特典、\rさらに講師があなたを徹底サポート!',
font: {
name: 'KozGoPr6N-Heavy',
sizes: [
50, 50, 40, 50, 40, 50,
40, 50, 40, 50, 40, 50,
50
],
colors: [
[ 217, 35, 103, 255 ],
[ 217, 35, 103, 255 ],
[ 217, 35, 103, 255 ],
[ 217, 35, 103, 255 ],
[ 36, 36, 36, 255 ],
[ 217, 35, 103, 255 ],
[ 217, 35, 103, 255 ],
[ 217, 35, 103, 255 ],
[ 36, 36, 36, 255 ],
[ 217, 35, 103, 255 ],
[ 217, 35, 103, 255 ],
[ 255, 153, 0, 255 ],
[ 217, 35, 103, 255 ]
],
alignment: [ 'center', 'center' ]
},
left: 0,
top: 0,
right: 0,
bottom: 0,
transform: { xx: 1, xy: 0, yx: 0, yy: 1, tx: 407, ty: 65.36346435546875 }
},
image: {}
},
],
document: {
width: 800,
height: 180,
resources: { layerComps: [], guides: [], slices: [] }
}
}
上記が psd.js で得られた結果ですが、
テキスト本文及び、スタイル毎のサイズと色は判るものの、どこからどこまでがこのサイズとこの色で〜という情報は一切取得できてません。いや、欲しい情報はポジションなので非常に惜しい!
3) Python - psd-tools
Python のパッケージで、こちらも PSD ファイルをパースしてくれますが
psd.js よりもさらにディープに取得してくれます。
今回の記事ではこちらを採用しました。
こちらも手順を Windows で試してみました。
途中、pip コマンド実行中に Microsoft Visual C++ 14.0 is required.
と何故か怒られてしまったので
「Microsoft Visual C++ 14.0 or greater is required.」が出た場合の対処方法
を参考に対処したところ無事、解決しました。
- Python3 をインストール
pip install psd-tools
mkdir %USERPROFILE%¥Desktop¥sample
cd %USERPROFILE%¥Desktop¥sample
- 以下の index.py を sample フォルダに保存
from psd_tools import PSDImage
psd = PSDImage.open('sample.psd')
for layer in list(psd.descendants()):
if layer.kind == 'type':
print(layer.engine_dict)
- PSD ファイルを sample フォルダに突っ込む
python index.py
{
'Editor': {
'Text': '100本の解説動画と6つの豪華特典、\rさらに講師があなたを徹底サポート!\r'
},
'ParagraphRun': {
'DefaultRunData': {
'ParagraphSheet': {
'DefaultStyleSheet': 0,
'Properties': {}
},
'Adjustments': {
'Axis': [1.0, 0.0, 1.0],
'XY': [0.0, 0.0]
}
},
'RunArray': [{
'ParagraphSheet': {
'DefaultStyleSheet': 0,
'Properties': {
'Justification': 2,
'FirstLineIndent': 0.0,
'StartIndent': 0.0,
'EndIndent': 0.0,
'SpaceBefore': 0.0,
'SpaceAfter': 0.0,
'AutoHyphenate': False,
'HyphenatedWordSize': 6,
'PreHyphen': 2,
'PostHyphen': 2,
'ConsecutiveHyphens': 8,
'Zone': 36.0,
'WordSpacing': [0.8, 1.0, 1.33],
'LetterSpacing': [0.0, 0.0, 0.0],
'GlyphSpacing': [1.0, 1.0, 1.0],
'AutoLeading': 1.75,
'LeadingType': 1,
'Hanging': False,
'Burasagari': False,
'KinsokuOrder': 0,
'EveryLineComposer': False
}
},
'Adjustments': {
'Axis': [1.0, 0.0, 1.0],
'XY': [0.0, 0.0]
}
}, {
'ParagraphSheet': {
'DefaultStyleSheet': 0,
'Properties': {
'Justification': 2,
'FirstLineIndent': 0.0,
'StartIndent': 0.0,
'EndIndent': 0.0,
'SpaceBefore': 0.0,
'SpaceAfter': 0.0,
'AutoHyphenate': False,
'HyphenatedWordSize': 6,
'PreHyphen': 2,
'PostHyphen': 2,
'ConsecutiveHyphens': 8,
'Zone': 36.0,
'WordSpacing': [0.8, 1.0, 1.33],
'LetterSpacing': [0.0, 0.0, 0.0],
'GlyphSpacing': [1.0, 1.0, 1.0],
'AutoLeading': 1.75,
'LeadingType': 1,
'Hanging': False,
'Burasagari': False,
'KinsokuOrder': 0,
'EveryLineComposer': False
}
},
'Adjustments': {
'Axis': [1.0, 0.0, 1.0],
'XY': [0.0, 0.0]
}
}],
'RunLengthArray': [19, 18],
'IsJoinable': 1
},
'StyleRun': {
'DefaultRunData': {
'StyleSheet': {
'StyleSheetData': {}
}
},
'RunArray': [{
'StyleSheet': {
'StyleSheetData': {
'Font': 1,
'FontSize': 50.0,
'FauxBold': False,
'FauxItalic': False,
'AutoLeading': False,
'Leading': 80.0,
'HorizontalScale': 1.0,
'VerticalScale': 1.0,
'Tracking': 0,
'AutoKerning': False,
'Kerning': 0,
'BaselineShift': -4.11664,
'FontCaps': 0,
'FontBaseline': 0,
'Underline': False,
'Strikethrough': False,
'Ligatures': True,
'DLigatures': False,
'BaselineDirection': 2,
'Tsume': 0.0,
'StyleRunAlignment': 2,
'Language': 0,
'NoBreak': False,
'FillColor': {
'Type': 1,
'Values': [1.0, 0.85098, 0.13727, 0.40393]
},
'StrokeColor': {
'Type': 1,
'Values': [1.0, 0.93329, 0.93329, 0.93329]
},
'YUnderline': 1,
'HindiNumbers': False,
'Kashida': 1
}
}
}, {
' 中略 '
}],
'RunLengthArray': [1, 3, 1, 4, 1, 2, 1, 4, 8, 3, 1, 2, 6],
'IsJoinable': 2
},
'GridInfo': {
'GridIsOn': False,
'ShowGrid': False,
'GridSize': 18.0,
'GridLeading': 22.0,
'GridColor': {
'Type': 1,
'Values': [0.0, 0.0, 0.0, 1.0]
},
'GridLeadingFillColor': {
'Type': 1,
'Values': [0.0, 0.0, 0.0, 1.0]
},
'AlignLineHeightToGridFlags': False
},
'AntiAlias': 4,
'UseFractionalGlyphWidths': True,
'Rendered': {
'Version': 1,
'Shapes': {
'WritingDirection': 0,
'Children': [{
'ShapeType': 0,
'Procession': 0,
'Lines': {
'WritingDirection': 0,
'Children': []
},
'Cookie': {
'Photoshop': {
'ShapeType': 0,
'PointBase': [0.0, 0.0],
'Base': {
'ShapeType': 0,
'TransformPoint0': [1.0, 0.0],
'TransformPoint1': [0.0, 1.0],
'TransformPoint2': [0.0, 0.0]
}
}
}
}]
}
}
}
実際の出力には改行が一切なかったので、下記オンラインツールで整形しました。
https://lab.syncer.jp/Tool/JavaScript-PrettyPrint/
上記が psd-tools で得られた結果です。
目的のデータ RunLengthArray
が入ってます。これならいけそう!
後編に続く。