Skip to main content
Participating Frequently
June 26, 2025
Answered

How to use a character style in a positive lookbehind

  • June 26, 2025
  • 2 replies
  • 663 views

Hello All,

I have a large document with hundreds of short phrases in an italic Character Style followed immediately by a comma with [No Style]. I want to apply the same italic Character Style to the trailing comma. That is, I want to change [italic-phrase], to [italic-phrase,].

 

I don't see any way to do this with the Find/Change GREP dialog, but maybe in ExtendScript? It sounds like a job for GREP with a positive lookbehind, but I'm not sure how to accomplish this in Extendscript.

 

Is there an existing script that might be adapted to such a use case? Or can someone show how to find a comma preceded by italic styled text? Or any better idea?

 

Thank you.

Correct answer m1b

Hi @Eugene Tyson that is a perfectly correct and legitimate way to approach this problem and works well.

 

In the spirit of sharing scripting techniques, I'd like to show a very similar script, but one that uses findGrep for collecting the texts. Just for learning—both our scripts do the same thing.

- Mark

 

/**
 * @file Italicize Commas.js
 *
 * Finds text in a character style, and expands
 * the style range to include a trailing comma
 * where applicable.
 *
 * @author m1b
 * @version 2025-06-26
 * @discussion https://community.adobe.com/t5/indesign-discussions/how-to-use-a-character-style-in-a-positive-lookbehind/m-p/15389281
 */
function main() {

    const FIND_CHARACTER_STYLE_NAME = 'Italic',
        COMMA = ',';

    if (0 === app.documents.length)
        return alert('Please open a document and try again.');

    var doc = app.activeDocument,
        style = getThing(doc.allCharacterStyles, 'name', FIND_CHARACTER_STYLE_NAME);

    if (!style)
        return alert('Could not find character style "' + FIND_CHARACTER_STYLE_NAME + '".');

    // reset grep prefs
    app.findGrepPreferences = NothingEnum.NOTHING;

    // find grep options
    app.findChangeGrepOptions.includeFootnotes = true;
    app.findChangeGrepOptions.includeHiddenLayers = false;
    app.findChangeGrepOptions.includeLockedLayersForFind = false;
    app.findChangeGrepOptions.includeLockedStoriesForFind = false;
    app.findChangeGrepOptions.includeMasterPages = false;

    // find criteria
    app.findGrepPreferences.appliedCharacterStyle = style;

    var found = doc.findGrep(),
        counter = 0;

    for (var i = 0, nextCharacter; i < found.length; i++) {

        nextCharacter = found[i].parentStory.characters.nextItem(found[i].characters.lastItem());

        if (COMMA === nextCharacter.contents) {
            nextCharacter.appliedCharacterStyle = style;
            counter++;
        }

    }

    alert('Changed ' + counter + ' commas.');

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Italicize Commas');

/**
 * Returns a thing with matching property.
 * If `key` is undefined, evaluate the object itself.
 * @author m1b
 * @version 2024-04-21
 * @param {Array|Collection} things - the things to look through.
 * @param {String} [key] - the property name (default: undefined).
 * @param {*} value - the value to match.
 * @returns {*?} - the thing, if found.
 */
function getThing(things, key, value) {

    for (var i = 0; i < things.length; i++)
        if ((undefined == key ? things[i] : things[i][key]) == value)
            return things[i];

};

 

2 replies

AshendeneAuthor
Participating Frequently
June 27, 2025

@Eugene Tyson and @m1b Thank you both for your quick and helpful responses. I learned something from both solutions. One checking every comma in the document to see if the previous character was styled, and the other checking each instance of the style to see if a comma followed. And in each case the lookahead/lookbehind had to be scripted instead of using GREP. Very helpful.

 

I expect I can only select one as the correct solution, but both approaches had advantages. Thanks again.

Community Expert
June 27, 2025

No problem, glad it helped, there's always different approaches, if you have long documents then Mark's is probably faster. 

 

You can mark as many as you like as correct answer, there can always be more than 1, I went ahead and marked Mark's as correct too.

Community Expert
June 26, 2025

Yeh you'll need a script for this, luckily I've come across the same limitations before and already have a script for it 😛
I've modified it for your specific case here - there's a section at the top you need to put in your exact style name. 

app.doScript(function () {
    var doc = app.activeDocument;
    var italicStyleName = "Italic"; // Change this to your character style name

    var italicStyle = doc.characterStyles.itemByName(italicStyleName);
    if (!italicStyle.isValid) {
        alert("Character style '" + italicStyleName + "' not found.");
        return;
    }

    var stories = doc.stories;
    for (var i = 0; i < stories.length; i++) {
        var chars = stories[i].characters;
        for (var j = 1; j < chars.length; j++) {
            var currentChar = chars[j];
            var prevChar = chars[j - 1];

            if (
                currentChar.contents === "," &&
                currentChar.appliedCharacterStyle.name === doc.characterStyles[0].name && // [None]
                prevChar.appliedCharacterStyle === italicStyle
            ) {
                currentChar.appliedCharacterStyle = italicStyle;
            }
        }
    }
}, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Apply Italic Style to Trailing Commas");

 

 

m1b
Community Expert
m1bCommunity ExpertCorrect answer
Community Expert
June 26, 2025

Hi @Eugene Tyson that is a perfectly correct and legitimate way to approach this problem and works well.

 

In the spirit of sharing scripting techniques, I'd like to show a very similar script, but one that uses findGrep for collecting the texts. Just for learning—both our scripts do the same thing.

- Mark

 

/**
 * @file Italicize Commas.js
 *
 * Finds text in a character style, and expands
 * the style range to include a trailing comma
 * where applicable.
 *
 * @author m1b
 * @version 2025-06-26
 * @discussion https://community.adobe.com/t5/indesign-discussions/how-to-use-a-character-style-in-a-positive-lookbehind/m-p/15389281
 */
function main() {

    const FIND_CHARACTER_STYLE_NAME = 'Italic',
        COMMA = ',';

    if (0 === app.documents.length)
        return alert('Please open a document and try again.');

    var doc = app.activeDocument,
        style = getThing(doc.allCharacterStyles, 'name', FIND_CHARACTER_STYLE_NAME);

    if (!style)
        return alert('Could not find character style "' + FIND_CHARACTER_STYLE_NAME + '".');

    // reset grep prefs
    app.findGrepPreferences = NothingEnum.NOTHING;

    // find grep options
    app.findChangeGrepOptions.includeFootnotes = true;
    app.findChangeGrepOptions.includeHiddenLayers = false;
    app.findChangeGrepOptions.includeLockedLayersForFind = false;
    app.findChangeGrepOptions.includeLockedStoriesForFind = false;
    app.findChangeGrepOptions.includeMasterPages = false;

    // find criteria
    app.findGrepPreferences.appliedCharacterStyle = style;

    var found = doc.findGrep(),
        counter = 0;

    for (var i = 0, nextCharacter; i < found.length; i++) {

        nextCharacter = found[i].parentStory.characters.nextItem(found[i].characters.lastItem());

        if (COMMA === nextCharacter.contents) {
            nextCharacter.appliedCharacterStyle = style;
            counter++;
        }

    }

    alert('Changed ' + counter + ' commas.');

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Italicize Commas');

/**
 * Returns a thing with matching property.
 * If `key` is undefined, evaluate the object itself.
 * @author m1b
 * @version 2024-04-21
 * @param {Array|Collection} things - the things to look through.
 * @param {String} [key] - the property name (default: undefined).
 * @param {*} value - the value to match.
 * @returns {*?} - the thing, if found.
 */
function getThing(things, key, value) {

    for (var i = 0; i < things.length; i++)
        if ((undefined == key ? things[i] : things[i][key]) == value)
            return things[i];

};

 

Community Expert
June 26, 2025

That's probably faster and better than mine 😄 

Thanks for sharing.