Skip to main content
Inspiring
January 12, 2022
Question

Find and replace an unregistered opentype feature

  • January 12, 2022
  • 1 reply
  • 440 views

Hi,
I am trying to make a script to find and replace the same character and applying a opentype feature.

This is not difficult using GREP and ChainGREP script.

My problem is the opentype feature I want to apply is not registered in Indesign

I am trying to use a "Character Variant" opentype feature.


This feature works if use this script:
app.selection[0].opentypeFeatures=[["cv01",1]];


but if You apply in the same text selection another Character Variant you remove the first one.
This is the reason I want a script to find and replace using this feature.

Using chainGREP script I got this:

 

//This script was auto generated by chainGREP.jsx
//chainGREP.jsx is provided by Gregor Fellenz https://www.publishingx.de/
//Download at https://www.publishingx.de/download/chain-grep

main();

function main() {
if (app.layoutWindows.length == 0) return;
if (app.selection.length == 0) {
var scope = app.documents[0];
}
else {
var w = new Window ('dialog', localize(({en:"Scope of Find/Change", de:"Bereich der Ersetzung", fr:"Portée de Rechercher/Remplacer", ja_JP:"検索置換の範囲", nl:"Zoeken in"})) );
var scopePanel = w.add ('Panel', undefined, localize(({en:"Scope of Find/Change", de:"Bereich der Ersetzung", fr:"Portée de Rechercher/Remplacer", ja_JP:"検索置換の範囲", nl:"Zoeken in"})) );
scopePanel.alignment = 'fill';
scopePanel.alignChildren = 'fill';
scopePanel.margins = [10,20,10,10];
with (scopePanel) {
rButScopeDoc = add( 'radiobutton', undefined, localize(({en:"Document", de:"Dokument", fr:"Document", ja_JP:"ドキュメント", nl:"Document"})) );
rButScopeDoc.value = true;
rButScopeStory= add( 'radiobutton', undefined, localize(({en:"Story (of Selection)", de:"Textabschnitt", fr:"Article (contenant la sélection)", ja_JP:"ストーリー", nl:"Artikel (van selectie)"})) );
}
var uiCtrlGroup = w.add ('group');
with (uiCtrlGroup) {
var cancelBtn = uiCtrlGroup.add ('button', undefined, localize(({en:"Cancel", de:"Abbrechen", fr:"Annuler", ja_JP:"キャンセル", nl:"Annuleren"})));
var okButton = uiCtrlGroup.add ('button', undefined, localize(({en:"Run", de:"Starten", fr:"Démarrer", ja_JP:"実行", nl:"Start"})) );
cancelBtn.onClick = function () {
w.close(2);
}
okButton.onClick = function () {
if (rButScopeDoc.value) scope = app.documents[0];
else if (rButScopeStory.value) scope = app.selection[0].parentStory;
w.close(1);
}
}
if(w.show() != 1) {
return
}
}
var changeObject = scope;
if (changeObject.hasOwnProperty('characters') && changeObject.characters.length == 0) return;
var doc = app.documents[0];
var style;
var scriptVersion = app.scriptPreferences.version;
app.scriptPreferences.version = 16.2;
var options = app.findChangeGrepOptions.properties;
app.findGrepPreferences = NothingEnum.NOTHING;
app.changeGrepPreferences = NothingEnum.NOTHING;
// Query [[b]] -- If you delete this comment you break the update function
try {
app.findChangeGrepOptions.properties = ({kanaSensitive:true, widthSensitive:true});
app.findGrepPreferences.properties = ({findWhat:"g"});
app.changeGrepPreferences.properties = ({changeTo:"g", pointSize:60, otfStylisticSets:8, fillColor:"C=15 M=100 Y=100 K=0"});
changeObject.changeGrep();
} catch (e) {alert(e + ' at line ' + e.line)}
app.findChangeGrepOptions.properties = options;
app.findGrepPreferences = NothingEnum.NOTHING;
app.changeGrepPreferences = NothingEnum.NOTHING;
app.scriptPreferences.version = scriptVersion;
};

function getStyleByString(docOrGroup, string, property) {
if (string == '[No character style]') return docOrGroup[property][0];
if (string == '[No paragraph style]') return docOrGroup[property][0];
if (string == 'NormalParagraphStyle') return docOrGroup[property][1];
stringResult = string.match (/^(.*?[^\\]):(.*)$/);
var styleName = (stringResult) ? stringResult[1] : string;
styleName = styleName.replace (/\\:/g, ':');
remainingString = (stringResult) ? stringResult[2] : '';
var newProperty = (stringResult) ? property.replace(/s$/, '') + 'Groups' : property;
var styleOrGroup = docOrGroup[newProperty].itemByName(styleName);
if (remainingString.length > 0 && styleOrGroup.isValid) styleOrGroup = getStyleByString (styleOrGroup, remainingString, property);
return styleOrGroup;
};

 

Them I tried to modify the script using Character Variant Opentype Feature:

//This script was auto generated by chainGREP.jsx
//chainGREP.jsx is provided by Gregor Fellenz https://www.publishingx.de/
//Download at https://www.publishingx.de/download/chain-grep

main();

function main() {
if (app.layoutWindows.length == 0) return;
if (app.selection.length == 0) {
var scope = app.documents[0];
}
else {
var w = new Window ('dialog', localize(({en:"Scope of Find/Change", de:"Bereich der Ersetzung", fr:"Portée de Rechercher/Remplacer", ja_JP:"検索置換の範囲", nl:"Zoeken in"})) );
var scopePanel = w.add ('Panel', undefined, localize(({en:"Scope of Find/Change", de:"Bereich der Ersetzung", fr:"Portée de Rechercher/Remplacer", ja_JP:"検索置換の範囲", nl:"Zoeken in"})) );
scopePanel.alignment = 'fill';
scopePanel.alignChildren = 'fill';
scopePanel.margins = [10,20,10,10];
with (scopePanel) {
rButScopeDoc = add( 'radiobutton', undefined, localize(({en:"Document", de:"Dokument", fr:"Document", ja_JP:"ドキュメント", nl:"Document"})) );
rButScopeDoc.value = true;
rButScopeStory= add( 'radiobutton', undefined, localize(({en:"Story (of Selection)", de:"Textabschnitt", fr:"Article (contenant la sélection)", ja_JP:"ストーリー", nl:"Artikel (van selectie)"})) );
}
var uiCtrlGroup = w.add ('group');
with (uiCtrlGroup) {
var cancelBtn = uiCtrlGroup.add ('button', undefined, localize(({en:"Cancel", de:"Abbrechen", fr:"Annuler", ja_JP:"キャンセル", nl:"Annuleren"})));
var okButton = uiCtrlGroup.add ('button', undefined, localize(({en:"Run", de:"Starten", fr:"Démarrer", ja_JP:"実行", nl:"Start"})) );
cancelBtn.onClick = function () {
w.close(2);
}
okButton.onClick = function () {
if (rButScopeDoc.value) scope = app.documents[0];
else if (rButScopeStory.value) scope = app.selection[0].parentStory;
w.close(1);
}
}
if(w.show() != 1) {
return
}
}
var changeObject = scope;
if (changeObject.hasOwnProperty('characters') && changeObject.characters.length == 0) return;
var doc = app.documents[0];
var style;
var scriptVersion = app.scriptPreferences.version;
app.scriptPreferences.version = 16.2;
var options = app.findChangeGrepOptions.properties;
app.findGrepPreferences = NothingEnum.NOTHING;
app.changeGrepPreferences = NothingEnum.NOTHING;
// Query [[b]] -- If you delete this comment you break the update function
try {
app.selection[0].hasOwnProperty("opentypeFeatures")
app.findChangeGrepOptions.properties = ({kanaSensitive:true, widthSensitive:true});
app.findGrepPreferences.properties = ({findWhat:"g"});
app.changeGrepPreferences.properties = ({changeTo:"g", pointSize:60, opentypeFeatures:[["cv02",1]], fillColor:"C=15 M=100 Y=100 K=0"});
changeObject.changeGrep();
} catch (e) {alert(e + ' at line ' + e.line)}
app.findChangeGrepOptions.properties = options;
app.findGrepPreferences = NothingEnum.NOTHING;
app.changeGrepPreferences = NothingEnum.NOTHING;
app.scriptPreferences.version = scriptVersion;
};

function getStyleByString(docOrGroup, string, property) {
if (string == '[No character style]') return docOrGroup[property][0];
if (string == '[No paragraph style]') return docOrGroup[property][0];
if (string == 'NormalParagraphStyle') return docOrGroup[property][1];
stringResult = string.match (/^(.*?[^\\]):(.*)$/);
var styleName = (stringResult) ? stringResult[1] : string;
styleName = styleName.replace (/\\:/g, ':');
remainingString = (stringResult) ? stringResult[2] : '';
var newProperty = (stringResult) ? property.replace(/s$/, '') + 'Groups' : property;
var styleOrGroup = docOrGroup[newProperty].itemByName(styleName);
if (remainingString.length > 0 && styleOrGroup.isValid) styleOrGroup = getStyleByString (styleOrGroup, remainingString, property);
return styleOrGroup;
};

This script doesn't work of course but I don't know how to fix it.

I am using Adobe Source Code Pro font (free font) to test this script.
Please, if anyone could help would be great.
Regards
Sami

 

This topic has been closed for replies.

1 reply

SumitKumar
Inspiring
January 28, 2022

Hi @Sami Artur,

 

This is your code modified by me.

 

#targetengine "Session"

if (!(app.selection.length)) exit(0);
var mySelection = app.selection[0];
var appFonts = app.fonts.everyItem().name;
//alert (appFonts.toString());

var MyFonts = [];
var MyStyle = [];
getFontInfo();
ShowUI();

function ShowUI() {
    // FIND_CHANGE
    // ===========
    var Find_Change = new Window("palette");
    Find_Change.text = "palette";
    Find_Change.orientation = "column";
    Find_Change.alignChildren = ["center", "top"];
    Find_Change.spacing = 10;
    Find_Change.margins = 16;

    // GROUP1
    // ======
    var group1 = Find_Change.add("group", undefined, { name: "group1" });
    group1.orientation = "column";
    group1.alignChildren = ["center", "top"];
    group1.spacing = 10;
    group1.margins = 0;

    // PANEL1
    // ======
    var panel1 = group1.add("panel", undefined, undefined, { name: "panel1" });
    panel1.text = "Select Fonts";
    panel1.preferredSize.width = 270;
    panel1.orientation = "row";
    panel1.alignChildren = ["left", "top"];
    panel1.spacing = 10;
    panel1.margins = 10;

    var statictext1 = panel1.add("statictext", undefined, undefined, { name: "statictext1" });
    statictext1.text = "Font";

    var winddlFonts = panel1.add('dropdownlist', undefined, MyFonts);
    winddlFonts.selection = 0;

    var panel5 = group1.add("panel", undefined, undefined, { name: "panel5" });
    panel5.text = "Font Style";
    panel5.preferredSize.width = 270;
    panel5.orientation = "row";
    panel5.alignChildren = ["left", "top"];
    panel5.spacing = 10;
    panel5.margins = 10;

    var winddlStyles = panel5.add('dropdownlist', undefined, ["Select Font"]);
    winddlStyles.selection = 0;
    winddlStyles.preferredSize.width = 257;

    // PANEL2
    // ======
    var panel2 = group1.add("panel", undefined, undefined, { name: "panel2" });
    panel2.text = "Find Character";
    panel2.preferredSize.width = 270;
    panel2.orientation = "column";
    panel2.alignChildren = ["left", "top"];
    panel2.spacing = 10;
    panel2.margins = 10;

    var edittext1 = panel2.add('edittext {properties: {name: "edittext1"}}');
    edittext1.text = "a";
    edittext1.preferredSize.width = 257;

    // PANEL3
    // ======
    var panel3 = group1.add("panel", undefined, undefined, { name: "panel3" });
    panel3.text = "Apply Feature";
    panel3.preferredSize.width = 270;
    panel3.orientation = "row";
    panel3.alignChildren = ["center", "top"];
    panel3.spacing = 10;
    panel3.margins = 10;

    var listbox1_array = ["aalt", "abvf", "abvm", "abvs", "afrc", "akhn", "blwf", "blwm", "blws", "c2pc", "c2sc", "calt", "case", "ccmp", "cfar", "cjct", "clig", "cpct", "cpsp", "cswh", "curs", "cv01", "cv02", "cv03", "cv04", "cv05", "cv06", "cv07", "cv08", "cv09", "cv10", "cv11", "cv12", "cv13", "cv14", "cv15", "cv16", "cv17", "cv18", "cv19", "cv20", "cv21", "cv22", "cv23", "cv24", "cv25", "cv26", "cv27", "cv28", "cv29", "cv30", "cv31", "cv32", "cv33", "cv34", "cv35", "cv36", "cv37", "cv38", "cv39", "cv40", "cv41", "cv42", "cv43", "cv44", "cv45", "cv46", "cv47", "cv48", "cv49", "cv50", "cv51", "cv52", "cv53", "cv54", "cv55", "cv56", "cv57", "cv58", "cv59", "cv60", "cv61", "cv62", "cv63", "cv64", "cv65", "cv66", "cv67", "cv68", "cv69", "cv70", "cv71", "cv72", "cv73", "cv74", "cv75", "cv76", "cv77", "cv78", "cv79", "cv80", "cv81", "cv82", "cv83", "cv84", "cv85", "cv86", "cv87", "cv88", "cv89", "cv90", "cv91", "cv92", "cv94", "cv95", "cv96", "cv97", "cv98", "cv99", "dist", "dlig", "dnom", "dtls", "expt", "falt", "fin2", "fin3", "fina", "flac", "frac", "fwid", "half", "haln", "halt", "hist", "hkna", "hlig", "hngl", "hojo", "hwid", "init", "isol", "ital", "jalt", "jp04", "jp78", "jp83", "jp90", "kern", "lfbd", "liga", "ljmo", "lnum", "locl", "ltra", "ltrm", "mark", "med2", "medi", "mgrk", "mkmk", "mset", "nalt", "nlck", "nukt", "numr", "onum", "opbd", "ordn", "ornm", "palt", "pcap", "pkna", "pnum", "pref", "pres", "pstf", "psts", "pwid", "qwid", "rand", "rclt", "rkrf", "rlig", "rphf", "rtbd", "rtla", "rtlm", "ruby", "salt", "sinf", "size", "smcp", "smpl", "ss01", "ss02", "ss03", "ss04", "ss05", "ss06", "ss07", "ss08", "ss09", "ss10", "ss11", "ss12", "ss13", "ss14", "ss15", "ss16", "ss17", "ss18", "ss19", "ss20", "ssty", "stch", "subs", "sups", "swsh", "titl", "tjmo", "tnam", "tnum", "trad", "twid", "unic", "valt", "vatu", "vert", "vhal", "vjmo", "vkna", "vkrn", "vpal", "vrt2", "zero", ""];
    var listbox1 = panel3.add("listbox", undefined, undefined, { name: "listbox1", items: listbox1_array, numberOfColumns: 2, columnWidths: [5] });
    listbox1.preferredSize.width = 257;
    listbox1.preferredSize.height = 200;
    listbox1.alignment = ["center", "top"];

    // PANEL4
    // ======
    var panel4 = group1.add("panel", undefined, undefined, { name: "panel4" });
    panel4.text = "Variant";
    panel4.preferredSize.width = 270;
    panel4.orientation = "row";
    panel4.alignChildren = ["center", "top"];
    panel4.spacing = 10;
    panel4.margins = 10;

    var edittext3 = panel4.add('edittext {properties: {name: "edittext3"}}');
    edittext3.preferredSize.width = 70;
    edittext3.text = "1";

    winddlFonts.onChange = function () {
        winddlStyles.removeAll();
        var arrStyle = MyStyle[this.selection.index];
        for (var i = 0; i < arrStyle.length; i++) {
            winddlStyles.add('item', arrStyle[i]);
        }
    }

    var btn_group = Find_Change.add("group");
    var close_button = btn_group.add("button", undefined, "Close", { name: "cancel" });
    var convert_button = btn_group.add("button", undefined, "Apply", { name: "ok" });
    convert_button.onClick = function () {
        try {
            var chosenFont = winddlFonts.selection.text,
                chosenStyle = winddlStyles.selection.text,
                findText = edittext1.text,
                list = listbox1.selection.text,
                edit3 = edittext3.text;
            //alert("Font chosen: " + chosenFont + "\rStyle chosen: " + chosenStyle);
            // this.parent.close(2);
            findChange(chosenFont, chosenStyle, findText, list, edit3);
            Find_Change.close();
        }
        catch (e) {
            alert(e.line + "\r" + e.message);
        }
    }
    close_button.onClick = function () {
        Find_Change.close();
    }
    Find_Change.show();

    function findChange(chosenFont, chosenStyle, findText, list, edit3) {
        app.findGrepPreferences = NothingEnum.nothing;
        app.changeGrepPreferences = NothingEnum.nothing;
        app.findChangeGrepOptions.includeFootnotes = false;
        app.findChangeGrepOptions.includeHiddenLayers = false;
        app.findChangeGrepOptions.includeLockedLayersForFind = false;
        app.findChangeGrepOptions.includeLockedStoriesForFind = false;
        app.findChangeGrepOptions.includeMasterPages = false;

        app.findGrepPreferences.findWhat = findText;
        app.findGrepPreferences.appliedFont = chosenFont;
        app.findGrepPreferences.fontStyle = chosenStyle;

        var matchArray = mySelection.findGrep(true);

        app.findGrepPreferences = NothingEnum.nothing;
        app.changeGrepPreferences = NothingEnum.nothing;

        for (var i = 0; i < matchArray.length; i++) {
            var curMatch = matchArray[i];
            if (curMatch.hasOwnProperty("opentypeFeatures")) {
                curMatch.opentypeFeatures = [[list, Number(edit3)]];
            }
        }
    }
}

function getFontInfo() {
    //array for font and style
    var counter = -1;
    for (var i = 0; i < appFonts.length; i++) {
        appFonts[i] = appFonts[i].split("\t");
        if (i == 0 || appFonts[i][0] != appFonts[i - 1][0]) {
            MyFonts.push(appFonts[i][0]);
            counter++;
            MyStyle[counter] = [];
        }
        MyStyle[counter].push(appFonts[i][1]);
    }
}
-Sumit