CommunityImagegithub.com

Ahkab Illustrator Text — texte Illustrator natif (un paragraphe…

Utilisez cette compétence pour livrer des mises en page modifiables dans Illustrator (magazines, profils, brochures) en générant un script ExtendScript qui recrée chaque paragraphe sous forme de zone de texte indépendante, évitant les lignes groupées.

Qu'est-ce que Ahkab Illustrator Text — texte Illustrator natif (un paragraphe… ?

Cette compétence transforme des SVG/PDF générés en pages Illustrator modifiables, en veillant à ce que chaque paragraphe devienne une zone de texte de type 'area' ou 'point' dans Illustrator. Elle résout le problème récurrent où Illustrator fusionne le texte en lignes groupées lors de l'import SVG/PDF. Le fonctionnement repose sur un flux en plusieurs étapes : enregistrer les métadonnées de chaque texte (position, taille, police, couleur, etc.) pendant la génération des pages SVG, puis générer un script ExtendScript (.jsx) qui recrée ces zones de texte nativement dans Illustrator. Le script peut être testé avec une maquette Node avant toute exécution dans Illustrator. Une fois exécuté, il produit un fichier .ai où chaque paragraphe est une zone de texte éditable, avec des calques nommés, des polices préservées (via une table de fallback), et une correspondance précise avec le rendu SVG d'origine. La compétence insiste sur la non-modification des SVG/PDF sources et sur la nécessité d'exécuter le script pour obtenir le fichier .ai propre.

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

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Ahkab Illustrator Text — texte Illustrator natif (un paragraphe = une zone de texte)

Par Ahmad Abdullahi Kabeer · Graphcent

Pourquoi

Illustrator divise toujours le texte SVG et PDF importé en un objet texte par ligne, groupés ensemble. Aucun balisage SVG ne peut empêcher cela. Solution : conserver les pages SVG pour les éléments graphiques, puis reconstruire TOUT le texte nativement dans Illustrator avec un script ExtendScript (.jsx) que l'utilisateur exécute une fois (Fichier > Scripts > Autre script…). Le script sauvegarde un véritable fichier .ai.

Flux de travail

  1. Enregistrer le texte lors de la génération des pages. Partout où le générateur de pages émet <text>, stocker un enregistrement par page : {id, kind: 'area'|'point', layer: '05', x, y (première ligne de base, SVG y vers le bas, pt), w (largeur de la zone), lead, n (nombre de lignes renvoyées), size, anchor: 'start'|'middle'|'end', ls (espacement des lettres en pt), runs: [[texte, poids, '#RRGGBB'], …], name}
    • Paragraphes renvoyés (et titres multi-lignes) -> area. Étiquettes, numéros, accroches sur une seule ligne -> point.
    • Utiliser exactement les valeurs x/y/largeur/interligne utilisées pour dessiner le SVG, afin que les positions correspondent au PDF.
    • Donner des noms significatifs (par ex. Nom — emplacement 01, Biographie — emplacement 04).
  2. Exigences pour les pages SVG : fichiers pages/NN_Nom.svg (NN = numéro de page) ; groupes de premier niveau id="L01_Arrière-plans", L02_…, etc. avec data-name = nom de calque lisible. Conserver le texte dans les SVG également (fallback + rendu PDF).
  3. Générer le .jsx en intégrant les enregistrements sous forme de littéral d'objet JS (json.dumps(..., ensure_ascii=True) — ExtendScript est ES3, pas besoin de JSON.parse).
  4. Test préliminaire du .jsx généré dans Node contre une maquette du DOM Illustrator (app, documents.add, open, textFrames.areaText/pointText, pathItems.rectangle, artboards, textFonts.getByName, enums). Vérifier : nombre de zones area/point, chaque zone a du contenu + police + nom, les coordonnées des rectangles sont des nombres, les artboards = pages.
  5. Documenter dans le README que le .ai modifiable provient de l'exécution du script ; l'ouverture directe du SVG/PDF donne toujours des lignes séparées. Indiquer clairement que le script a été testé sur une maquette, pas dans Illustrator lui-même.

Logique principale du script (ExtendScript)

#target illustrator
var PAGE_TEXT = /* {"1":[enregistrements…], "2":[…]} */;
app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
app.coordinateSystem = CoordinateSystem.DOCUMENTCOORDINATESYSTEM;   // y augmente vers le haut
// 1) doc = app.documents.add(DocumentColorSpace.RGB, W, H); créer des calques nommés (doc.layers.add() ajoute en haut).
// 2) par page p : rectangle artboard [left, top, left+W, top-H] avec left = col*(W+GAP), top = -row*(H+GAP).
//    src = app.open(svgFile); supprimer le texte importé :
//      for (var i = src.textFrames.length-1; i >= 0; i--) src.textFrames[i].remove();
//    trouver les groupes/sous-calques dont le nom correspond à /^L?(0[1-9])/ et les dupliquer dans le calque correspondant :
//      item.duplicate(targetLayer, ElementPlacement.PLACEATBEGINNING).translate(left - sr[0], top - sr[1]);
//    (parcourir container.pageItems, filtrer typename === 'GroupItem' ; ne pas comparer les objets DOM avec ===)
//    src.close(SaveOptions.DONOTSAVECHANGES); puis 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"] };  // mettre les noms PostScript du projet en premier
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);  // marge de +1 ligne pour les changements de police
      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);
    // spans enrichis : pour les runs suivants dont le poids/couleur diffèrent, styliser les caractères [pos, pos+len) :
    //   try { var rr=tf.textRange.characters[pos]; rr.length=len; styleRange(rr,…); } catch(e){ boucle par caractère }
    tf.name = t.name || t.id; } }
// 3) IllustratorSaveOptions {pdfCompatible:true, compressed:true, embedLinkedFiles:true}; doc.saveAs(File(root+'/<Nom>.ai'));
//    Afficher une alerte finale avec les éventuelles notes (polices manquantes). Tout encapsuler dans try/catch et restaurer userInteractionLevel.

Vérifications avant la livraison

  • Le test préliminaire sur maquette passe ; le nombre de paragraphes correspond au nombre de blocs de texte renvoyés dans le générateur.
  • Les zones de texte utilisent la largeur d'origine (+2pt) pour que les retours à la ligne correspondent au PDF ; avec une police de remplacement plus large, le texte se réorganise dans la zone.
  • Le README explique : exécuter le script pour obtenir le .ai modifiable ; Rechercher/Remplacer la police si le changement de police est nécessaire ; le script n'a pas été exécuté dans Illustrator par Claude.

Skills associés