Skip to main content
Bedazzled532
Inspiring
June 30, 2024
Answered

String Formatting in Extendscript

  • June 30, 2024
  • 2 replies
  • 1276 views

I found this great script by @rob day  in this group which returns font metrics data.

I wish this could be included in InDesign's info panel by Adobe. 

 

Currently the script gives output in points. I have modified it to give data in MM also.

Issue is that the output is not properly formatted. I have attached a screenshot.

 

Is there a way to give proper formatting. I tried printf, sprintf, console.log but all these do not work in extendscript.

 

I want the top headers to be in bold, left headers to be in bold. ":" should be aligned. The values of Points to be aligned so that it becomes easier to read.

 

I have attached @rob day script here with modification.

// the selected character
var s = app.activeDocument.selection[0]; 
// the fixed decimal place
var dn = 3;

if (s.constructor.name == "Character") {
    var p = getFontMetric(s).pointSize;
    var bl = getFontMetric(s).baseline;
    var a = getFontMetric(s).ascent;
    var d = getFontMetric(s).descent;
    var ch = getFontMetric(s).capHeight;
    var xh = getFontMetric(s).xHeight;
    

alert("\u0009Points:" + "\u0009" + " MM:\r" + "Point Size:" + p + "\u0009" + p*.3572 + "\r" + "Baseline: " + bl + "\u0009" + bl*.3572 + "\r" + "Ascender: " + a + "\u0009" + a*.3572 +  "\r" + "Descender: " + d + "\u0009" + d*.3572 + "\r" +  "Cap Height: " + ch + "\u0009" + ch*.3572 + "\r" + "x-Height: " + xh + "\u0009" + xh*.3572);

} else {
    alert("Please Select a Single Character");
}


/**
* Gets the selected character’s font metrics 
* @ param the character selection  
* @ return an object with pointSize, baseline, ascent,descent, xHeight, and capHeight 
*/
function getFontMetric(s){
    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
    var o = new Object;
    o.pointSize = s.pointSize.toFixed(dn);
    o.baseline = s.baseline.toFixed(dn);
    o.ascent = s.ascent.toFixed(dn);
    o.descent = s.descent.toFixed(dn);
    app.copy();
    var tf = app.activeDocument.textFrames.add({geometricBounds: [0,0,500,500], textFramePreferences: {firstBaselineOffset: FirstBaseline.CAP_HEIGHT, insetSpacing: 0, minimumFirstBaselineOffset: 0, verticalJustification: VerticalJustification.TOP_ALIGN}});  
    app.select([tf.parentStory.insertionPoints[0]]);    
    app.paste();
    tf.texts[0].alignToBaseline = false;
    o.capHeight = tf.texts[0].insertionPoints[0].baseline.toFixed(dn);
    tf.textFramePreferences.firstBaselineOffset = FirstBaseline.X_HEIGHT;
    o.xHeight = tf.texts[0].insertionPoints[0].baseline.toFixed(dn);
    tf.remove();
    app.select(s)
    app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL;
    return o
}
This topic has been closed for replies.
Correct answer rob day

@Bedazzled532

 

I don't think padding will work - as font used in UI is "variable width".

 

But as the tab works - \u0009 - you can use it to align your results.

 


Also, you might look at the unitValue object which lets you convert units—it’s returning a different value than your .3572 multiplier:

 

// the selected character
var s = app.activeDocument.selection[0]; 
// the fixed decimal place
var dn = 3;

if (s.constructor.name == "Character") {
    var t = "Metric\tPoints\tMillimeters\r"
    var p = getFontMetric(s).pointSize;
    p = "Point Size:\t" + p + "\t" + UnitValue( p, "pt" ).as("mm").toFixed(dn) + "\r";
    
    var bl = getFontMetric(s).baseline;
    bl = "Baseline:\t" +bl + "\t" + UnitValue( bl, "pt" ).as("mm").toFixed(dn) + "\r";
    
    var a = getFontMetric(s).ascent;
    a = "Ascent:\t" +a + "\t" + UnitValue( a, "pt" ).as("mm").toFixed(dn) + "\r";

    var d = getFontMetric(s).descent;
    d = "Descent:\t" +d + "\t" + UnitValue( d, "pt" ).as("mm").toFixed(dn) + "\r";

    var ch = getFontMetric(s).capHeight;
    ch = "Cap Ht:\t" +ch + "\t" + UnitValue( ch, "pt" ).as("mm").toFixed(dn) + "\r";

    var xh = getFontMetric(s).xHeight;
    xh = "xHeight:\t" +xh + "\t" + UnitValue( xh, "pt" ).as("mm").toFixed(dn) + "\r";
    
    alert(t + p + bl + a + d + ch + xh)

} else {
    alert("Please Select a Single Character");
}


/**
* Gets the selected character’s font metrics 
* @ param the character selection  
* @ return an object with pointSize, baseline, ascent,descent, xHeight, and capHeight 
*/
function getFontMetric(s){
    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
    var o = new Object;
    o.pointSize = s.pointSize.toFixed(dn);
    o.baseline = s.baseline.toFixed(dn);
    o.ascent = s.ascent.toFixed(dn);
    o.descent = s.descent.toFixed(dn);
    app.copy();
    var tf = app.activeDocument.textFrames.add({geometricBounds: [0,0,500,500], textFramePreferences: {firstBaselineOffset: FirstBaseline.CAP_HEIGHT, insetSpacing: 0, minimumFirstBaselineOffset: 0, verticalJustification: VerticalJustification.TOP_ALIGN}});  
    app.select([tf.parentStory.insertionPoints[0]]);    
    app.paste();
    tf.texts[0].alignToBaseline = false;
    o.capHeight = tf.texts[0].insertionPoints[0].baseline.toFixed(dn);
    tf.textFramePreferences.firstBaselineOffset = FirstBaseline.X_HEIGHT;
    o.xHeight = tf.texts[0].insertionPoints[0].baseline.toFixed(dn);
    tf.remove();
    app.select(s)
    app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL;
    return o
}

 

 

 

 

2 replies

rob day
Community Expert
Community Expert
June 30, 2024

Hi @Bedazzled532 , There‘s no way that I know of to format the alert() dialog result. You might be able to use the scriptUI window class to create some alignment in a window aor palette.

 

You could also create a text frame somewhere in the document with a tab delimited string as the contents and style that, but that would take some work.

Bedazzled532
Inspiring
June 30, 2024

@rob day Ok. Thanks. Actually I was thinking of formatting a string as we use to do in printf in earlier days and then show it through alert. I will try what you suggested.

I have limited decimal places to 3 by @Robert at ID-Tasker suggested function.

 

Here is how the alert function looks like:

alert("\u0009Points:" + "\u0009" + " MM:\r" + "Point Size:" + p + "\u0009" + (p*.3572).toFixed(3) + "\r" + "Baseline: " + bl + "\u0009" + (bl*.3572).toFixed(3) + "\r" + "Ascender: " + a + "\u0009" + (a*.3572).toFixed(3) +  "\r" + "Descender: " + d + "\u0009" + (d*.3572).toFixed(3) + "\r" +  "Cap Height: " + ch + "\u0009" + (ch*.3572).toFixed(3) + "\r" + "x-Height: " + xh + "\u0009" + (xh*.3572).toFixed(3));

How can I use a method padEnd and padStart. I see that there is a function but when I use this function, I get that there is no function named padEnd or padStart.

 

Thanks

Robert at ID-Tasker
Legend
June 30, 2024

@Bedazzled532

 

I don't think padding will work - as font used in UI is "variable width".

 

But as the tab works - \u0009 - you can use it to align your results.

 

Robert at ID-Tasker
Legend
June 30, 2024

Can't check right now but maybe this will work:

 

number.toFixed(places);

 

or

 

Math.round(number * 1000) / 1000;

 

Bedazzled532
Inspiring
June 30, 2024

@Robert at ID-Tasker @rob day Hi Robert. Thanks for the reply.

Actually this the kind of output I am looking for:

 Thanks. I am not in a hurry. Plz do have a look at it whenever you get time. In the meantime, I will try the function which you have suggested.

Thanks.