Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
13

Is there any specific algorithm relationship between Letter spacing and font size in InDesign?

Explorer ,
Jun 13, 2023 Jun 13, 2023

68.png

ABCD Name

AD Name

ABD Name

 

I need to align the three above.

Some people may use grids, but that feature is difficult to use and I usually don't use it. It's better to use font spacing.

 

However, it is troublesome to adjust the font spacing. For example, when the font size becomes larger, I have to try every Letter spacing value.

Just want to ask: What is the relationship between font size and spacing, can we calculate it?

 

TOPICS
Bug , How to , Import and export , Scripting , Sync and storage
5.1K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 4 Correct answers

Community Expert , Jun 14, 2023 Jun 14, 2023

Hi @dublove5CFE, the issue here is converting tracking units (which I assume you are using to space out the A in the second line) into ruler units. Tracking is measured in em units which relate to the font size. The conversion factor is, 1000 / font size. Some fonts have differing sized em squares but Indesign seems to calibrate them all to 1000 units in terms of the UI and scripting API. You can see how it works in this script, that attempts to solve your problem.

 

 

/**
 * Letterspace Chars T
...
Translate
Community Expert , Jun 15, 2023 Jun 15, 2023

Hi @dublove5CFE, I have written a modified version that also sets the tab stop so that the tab character width is 5mm (you can adjust this in the script). I've also put the letterspacing into a function so it can be used for other purposes.

demo2.gif

Try this version and see what you think.

- Mark

 

/**
 * Letterspace Chars Before Tab
 * Script expects to have a text selection that includes
 * paragraphs that share a tab stop, and will and will
 * adjust tracking of characters before the tab character
 *
...
Translate
Community Expert , Jun 15, 2023 Jun 15, 2023

Hi @dublove5CFE, it sounds like it might be better in your case just to replace the tab with another character of your choice. Here is a re-write of the script that replaces tab with em space u+2003. You could choose another unicode space character.

- Mark

demo3.gif

 

/**
 * Letterspace Chars Before Tab
 * Script expects to have a text selection that includes
 * paragraphs that share a tab stop, and will adjust
 * tracking of characters before the tab character
 * so that the last characters before each 
...
Translate
Community Expert , Jun 16, 2023 Jun 16, 2023

Thank you Robert.

Translate
LEGEND ,
Jun 16, 2023 Jun 16, 2023

And @Peter Spier has been right from the beginning with his table suggestion ...

 

RobertTkaczyk_0-1686916857531.png

 

In this case script would be much simpler - convert text to table and then set width of the column(s) and insets of the cells ...

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 16, 2023 Jun 16, 2023

Thank you Robert.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 16, 2023 Jun 16, 2023

Ah! I think my misunderstanding is because in our demo, the text is Latin and the font proportionally-spaced which means that each character has different widths—there isn't such a thing as "one character width" in this case. But now I assume you are using Chinese characters. Here is a version of the script that just gets the tabWidth variable by measuring the width of the very first character. Perhaps this will be good for you.

- Mark

/**
 * Letterspace Chars Before Tab
 * Script expects to have a text selection that includes
 * paragraphs that share a tab stop, and will and will
 * adjust tracking of characters before the tab character
 * so that the last characters in each paragraph align.
 * It will set a tab stop so that the width of the tab
 * character equals `tabWidth` which is set to the first
 * character width.
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/is-there-any-specific-algorithm-relationship-between-letter-spacing-and-font-size-in-indesign/m-p/13861581
 */
function main() {

    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;

    var doc = app.activeDocument,
        text = doc.selection[0];

    if (
        text == undefined
        || typeof text.findGrep !== 'function'
        || text.contents == ''
    ) {
        alert('Please select some text and run script again.');
        return;
    }

    // find paragraphs with tabs
    app.findGrepPreferences = NothingEnum.NOTHING;
    app.findGrepPreferences.findWhat = '^[^\\t]*\\t';
    var found = text.findGrep();

    var tabWidth = found[0].characters[0].endHorizontalOffset - found[0].characters[0].horizontalOffset;

    // store the horizontal position
    // of the right-most tab
    var positions = [],
        maxPosition = -Infinity,
        tabPosition = 0

    for (var i = 0; i < found.length; i++) {
        found[i].tracking = 0;
        positions[i] = found[i].insertionPoints[found[i].insertionPoints.length - 2].horizontalOffset;
        if (positions[i] > maxPosition) {
            maxPosition = positions[i];
            left = found[i].insertionPoints[0].horizontalOffset;
            tabPosition = found[i].insertionPoints[found[i].insertionPoints.length - 1].horizontalOffset;
        }
    }

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

        var tabStops = found[i].tabStops;

        // remove all tab stops in alignment area
        for (var j = tabStops.length - 1; j >= 0; j--)
            if (tabStops[j].position <= Math.max(maxPosition + tabWidth, tabPosition))
                tabStops[j].remove();

        // set a tab stop to match the tabWidth
        tabStops.add({ position: maxPosition - left + tabWidth });

        if (
            positions[i] !== maxPosition
            && found[i].characters.length > 1
        )
            // letterspace the characters before tab
            letterspaceToWidth(found[i].characters.itemByRange(0, found[i].characters.length - 2), maxPosition - found[i].insertionPoints[0].horizontalOffset);

    }

};

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Space Chars Before Tab");


/**
 * Applies tracking to text so that
 * the width of the text will match
 * with `width` parameter supplied.
 * Assumptions:
 * - text is justified left
 * - text is uniform point size
 * - text doesn't span multiple lines
 * @author m1b
 * @version 2023-06-16
 * @Param {Text} text - an Indesign text object.
 * @Param {Number} width - the desired width in pts.
 */
function letterspaceToWidth(text, width) {

    if (!text.hasOwnProperty('insertionPoints'))
        return;

    const emSquare = 1000;

    var left = text.insertionPoints[0].horizontalOffset,
        right = text.insertionPoints[text.insertionPoints.length - 1].horizontalOffset,
        chars = text.characters.itemByRange(0, text.characters.length - 2).characters,
        delta = width - (right - left);

    for (var i = 0; i < chars.length; i++)
        chars[i].tracking = (delta / chars.length) * (emSquare / chars[i].pointSize);

};

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 16, 2023 Jun 16, 2023

just

I explained in detail that I want the spacing to automatically be the width of one character (full or half width)

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 16, 2023 Jun 16, 2023

Did my last script do what you want?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 16, 2023 Jun 16, 2023

I tried, but I couldn't find where to modify the interval value.

This interval should vary with font size.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 16, 2023 Jun 16, 2023

In the last script, it uses the width of the first character (eg. the A in the demo file).

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 16, 2023 Jun 16, 2023

Difficult to control.

Can't there be three options?

Tracking=1 full width word width

or

Tracking=1 half width word

or

Tracking="5" mm

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 01, 2024 Feb 01, 2024

I replied to the end.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 16, 2023 Jun 16, 2023

Sorry, it's a bit messy~ I replied incorrectly to another person.

Should add a version number to the script.

Perhaps this is the most applicable.

How to add the situation of to it, which is a colon (:)

 

 

  app.findGrepPreferences.findWhat = '^[^\\t]*\\t';

 

 

 

There are generally two situations:

① Tab separation

② Separate with ':or :', just align the colon here

 

This width will change

5mm at 12pt font size

But when it comes to size 30, it needs to be adjusted to 8mm.

I hope it is automatic.

I want to keep the tab, always one full width word wide

The gap is always the width of a full width character (or half width character)

585.png

 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 16, 2023 Jun 16, 2023

So, would it help to have a function that set the tabWidth based on the point size? It would be like this:

 

function interpolateLinear(n) {
    var v = [
        [12 /* font size --> */, 5 /* mm output*/],
        [25 /* font size --> */, 8 /* mm output*/],
    ];
    return v[0][1] + ((n - v[0][0]) / (v[1][0] - v[0][0])) * (v[1][1] - v[0][1]);
};

 

 This is configured to return 5mm when given 12pt font size and 8mm when given 25pt font size. It would interpolate/extrapolate when given other values of n, eg. 30pt font size would return 9.15mm,  font size 9pt would return 4.3mm.

What do you think?

- Mark

 

Like this:

/**
 * Letterspace Chars Before Tab
 * Script expects to have a text selection that includes
 * paragraphs that share a tab stop, and will and will
 * adjust tracking of characters before the tab character
 * so that the last characters in each paragraph align.
 * It will set a tab stop so that the width of the tab
 * character equals `tabWidth`, which is based on the
 * function `tabWidthForPointSize`.
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/is-there-any-specific-algorithm-relationship-between-letter-spacing-and-font-size-in-indesign/m-p/13861581
 */
function main() {

    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;

    var doc = app.activeDocument,
        text = doc.selection[0];

    if (
        text == undefined
        || typeof text.findGrep !== 'function'
        || text.contents == ''
    ) {
        alert('Please select some text and run script again.');
        return;
    }

    // find paragraphs with tabs
    app.findGrepPreferences = NothingEnum.NOTHING;
    app.findGrepPreferences.findWhat = '^[^\\t]*[:\\t]';
    var found = text.findGrep();

    var tabWidth = new UnitValue(tabWidthForPointSize(found[0].characters[0].pointSize)).as('pt');

    // store the horizontal position
    // of the right-most tab
    var positions = [],
        maxPosition = -Infinity,
        tabPosition = 0

    for (var i = 0; i < found.length; i++) {
        found[i].tracking = 0;
        positions[i] = found[i].insertionPoints[found[i].insertionPoints.length - 2].horizontalOffset;
        if (positions[i] > maxPosition) {
            maxPosition = positions[i];
            left = found[i].insertionPoints[0].horizontalOffset;
            tabPosition = found[i].insertionPoints[found[i].insertionPoints.length - 1].horizontalOffset;
        }
    }

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

        var tabStops = found[i].tabStops;

        // remove all tab stops in alignment area
        for (var j = tabStops.length - 1; j >= 0; j--)
            if (tabStops[j].position <= Math.max(maxPosition + tabWidth, tabPosition))
                tabStops[j].remove();

        // set a tab stop to match the tabWidth
        tabStops.add({ position: maxPosition - left + tabWidth });

        if (
            positions[i] !== maxPosition
            && found[i].characters.length > 1
        )
            // letterspace the characters before tab
            letterspaceToWidth(found[i].characters.itemByRange(0, found[i].characters.length - 2), maxPosition - found[i].insertionPoints[0].horizontalOffset);

    }

};

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Space Chars Before Tab");


/**
 * Applies tracking to text so that
 * the width of the text will match
 * with `width` parameter supplied.
 * Assumptions:
 * - text is justified left
 * - text is uniform point size
 * - text doesn't span multiple lines
 * @author m1b
 * @version 2023-06-16
 * @Param {Text} text - an Indesign text object.
 * @Param {Number} width - the desired width in pts.
 */
function letterspaceToWidth(text, width) {

    if (!text.hasOwnProperty('insertionPoints'))
        return;

    const emSquare = 1000;

    var left = text.insertionPoints[0].horizontalOffset,
        right = text.insertionPoints[text.insertionPoints.length - 1].horizontalOffset,
        chars = text.characters.itemByRange(0, text.characters.length - 2).characters,
        delta = width - (right - left);

    for (var i = 0; i < chars.length; i++)
        chars[i].tracking = (delta / chars.length) * (emSquare / chars[i].pointSize);

};


/**
 * Returns a width string (mm)
 * given a point size (pt).
 * @Param {Number} n
 * @Returns {String}
 */
function tabWidthForPointSize(n) {
    var v = [
        [12 /* point size --> */, 5 /* mm output*/],
        [25 /* point size --> */, 8 /* mm output*/],
    ];
    return (v[0][1] + ((n - v[0][0]) / (v[1][0] - v[0][0])) * (v[1][1] - v[0][1])) + 'mm';
};
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 17, 2023 Jun 17, 2023

This is too complicated.

You still need to try different values and modify them.

 

The font size will not be fixed.

The font size may not be 25pt or 12pt, it is variable, I am just giving an example.

 

What I think is that the gap will adapt to the width of one character based on the font size (there is already a version where the tab is converted to a space, but it's a bit strange without the tab).

 

It would be great if the gap (1 full or half width character) could automatically adapt to the font size.

The user only needs to choose whether it is a full width or half width, and no other operations are required.

 

Of course, it would be more perfect to reserve the ability to set specific values.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 19, 2023 Jun 19, 2023

Did you try that script? It does return a width based on the font size (for *any* font size).

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 01, 2024 Feb 01, 2024

hello@m1b 

There are still some minor issues with this script.

Could you please take a look again? 

Thank you very much

More important issues:

If you run it for the second time, it may not work. The reason is that it cannot clear the first "tab" setting. Perhaps the script should be initialized before starting to run each time.

2. Cross column, cross page operation, script error.

3. There is an empty line between the selected areas, or there is no "tab" in the line, resulting in an error in the script.

er.jpg

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
May 20, 2024 May 20, 2024

@m1b 

Hello, great M1B,
Thanks, I finally found you.

Help test this.
After running the script above, TAB did not align to the widest position.
There is no alignment before and after, it seems that it is not the width of a character.
It seems that there is a space in front of TAB, or an error occurs without a tab. The running script (two columns together) and cross -page (two pages together) will also make an error.

 

The script sometimes makes an error after repeated operation. It may be that the old TAB value is not cleared before each operation. At the same time, the word distance should be removed before performing the follow -up operation.

 

In addition, in the process of using it, I found that using TAB as a interval is more convenient, and the space -based interval is not conducive to later modification.
It is hoped that the width of the TAB defaults a full -angle word, but it can be customized and modified, such as 2 full -angle or 1 half -angle character interval.
The full -angle is targeted at Asian text and half -horn for English.
Thank you very much ~

align.png

 

 

If there is no TAB in the selection, it will not be aligned.

 

As if:

This situation should skip the line without TAB

I was right when I aligned the first part.
When I aligned the second part, I found that there was no reference object, so I chose the first part together, and the result could not be aligned.

There is no tab line.png

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 11, 2024 Jun 11, 2024

Hi @dublove, can you please post a .indd document that shows on page 1, and example BEFORE script and on page 2 the same example AFTER script, so I can understand exactly what you want. I'm very confused.

- Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jun 11, 2024 Jun 11, 2024

688.png

 

Explain more details in the ID file
Thanks!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 11, 2024 Jun 11, 2024

Thanks @dublove but please set up a demo .indd document how I asked. I don't need any expanation, just BEFORE and AFTER. It is your job to make sure the BEFORE and AFTER accommodate all the different possibilities you want to cover. Honestly though, this is getting too complicated to warrant a free script.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jun 11, 2024 Jun 11, 2024

Sorry, at the beginning, I misunderstood what you mean

It is mainly possible to skip the line that does not include TAB.
It is better to solve the problem of crossing two columns and errors across two pages.
Others, it doesn't matter.
Thanks

666.png

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 14, 2024 Jun 14, 2024

Hi @dublove, I've re-written script to fit your demo document. Give it a try and let me know how it goes.

- Mark

 

 

/**
 * Letterspace Chars Before Tab.js
 * Script expects to have a text selection, and will adjust
 * tracking of characters before the tab character so that
 * the last characters before each tab align horizontally.
 *
 * Notes and assumptions:
 * - Script assumes each paragraph is a single line.
 * - Script will remove all tracking on text.
 * - Tab stop is set according to maximum width of characters
 *   before tab, plus an em space width.
 * - Some formatting will distort result, eg. first line indent.
 * - Script will ignore a colon character directly before the tab.
 *
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/is-there-any-specific-algorithm-relationship-between-letter-spacing-and-font-size-in-indesign/m-p/13861581
 */
function main() {

    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
    const EM_SPACE = '\u2003';

    var doc = app.activeDocument,
        text = doc.selection[0];

    if (
        text == undefined
        || typeof text.findGrep !== 'function'
        || text.contents == ''
    )
        return alert('Please select some text and run script again.');

    if ('TextFrame' === text.constructor.name)
        text = text.texts[0];

    var paras = text.paragraphs.everyItem().getElements();

    // set tab stop at longest tab
    var zeroPos = -Infinity,
        tabStopPos = -Infinity,
        justifyPos = -Infinity,
        maximums = { tabStopPos: tabStopPos, justifyPos: justifyPos },
        metrics = [],
        findFirstTab = /\t/,
        offset = paras[0].leftIndent + paras[0].firstLineIndent,
        offset,
        match;

    for (var i = paras.length - 1; i >= 0; i--) {

        match = paras[i].contents.match(findFirstTab);

        if (null === match)
            continue;

        // remove tracking
        paras[i].tracking = 0;

        // remove tab stops
        while (paras[i].tabStops.length)
            paras[i].tabStops[0].remove();

        // replace first found tab with em space
        paras[i].characters[match.index].contents = EM_SPACE;

        // start of line
        zeroPos = paras[i].characters[match.index].lines[0].characters[0].horizontalOffset;
        // position of tab stop
        tabStopPos = paras[i].characters[match.index + 1].horizontalOffset;
        // justify position
        justifyPos = paras[i].characters[match.index].horizontalOffset;

        if (maximums.tabStopPos < tabStopPos - zeroPos) {
            // update maximum tab position
            maximums.tabStopPos = tabStopPos - zeroPos;
            maximums.justifyPos = justifyPos - zeroPos;
        }

        // keep some metrics for each paragraph
        metrics[i] = {
            tabIndex: match.index,
            zeroPos: zeroPos,
            justifyPos: justifyPos,
            hasColon: ':' === paras[i].characters[match.index - 1].contents,
        };

        // return text to normal tab
        paras[i].characters[match.index].contents = '\t';

    }

    // add a tabStop at the maximum
    text.tabStops.add({
        alignment: TabStopAlignment.LEFT_ALIGN,
        position: maximums.tabStopPos + offset,
    });

    // now force justify the text before the tab
    for (var i = metrics.length - 1, charactersBeforeTab; i >= 0; i--) {

        if (!metrics[i] || !metrics[i].tabIndex)
            continue;

        rightIndex = metrics[i].tabIndex - 1;

        if (metrics[i].hasColon)
            rightIndex--;

        charactersBeforeTab = paras[i].characters.itemByRange(0, rightIndex);

        // space out the characters before the tab
        letterspaceToWidth(charactersBeforeTab, maximums.justifyPos);

    }

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Letterspace Characters Before Tab');

/**
 * Applies tracking to text so that
 * the width of the text will match
 * with `width` parameter supplied.
 * Assumptions:
 * - text is justified left
 * - text is uniform point size
 * - text doesn't span multiple lines
 * @author m1b
 * @version 2023-06-16
 * @param {Text} text - an Indesign text object.
 * @param {Number} width - the desired width in pts.
 */
function letterspaceToWidth(text, width) {

    if (!text.hasOwnProperty('insertionPoints'))
        return;

    const EM_SQUARE = 1000;

    var left = text.insertionPoints[0].horizontalOffset,
        right = text.insertionPoints[text.insertionPoints.length - 1].horizontalOffset,
        chars = text.characters.itemByRange(0, text.characters.length - 2).characters,
        delta = width - (right - left);

    for (var i = 0; i < chars.length; i++)
        chars[i].tracking = (delta / chars.length) * (EM_SQUARE / chars[i].pointSize);

};

 

EDIT 2024-06-15: added code to handle a colon character directly before the first tab (see @dublove's comment below).

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jun 14, 2024 Jun 14, 2024

Hi~ m1b

The 2024-6-14 version you provided, I tested it, and seemed to solve all the problems.
Too perfect!
Thank you so much!
You are too great.
The best wish for you.
I wish you good health, happy every day, congratulations to getting rich.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Sep 15, 2024 Sep 15, 2024
LATEST

@m1b 

Hi m1b, I an sorry to trouble you again.

I still want this colon(:) to be directly aligned.
: Occupies one word width.
Some customers like to use colons.
When the workload is heavy, using regular still takes up a lot of time.

Thank you very much.

 

colon align.png

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jun 13, 2024 Jun 13, 2024

Hello, M1B
The new samples I officer are still wrong?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 14, 2024 Jun 14, 2024

Hi @dublove that demo document is perfect. Thanks.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jun 14, 2024 Jun 14, 2024

The script is perfect, It seems to solve all the problems that have been discovered.
sorry.
I suddenly remembered another situation:
Sometimes ":" as a reference.
Like below:

冒号.png

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines