Copy link to clipboard
Copied
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:
1 Correct answer
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
...
Explore related tutorials & articles
Copy link to clipboard
Copied
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"];
}
}
Copy link to clipboard
Copied
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').
Copy link to clipboard
Copied
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;
}
Copy link to clipboard
Copied
Thank you so much, this works great!
Now there is one more issue which is quite complex, and I suppose this goes beyond the purpose of this support community?
But it is, when an allergen is specified (by its ingredients between parentheses), the allergen itself is not put in bold, but only the component that is the 'real' allergen.
To illustrate the possible situations:
• pork bacon, salt, soy protein -> pork bacon, salt, soy protein > ok!
• spices (contains mustard) -> spices (contains mustard) > ok!
but:
• mustard 9 % (mustard 77 % (vinegar, mustard seed, salt, curcuma), dextrose, corn starch) -> mustard 9 % (mustard 77 % (vinegar, mustard seed, salt, curcuma), dextrose, corn starch)
It seems very complex to me to code this sort of 'human' reasoning, as it has to take into account the context, that is, the appearence of (one or more) parentheses after a possible match. And also, I think I should be paying you by now for such amount of magnificent support 🙂
Copy link to clipboard
Copied
My immediate impression is that you need to
(1) parse the parenthesised string into a nested array; and
(2) recursively iterate the nested array, getting the matches if they are not in succeeding inner arrays.
I can do (1), but I'm unsure how to do (2). If I have the time, I'll try to think about it in the next couple of days. Hopefully, someone else might think of something I haven't.
Copy link to clipboard
Copied
Hello Femke,
in the above script, would it be possible to only check on whole words to but in bold? So that 'mustard' is put in bold, but not 'mustardflavour' ?
Copy link to clipboard
Copied
The above code manipultes strings; it does not recognise words. But you can add your own logic to define a "word". So you can add a conditional that boldens a substring only if it is 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]._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;
}
Copy link to clipboard
Copied
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?
Copy link to clipboard
Copied
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;
}
Copy link to clipboard
Copied
Hi Femke, great, this is my solution! I added some extra characters:
for (var i = 0; i < indices.length; i++) {
if ((string[indices[i]._1st - 1] == "(" ||
string[indices[i]._1st - 1] == " " ) &&
(string[indices[i]._nth] == " " ||
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"];
}
}
}
Many more functions to add still and so much to learn and explore, but this was very helpful and educational, thanks again!
Copy link to clipboard
Copied
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.

