Skip to main content
Participating Frequently
May 21, 2023
Answered

Changing font of specific words in a text range using an array

  • May 21, 2023
  • 11 replies
  • 1449 views

Hi,

In a selected Illustrator area text object, I'd like to put all allergens of an ingredient list in a bold font.

 

Example ingredients list:

Ingredients: sausage 34% (pork 67%, water, potato starch, pork bacon, salt, soy protein, spices (contains mustard), herbs (contains celery), milk protein, emulsifier (triphosphates), antioxidants (sodium ascorbate, monosodium glutamate), preservative (sodium nitrite)).

 

My allergens array: 

allergenList = ["soy", "mustard", "celery", "milk"]
 
(part of) my script:
var ingredientList = doc.selection[0].textRange;
 
var i = 0;
for (i=0; i < ingredientList.words.length; i++){
var wordSelected = ingredientList.words[i];
//checking matches between ingredientList and allergenList
var k = 0;
for (k=0; k < allergenList.length; k++){
if (wordSelected.contents == allergenList[k]){
// formatting the selection
wordSelected.characterAttributes.textFont = textFonts.getByName("MyriadPro-BoldCond")
break;
}
}
}
 
But it appears the .word subrange is not the ideal approach: when an allergen word is followed by a parenthese, it is not correctly selected. As a matter of fact, the .contents returns a word without the last letter (e.g. 'celer' instead of 'celery')
 
I am sure there are better and smarter approaches but I am a newby to AI scripting 🙂
 
Also, I think it would be wiser to load the allegens list from a text file rather than a hard-coded array, but that is another challenge to tackle.
 
Me and all food sensitive people will be very grateful for your help:)
This topic is closed to new replies. Start a new post to keep the conversation going.
Correct answer femkeblanco

Hello Femke, thank you so much! Now it only still puts words in bold that contain an allergen word (like chicken legg > chicken legg). I tried to identify the character (space, comma,...) before each word by using index-1, but it doesn't seem to work. Or is it possible to check if both words have the same lenght and add this as a condition for putting in bold?


You can refine the logic defining a "word" so it is preceded by a space and followed by a space, comma or full stop. 

// select text frame
var array = ["soy", "mustard", "celery", "milk"];
var string = app.selection[0].contents;
var indices = [];

for (var i = 0; i < array.length; i++) {
    indices = indices.concat(getIndices(array[i]));
}

for (var i = 0; i < indices.length; i++) {
    if (string[indices[i]._1st - 1] == " " && 
        (string[indices[i]._nth] == " " || 
         string[indices[i]._nth] == "," ||
         string[indices[i]._nth] == ".")) {
        for (var j = indices[i]._1st; j < indices[i]._nth; j++) {
            var attributes = app.selection[0].textRanges[j].characterAttributes;
            attributes.textFont = textFonts["MyriadPro-BoldCond"];
        }
    }
}

function getIndices(substring) {
    var indices = [];
    var index = string.indexOf(substring);
    while (index != -1) {
        indices.push({_1st: index, _nth: index + substring.length});
        index = string.indexOf(substring, index + 1);
    }
    return indices;
}

 

11 replies

Legend
May 23, 2023

Such things can be achieved with regular expressions. The following tools seem to work in Illustrator.

 

 

All explanations are written in Japanese, but please use a translation tool to read them.

femkeblanco
Legend
May 21, 2023

I am sure there are better ways, but this is what popped into my head.  It won't do repeated words though. 

// select text frame
var array = ["soy", "mustard", "celery", "milk"];
var string = app.selection[0].contents;
for (var i = 0; i < array.length; i++) {
    var firstChar = string.search(array[i]);
    var lastChar = firstChar + array[i].length;
    for (var j = firstChar; j < lastChar; j++) {
        var attributes = app.selection[0].textRanges[j].characterAttributes;
        attributes.textFont = textFonts["MyriadPro-BoldCond"];
    }
}

 

Participating Frequently
May 22, 2023

Hi femkeblanco, thanks a lot for taking timing to look into my challenge. This indeed is a smart approach, but some words do repeat a lot (like 'milk' or 'soy').

femkeblanco
Legend
May 22, 2023

Sticking with the same idea, this should do repeated words.

// select text frame
var array = ["soy", "mustard", "celery", "milk"];
var string = app.selection[0].contents;
var indices = [];

for (var i = 0; i < array.length; i++) {
    indices = indices.concat(getIndices(array[i]));
}

for (var i = 0; i < indices.length; i++) {
    for (var j = indices[i]._1st; j < indices[i]._nth; j++) {
        var attributes = app.selection[0].textRanges[j].characterAttributes;
        attributes.textFont = textFonts["MyriadPro-BoldCond"];
    }
}

function getIndices(substring) {
    var indices = [];
    var index = string.indexOf(substring);
    while (index != -1) {
        indices.push({_1st: index, _nth: index + substring.length});
        index = string.indexOf(substring, index + 1);
    }
    return indices;
}