Community画像github.com

4hm4di/ahkab-illustrator-text

Illustratorで編集可能なレイアウト(雑誌、プロフィール、パンフレット)をSVG/PDFとして構築し、各段落がグループ化されずに1つのエリアタイプのテキストボックスになるようにするために使用します。

ahkab-illustrator-text とは?

このスキルは、Adobe Illustratorでネイティブな編集可能テキスト(1段落=1テキストボックス)を生成するExtendScript(.jsx)ビルドスクリプトを提供します。Illustratorは、インポートしたSVG/PDFのテキストを常に行ごとに1つのテキストオブジェクトに分割してグループ化するため、その制限を克服するために設計されています。ワークフローでは、ページ生成時にテキストレコード(ID、種類(area/point)、レイヤー、座標、幅、行送り、行数、サイズ、アンカー、文字詰め、テキスト実行)を保存し、それらをJSオブジェクトリテラルとして.jsxファイルに埋め込みます。スクリプトはIllustrator内で実行され(File > Scripts > Other Script…)、元のSVG/PDFのアートワークをレイヤー構造ごと貼り付け、保存されたレコードに基づいてネイティブテキストフレーム(areaText/pointText)を再構築し、最後に編集可能な.aiファイルを保存します。このアプローチにより、雑誌、プロフィール、パンフレットなどのレイアウトで、各段落が個別の編集可能なテキストボックスとして保持され、元のフォント(候補リストを使用)、サイズ、行送り、色、配置が維持されます。スクリプトはNode.js上のIllustrator DOMモックに対してドライラン可能で、成果物の品質を検証できます。

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/4hm4di/ahkab-illustrator-text/tree/HEAD/ahkab-illustrator-text

Installed? Explore more 画像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Ahkab Illustrator Text — ネイティブIllustratorテキスト(1段落=1テキストボックス)

Ahmad Abdullahi Kabeer · Graphcent 著

なぜ

Illustratorは、インポートしたSVGおよびPDFテキストを常に行ごとに1つのテキストオブジェクトに分割し、グループ化します。これを防ぐSVGマークアップはありません。そのため、アートワーク用のSVGページを維持し、ユーザーが一度実行するExtendScript(.jsx)ビルドスクリプト(ファイル > スクリプト > その他のスクリプト…)を使用して、Illustrator内ですべてのテキストをネイティブに再構築します。このスクリプトは真の.aiファイルを保存します。

ワークフロー

  1. ページ生成時にテキストを記録します。 ページジェネレータが<text>を出力する場所には、ページごとに次のレコードも保存します: {id, kind: 'area'|'point', layer: '05', x, y(最初のベースライン、SVG y-down、pt), w(ボックス幅), lead(行送り), n(折り返し行数), size, anchor: 'start'|'middle'|'end', ls(文字詰め pt), runs: [[text, weight(ウェイト), '#RRGGBB'], …], name}
    • 折り返し段落(および複数行のタイトル)-> area。1行のラベル、数字、キャプション -> point。
    • SVGの描画に使用したx/y/width/leadingを正確に使用し、位置がPDFと一致するようにします。
    • 意味のある名前を付けます(例:Name — slot 01、Biography — slot 04)。
  2. SVGページ要件: ファイル pages/NN_Name.svg(NN = ページ番号);トップレベルグループ id="L01_Backgrounds"、L02_… など、data-name = 可読なレイヤー名。テキストもSVG内に保持します(フォールバック + PDFレンダリング用)。
  3. .jsxを生成 レコードをJSオブジェクトリテラルとして埋め込みます(json.dumps(..., ensure_ascii=True) — ExtendScriptはES3で、JSON.parseは不要です)。
  4. 生成された.jsxをドライラン Illustrator DOMのモック(app、documents.add、open、textFrames.areaText/pointText、pathItems.rectangle、artboards、textFonts.getByName、enums)に対してNodeで実行します。チェック:area/pointフレームの数、すべてのフレームに内容+フォント+名前があること、矩形の座標が数値であること、アートボードがページ数と一致すること。
  5. READMEに記載 編集可能な.aiはスクリプトを実行することで得られること。SVG/PDFを直接開くと分割された行が残ることを明記してください。スクリプトはIllustrator自体ではなくモックでテストされたことを簡潔に述べてください。

コアスクリプトロジック(ExtendScript)

#target illustrator
var PAGE_TEXT = /* {"1":[records…], "2":[…]} */;
app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
app.coordinateSystem = CoordinateSystem.DOCUMENTCOORDINATESYSTEM;   // y increases upward
// 1) doc = app.documents.add(DocumentColorSpace.RGB, W, H); create named layers (doc.layers.add() adds on top).
// 2) per page p: artboard rect [left, top, left+W, top-H] with left = col*(W+GAP), top = -row*(H+GAP).
//    src = app.open(svgFile); delete imported text:
//      for (var i = src.textFrames.length-1; i >= 0; i--) src.textFrames[i].remove();
//    find groups/sub-layers whose name matches /^L?(0[1-9])/ and duplicate into the matching layer:
//      item.duplicate(targetLayer, ElementPlacement.PLACEATBEGINNING).translate(left - sr[0], top - sr[1]);
//    (iterate container.pageItems, filter typename === 'GroupItem'; do not compare DOM objects with ===)
//    src.close(SaveOptions.DONOTSAVECHANGES); then buildText(PAGE_TEXT[pageNo], left, top).
var FONT_CANDIDATES = { 300:["Kreadon-L","Outfit-Light"], 400:["Kreadon-R","Kreadon-M","Outfit-Regular"],
  500:["Kreadon-M","Outfit-Medium"], 600:["Kreadon-Demi","Kreadon-D","Outfit-SemiBold"],
  700:["Kreadon-B","Outfit-Bold"], 800:["Kreadon-EB","Outfit-ExtraBold"] };  // put the project's PostScript names first
function fontFor(w){ var n=FONT_CANDIDATES[w]||FONT_CANDIDATES[400]; for(var i=0;i<n.length;i++){ try{ return app.textFonts.getByName(n[i]); }catch(e){} } return null; }
function rgb(h){ var c=new RGBColor(); h=h.replace('#',''); c.red=parseInt(h.substr(0,2),16); c.green=parseInt(h.substr(2,2),16); c.blue=parseInt(h.substr(4,2),16); return c; }
function styleRange(r,w,size,col,lsPt,lead){ var a=r.characterAttributes, f=fontFor(w); if(f) a.textFont=f; a.size=size;
  if(lead){ a.autoLeading=false; a.leading=lead; } a.fillColor=rgb(col); a.tracking=Math.round((lsPt||0)/size*1000); }
function buildText(recs, left, top){
  for (var i=0;i<recs.length;i++){ var t=recs[i], layer=layerByKey[t.layer]||layerByKey['06'], s='', tf;
    for (var r=0;r<t.runs.length;r++) s+=t.runs[r][0];
    if (t.kind==='area'){ var lead=t.lead||t.size*1.4;
      var rect=layer.pathItems.rectangle(top-(t.y-lead), left+t.x-1, t.w+2, (t.n+1)*lead);  // +1 line slack for font swaps
      tf=layer.textFrames.areaText(rect); tf.contents=s; styleRange(tf.textRange,t.runs[0][1],t.size,t.runs[0][2],t.ls,lead);
      try{ tf.firstBaseline=FirstBaselineType.LEADING; }catch(e){ tf.translate(0,-(lead-t.size*0.95)); }
    } else { tf=layer.textFrames.pointText([left+t.x, top-t.y]); tf.contents=s; styleRange(tf.textRange,t.runs[0][1],t.size,t.runs[0][2],t.ls,null); }
    tf.textRange.paragraphAttributes.justification = t.anchor==='middle'?Justification.CENTER:(t.anchor==='end'?Justification.RIGHT:Justification.LEFT);
    // rich spans: for runs after the first whose weight/colour differ, style chars [pos, pos+len):
    //   try { var rr=tf.textRange.characters[pos]; rr.length=len; styleRange(rr,…); } catch(e){ per-character loop }
    tf.name = t.name || t.id; } }
// 3) IllustratorSaveOptions {pdfCompatible:true, compressed:true, embedLinkedFiles:true}; doc.saveAs(File(root+'/<Name>.ai'));
//    Show a final alert with any notes (e.g. missing fonts). Wrap everything in try/catch and restore userInteractionLevel.

納品前のチェック項目

  • モックのドライランに合格。段落数がジェネレータの折り返しテキストブロック数と一致すること。
  • エリアボックスが元の幅(+2pt)を使用しているため、改行がPDFと一致すること。より幅広い代替フォントを使用しても、ボックス内でリフローすること。
  • READMEで説明:編集可能な.aiを得るにはスクリプトを実行すること;書体を変更する場合は検索/置換フォントを使用すること;スクリプトはClaudeによってIllustrator内で実行されたわけではないこと。

関連スキル