Regular update (March 24, 2026.) Global re-generation of the core structure, including recent fixes and additions.
- File: Added optional
len(uint) argument in$$.File.readBinary(file,?len)— See 260201. - Ext/string: Added optional
AS_HEXA(bool) argument inString.prototype.toBytes()— See 260131. Improved security ofString.fromBase64()andString.prototype.toBase64()— See 260130. Added Adler-32 algorithm:myString.adler32()yields the uint32 checksum. - Env and ESTK more accurately managed — See 260129.
- Log: Calling
$$.Log.push()with no argument writes an empty line.
(Other changes do not affect the core branch. See previous log entries regarding updated extra modules.)
- ArrayAs2D: Added various features, public methods and customization options relative to angle orientation and the swap operator (
~). See the public methodsswapSimple(),isSwapSimple(),swapOrthogonal(),angleOrientation(),isClockwise()for more detail. The new methodequalNumbers(a,b)(epsilon-aware utility for comparing numbers) is a shortcut of the internal~.EQUA(a,b), it may be invoked from a client module to keep external numeric routines consistent withArrayAs2Dapproximations.
- ArrayAs2D: Added the public method
getEpsilon()(returns the current epsilon-machine). Bugfix:1/Uwas returning[0,0]instead of the normalized vector when one of the coordinates were 0. Corrected a few typos.
-
The ArrayAs2D module now supports the
%operator. Allows to quickly apply a numeric function to each coordinates:// Basic usage: `fct % [x,y]` var xy = [-2,-3]; var res = Math.abs % xy; // => res :: [2,3] ; xy unchanged // If you use `[x,y] % fct` instead (function as 2nd operand) // then the array is internally modified: var ref = [-2,-3]; ref % Math.abs; // now ref contains :: [2,3]Any function that takes a number and returns a number is fine, including your own functions. The example above uses
Math.absto yield the absolute value of each coordinate.
⚡ New Implementation of ZDeflate (compressors) and ZInflate (decompressors)
- Supports “raw DEFLATE” format, ZIP, GZIP, and ZLIB comp/decomp with proper checksums (CRC32/ADLER32). ZIP support includes UTF-8 filename handling via the
zip()method. - All public methods accept strings, arrays, or File objects — with a requirement to ensure input is byte-level (e.g., UTF8-encoded text).
- Automatically leverages
app.packageUCF()/app.unpackageUCF()for large files (much faster) and falls back to internal algorithms for smaller inputs or when InDesign's DOM methods are unavailable. - In
$$.ZDeflate, implements a binary-search-based prefix matching algorithm. Default settings (maxLen=10, maxDis=4096) deliver ~40% compression ratio on ASCII streams in optimal time. - Supports both dynamic and static Huffman trees. Dynamic mode uses a package-merge algorithm for optimal code length generation, while static mode uses precomputed canonical maps for speed.
- The
ForceInternalflag (public) allows the client script to bypasspackageUCF()/unpackageUCF()for testing (or in pure ExtendScript environments.) - Comprehensive error messages and fallback logic ensure reliable operation across different environments.
→ Go to the respective NOTICE and source for more detail on the public API: ZDeflate, ZInflate.
Use Cases:
- File format processing (e.g. PNG chunks).
- High-performance compression in InDesign scripts.
- Cross-platform compression with fallbacks for legacy environments.
→ For testing both modules in a basic zip/unzip task: ZDeflate_ZInflate_Test.jsx.
- File: Added an optional
len(uint) argument in$$.File.readBinary(file,?len). When supplied,readBinaryreturns at mostlenbytes instead of the entire file. Useful when you only need to check the ‘signature’ of a binary file.
- Added an optional
AS_HEXA(bool) argument inString.prototype.toBytes(). A purely convenient flag for generating hexa strings (like['03','FF','2C'...]) instead of pure int8 elements[3,255,44...]. If your string bin is intended to encode bytes, you can easily inspect data using e.g.bin.toBytes(true).join(' '), which yields a typical byte stream of the form"03 FF 2C...".
- Improved security of
String.fromBase64()andString.prototype.toBase64()in Ext/string.
- Env and “estk entry point” have undergone a few adjustments in order to make scripts running from ExtendScript ToolKit more accurately managed. When you create an IdExtenso script that should run outside of InDesign, use
#include 'path/to/$$.estk.jsxinc'as your entry point. As long as InDesign DOM features are not involved in your project, this should work as expected. The present update concerns$$.Envmethods related to this particular option:$$.Env.isToolKit(0|1) tells whether your script runs in “estk mode”,$$.Env.summary()now returns information better suited to the ESTK environment.
- Log: Slight improvements. Ability to call
$$.Log.push()without argument (forcibly generates an empty line in the log.) This is equivalent to$$.Log.push("").
- Added Adler-32 checksum algorithm to Ext/string. Use
myString.adler32()to get the uint32 checksum.
- Updated the ByteStream class with new public methods and helpers (
clone(),copy(), etc). See the code for more detail.
- Added Canadian Aboriginal Syllabics Extended-A range (
U+11AB0..U+11ABF) to Linguist/WSYS.
- New generation of MetaCollator data (based on UCA
allkeys-16.0.0anddecomps-16.0.0) leading to a new set of collator.keys. - Automatic re-generation of internal Collator data (
~.WMAP,~.MTCH,~.ZROS, etc).
- Updated Unicode module data with respect to the freshest unicode.org/Public/UCD files (Sun, 25 Aug 2024.) Changes apply to
~.CATG(Unicode General Categories),~.SCRI(Unicode Scripts) and~.UBLK(Unicode Character Blocks). The following new blocks have been added:
[ 0x105C0, 0x105FF, "Todhri" ]
[ 0x10D40, 0x10D8F, "Garay" ]
[ 0x10EC0, 0x10EFF, "Arabic Extended-C" ]
[ 0x11380, 0x113FF, "Tulu-Tigalari" ]
[ 0x11380, 0x113FF, "Tulu-Tigalari" ]
[ 0x116D0, 0x116FF, "Myanmar Extended-C" ]
[ 0x11B00, 0x11B5F, "Devanagari Extended-A" ]
[ 0x11BC0, 0x11BFF, "Sunuwar" ]
[ 0x11F00, 0x11F5F, "Kawi" ]
[ 0x13430, 0x1345F, "Egyptian Hieroglyph Format Controls" ]
[ 0x13460, 0x143FF, "Egyptian Hieroglyphs Extended-A" ]
[ 0x16100, 0x1613F, "Gurung Khema" ]
[ 0x16D40, 0x16D7F, "Kirat Rai" ]
[ 0x1CC00, 0x1CEBF, "Symbols for Legacy Computing Supplement" ]
[ 0x1D2C0, 0x1D2DF, "Kaktovik Numerals" ]
[ 0x1E030, 0x1E08F, "Cyrillic Extended-D" ]
[ 0x1E4D0, 0x1E4FF, "Nag Mundari" ]
[ 0x1E5D0, 0x1E5FF, "Ol Onal" ]
[ 0x2EBF0, 0x2EE5F, "CJK Unified Ideographs Extension I" ]
[ 0x31350, 0x323AF, "CJK Unified Ideographs Extension H" ]
Partial patch (June 19, 2025.)
InDesign 20.4.0 has introduced bugs of exceptional gravity weighing on file and folder management in macOS environments. Most are slated to be fixed by Adobe in an upcoming 20.4.1 release. IdExtenso 2.50619 essentially consolidates the displayName property access feature that has become erratic. These fixes address various core elements with no negative impact on previous (or future) versions of ExtendScript.
The main new feature to integrate into your code, in order to make it more robust, is the call to the File.getDisplayName() method — resp. Folder.getDisplayName() — so you can safely retrieve the raw name (i.e., without URI notation) of a file or folder. This ensures that your script works in all versions of InDesign supported by IdExtenso, including v20.4.0.
Note: On the other hand, the bug affecting (File|Folder).execute() is not fixed here. (It is workable through AppleScript, but the effort seems a bit excessive for a version of InDesign that's due for an imminent update.)
- Fixed the
CLNEroutine (object cloner) in the Root module. Due to recent changes in $$.JSON defaults, the cloner must explicitly set therichArroption to1in order to fully recreate rich arrays. Here is the patched code:
return callee.µ.JSON.eval(callee.µ.JSON.lave(o,
{
spacing: 0, // single line
domAccess: 0, // default option
forceObj: 0, // default option
cycleCheck: 0, // faster (default option)
richArr: 1, // regenerate rich array (IMPORTANT) [FIX250507]
bypassHooks: 0, // default option
skipUndefined: 0, // default option
}));
Important update (March 20, 2025.) Global re-generation of the core structure, including recent fixes and additions.
- Enhanced JSON module — see detail in 250319 entry.
- Ext/folder: Restricts Folder's
createpatch to macOS ID 20.1 since Adobe has fixed the bug in v20.2. - Ext/string: Added
String.fromBytes(<array>)andString.prototype.toBytes().
(Other changes do not affect the core branch. See previous log entries regarding updated extra modules.)
- BigInt and Complex classes now use the regular
$$.JSON.registerHook(...)method exposed by the public API. (This is the 'clean' way to declare JSON hooks, it avoids accessing the private zone from the outside and manually setting obscure\x02...keys.)
- JSON. Reworked in depth, added many new
$$.JSON(...)options (cycleCheck,richArr,bypassHooks,skipUndefined,symLayout). AddedregisterHook()andunregisterHook()utilities. See the source code and the NOTICE for further detail.
⚠ Default behaviors have been changed regarding cycle detection, “rich arrays”, etc. If you plan to supply a cycling object to$$.JSON(), make sure you set thecycleCheckoption to 1 to prevent infinite loop!
- ByteStream. Huge refactoring of the
$$.ByteStreamclass including bug fixes, enhancements and important additions. Added'FXP'/'UFX'tags (signed/unsigned “16.16 Fixed Point”), and'F2D'for “2.14 fixed numbers”. TheHEXtag (hex strings) has been extended to support multibyte strings like"F3A027FF"(then identified to the scheme"HEX*4"). The main encoding/decoding routine — called frompeek(),read(), andwrite()— now handles consistently special parameter values like<TAG>*0(zero count) or<TAG>:0(zero key). Read the notice for further information on these special cases. The scheme processor also throws a syntax error when it fails to parse your code… instead of silently eating irrelevant bytes!
- Added
String.fromBytes(<array>)andString.prototype.toBytes()to the core extension Ext/string. These methods allow to quickly translate strings from/to sequence of bytes (unsigned integers ranging in 0..255). - The internal
B2ACmap of theunaccentmethod (String.prototype.unaccent) has been moved in a dedicated subdirectory for readability.
- Added TinyInflate, a lightweight GZIP-inflate (=decompression) module.
- Added Clipboard, a lightweight module that allows your script to get and set the clipboard (text only). Use
var str = $$.Clipboard.get()(or justvar str = $$.Clipboard()) for getting the string, and$$.Clipboard.set(someString)to load any string in the cb. Interesting feature: those methods still work in modal state since they do not send active DOM commands to InDesign.
- Linguist. Slight adjustment of the ISO subset regarding “Norwegian (Bokmål)” (
no) vs. “Norwegian Bokmål” (nb). Since the codenbis expected in the InDesign ICU string (“nb_NO”), it is desirable to set it as the default (instead ofno). Semantically, Norwegian (Bokmål) means “Norwegian language, Bokmål implied”, while Norwegian Bokmål is the explicit name of that very language. Modules like StopWords or Collator usually display “Norwegian Bokmål” (nb) vs. “Norwegian Nynorsk” (nn). They should then invoke the respective ISO codes (and abandonno.) - MetaCollator. Cleaner
$$.LING.yalt.jsxresoutput (sorted list.) - Collator.
$$.Collator's tailoring rules andLINGmap have been updated from$$.MetaCollator. This basically reflects theno→nbchange in$$.Linguist: the Norwegian Bokmål language should now be accessed from thenbkey in all scripts that rely on$$.Collator. (In case your client script still uses the codeno, you can either invoke $$.Linguist aliases or change it manually tonb.)
- Ext/folder applies a patch to the native method
Folder.prototype.create()—which no longer works as expected on macOS/InDesign 20.1.
- TextParcels: Added a special format in the
pageMatchmethod: you can now specify the first (resp. last) page of a section usingMySecIdentifier:<(resp.MySecIdentifier:>).
- Collator: Changed the logic of the
~.TMAProutine: when processing a>noperator we don't want to strictly erase the remaining bits, since this will lead to zero weighting at the corresponding level(s). This is not what is usually expected. Tailoring rules likeA << à(aka'à': '>2A') orb <<< B(aka'B': '>3b') are not intended to reset to zero the L2 (resp. L3) bits. Instead, we want a minimal non-zero base to be set, allowing us to increase extra bits in the1111 1111 1111 1xxx 2222 222y 3333 3zzVstructure. Zero weighting would lead to entirely bypass L2 or L3 data inWG_routines, hence tailored languages cannot properly sort items based on L2 or L3 differences. The present fix should solve this issue. - Added the distinct Cyrillic Ёё letter (Yo) in the Russian language, thanks to Mikhail Ivanyushin who reported the issue (see forum.rudtp.ru/(...)/#post-1412025). According to en.wikipedia.org/wiki/Russian_alphabet, although “the letter ⟨ё⟩ (…) is not always distinguished — from ⟨е⟩ — in written Russian”, the dictionary “makes difference between е and ё”, so Ёё (U+0401/U+0451) shouldn't be treated in
$$.Collatoras a diacritical variant of Ее (U+0415/U+0435). ~.TLRM now provides a dedicated set of tailoring rules for Russian (rukey). The modification was processed from MetaCollator after adding the custom file tailoring/$$.ru.jsxres.
(The above changes will lead to regenerating the source code of SmartSort, IndexMatic3, and other InDesign scripts built upon $$.Collator.)
- ArrayAs2D: This lightweight utility module provides custom operators for 2D arrays:
[x1,y1]+[x2,y2],k*[x,y], etc.
Regular update (June 26, 2024.) Global re-generation of the core structure, including recent fixes and additions.
- SUI/mini: Improved
forceRedrawfunction (now dealing with empty groups.) - JSON: Custom error detection in
$$.JSON.lave().
(Other changes do not affect the core branch. See previous log entries regarding updated extra modules.)
- JSON: Added a custom error detection in
$$.JSON.lave()(thrown if the argument is not a string, or is empty). This bypasses the meaningless native error message.
- Yalt: Added the public method
translate(inputArr, CHANGE_IN_PLACE). This utility runs Yalt on an entire array (theinputArrargument). The BooleanCHANGE_IN_PLACE(false by default) decides whether the incoming array is to be internally modified. Useful if you have an array of unlocalized strings and need to get it quickly localized (e.g. to pass in final strings in a UI Listbox, etc.)
- Dom.UIColor: New DOM module making easier to address
UIColorsenumerators and alternate[r,g,b]colors. Use theencode/decodemethods to manage color assignments and translate data in common#RRGGBBform.
ColorPalette(Factory): New factory component that automatically shows/hides a color palette over some ‘client’ control and allows the user to select a new color. See TestColorPalette.jsx for a quick demo.
- Dom.Space: Bugfix applied to the
convert()method: thexyOutputargument was not considered (due to a typo) and led to a runtime error. Solved.
- AnyScript/initialize: Improved the parsing of the incoming settings object. Since every constant setting (cf $$.Settings module) can be declared in two alternate ways,
{ ..., _MYKEY:data, ... }(key prefix ‘_’) in the root branch{ ..., CONST:{ ..., MYKEY:data, ... }, ... }(no ‘_’ prefix) in the dedicatedCONSTbranch
it is safer (and required!) to explore each option when extracting existing settings from the declarator object.
- Dom.TextParcels:
getSamplesoptions now support a boolean property,unionStyles, that tells whether target Character Styles and target Paragraph Styles (cfthis.options.csIdsandthis.options.psIds) must be processed separately (UNION) instead of selecting the ranges they have in common (INTERSECTION). INTERSECTION was and remains the default behavior.
- Dom.Space. Since InDesign CS6, it is no longer guaranteed that the upper left corner of a page coincides with the origin of its coordinate space. In other words
myPage.resolve( [ [0,0], CoordinateSpaces.innerCoordinates ], <someSpace> )[0]may return coordinates that differ frommyPage.resolve( AnchorPoint.topLeftAnchor, <someSpace> )[0]. This situation occurs particularly when the dimensions of a page have been modified or, more generally, when a document shares pages of different sizes. This can become an annoying problem if your script has to rely on Page coordinates (assumed to be) relative to the upper left corner, that is, the “top-left anchor point” of the bounding box of the page. To circumvent these inconsistencies,$$.Dom.Spacenow provides a specialfromPG(<pge>, <space>)initializer that differs fromfromXY(<pge>, <space>)in the following way
Initialize the `convert` method so that it takes as input arguments actual (x,y) coordinates, in pt,
relative to the upper left corner of `pge` in the perspective of `space`. With space=='inner'
(default), this amounts to shift the origin accordingly (=translation). If a parent space is
considered (spread, board) the page bounding box is taken in that perspective, orientation and
scaling, and the incoming coordinates are then expected to be consistent with that space,
relative to the custom origin.
This new method allows you, for example, to safely convert what we may call “true page coordinates” into any other system (rulers, UV, etc) without having to worry about the (X,Y)-shift possibly occurring in the actual Page Coordinate Space. (As a general rule, better is to trust page bounding box rather than page inner space. $$.Dom.Space applies that very principle for computing, behind the scenes, the correct matrix.)
Edit(Factory): Had to inhibit Enter keydown handling with multiline edits (in order to preserve their legacy behavior).- Go to TestEditAndStepper.jsx for testing various Edit/EditInteger examples.
Edit(Factory): Fixed a tiny bug in the watcher callback — see also 231020 — recallingthis.valueToText(nv)was required in all cases. Added akeydownevent handler that inhibits the Enter key when the user is editing the text.EditInteger(Factory): Various improvements. Added a publicstep()method (allows to increase or reduce the value based on thedelta/jumpsettings).ScriptUI.EditIntegerFactorynow has a staticGroup()function that can integrate a stepper with the EditInteger component.ScriptUI.StepperFactoryis required then.- Added the
Stepper(Factory), a nice Up/Down stepper for Edit components or similar widgets.
- Unit now conditionally includes a convenient YALT package covering measurement units (names and abbr.) in six languages.
- SUI/mini:
forceRedrawnow invokes the specialhide(); show();trick when it encounters an empty group. (Works in InDesign CC/CS.)
- Unit module and UnitData class updated, now supporting a special MICRO_POINTS unit (abbr.
µp) that represents one millionth of a point: 1 pt == 1,000,000 µp. This IdExtenso-specific unit is generally not exposed to users, it allows metric quantities to be stored with high precision as pure JS integers, that is, magnitudes betweenNumber.MIN_SAFE_INTEGERandNumber.MAX_SAFE_INTEGER(the maximum absolute value in micropoints is then 9,007,199,254,740,991 — which is more than sufficient to express any valid metric quantity in InDesign.) Managing the measurements/settings of your script primarily in micropoints avoid rounding errors with floating point numbers, while$$.Unitcan still convert and display those values in any other user-friendly unit.
- SUI/mini: Added the optional 2nd argument
TRY_NOTIFYinScriptUI.forceRedraw. In some environments—mostly CC versions—the commandmyWidget.notify('onDraw')might work, although not 100% safe. TheTRY_NOTIFYflag makesforceRedrawtry this approach first, using the schemetry{ wg.notify('onDraw'); retval=1; }catch(_){ retval=0; }. If it fails, the regularforceRedrawstrategy is used.
Edit(Factory): Slight change in the watcher callback, thevaluekey is now re-normalized even ifthis.textalready matchesthis.valueToText(nv). Purpose: make sure that setting a value always results in the expected type in case your custom value-to-text converter also coerces foreign value types (e.g string → number). ThetextToValue(…)method is invoked to forcibly returnnvin the valid value type.- Yalt: Added the key
"Invalid numeric value"in the resource file. - Unit: The static
$$.Unit.DecimalCharproperty is now predefined asNumber.DecimalChar, which sounds more consistent (you don't have to manually adjust it unless your code forcibly uses a custom locale). Of course it is still possible to explicitly re-assign$$.Unit.DecimalCharwhen your script starts up (or whenever needed.)
- Unit: Fixed wrong formatting of zero in
$$.Unit.format()when 'pc' or 'ci' unit is involved withUseTypographicNotationturned on. E.g.0.5 pc→0p6.
Important update (Oct 8, 2023.) Global re-generation of the core structure, including recent fixes and additions.
- Env: Added the
forceUnit()method (also callable from$$), allows a script to work safely in whateverMeasurementUnitsmode. Supportsfalseas direct arg to get units instantly restored.$$.forceUnit(-1)can be used in CC/CS6/CS5 (while remaining transparent in CS4): turns your script inAUTO_VALUEmode, which makes sense if the code is designed to deal with ruler units rather than some preferred script unit. - Root/help. Ability to preselect a module while showing IdExtenso's API: just call
$$.help(<someModule>)(first argument added), e.g.$$.help($$.JSON). By default$$.help()still preselects the$$item (first of the list). - JSON. Fixed reported issue with augmented
Array.prototype. - Ext/string. Bugfix, makes
String.prototype.indexOf(...)still reliable when the string contains"\u0000".
(Other changes do not affect the core branch. See previous log entries regarding updated extra modules.)
- Dom.TextParcels: Fixed an issue with continued footnotes when containing spanned tables or similar empty-line structures.
- Improved the MultiStream class (used by
Dom.TextParcels):appendcan now digest most not-well formedEndnoteRanges, based on a more general detection pattern:/\uFEFF[^\u0004\uFEFF]{0,2}\u0004/. This reduces the cases whereDom.TextParcelsfails to parse document endnotes (in particular, imported notes that tend to alter the regularU+FEFFU+0004sequence.) Note that the characterU+0004(endnote reference marker) is still required at the end of the pattern. If the user manually removes note numbers, the algorithm cannot work as expected. In such a case,appendnow provides a safer fallback mechanism that simply ignores endnote IDs: input data is then treated as the text stream of a basicTextFrame.
- Dom.TextParcels: Enhanced
forceSectionPrefixin two ways:
1. the option now supports three values0(auto, default),+1(forcibly add the section prefix),-1(forcibly remove it).
2. the new methodchangeSectionPrefixBehavior(<newFlag>)allows you to change it after construction.
- Dom.TextParcels: added a
forceSectionPrefixparameter in the constructor options (iniargument). Allows to treat all page names as including their section prefix even if “Include Prefix when Numbering Pages” is disabled in InDesign's section options. The client code can use this option to manage and display page numbers (cfpagesMapproperty) as in the Pages panel. This is also a way to work around duplicate page names. (To be used with caution though, since mapping is no longer aligned withmyDoc.pages.everyItem().name.)
- Env: Enhanced the implementation of
forceUnit; now supportingfalseas direct argument to get units instantly restored. Also,$$.forceUnit(-1)can be used in CC/CS6/CS5 (while remaining transparent in CS4): it turns your script inAUTO_VALUEmode, which makes sense if the code is designed to deal with ruler units rather than some preferred script unit. Rem.: The main issue withapp.scriptPreferences.measurementUnitis that it is session-persistent and could be changed by another script beyond your control. So IdExtenso provides a safe “unit policy” in its own scope AND restores the original context when$$.unload()is finally invoked.
- Env: Added the
forceUnit()method (also callable from$$). Key idea: allows a script to work safely in whateverMeasurementUnitsmode —you often need points— and automatically restores the original context when$$.Envis unloading. In CS5/CS6/CC it's just a matter of setting and restoringapp.scriptPreferences.measurementUnit; in CS4 we need to temporarily change theviewPreferencesproperty of the host object (active document assumed, if available). The whole mechanism is now implemented in the unit.jsxinc snippet (part of theEnvmodule). In practice, just call$$.forceUnit(…)when$$is loaded. You don't have to worry about restoring the original units in CS4, the framework has the job automatically done (cf$$.Env.onUnload).forceUnit()expects aMeasurementUnitsenum or the equivalent number; if no argument is supplied,MeasurementUnits.POINTSis assumed.
Edit(Factory)andEditInteger(Factory): These advancedEditTextfactories provide a better control of the native ScriptUI widget, dealing with internal events and validation mechanisms.EditInteger(Factory)inherits fromEdit(Factory): it overrides the API in order to strictly manage integers (signed or unsigned) in a custom range defined by the client code.
- Dom.TextParcels: this new class is the perfect tool for efficiently exploring text containers and capturing their contents from any InDesign
Document.$$.Dom.TextParcelsis aimed at experienced developers only. (For the record, this code is the “load-bearing wall” that underlies all the power of IndexMatic3, so don't tell your friends that you can access it directly in IdExtenso ;-) Want to run and study a superbasic sample script? Go to tests/DomTextParcelsTest.jsx. - Root/help. Ability to preselect a module while showing IdExtenso's API: just call
$$.help(<someModule>)(first argument added), e.g.$$.help($$.JSON). By default$$.help()still preselects the$$item (first of the list).
- JSON. An unusual situation arises when
Array.prototypehas been augmented from the client code:myArr.__count__then mistakenly increases byArray.prototype.__count__(natively 0), which led$$.JSONto produce a useless rich array representation. We've fixed that by double-checking the actual count of extra properties. If still zero, the usual array representation is preserved.
- Ext/string. An incredible bug was detected in ExtendScript CS4. In that version, the native
String.prototype.indexOf(...)method is no longer reliable if the host string contains"\u0000"(i.e, the U+0000 character) and if the searched string has more than one character. Fortunately, it happens thatString.prototype.lastIndexOf(...)still works fine in such a context, and we were able to use this fact to patchindexOfin a way that restores the expected behavior. (This fix does not affect later versions of ExtendScript.)
Important update (May 18, 2023.) Global re-generation of the core structure, including last fixes and additions.
- JSON v2.30518 aka
$$.JSON(...): Fixed a serious bug that made main InDesign DOM components unparseable through$$.JSON(someIndesignObject, 1, 1). A typo made the~.BRKNfilter completely transparent (for almost two years!), which resulted in an InDesign crash whenever you had to stringifyapporDocumentobjects :-/ (Reminder: The reason for this filter is to prevent browsing of buggy DOM properties likeapp.scriptPreferencesor.find<...>ShadowSettings.) - Root/messaging: Safer memory cleanup: the method discussed in 230311 should also significantly enhance garbage collection in
$$.ModalScript-based scripts and similar UI-intensive projects. Added the helper$$.dual(msg, captionA, captionB, title)for supporting custom A/B choices in a Yes/No box. - Ext/string: Fixed a bug in
String.fromBase64(). - SUI/mini: Added the property (uint)
ScriptUI.NoCharWidthreturning the probable width of the no-character glyph.
(Other interesting changes do not affect the core branch. See previous log entries regarding updated extra modules.)
- Root/messaging: Added
$$.dual(msg, captionA, captionB, title), just a variant of$$.yesNo(...)that supports custom captions instead. Two options are offered anyway: answer A returns1, answer B returns0.
DrawnCheck(Factory): Added dynamic boolean__mouseOver__and__hasFocus__properties (assumed private and read-only), can be used in yourScriptUI.DrawnCheckFactory.Icons.<MyIcon>function to customize further the appearance of the icon depending onthis.__mouseOver__and/orthis.__hasFocus__states.
- Settings: There were some embarrassing typos in
activate(),reset()andbackup()methods. Fixed. - Dom.Scope: The
TREE_SELargument of thelist()method now supports a 4th case,"bookall", which instructs the module to Preselect all book documents if any, all visible documents otherwise. (By contrast, using"book"means Preselect all book documents if any, active document otherwise.)
- Unicode: Adjusted the
getCategory()method so it supports case-insensitive argument, e.g"lu"instead of"Lu". (Of course the internal~.CATGmap remains case-sensitive.)
-
Popup(Factory): Found that a popup component may fail to show up when a timer is set on it. The issue seems to occur especially when the script is launched from an InDesign menu (!?) CallingWindow.update()happens to solve the problem. -
Progress: The window is now updated even if we only call
$$.Progress.title(...). This solves some refreshing issues.
- SUI/mini: U+FFFE seems a better candidate for computing
ScriptUI.NoCharWidth. (U+0001 wasn't reliable in some environments.) The trick remains highly experimental though!
ScriptUI CS is known for having weird issues in garbage-collecting Window controls that are no longer used. By exploring the $.list() report it can be shown that many internal addresses of ScriptUI objects are lost (Refs=0) while still polluting the memory. This typically happens with modal dialog windows. Such a Window instance may be properly closed -- after myWin.show() -- and its local identifier removed from the scope, there are still empty pointers in memory. The issue gets critical in persistent-engine scripts based on #targetengine... and having rich UI components. The memory stack then grows unstoppably and leads InDesign to crash after a dozen successive execs of your script within the session. At each step the interface is getting slower and slower to display. I don't know of a definitive way to clean up memory properly once the damage is done, short of giving up all the benefits of a persistent script altogether. However, it seems that removing manually the Window widgets and calling $.gc() right before returning your UI function almost completely solves the problem:
for( i=myWin.children.length ; i-- ; myWin.remove(i) ); // Remove win components.
for( k in myWin ) delete myWin[k]; // Clear custom win props.
$.gc(); // Garbage collector.
-
This snippet is now added at different strategic points, in Root/messaging's functions and in ModalScript::UserInterface. This slight fix is harmless in InDesign CC.
-
SUI/mini now defines
ScriptUI.NoCharWidth = ScriptUI.measureWidth("\x01")ScriptUI.NoCharWidth = ScriptUI.measureWidth("\uFFFE"), which indicates the width of the no-character glyph (usually an empty square). This information should help us decide whether a Unicode character is probably missing in ScriptUI default font. The idea is to compareScriptUI.measureWidth(someCandidateCharacter)withNoCharWidth-- although this is not a 100% reliable test. When the two measurements coincide you may have reason to assume that the candidate glyph is missing. Of course there can be regular glyphs whose width is exactly that ofNoCharWidth. But if other properties are known elsewhere, this sometimes allows a decision to be made. -
CheckList(Factory): Some users reported that the CheckList component does not display properly because the underlying characters ◻ (U+25FB), ◼ (U+25FC), ⬓ (U+2B13), ※ (U+203B) are not supported in their system (that is, they're not available in the default ScriptUI font). This typically occurs in Windows7 environments with the font “Segoe UI” (v5.x) which, in newer Windows versions, was completed with “Segoe UI-Emoji”. A workaround is now proposed:CheckListFactorytries to detect whether U+2B13 is supported (usingScriptUI.NoCharWidth); if the test fails, fallback characters are used and the checklist will look like this:based on the correspondance
◻ (U+25FB) →
[ ]◼ (U+25FC) →
[•]⬓ (U+2B13) →
[~]※ (U+203B) →
[#]For testing this component: https://github.com/indiscripts/IdExtenso/blob/master/tests/SuiFactories/TestCheckList.jsx
- Ext/string: Found a bug in
String.fromBase64(). The function wasn't supporting 1st argument supplied as an array of uint8. Fixed.
Minor update (January 23, 2023.) Global re-generation of the core structure, including last fixes and additions.
File:startupAliasfix. Solves the “tt.nudeName is not a function” error.- Ext/file:
nudeNamefix. - Added the method
File.prototype.fresh()(returning a non-existing File instance based on the present File object). Env: added theisHighContrastproperty (bool) in addition toisDark.
(The most important changes do not affect the core branch. See previous log entries for detail on updated extra modules.)
- PageRange: Added the value
"Chicago"for the.elisionoption. It implements the specific rules of the Chicago Manual of Style, as specified in the 2010 edition, p. 816:
- Yalt: Now fully supports optional punctuation terminators (
...,:,.,!) after a mute terminator (\x01,\x02,\x03,\x04). This feature was already functional while translating the key into another language (e.g"Advanced\x01:"→"Avancée :"), but there was a bug for the default (English) language: the control character\x01wasn't removed from"Advanced\x01:". Fixed.
- Yalt (res): Added a few L10N strings relative to number validation. (Might be used in UI factories, etc.)
File: fixed thestartupAliasmethod. It could produce a runtime error “tt.nudeName is not a function” becauseFile.prototype.resolve()can sometimes result in aFolderobject (!)
- The modules ModalScript (resp. BasicScript) provide an aggregate of sub-modules (
Context,UserInterface,Server) that encapsulate the abstract logic of an entire script, based on either a ScriptUI modal dialog or a DOM dialog. Although$$.Settingsremains the ideal—and optimal—place for sharing data throughout the script and between those sub-modules, it may turn out that you want to access e.g. the Context from the UserInterface (or from another location.) Then you'll have to use a path like$$.ModalScript.Contextto get the desired reference. But this syntax has two drawbacks: first, it is a bit cumbersome; secondly, it requires hardcoding the “branch name” (ModalScript vs. BasicScript vs. etc) of the scheme you're using. This lacks flexibility, because if you were to change that scheme along the way, you would have to rewrite the corresponding path(s) in your code. For these various reasons, it seemed beneficial to make the sub-modules accessible straight from$$. Thus you can now use the aliases$$.Context,$$.UserInterfaceand$$.Serverto enter the corresponding sub-modules, without worrying about the actual parent scheme. - The same enhancement has been applied to the extended modules ModalScriptMenu (resp. BasicScriptMenu), making the extra sub-module
MenuExtensionvisible from$$.
-
Added the
moreOptions(resObj&, anyObj)method toScriptUI/factories. A simple utility for adding extra options to a resource before calling the builder. Will be used in IdExtenso'sfactoriesfor handling the optionmore. Do the same with your own factories if needed. -
Updated all existing factory components so they now support the option
morewhen you call the factory. This must be anObjecthaving extra properties that you want to append to the resource object before the internal call toScriptUI.builder. From then, you no longer need an external mechanism if you have to load extra properties at construction time. Say you want a Check component to have a custom ID, just add it in amoreobject:CheckFactory$MyCheck1: [{ text: __("Binary Check (with custom box)"), value: 0, ternary: false, help: __("Right-click the control to change its label..."), more: { myID:123 }, }],
Note. — This way, all IdExtenso components can be constructed with their own, unfiltered properties, as you would do very similarly with ScriptUI.builder(myResourceObj). The only difference is the requirement to use the more key (a sub-object) in your options object.
- Added the
RectPackmodule, a fast and simple rectangle-packing algorithm that you can use for various layout-optimization projects. Goto tests/RectPackTest for a basic InDesign demo script.
- Fixed a typo in Ext/file--the
nudeName()wasn't honoring its argument--and added the methodFile.prototype.fresh()which always return a non-existing File instance based on the present File object.myFile.fresh()creates if necessary an incremental suffixed path, like in"path/to/myFile (2).txt", etc.
PageRange: added the optionsreduxPairandreduxMoreto theformatmethod.
reduxPair (str) Special suffix for formatting pairs if minRange > 1.
(`minRange` is set to at least 2 if not supplied.)
Note: If reduxPair is missing while reduxMore is
non-empty, assume reduxPair=reduxMore.
E.g $$.PageRange([1,2,4,5,6,10,11,15], {reduxPair:"f."})
=> "1f., 4-6, 10f., 15" ; implied minRange=2
reduxMore (str) Special suffix for formatting N consecutive numbers
from N=3 to N=minRange, provided that reduxPair is
defined. (`minRange` is set to 3 if not supplied.)
E.g $$.PageRange([1,2,4,5,6,10,11,15], {reduxPair:"f.", reduxMore:"ff."})
=> "1f., 4ff., 10f., 15" ; implied minRange=3
WARNING reduxPair/reduxMore operate whatever the `style` option,
which might lead to Roman numbers (i, ii, iii...) or
alphabetic sequences (a, b, c...) The client code is
responsible for adjusting the redux string accordingly.
-
Due to a specific limitation of ExtendScript CS4 —unability to retrieve function keys using
for( k in o )— the ScriptUI factory callbacks aren't available in InDesign CS4 (til someone finds a genius hack!) So, if your script has to support this version, it is recommended to provide a fallback strategy at the factory level. Basically, theonLoadmethod of your factory won't be invoked in CS4. A simple trick is to add the line$$.domVersion(7) || ScriptUI.MyCustomFactory.onLoad(); // CS4 fallback
at the end of your code. This solution is now used in Check(Factory) and DrawnCheck(Factory).
Envnow exposes aisHighContrastproperty (bool) in addition toisDark. So you can determine whether the UI, dark or light, is in high contrast state. Both properties are inherited by$$. The combination of$$.isDarkand$$.isHighContrastallows your script to adjust its UI colors to the four possible states of the InDesign GUI.- The ScriptUI factories wrapper,
$$.factories, now embeds a special, hidden module$$.ScriptUIFactoriesthat connects any factory to IdExtenso'sonEngine/onLoad/onUnloadcallback mechanism. Thus, you can declare a staticonLoadmethod (resp.onEngine,onUnload) in your custom factory and then have it automatically called at the corresponding$$stage. Since ScriptUI factories are not modules, you couldn't enjoy usual callbacks in previous versions. ImplementingScriptUI.myComponentFactory.onLoadis very likely what you'll want to do to have internal data updated with respect to the context in which the framewok is loading. Typically,$$.isDarkmay have changed between two executions of your script in a session-persistent engine, so you may need to adjust UI colors accordingly, etc. - Updated
Check(Factory)andDrawnCheck(Factory)(better color management using theonLoadcallback: the components now fit dynamically the InDesign UI theme.)
- Added the module
Dom.Endnote, the counterpart ofDom.Footnotefor endnotes. Both now rely on a common toolbox.
Check(Factory)andDrawnCheck(Factory): Better detection of Ctrl+Click.
DrawnCheck(Factory). Technically, theonClickChangehandler of your DrawnCheck component receives as 1st argument a customclickedevent which is of little interest in most applications. But you may want to know more about that event in some specific cases. For example, was it a “Click” or a “Ctrl Click”? Or what was the location of the mouse cursor? This information is now present in theclickedevent. It contains, when available, the essential properties of a ScriptUIMouseEvent, that is
screenX (int=0) Screen X coord.
screenY (int=0) Screen Y coord.
clientX (int=0) Client X coord.
clientY (int=0) Client Y coord.
ctrlKey (bool=false) Whether the [Ctrl] key is down.
altKey (bool=false) Whether the [Alt] key is down.
shiftKey (bool=false) Whether the [Shift] key is down.
metaKey (bool=false) Whether the [Meta] key is down.
button (uint=0) Mouse button (0|1|2).
Check(Factory). The same enhancement has been applied to the Check component.
- Dom.Scope: added the methods
hasStyle()andhasLayer().
- Minor update (May 7, 2022.) Provides cosmetic changes and a global cleanup (missing declarations added in a few core functions.)
- Root: slight change in the 'unloading' mechanism,
$$.Log.show()is called whatever the final log level as soon as the log file has been accessed. This makes the logging system more responsive even if the script just used raw$$.Log.push(...)commands (which are still honored in MUTE mode.) - Log now exposes a
hits()method that tells whether the logging system has been invoked during the execution of the script. - Updated Env/winver.
- Unicode: this module had a wrong prolog, this is now fixed. Note: if your project uses it, the present fix is required to restore the normal behavior of your script with a
#targetenginedirective. Indeed, the error was to introduce the module using only
;eval(__(MODULE, $$, 'Unicode', etc ))...
instead of the regular form
;$$.hasOwnProperty('Unicode') || eval(__(MODULE, $$, 'Unicode', etc ))...
The missing part $$.hasOwnProperty('Unicode') || is of primary importance. If you write your own IdExtenso modules, do not forget this crucial part and always apply the entire scheme above for every extension (i.e., outside of the core branch.) Otherwise, the intepreter will throw an obscure "Unknown MODULE identifier" error while re-running the script in a persistent engine. The #targetengine directive is a great way of speeding up our scripts, since all heavy structures (core data and outer modules) can be declared once and for all (throughout the app session). However, we need to take great care of global identifiers then. Once loaded, IdExtenso automatically cleans up its own temporary globals (MODULE and many more.) Hence, the command eval(__(MODULE, ... )) would fail!
- Global cleanup in various modules, adding missing declarations in a few functions. (This is not a critical fix but it keeps the
[[global]]scope much cleaner and may improve performances.) - Settings: Added the method
footprint(scope)that creates a unique footprint of the current settings in the specified scope(s). Useful when you need to determine whether some changes have been applied (to the settings) between two points of your process. Typical use: display a conditional "Save settings?" message when the user closes the main dialog. Just take a footprint before and after and compare the strings. Thanks to the scope arg you can decide which kind of settings are traced here. The default value is120which merges the scopesENGI|SESS|OBJ|APP|HYBand represents all keys that might be restored, regardless of CONST, RESET, and LIVE keys that are meaningless to this respect.
- Collator: Adjusted the
baseKey()method so it takes care of tailored level1 weights in a way that gives them precedence over attractor(s).
- UniAsc: Added the method
sibling(anyChar)that returns the whole string of sibling characters (incl. anyChar), that is, the set of characters that share the same ASCII base.
- Added a
IDEX_SESSIONenv variable, cf ENTRY POINT, and the corresponding$$.Env.session()method. - A few technical details added to $$.Env too.
- Dom.Scope: Made some improvements. Better internal
UNIQproperty inselect().
- Linguist: Made the
~.LNGSmap a separate resource file, so it might be accessed from an external module (just in case.)
- Important update (Apr. 11, 2022.) ⚠ A highly critical bug was found (and fixed!) in the core/Ext/patterns registry. It was affecting the static regexes
RegExp._BK,RegExp._SL,RegExp._DT,RegExp._ORcapturing respectively the escaped forms of\(backslash),/(slash),.(dot), and|(vertical line). Even if your script does not explicitly use these predefined patterns you should update the framework as soon as possible. Serious internal routines were indeed impacted, likeString.prototype.toSource()or$$.JSON()!
- MetaCollator improves
W1BA's base keys using local replacements for a few letters whose level1 weight could appear prematurely in the Unicode map. See details in~.REBA:
// Old Key New Key (fix)
// ---
'\u037A': '\u0399', // iota subscript -> IOTA (Greek)
'\xB5': '\u039C', // µ -> Μ (Greek)
// etc
-
Updated Collator/W1BA accordingly (data auto-generated using RebuildCollator.jsx.)
-
Added
GREEKandCYRILLICattractors for use in Collator'sbaseKey()method. The function now supports multiple attractors if needed (underscore-separated, e.g"LATIN_GREEK".)
- Important changes in the Collator and MetaCollator modules (the latter being only involved in regenerating the resources of the former.) First, a small bug was identified (and fixed!) in the
~.TMAProutine. Although dormant, it could have had devastating effects on tailoring rules. Furthermore, a new public methodbaseKey(str)is now exposed in$$.Collator. It is independent fromsort()and does not interact with the collating process. However, it provides a useful functionality, the ability to represent the level1 initial key of any string as a basic character, e.g'ä'=>'A','œ'=>'O'(in Latin script), and the same in other supported writing systems. Typically,baseKey(input)can be used for creating alphabetic groups ('A', 'B', 'C'…) surrounding your data. It automatically ignores variable elements (punctuation marks, etc) sobaseKey("[hello]")will still return'H'. Also,baseKey()is aware of the active tailoring rules defined bysetTailor(someLocale). So, for example, the code
$$.Collator.setTailor('br'); // Select Breton
alert( $$.Collator.baseKey("C'hweg") ); // => C'H
will display the base key C'H (which is an independent letter in Breton.) In Spanish, ñ will be identified to Ñ (separate letter) while it would just produce N in the scope of European Ordering Rules (EOR.)
- Yalt: added a 2nd param (inCurrentLocale) to the
hasKey()method. Purpose: allows the client code to check whether a key string is available in either the global YALT map (whatever the locale), or specifically in the current, active locale. - Linguist: added more than 120 keys to
~.WSYSin order to address ISO 15924 writing systems that weren't supported yet.
- UniAsc: this new module provides basic Unicode-to-ASCII transliteration. When included, it appends a
translit()method toString.prototypeso you can simply use e.g."北亰".translit()(which returns"Bei Jing ".)
- Security update (March 24, 2022) including latest fixes and additions. Main changes in the core area: 1. The CS4 patch
String.prototype.splitwasn't working as expected on strings that do not contain U+0000. It is now fixed. 2.RegExp.escapewasn't supporting the empty string. Fixed! 3.RegExp.fromCodeRangeshad a logical bug related to surrogate pairs. Fixed! Also, the special escape sequence\-is now used for U+002D, instead of\u002Dwhich is not properly handled in ExtendScript. In addition,fromCodeRangessupports a new option as 2nd argument,OUT_MODE(set it to-1to get a more compact range pattern.)
DrawnCheck(Factory)is a new component that manages CS/CC-consistent icon buttons (18×18 px) based on a customizedonDrawcallback. Unlike PNG sprites (that consume more memory and undergo UI scaling issues in various environments),DrawnCheckcomponents are purely drawn from theScriptUIGraphicscanvas. You need to provide a unique key and function for each icon, as detailed in the notice. See also TestDrawnCheck.jsx for a working example with three distinct icons.- ScriptUI/factories: Added the helper
ScriptUIGraphics.prototype.draw(x,y), providing a compact syntax for drawing a path fromanyWidget.graphics. Instead of
gx.moveTo(3,5); gx.lineTo(10,20); gx.lineTo(8,5); etc
use
gx.draw(3,5)(10,20)(8,5);
(Each time you initiate draw() from a ScriptUIGraphics instance it interprets the first (x,y) pair as a moveTo command, then the next coordinates passed to the function are interpreted as a lineTo command.)
- PageRange. A subtle option,
singletons, has been added to the mainformatmethod (see the specification of theoptionsargument.) In substance,singletonsallows you to prevent some special numbers from being included in a range, disregarding any other rule that would otherwise apply. There are indeed particular circumstances where you want to detach a page number and preserve its visibility, for example if it is associated to a footnote whose number must in turn be rendered in some way during postprocessing. Then, you can tell$$.PageRangeto exclude such page number, say 123, from a range like 120-128. Add the option{singletons:[123]}(array of uint) and you will retrieve something like"120-122, 123, 124-128"instead of"120-128". If found in the input array, your singleton number(s) is/are always detached from possible ranges.
Keep in mind that those singletons are not added to the input array. This is strictly a formatting option that reacts when such number is encountered while parsing and processing your data.
CheckList(Factory): 1. Added therootoption which tellsScriptUI.CheckListFactory()to automatically prepend a root node on top of all supplied branches. If<yourOptions>.rootis a non-empty string, it becomes the root node of the tree. Useful to add a global ON/OFF control to your CheckList without re-indenting branches and nodes. Note that the gettersgetString()andgetValue()will NOT report the root node, so the output data (items and levels) remain consistent with the input.
2. Added thepreCheck()method, to wich you can pass an array of node paths assumed to describe a new set of checked nodes. Use this routine when your CheckList is already built and loaded in a particular state but then requires a new ‘selection’ of nodes from the client code. UnlikesetValue, which entirely resets the tree based on new items,preCheckkeeps all branches/nodes and only update their state in order to reflect your specification.
- Settings: Various improvements and optimizations. In particular, avoids accessing the DOM label twice when
appis passed as 1st argument toactivate(),reset(), orbackup(). - Dom.Footnote: Unlike variable instances (represented by U+0018), footnotes (U+0004) have no property that reveals the underlying number, as would do
myVar.resultText. So, if you need to determine which ‘numeral’ a footnote is associated to, you have first to determine the actual index of that tootnote in its context, then you have to compute the resulting text with respect to various options likeFootnoteNumberingStyleand so. All of these tedious tasks are taken over by the Dom.Footnote module. Typical uses:
// Get the numeral of a FN ; e.g "3", "iii", "003", "ث", etc
var num = $$.Dom.Foonote(myFootnote);
// Array of numerals of a plural FN ; e.g ["003","004","005"...]
var a = $$.Dom.Foonote(myStory.footnotes.everyItem());
- Dom.Scope: new module for managing a set of InDesign documents as a single entity. Read the notice.
- Unicode: updated the Unicode module and its dependencies; added the
~.SCRImapping related to Unicode scripts. - Updated MetaUnicode accordingly.
- Settings: The methods
activate(src),reset(src), andbackup(dst)now support any arbitrary host object, that is, not necessarily an InDesign DOM object. In such case, the commandsextractLabelandinsertLabelare not invoked for reading/writing OBJ keys. Instead, the supplied object provides and receives data thru a SUID property, where SUID denotes the uid string of the active Settings. For example, if your settings are associated to the SUID"xyz", then$$.Settings.activate(myObj)will usemyObj.xyz(if defined) as the set of OBJ-scoped keys, and$$.Settings.backup(myObj)will setmyObj.xyzto the corresponding JSON string while saving the data. Note thatmyObj.xyzshould be an Object when used as a source while it becomes a string when used as a destination. This kind of hack is useful when no DOM object is available when activating or saving the Settings, although object (or hybrid) keys are needed in your project. Suppose that a particular sequence of existing documents has to be treated as a single src/dst entity. No DOM object is associated to that set (unless you have aBookon hand.) However, your script could still elaborate a special structure and some unique ID for addressing that entity. And then you might want to assign OBJ keys to the entity, instead of global APP keys, whenever the client code works with that specific sequence of documents. You can then supply the dedicated object to$$.Settingsmethods in order to enjoy the mechanism of recovering and saving OBJ keys. (What is left to you is the process of reconstructing the entity and/or saving its own data in a persistent way when your project requires it.)
CheckList(Factory): Modified the default behavior ofgetString()when no argument is supplied: it now returns the full state/item sequence, hence equivalent tomyCheckList.getValue(). This change was required to keep this factory consistent withModalScriptsemantics regarding theSmartListItemGetteroption. See ModalScript/UserInterface. If you need to retrieve the items without state prefixes, usemyCheckList.getString(false)(or0) instead of an undefined argument. The other options ofgetString()are unchanged.
- Ext/regexp:
RegExp.escape()wasn't supporting the empty string! Fixed.
-
CheckList(Factory): Added a new state for locked nodes. This change has no consequence on existing scripts. You can now declare a checked item as locked using the prefix#instead of+(this mechanism is only available for terminal nodes, do not attempt to lock an entire branch.) A locked item cannot be unchecked, so it visually informs the user that the corresponding element will be automatically present in the final selection. Locked items are represented using the prefix ⏺ (U+23FA) in the listbox. Here is a typical declaration in aScriptUI.builderresource object:. . . CheckListFactory$MyCheckList: [{ data: ["+ Adobe", "## InDesign","-- Illustrator","++ Photoshop", "+ Other", "++ IndyFont", "-- Wordalizer"], help: "The InDesign element cannot be unchecked.", }], . . .
CheckList(Factory): fixed the “wg is undefined” error insetValue(!)
- Ext/regexp: Found a logical bug in
RegExp.fromCodeRanges(related to surrogate pairs.) Fixed!
- Ext/regexp: Fixed and improved the static method
RegExp.fromCodeRanges(codeRanges,OUT_MODE). The special escape sequence\-is now used for the hyphen (U+002D), instead of\u002Dwhich is not properly handled in ExtendScript's RegExp classes. In addition,fromCodeRangessupports a new option for its 2nd argumentOUT_MODE: set it to-1to get a more compact range pattern. Only special characters are then escaped, using the• -> \•scheme.
- Unicode. Updated Unicode blocks (
~.UBLK); added category mapping (~.CATG) for future methods. - Collator. Full update based on Unicode “allkeys” 14.0.0. (New data automatically generated from MetaCollator.)
- PageRange. The methods
parseandnormalizenow support themapargument as a function too. For example,$$.PageRange.parse("15, 10-12, 18", null, function(x){ return x.toString() })
returns the array of strings["10", "11", "12", "15", "18"]rather than the corresponding array of numbers. Of course you can use more sophisticated functions ;-)
- SUI/mini: Added an additional condition in
ScriptUI.setFocus()so that one can forcibly exclude particular widgets from the “focus loop.” How? Just set the custom property__cantFocus__to a truthy value. When found, this flag is taken into account bysetFocus()which then skips the widget as a possible target. Example: you have created a custom control (or factory) that technically supports theactiveproperty and could receive the focus, but you made it behave so that it does not respond to thefocusevent. In such case you want to informScriptUI.setFocusthat it should ignore your component. This is now possible usingmyComponent.__cantFocus__ = true.
- Dom/items solves the issue of retrieving items (from any
Collectionor plural specifier) having a specific property set to a specific value. It provides the general methodallItemsByKeyVal(host,key,value), then two useful methods based on it:allItemsByName(host,name)andallItemsByLabel(host,label). Note that the native DOM commandmyCollection.itemByName(someName)does not return a plural specifier (as you may expect), so it won't reach all items that share the incoming name within the collection. Use$$.Dom.allItemsByName(myCollection,someName)to get the whole array of target items. The methods support DOM specifiers as well, e.gmyLayer.textFrames.everyItem(), etc.
CheckList(Factory): added the'x2'option as 2nd argument ofgetString(), which then produces paths of the form<parent>\x02<parent>\x02...<node>. Useful if both brackets and slash characters may appear in node names.
-
Important update (Sept 1, 2021) including latest fixes and additions. Main changes in the core area: added the method
String.prototype.unaccent()for removing accents/diacritics from a string, fixed the patternRegExp.LINEin Ext/patterns, SUI/builder can optionally preventhelpTipinheritance on a particular component (usehelpTip: false), addedScriptUI.measureWidth()toSUI/mini, which fixes the biased results ofgraphics.measureString()in CC/Win environments. -
The YALT module now supports “mute terminators”:
You have the option to register variants for the same English key using a special terminator among the control characters '\x01', '\x02', '\x03' or '\x04'. Hence you can provide distinct sets of translation strings for words or expressions — like "All", "[None]", "match", etc — that have variant forms in the target language depending on the context. For example, in French,
All # Tous
All\x01 # Toutes
All\x02 # Tout
offer three possible translations for the word "All". The suffixes \x01 and \x02 are used to discriminate these three cases. If the default (English) language is active, both key strings will result in the word All (the terminator is removed). Otherwise, the desired translation will be selected.
This new feature allows you to address gender or number inflections that are not marked in English, as well as pure homographs like "left" (side) vs. "left" (past participle of leave.)
- Fixed the routine
ScriptUI.measureMulti()for Win platforms in ScriptUI/factories. An infinite loop could occur with huge un-splittable strings. Popup(Factory): improved text wrap using ZERO WIDTH SPACE suffix after some punctuation marks:.,-,/,\.
- ScriptUI/factories/: made states (i.e.
enabledandvisibleproperties) configurable at creation time forCheck(Factory),CheckGroup(Factory)andCheckList(Factory). This allows you to predefine states straight from theoptionsobject.
- Improving the
Popup(Factory). 1. Added a cache to avoid re-processing the same arguments from theupdatemethod while the component is already shown in that state. Should deal smoothly with unconsidered duplications of 'popup' events. 2. Fixed resizing issue in CS4/CS5.
- PageRange. New module for parsing-formatting-normalizing numeric sequences of the kind “3, 5-8, 10, 12-13...”. Typical use is checking and reformatting page ranges of your target document or book. (See the demo in
/tests/PageRangeTester)
- Added a
CheckListcomponent in ScriptUI/factories/. This control allows to display and check/uncheck hierarchical data in a list (the underlying widget is a native ScriptUIListbox.) Very useful for showing style groups and similar tree structures available in InDesign. - Added a
SideMenucomponent in ScriptUI/factories/. Provides a sidebar menu that controls the visibility of UI components (referred to as “menu targets”.)
- Loaded some custom components in the folder ScriptUI/factories/:
Checkimplements a customizable checkbox that optionally supports three states and deals consistently with events. Can replace the nativeCheckboxwidget.CheckGroupmanages a set of uniformCheckcomponents. (Hence it requires theCheckfactory.)Popupimplements a hidden container that you can make temporary visible for displaying messages alongside UI widgets.
- ScriptUI/factories. This new snippet introduces a set of common functions used in custom ScriptUI factories. Mainly:
ScriptUI.factoryOptions(ini,defs): Merges the incominginiset with a default set of options.ScriptUI.setWatcher(widget,keys,watchFct,options): Attaches a watcher (“watch function”) to widget keys.ScriptUI.dispatch(widget,evType,options): Dispatches a custom event.ScriptUI.measureMulti(text,widget,maxWidth): Returns the probable dimensions of the stringtextwhen laid out in a multiline text widget (StaticText, EditText.)
- SUI/mini: added the
RETMAXargument (boolean) inScriptUI.measureWidth(text,widget,RETMAX). The function then returns the highest result when legacyWidth and computedWidth differ.
- SUI/builder now allows you to prevent
helpTipinheritance on a particular component thas doesn't want to display any help tip. Simply use the rulehelpTip: false.
- ScriptUI/events. Better management of modifier keys (Alt/Ctrl/Shift/Meta) while cloning a
KeyboardEventviaScriptUI.event('my_custom_type', 'K', originalKeyboardEvent). - Ext/patterns: Changed
RegExp.LINE = /\u000D|\u000A|\u000D\u000A/gintoRegExp.LINE = /\u000D\u000A|\u000D|\u000A/g(longest match first.) The latter form is more conform and fixes inconsistencies between ExtendScript CS and CC.
- Ext/string: Added the core method
String.prototype.unaccent(), a basic routine for removing accents/diacritics from a string. E.g."ÀçĎéĩĵĶńőŕşūŵŷż".unaccent()returns"AcDeijKnorsuwyz". SUI/mini: AddedScriptUI.measureWidth(), which fixes the biased results ofgraphics.measureString()in CC environments (Windows only, as the bug seems Win-specific.) Go to StaticTextMetrics.jsx for testing.
- Important update (June 06, 2021) including latest fixes and additions.
- Main changes in the core area: fixed a potential error in
$$.Env.globalEvent()(Env/script); prevents JSON from accessing invalid name-based specifiers; added thestartupAlias()method in File for dealing with “startup scripts.”
- Collator. Fixed a CS4 bug involving empty string(s): the
~.SPLTroutine was killing CS4 if the input string was empty. Nows.length > 0is a condition before callings.replace(callee.CUR_MTCH, F).
- YALT. Added automatic support of
...terminator. That is, if the keyabcis present in your Yalt package and translated intoxyz, thenabc...will be recognized as well, and translated intoxyz.... (The other automatic terminators are.,:, and!)
- Collator. Made zero-padding (
~.ZPAD) simpler, cfsortNumbersoption. Any word boundary (incl..) can now initiate a valid digit sequence:XYZ.123is no longer interpreted as0.123, and regular decimal point as inXYZ 123.45is parsed normally.
- Collator. Small improvement of the Word-by-Word system, removing spaces and hyphens followed by
(or,while preprocessing text items (cf~.PWBW) This strengthens the rule[PARENTHESIS] < [COMMA] < [SPACE]and ties in with Chicago Manual of Style example (p. 833, 2010.)
- AnyScript/menu_extension Made
menuAction()capable of targetting submenus as well as menuitems by calling$$.Dom.Menu.get()instead of...getMenuItem()while resolving menu references. As a result, any path in your ...ScriptMenu template can point out to either aMenuItemorSubmenuinstance.
- Ext/regexp: Removed duplicated formal parameters X,Y in
RegExp.fromCodeRanges. (No side effects but had to be fixed.)
- Dom.Menu: re-implemented the menu access routine, taking into account the many bugs and limitations identified in InDesign CS4/CS5/CS6 regarding name-based specifiers (
Menu,Submenu, andMenuItemobjects.) In summary, the path solver had to avoid both.getElements(),.constructorand.parentcommands to work around CSx bugs. In such environment, the algorithm tries to strictly resolve menu paths by index (cf the routines~.RESO(),~.INTO(), etc.) - Added the
getAction()method in MenuExtension and fixed a few typos.
- JSON: Skips invalid name-based specifiers altered by inner double quotes, like
/menu[@name="Контекстное меню "Общие""]/menu-item[@id=118791]. This InDesign bug occurs in CS4/CS5 and leads to broken DOM paths.$$.JSONnow detects it and labels such specifiers as “broken”.
- ModalScriptMenu (resp. BasicScriptMenu) provides a simple and natural extension of the
ModalScript(resp.BasicScript) module, based on the private~.EXTNmember introduced in AnyScript/run. Thanks to this extension mechanism, the Context/UI/Server model now supports an additionalMenuExtensioncomponent that fully manages menu installation and event handling. It is then super-easy to attach a menu to an existingModalScript(resp.BasicScript). The whole logic is detailed in the AnyScript/menu_extension snippet, which adds four hooks to the system:
onStartup(runMode,parentModule): Called only if the script is presently running as a startup script.beforeDisplay(runMode,parentModule,scriptMenuAction): Called when thebeforeDisplayevent occurs. If defined, this function must return TRUE (resp. FALSE) to enable (resp. disable) the menu item.beforeInvoke(runMode,parentModule,scriptMenuAction: Called when thebeforeInvokeevent occurs.afterke(runMode,parentModule,scriptMenuAction: Called when theafterInvokeevent occurs.
See full example in tests/BasicScriptMenuDemo.jsx
- Dom.Menu: Made
removeAction()a bit safer using aisValidcheckpoint onScriptMenuActioninstance(s). - File: Added a generic
startupAlias()method that will create, check or remove an alias of thetargetscript file in thestartup scriptssubfolder of the user branch.
- Added a preliminary step in AnyScript/run that checks whether the private member
~.EXTNis defined and functional. In such case,~.EXTN(runMode)is called and if the returned value isfalsethe whole script execution is stopped. This block is processed before the regular Context/UI/Server cycle (settings are not activated at that point.) The general purpose of this preliminary step is to bring extensibility to the AnyScript template (on which BasicScript and ModalScript are based.) A typical use of~.EXTNwould be to provide menu and/or startup-script installation mechanisms, entirely decoupled from the Context/UI/Server scheme, while offering dedicated event handlers (hooks) likeonStartup,beforeDisplay, etc. This will be done in extended modules (coming soon.)
- Quick fix of
$$.Env.globalEvent()in Env/script: added anisValidtest on the incoming event (since it's a DOM object.) - Added
removeAction()in Dom.Menu.
- Quick update (April 04, 2021) introducing the important
$$.Env.inStartup()method. This function tells whether the code is presently running “as a startup script”, based on the value ofapp.performanceMetric(PerformanceMetricOptions.MINISAVE_COUNT)and taking into account the engine state. More details in theEnv/scriptsnippet. As all other Env features,$$.Env.inStartup()is now part of the core and will help manage interesting tasks in relation with startup scripts (in particular the InDesign menus and menu actions subsystem.) You can now determine if your program is now running as a startup script from any point of your client script:$$.Env.inStartup()will return1(yes) or0(no) so you can decide, for example, if it is relevant to display a modal alert, go into time-consuming code, etc.
- Dom.Menu added, a handy module for accessing and managing
Menu,Submenu,MenuIteminstances, as well as customScriptMenuAction. See the BACKGROUND section to get started with Dom.Menu features. See also the MenuCamelCase demo, which implements a custom menu action usingDom.Menu.setAction()and more advanced stuff.
- Stabilized version (March 22, 2021) including latest fixes, improvements, and additions.
Env/script: Enhanced the$$.Env.globalEvent()method so it will not return the sameEventinstance twice, unless explicitly allowed. This is a tricky adjustment but definitely needed in advanced projects:$$.Env.globalEventrecovers the current DOM event (e.g, the'onInvoke'stage of aScriptMenuAction) by reading the global variableevt(aka$.global.evt) which is automatically set by InDesign/ExtendScript. However, a problem may arise if you use a persistent engine and allows your script to be executed by different means (triggered by an event listener, launched from the Scripts panel, etc.) Then, the$.global.evtreference may persist (as previously initiated by a listener) and is still in memory while your script now runs from a different launcher. So your code may misinterpret the returned ref of$$.Env.globalEvent()as a new Event and react inappropriately. To prevent any confusion, you could probably delete$.global.evtonce processed (not tested though), but it sounds safer to address the issue from$$.Env.globalEventitself. The new code uses an internal event stamp that detects a previously returned event. In such case, the method returns0instead of the oldEventreference, unless you supply a truthyALLOW_PREVIOUS_EVENTargument as 1st parameter.- Recent additions/changes:
SUI/mini:ScriptUI.HDI_SCALING(will manage HiDPI issues),ScriptUI.callback(),ScriptUI.setFocus(), plus the option to attach multiple events to a single listener inSUI/builder.
SUI/mini: AddedScriptUI.HDI_SCALING, an array of two factors[<xFactor>,<yFactor>]that reflect how ScriptUI coordinates are sometimes affected in HiDPI displays.ScriptUI.HDI_SCALINGshould normally be[1,1]. In some environments (esp. Win10 with UI scaling applied) the factors can be higher, e.g[1.5, 1.5]in 150% UI scaling. Knowing these factors helps solve various inconsistencies altering ScriptUI coordinates.
- Web: Fixed redirection issue, automatic
http -> httpsredir is now supported. Relaxed the non-modalstate condition in InDesign >= CS5 (7.0) since it has been found thatapp.doScriptcan work in modal state from that ID version. Huge redesign of the HTTP Secure (Win) snippet, made safer and more compact. (Still searching how to manage timeout here…)
-
SUI/mini: AddedScriptUI.callback(), a helper that removes and/or attaches event listeners for specified event type(s). -
SUI/buildernow provides the option to associate multiple events to a single listener in one line, e.g_blur_focus: function onBlurFocus(ev){ . . . }You just have to concatenate one or several supported keys among
_move,_moving,_resize,_resizing,_show,_close,_focus,_blur,_change,_changing,_click,_mousedown,_mouseup,_mousemove,_mouseover,_mouseout,_enterKey,_keydown,_keyup.
SUI/mini: ImprovedScriptUI.setFocus(), which now supports a 2nd argument (NoRetWin) that tells the function to return0if the Window is finally made active as a fallback.
- Stabilized version (January 16, 2021) including latest patches and additions.
- Added in Env the
uiLevel()method that makes it easy to mute/restore user interaction level while opening or processing documents. Typical use:
// [REM] `$$.Env.uiLevel` is exposed in `$$`
$$.uiLevel(0); // mute user interactions
app.open(myArrayOfInddFiles);
$$.uiLevel(1); // restore
- Recent additions:
$$.Env.canToolKit()(so$$.Logcan now operate in ESTK console as well) ;ScriptUI.event();$$.Dom.parentSpread(item)and$$.Dom.parentPage(item)(exposed in$$). String.prototype.charAt()fixed so it can pick U+0000.
-
The Env module now checks ExtendScript Toolkit's status via
BridgeTalk(see~.ESTK()in /script.jsxinc.) This information is reported in$$.Env.summary(). Also, the newcanToolKit()method tells whether ESTK is in the place and presently running. -
The Log module now outputs trace and/or warn messages in the ESTK console if you opened it before running the script. This is useful to get instant feedback while debugging. (The log file is still processed in parallel.)
Ext/string: In pure JavaScript thecharAtmethod can pick a U+0000 character, e.g"x\0y".charAt(1)returns"\0". But in ExtendScript an empty string is returned whenevercharAtshould output"\0".Ext/stringhacksString.prototype.charAtin order to fix the problem.
- ScriptUI/events snippet added in the
etcbranch. Provides the functionScriptUI.event()and advanced tools and tricks for manipulatingEvent,UIEvent,MouseEvent, andKeyboardEventinstances at the ScriptUI level.
- The core Dom module now provides two essential functions
$$.Dom.parentSpread(item)and$$.Dom.parentPage(item)that were highly expected in many InDesign scripts. This routines have aliases at the root level so you can simply call$$.parentSpread(...), resp.$$.parentPage(...). They support DOM objects that fit theparentPageproperty in CS5/CS6/CC:
PageItem, SplineItem, Oval, Rectangle, GraphicLine, Polygon, Group, TextFrame, EndnoteTextFrame, Guide, HtmlItem, MediaItem, Movie, Sound, SVG, ImportedPage, EPSText, Graphic, PICT, WMF, PDF, EPS, Image, FormField, Button, MultiStateObject, CheckBox, ComboBox, ListBox, RadioButton, TextBox, SignatureField.
Note that $$.parentPage() is available in whatever version, including CS4 :-) Also, $$.parentSpread(...) and $$.parentPage(...) can work on plural specifiers, e.g myDoc.ovals.everyItem(), and will then return, if relevant, an array rather than a single object.
- Stabilized version (November 27, 2020) including latest fixes, improvements, and additions.
- Cosmetic changes in Root/errors.
- Recent patches and additions:
String.prototype.subReplace();RegExp.fromCodeRanges(). Ext/math: In ExtendScript CS4/CS5 (InDesign versions <= 7.0)Math.min(...)andMath.max(...)weren't supporting more than two arguments. In particular, theMath.max.call(null, [1,2,3,4,5])trick (resp.Math.min...) can't be used in these older script engines. The present snippet provides a patch that makes all scripts consistent regardingMath.minandMath.max. (Returned values comply with ECMA-262 rules.)
Root/error: Madeerror()andreceiveError()less verbose on displaying the stack.
Ext/string: Added a convenientString.prototype.subReplace()method that performs replacements only in specific substrings determined by a regular expression. In the following example, the replacement/a(\d+)/g -> "X$1"is processed only in<...>sub-regions:
"a12<a34>a567<a998>".subReplace( /a(\d+)/g, "X$1", /<[^>]+>/g )
-> a12<X34>a567<X998>
A 4th parameter (boolean) can be supplied, it then specifies whether replacements must be processed outside the sub-regions (default being inside.)
Ext/regexp: ImprovedRegExp.fromCodeRanges(). The function now manages large ranges of surrogate pairs and optimizes the result. For example,
RegExp.fromCodeRanges('1F5F4..20AD2')
-> \uD83D[\uDDF4-\uDFFF]|[\uD83E-\uD841][\uDC00-\uDFFF]|\uD842[\uDC00-\uDED2]
Ext/regexp: addedRegExp.fromCodeRanges()(static), an experimental routine that allows you to buildRegExppatterns from an array of Unicode codepoints and/or range of codepoints, including characters beyond U+FFFF that then require UTF16 encoding of surrogate pairs. See the detailed description.
- Collator: Added sort options and many refinements (letter-by-letter and word-by-word systems, stable sort, upperFirst mode at level 3, ability to sort separate digit sequences as numbers.)
- YALT: In order to make long strings more readable you can now write any translation string in a separate line starting with
<spacing>#, where<spacing>denotes zero or more spacing characters (space or tab.) Here is an example of valid multiline L10N string:
Collect All Threaded Frames
# Récupérer tous les blocs liés
# Alle verketteten Rahmen aufnehmen
# Recopilar todos los marcos enlazados
-
Updated European Ordering Rules (EOR), cf MetaCollator/tailoring/$$.EOR.jsxres reflected in Collator/TLRM.
-
Collator
.sort(): Refinement of the rules regarding input/ouput processing when incoming data contain\0. A more consistent solution is adopted:
If an input string matches the pattern "abc\0...\0xyz", where the first (resp. last) \0 denotes the first (resp. last) occurence of U+0000, then:
- Only the
abcpart (prefix) will be considered while computing collation keys, the next characters being entirely ignored. - Only the
xyzpart (suffix) will be present in the output array. Note that an input of the form"abc...\0"will lead to an empty output ("").
- Collator: Since
String.prototype.replace()is unsafe (in ExtendScript) as soon as'\0'is involved, input strings are now sanitized before splitting. (In particular, this prevents casual infinite loops in CS4!)
- Collator: Enhanced (and simplified!)
~.SPLTroutine. The separatorU+FFFDis no longer used by default while splitting the input string into keys. It had side effects and no application in the present implementation. (However the option is still available through the 3rd parameterSPLIT_BY_FFFD.)
-
Collator: Added the parameter
RET_MODEingetRichList(). You can now get a full clone of the rich array language list. -
JSON: A more accurate solution has been found for dealing with rich arrays. The JSON string now evaluates to an actual
Arrayobject with additional properties, based on the following pattern:
(function(a,o...){...})([...],{...})
For example, the arr array originally defined by
var arr = [10,20,30];
arr.name = "Hello";
will be stringified '(function(a,o,k){for(k in o)o.hasOwnProperty(k)&&a[k]=o[k];return a})([10,20,30],{"name":"Hello"})'.
This enhancement is required in various contexts, in particular when one needs to clone a rich array and send the result to a ScriptUI ListBox. Indeed this control expects a true Array class at construction time. A fake entity based on __proto__ alteration wouldn't be recognized.
Collator: Added findTailor(iso), a generic public method for translating an isoKey into a valid tailorKey. (See the private routine ~.ITOK.) Unlike setTailor(), findTailor() does not change the current tailoring rules.
ModalScript: Added a public changeLocaleTo(iLocale) method in order to reflect the equivalent feature already available in BasicScript. This routine just reactivates YALT to a different locale, i.e, it basically calls $$.Yalt.activate(iLocale).
JSON: Added support of rich arrays in ~.['\x01Array']. A "rich array" is an Array object whose length is lower than __count__, that is, having additional properties beyond '0', '1'... indices. E.g:
var arr = [10,20,30];
arr.name = "Hello";
New workaround, see [200613]
In this particular case, a regular Object is created (all properties are then explicitly set), and __proto__ is set to Array.prototype.__proto__, so the evaluated result behaves as a regular array (all usual Array members are inherited.) The string $$.JSON(arr) will now look like:
'(function(o){o.__proto__=[].__proto__;return o})({"0":10,"1":20,"2":30,"name":"Hello"})'
which evaluates to a quasi-array arr (arr instanceof Array is true, arr.length is 3, etc.), although arr.__class__ is still "Object" (read-only) and arr.toSource() cannot work.
- Stabilized version (June 1, 2020) including latest fixes, improvements, and additions.
- Added extra info in Root/errors, plus some code refinements.
- Recent fix:
String.prototype.lastIndexOf()patched (CS4.)
- Collator: New extra module that implements a simplified version of the Unicode Collation Algorithm (UCA) in ExtendScript. You can test it using the script CollatorTester.
- MetaCollator: Meta-module for rebuilding Collator resources if needed. See tools/RebuildCollator.jsx for a ready-to-use tool.
- YALT: The default YALT package now offers 300+ essential translation strings in
FR,DE,SP,IT,RU. Most are inherited from InDesign L10N strings so they fit the conventions of the application. - Useful improvement of the main
YALT()function -- aka__()-- which now sanitize any missing argument. That is, if a YALT pattern specifies %i placeholders but you don't supply the corresponding args, thoseundefinedvariables are automatically coerced into an empty string, instead of the string"undefined". For example, calling__("abc%1xyz")without the %1 extra parameter will now return"abcxyz". (In the previous version,"abcundefinedxyz"would have been returned.)
- DateFormat: Versioning and slight refinements.
- Linguist: New module designed as a central place for addressing language and locale data. Its main component (
~.LISO) maps ISO639-1 codes. - DateFormat: Added IT (Italian) and RU (Russian) localization patterns, so the module now supports
EN FR DE SP IT RUdate/time formats.
Env/locale: AddedlocalePrefix(), a getter that simply returns the current locale name prefix, e.g"FRENCH","SIMPLIFIED_CHINESE","INTERNATIONAL_ENGLISH"... Also, thelocaleIdToString(iLocale,keepSuffix)method now implicitly considers the current InDesign locale if theiLocalearg is missing.Ext/string: CS4 patch ofString.prototype.lastIndexOf(), which was unable to addressmyStr.lastIndexOf('\0').
- Unicode: Utility module added for dealing with Unicode data (work-in-progress.) So far, it manages Unicode blocks through the methods
getParentBlock(codePoint)andgetRange(blockName). - MetaUnicode: Meta-module for rebuilding Unicode resources. See tools/RebuildUnicode.jsx for a ready-to-use tool.
Dom/app: Notice and cosmetic refinements (fromLocaleStrandtoLocaleStr.)
- ByteStream: Added the
TAGencoding (equivalent toASC*4) to handle OpenType tag type or similar 4-letter strings. Added a convenienttoSource()method that both supports input and output streams.
- Stabilized version (Feb. 28, 2020) including latest fixes and additions.
- An alternate entry point is provided,
$$.spin.jsxinc, which lets you display a spinner from the including stage. Call$$.spin()at any point of your script/module to get the spinner updated while performing time-consuming tasks. To enjoy this feature, change#include path/to/$$.jsxincinto#include path/to/$$.spin.jsxincin your client script. The method$$.spin()is otherwise transparent. - Recent additions in the
corebranch:String.fromBase64(),String.prototype.toBase64(),String.prototype.rpad(),String.prototype.lpad(),String.levenFilter(arr,str,max),$$.input(),$$.Env.tempRedraw().
- Web: Fixed a typo in
HttpSocket. This was causing a not-a-function runtime error in non-trace mode.
Ext/string: addedString.fromBase64()andString.prototype.toBase64().Root/messaging: slight improvements ; uses a panel in borderless windows.
- Fixed a typo (wrong variable) in
AnyScript/initialize. Ext/string: added string methodsString.prototype.rpad(right padding) andString.prototype.lpad(left padding.)
Root/messaging: Added$$.input(caption,defVal...), which displays a OK/Cancel prompt box. Allows to get an input string from the user. (Supports dropdown list.)
- Dom.Space: Enhanced coordinate processor (see
~.RESO.) Due to a CS6-CC bug affectingAnchoredObject's coordinate system, a stronger routine was needed to support anchored items as well as regular InDesign components. We found a set of fine-tuned workarounds to resolve locations in almost all cases whatever the incoming format (coordinate space, bounding space or ruler coordinates.)
- Dom.Space: Added
fromCustom(), a specialfrom...method that inializes the converter so it takes as input arguments (x,y) coordinates in your own (O,I,J) system. Pass in an array of three valid locations to defineO(origin),I(right point),J(bottom point). This method is useful if your script cannot supply coordinates in the usual XY, UV or RL systems. - In addition, the method
$$.Dom.Space.preScale(kx,ky)provides the option to preset multipliers (x- and y- factors) that the converter will apply to any incoming coordinate pair.
- Dom.Space: Added the method
matrixValues()which returns the internal matrix numbers used byconvert(). (And fixed a minibug inconvert().)
Env/screen: The$$.centerWindow()method now supports its 2nd argument as eitherWindoworLayoutWindowtype. So you can explicitly center a ScriptUI window (1st argument) relative to another one, or relative to a document window (LayoutWindowinstance.) When no 2nd argument is supplied, the method still tries to guess the active screen center point based on internal checks.
Env/script: Added the method$$.Env.tempRedraw()(also available straight in$$). Allows to invoke a specific function (1st argument) and optionally from a particular context (2nd argument) withapp.scriptPreferences.enableRedrawtemporarily set to true during the execution of that function. IfenableRedrawis already turned on, the function is simply executed. If it was turned off, the original state is restored once the function has returned. In addition,$$.tempRedraw(myFunc)returnsmyFunc's returned value just in case you'd need it.
- Settings: Added a
DontCloneglobal option. Usually it's safer to let$$.Settingsperform a JSON clone while setting a key to an object reference (ss.myKey=myObj), because that reference may be lost andss.myKeyis supposed to work anyway. But in specific cases you may want to explicitly prevent the module from cloning objects during script execution, either for performance gain or for bypassing cloning limitations over complex objects like augmented arrays etc. Then you can set$$.Settings.DontCloneto 1 before invoking$$.Settings.declare(...)
- Dom.Space: The
fromUV()method supports a new parameter,centered, that lets you work in a variant of the (u,v) system. When UV is centered, the coordinates[0,0]denote the center anchor, while[1,0](resp.[0,1]) refer to center-right (resp. center-bottom) anchor. This variant is handy when you want to provide signed coordinates in-1..+1on both axes and have a true center point at[0,0]in the bounding box. (Rem: the regular UV system has its origin at top-left and the center point is located at[0.5,0.5].) ScriptUI/colors: AddedscriptUI.colorPen(), which returns a cachedScriptUIPenfrom a uint240xrrggbbvalue. (Simple shortcut toScriptUI.colorSetter.MAKP.)
- ZDeflate: Added the
zlib()method, which embeds the compressed stream within a zlib wrapper.
ScriptUI/colors: AddedscriptUI.colorBrush(), which returns a cachedScriptUIBrushbased on both a colorValue0xRRGGBBand an alpha component in0..1. Fixed a stupid bug inScriptUI.colorArray()(transparency was not treated.)
- Refactored both BasicScript and ModalScript to get all shared code at a single place. Cf
/etc/AnyScript/. These changes do not impact the API, so existing scripts based on either BasicScript or ModalScript infrastructure should still work as expected.
SUI/builder: Fixed a problem inARGS.jsxresandWIND.jsxressnippets. The previous code was changing the input descriptor to adjust thepropertiesobject to its needs. Worked fine unless the client script used a cached object from within a persistent engine! Solved.
Web/HttpSocket: The request headerConnection: keep-alivewas not a good idea. It makes ExtendScript Socket much slower. During a single http GET, there is no reason to require a persistent connection.SUI/builder/WSTA: On Mac OS, changing theenabledproperty may not update the appearence of a visible widget (in particular, the background color of inner components.) The hide-show technique seems to fix that. It is implemented in theHARD_REFRESHsubfunction ofWSTA.
- Web module fully rewritten, with clear dependencies, improved code, etc. Should work much better now, on both Mac and Win platforms!
- ModalScript: Improved get-string-key mechanism (
~._GS_). If the widget under consideration provides agetStringmethod, invoke it. Otherwise, stringify the value. ModalScript/UserInterface: Added theCancelValueattribute (uint, default:2) and fixed the treatment of the value returned from the SUI dialog. TheonClosehook can now handle the dialog retval as such: theokargument isfalseonly if retval===µ.CancelValue.BasicScript/UserInterface: The~._GO_method wasn't supposed to returntruein case the user validates the dialog while noonClosecallback is available. Indeed,truehas the meaning “Skip the server”. This tiny bug had no critical impact in practice, because theonClosehook is almost always implemented!
- Web: finally found a way to escape XMLHTTP
responseBodyin VBS and parse the returned string in JS. Should significantly reduce failures of yourhttpsrequests (in Windows.)
- Ext/string: added
String.levenFilter(arr,str,max). Returns a subset ofarr(string array) whose items are the most similar tostrwith respect to the maximum distancemax. Based onString.levenDist(). A 4th argument allows to make this function case-sensitive, by default it is not.
- Ext/string: added
String.levenDist(stringA,stringB). Returns the Levenshtein distance between two input strings. String.random()no longer usesDatetimestamp, as this caused biases.
SUI/builder/SETK: the special keyoptimalSizecan be used to set bothpreferredSizeANDminimumSizein one step. This is a useful shortcut, since many ScriptUI controls require both apreferredSizeand aminimumSizeto get properly aligned.- Env module: fixed a bug regarding
~.IDEXand the public propertyidexEntryPath(“URI path to IdExtenso Entry Folder, if available”). There was a mistake on the location$.fileNamerefers to in the context of included subfiles. Interesting (and no so obvious) conclusions can be found here.
ScriptUI.builder: Splitted inner functions into separate resources (core/SUI/builder/...). Added state watching and management.
ScriptUI.setFocusimproved and made smarter. SinceGroupandPanelobjects don't provide theactiveproperty natively, it's not easy to implicitly activate the main control within a container. To bypass this limitation, we now provide a generic algorithm dealing with containers although they don't own anactiveproperty.
ScriptUI.builder: the patterns"custom$..."and"...Factory$..."were missing in the reverse routine~.RVRS. Fixed.
- Stabilized version (March 3, 2019) including latest fixes and additions.
- In
Root.unload, added atry..catchblock for nestingapp.activate(). This bypasses a runtime error that sometimes occurs when multiple InDesign CC versions are running in parallel! - Due to
app.layoutWindowsaccess inEnv/screen, theESTKentry point wasn't working anymore! AddedA.layoutWindows = 0;in$$.estkto fix that.
ScriptUI.builder: Assigning falsy or invalid dimensions tosize(resp.preferredSize,minimumSize,maximumSize) could cause runtime errors. Fixed and made safer. See NOTICE, Section 8.
- Env/screen: In ExtendScript, accessing
$.screensfrom within a function scope create an inexplicable(workspace)instance which then alters actual function (workspace) count. A workaround is to access$.screensonly from the[[global]]scope and create a new reference. Functions can then safely read data from that reference. Fixed here.
- Ext/patterns: added
RegExp.JSID, a regex for testing basic JavaScript identifiers of the form^[\$_A-Za-z][\$_A-Za-z0-9]*$. Keep in mind that this pattern is for simple checking only, it does not detect reserved tokens.
ScriptUI.builder()now supports a special type,"list", for declaring either aListBoxor aDropDownList, depending on the flag...properties.dropdown.
- Slight change in
ScriptUI.forceRedraw()(cf SUI/mini) using specialized routines for list controls (ListBoxandDropDownList).
- Enhanced Root/help, based on my recent study of multi-column
ListBoxcontrol in ScriptUI. Improves the refresh mechanism of$$.help's listbox.
- Settings: made the
backupmethod JsxBlind-safe, using thecallee.ARGtrick. Discussion here: “The Case of Nested Variable Names”.
- Stabilized version (Feb. 04, 2019) including latest fixes and additions.
- Root/$$.messaging.jsxinc: bug fixes.
- Added the
Evententry in Root/casting. - Added
globalEvent()in Env/script. Returns the global DOM event in case your script is triggered from the app as an event handler (e.g from aMenuActionlistener.) - Fixed non-declared
qargument in Env/screen.
-
Splitted the Env module into subparts throughout the
Env/directory :#include 'Env/$$.system.jsxinc' #include 'Env/$$.script.jsxinc' #include 'Env/$$.application.jsxinc' #include 'Env/$$.locale.jsxinc' #include 'Env/$$.screen.jsxinc' #include 'Env/$$.unit.jsxinc' #include 'Env/$$.user.jsxinc' -
Fixed problems with active screen detection -- Env/$$.screen.jsxinc -- now delayed to
Env.onLoad()for addressing cases where the active monitor changes within a session. -
Added
$$.Env.system()-- cf Env/$$.system.jsxinc
- Env/$$.screen.jsxinc: the new method
$$.Env.screenIndex()returns the index of the monitor that contains a point[x,y]specified in screen coordinates. Useful to identify the screen in which a window is shown. - The new method
$$.Env.setActiveScreen(index)allows to register, from any point of your code, the index of the active screen as soon as it can be determined, e.g. whenapp.activeWindowexists. Registering the active screen improves messaging functions and may help you position UI stuff with respect to the application area. - Added
$$.Env.getActiveScreen()too.
- ScriptUI/$$.layout.jsxinc added. This small extension allows to register a layout handler, that is, a special function that automatically executes when the attached UI component (a ScriptUI container) is subject to the layout manager. As explained in the NOTICE, “this technique makes it possible to update some attributes (including those of dependent widgets) when the component is laid out, despite the fact that no native event is associated to this particular process. Typically, the layout mechanism takes place just before the
showevent of the Window (unless the code explicitly invokes thelayout()function at some point.) Hence, an interesting use of handling our fake_layoutevent is to perform last-minute adjustments on particular containers before the window shows up.”
- ScriptUI/$$.colors.jsxinc required the precondition
if( $$.isBooting() ){ ... }in order to work fine in persistent engines. As a general rule, any extra snippet should make sure that it loads stuff at include stage under$$.isBooting()condition. - ScriptUI.setFocus() added in SUI/mini. Forcibly set the focus on a control, as
myControl.active=truedoesn't do the job right.
This update (Jan. 20, 2019) applies an important change in the directory structure: the minimal ScriptUI stuff is no longer part of the Ext dir (reserved to “external” features). The code has been moved into a dedicated SUI folder. As a result, core/Ext/$$.scriptui.jsxinc is no longer available; and the entry point $$.jsxinc reflects new locations and structure:
#include 'core/$$.Ext.jsxinc'
// ---
#include 'core/$$.Root.jsxlib'
#include 'core/$$.Env.jsxlib'
#include 'core/$$.JSON.jsxlib'
#include 'core/$$.File.jsxlib'
#include 'core/$$.Log.jsxlib'
#include 'core/$$.Dom.jsxlib'
// --- [190120]
#include 'core/$$.SUI.jsxinc'
SUI/$$.mini.jsxinccontains basic extensions of theScriptUIobject: alignment shortcuts,ScriptUI.isWidget(),ScriptUI.forceRedraw(), etc.SUI/$$.builder.jsxincspecifically provides theScriptUI.builder()function, fully documented. It now deals consistently with{ orientation:"stack" }in whatever platform, fixing the well-known incompatibility between Windows CS and other environments.- SUI needed a special treatment because of those environment issues. The snippet is included after other core modules so that it can invoke
$$.Envfeatures such that$$.inCC,$$.inWin, etc. - Other small fixes are included in version 1.90120.
- ScriptUI/$$.colors.jsxinc added. This snippet loads various color-related methods in
ScriptUIto make background/foreground management easier and safer in cross-version scripts. NOTE: This is an optional snippet (etcbranch) so you have to explictly include it in your project for using those features:#include './etc/ScriptUI/$$.colors.jsxinc' - ScriptUI.forceRedraw() added. A short function that forces a given widget to invoke its
onDrawhandler (if available.) Useful when a special refresh/repaint mechanism is required on a custom UI component.
- ScriptUI.builder() deeply redesigned. Added
addKeyHandler()andremoveKeyHandler()utilities.
- Stabilized version (Nov. 28, 2018) mostly including cosmetic adjustments.
Ext/$$.function.jsxincandExt/$$.object.jsxincnow use a special function flag,$TMP$, that tells the root cleaner (cf~.ISCL) which keys must be deleted from the[[global]]space at load-time.$$.estk.jsxinctakes advantage of the change mentioned above.$$.Root.jsxlibdeclares$$.resolve()and$$.isModule()a bit sooner to make those features available when including inner snippets likeerrorsormessaging.- The method
$$.error()is now available in the[[global]]scope as well, due to a frequent usage in so many modules and snippets. Instead of$$.error(), just callerror().
- ZInflate and ZDeflate modules now available. Port the inflate/deflate algorithms into ExtendScript. Useful for decompressing and/or compressing strings of reasonable size, e.g PNG
IDATchunks...
- ByteStream: added the optional param
last(integer) in thetoString()method. Allows to get only the specified number of trailing characters—i.e, from the end of the stream—rather than the entire string. Also added the methodgetSource()that simply returns the source of an input stream; for output stream result isfalse.
- Stabilized version (Nov. 17, 2018) that integrates various additions from the previous weeks.
Ext/$$.global.jsxincis a new snippet included from$$.Ext.jsxinc. It provides an important fix to$.global.parseInt()after the discovery of a critical, native bug in ExtendScript.Ext/$$.scriptui.jsxinc: nowScriptUI.builder()autosets thenameproperty of the output widget, provided a name is available and wouldn't override an existingnameproperty. This improvement is useful in event handlers that require simple name checking rather than deeper identification steps.
Ext/$$.string.jsxinc: addedString.random(), a simple method for randomly generating lowercase, alphanumeric IDs of a determined length. By default,String.random()returns a string of 4 characters (e.g"i1x4"). Pass in the desired length if needed. The result is guaranteed to match the pattern/^[a-z][0-9a-z]*$/(that is, the first character is always alphabetic.)
- Meta, added the
parseHeader()method, which somehow reverses theheader()function. It recovers (key,value) elements from a header string. (Useful when parsing IdExtenso files.)
- Progress, porting the logics of ProgressBar.jsx in IdExtenso.
- ByteStream, a class to easily handle binary data stored in files. Deals with strings, characters, hex format, signed and unsigned integers (byte, short, int24, long), float (32bit) and double (64bit) numbers. Supports BE and LE ordering. Goto the NOTICE for details.
Ext/$$.string.jsxinc: addedString.fromUTF8()andString.prototype.toUTF8().
- ModalScript: still improving default getter/setter mechanisms.
Ext/$$.scriptui.jsxinc: If unassigned, thehelpTipproperty inherits from parent's help tip (inScriptUI.builder.) Useful to spread a tip throughout a container.
- ModalScript: small fix in
~._SV_(theitemsproperty of a list wasn't properly parsed thru the autosetter algorithm.) Added the methodWindow.prototype.getWidgetKey(cf.~._GW_) to mirror BasicScript's API.
Ext/$$.number.jsxinc: changed thetoSource()method so it supports amodeargument for compact vs. short vs. native output string. By default (mode=0) the function removes leading zero from floating-point number in )-1,1(. For instance,(-0.75).toSource() -> "-.75".
Ext/$$.number.jsxinc: addedNumber.fromIEEE754_32(hexStr)andNumber.prototype.toIEEE754_32()for decoding from (resp. encoding to) IEEE754 32bit format (single-precision floating-point representation.) Keep in mind that JS numbers are still double (i.e float64), so you cannot assert, in general, thatx === Number.fromIEEE754_32(x.toIEEE754_32())for any JS numberx. However, the hex-to-number conversion is safe:hex8 === (Number.fromIEEE754_32(hex8)).toIEEE754_32()(OK.)
Ext/$$.string.jsxinc: PatchedString.prototype.split()for CS4.
Ext/$$.string.jsxincnow implementsString.prototype.codePointAt()as specified in ECMA-262 9.0.
Ext/$$.number.jsxinc: addedNumber.fromIEEE754(hexStr)andNumber.prototype.toIEEE754()for decoding from (resp. encoding to) IEEE754 64bit format (double-precision floating-point representation.)
Ext/$$.string.jsxincnow implementsString.fromCodePoint()as specified in ECMA-262 9.0, including the ability to supply anArrayof code points rather than an arg list. The purpose of this function is to allow to build a JS string (sequence of UTF-16 units) from code points that may be greater than 0xFFFF, that is, in the range U+10000-U+10FFFF. This then involves surrogate pairs as defined by the Unicode standard.
- Introducing the MatrixArray module, a tool for dealing with transformation matrices throughout
Array.prototype, without involving DOM objects :-)
$$.estk.jsxincadded. An alternate entry point for using IdExtenso from ExtendScript ToolKit--without InDesign. Experimental feature.
- Dom.Space: Added a patch
MasterSpread.prototype.resolve()for InDesign CS4. (For some reason this method is not available in the CS4 DOM whileSpread.prototype.resolveis OK. Thanks toPage's API we can implement a fully functionalresolvemethod for master spreads. See detail in the COMPATIBILITY PATCHES section.)
- Dom.Space: a new DOM oriented module aimed to simplify management and conversions throughout InDesign coordinate systems.
- BasicScript and ModalScript now provide the user with the option to reset the preferences (Settings) to factory values when an error occurs. (Of course this is just a workaround in case your script, being in debug phase, does not properly address weird or out-of-range settings. This event is not supposed to occur in the final release of the script! Also, keep in mind that an error is not necessarily caused by wrong settings...)
- Settings: the
backup()method now calls the internal~.BCKProutine from withinapp.doScript(..., UndoMode.autoUndo), which prevents this step from being undone. Usually, when a user runs a script and validates the UI, s/he expects Undo to reverse the process but wants the settings to reflect the validated choices.
- Introducing ModalScript (
/etc/ModalScript), a variant of the BasicScript module that supports ScriptUI dialogs instead of DOM dialogs. While BasicScript relies on the Dom.Dialog module, ModalScript only involves theScriptUI.builder()routine available in the core branch. Aside from that, ModalScript provides the same functionalities based on Settings and Yalt.
- Added
$$.yesNo(). And the whole messaging toolbox -Root/$$.messaging.jsxinc- has been re-factored, now usingScriptUI.builder's API--much more secure than the old ScriptUI resource strings! - Fixed a bug in
Dom.Dialog['~'].XDLG(XML dialog builder): needed to changewx.name()intoString(wx.name())to prevent the code from handling a QName object. (This bug had undesirable side effects on InstantDialog.jsx sample script.)
core/Root/$$.help.jsxinc: Improved the implementation of the dialog -- it now usesScriptUI.builder():-)ScriptUI.builder()now parses event types preceded by an underscore (e.g_mousedown) and declares the corresponding event listener if the associated value is a function.
Ext/$$.scriptui.jsxinc: Added the staticScriptUI.builder()method. Provides a compact and generic tool for building resource-based user intarfaces (fullWindowor custom components.) Unlike the native 'resource string' mechanism which involves literal strings and therefore leads to issue when dynamic data are to be treated,ScriptUI.builder()deals with actual objects whose internal data may still be browsed and refined just before being sent to the builder.ScriptUI.isWidget()is a companion tool ofScriptUI.builder; its internal map might be used in more advanced modules.- Also, we have fixed the combined alignment shortcuts (
ScriptUI.LT,ScriptUI.RT, etc) as the numeric values caused problems in recent ScriptUI versions.
- Added string truncation methods
trunc(),rtrunc(), andltrunc()toString.prototype; cf polyfill inExt/$$.string.jsxinc.
- Introducing the Meta module. Will provide tools for building IdExtenso components (file templates, etc.)
- Added
String.prototype.relativePath()and much more detail on all these POSIX-path-oriented routines:asPath(),toPath(), andrelativePath(). These methods are internally used by the framework to manage module relationships, but they can do a great job outside too. In particular,myFolder1.fullName.relativePath(myFolder2.fullName)returns the relative path frommyFolder1tomyFolder2in"../../path/to"form. The code works with generic strings as well, subject you use the universal/separator.
- Entry Point (
$$.jsxinc) now allows up to 9 formal arguments in automatic methods and contructors. Indeed, there are cases where the__auto__property of a module may refer to a function that expects many parameters. The previous implementation was using a general(x,y,z,t)argument list limited to four parameters. Same thing with constructors built from theCLASSmacro. (REM. - For technical and performance reasons, IdExtenso does not invoke theargumentsproperty ofFunctioninstances. This would pollute ExtendScript memory with additional[Workspace]objects that puzzle garbage collection.) - Added the method
$$.failure()inRoot/$$.messaging.jsxinc.
- The Dom.Dialog module now provides a public property
SmartMeasurementBoxes(0 or 1) that affects the behavior of getters and setters attached to measurement controls (MeasurementEditboxandMeasurementComboboxinstances.) In summary,SmartMeasurementBoxes==1guarantees that numeric values managed through the module interface are understood relative to the control unit (editUnits). This is useful when you need to set, get, and compute magnitudes straight into a particular unit (instead of points.) More details in the NOTICE. - Small addition: Dom.Dialog also installs the accessor
Dialog.prototype.getWidgetKey()which returns the widget associated to some key. Usually you don't need this, since the existing getters and setters do a great job while hiding access to the DOM widget. Just in case you'd need more tweaking capabilities... - The UserInterface submodule of BasicScript now has a public flag
SmartListItemGetter(default=0) which improves the getter mechanism of key-based dropdowns. By default, the current item is returned by index (its index in thestringList.) But ifSmartListItemGetteris set to 1, then any Settings key that has been declared as a string will be returned as the corresponding string in the list. This option is useful when you don't want to manage dropdown's list from the outside of the XML UI resource (the string list is fixed and you don't care about item indices, what you want is only the selected item, as a string.)
- Added
$$.Env.toPoints(myValue,myMeasurementUnits), a basic tool that converts a value, given in someMeasurementUnitsenum, into POINTS. Promoted in$$($$.Env.toPoints===$$.toPoints). Example:$$.toPoints(10, MeasurementUnits.AGATES) => 51.4285714285714. - Thanks to sysys.blog.shinobi.jp/Entry/20/ the Unit module now supports conversions involving
MeasurementUnits.BAI(6.336pt) andMeasurementUnits.U(0.792pt). See the private method~.FEED()for more detail on howUnitDatainstances are loaded. $$.Env.isUnit()now supports numeral inputs, that is, strings having the form"2054187384"or"0x7A696E63". (Useful in XML context.)
- Yalt : The
YALTroutine now automatically handles terminators:.and!. For example, if"Hello"has a translation while"Hello!"is not registered, then__("Hello!")is interpreted as__( "%1!" , __("Hello") ). - A temporary global
__jsxinc__is declared in$$.jsxincto keep track of the entry point location. - Env : Added the
userName()method. Added theidexEntryPathproperty. Added thescriptsPanel()method (returns the path of the Scripts Panel folder in either app or user branch.) - Dom.Dialog : Added the global attributes
captionWidth(resp.editWidth) for declaring defaultminWidthfor labeled (resp. editable) widgets. Example:<Dialog name="My Dialog Title" canCancel="true" captionWidth="100" editWidth="150">....
- Added the Unit module, a consistent facade for handling metrical units. Test script: PlayWithUnit.
- Corrected a few typos in Dom.Dialog comments. Added the alias
selectedfor either Dropdown or RadiobuttonGroup widgets: it is interpretedselectedButtonin case of radio group, andselectedIndexin case of dropdown. - Dom.Dialog now installs a method named
Dialog.prototype.getStringKey(k)which, unlikegetValueKey(k), returns the string associated to the accessed widget. Useful for dropdowns and similar widgets that basically would return an index. - Added a pattern for the vertical line
|(i.eU+007C) incore/Ext/$$.patterns.jsxinc. It definesString.OR,RegExp.ORetc.
- Introducing the Dom.Style module (
/etc/Dom.Style) for handling and browsing InDesign DOM styles (character/paragraph/object styles.) The automatic method isflatList(), a very flexible routine whose options are detailed in the code.
- JSON : In ExtendScript the test
x===nullis not reliable whenxrefers to aUnitValueinstance whose value is in the range )-1,1(. Indeed, due to an implementation error regarding the===operator,UnitValue(0.5,'pt')===nullis true! TheLAVEroutine has been updated to work around this bug.$$.JSON(UnitValue(<any>))now works fine whatever the magnitude of theUnitValue.
Ext/$$.number.jsxinc: static routinesNumber.parse()andNumber.format()added, with basic localized delimitersNumber.DecimalCharandNumber.ThousandsChar.
Ext/$$.number.jsxinc: AddedNumber.prototype.toDecimal(), a variant oftoFixedthat fixes rounding issues and provides more control over the decimal notation.
Ext/$$.number.jsxinc: AddedNumber.flatten()(static) for coercing the exponential representation of a Number into its decimal form. E.g:Number.flatten(1.234e-8) -> "0.00000001234". Also supports string-to-string conversions, e.g:Number.flatten("12.345678e-15") -> "0.000000000000012345678".
$$.unload()(Root module) now supports an argument namedKEEP_DORMANT, falsy by default. The client code can use it to prevent IdExtenso from waking up InDesign when the framework is unloading. The main usage of this flag is to keep active an external process launched by your script at the very end of its own procedure, for examplemyFile.execute(), etc.- The BasicScript module (
etc/$$.BasicScript.jsxlib) takes into account the previous point. It now conveys the returned value fromContext.onQuit(hook) to$$.unload().
Ext/$$.patterns.jsxinc: addedRegExp.SPCEfor capturing controls and InDesign specific space caracters.Ext/$$.string.jsxinc: addedString.prototype.stripSpaces()for removing outer and inner spaces from a string. Also,U+205F(MEDIUM MATHEMATICAL SPACE) is now seen by thetrimmethods.
- Env now includes
Env/$$.screen.jsxinc, a snippet that collects data relative to the current display config ($.screens, ScriptUI workspace, active window bounds (if available) and additional information fromapp.generalPreferences(mainMonitorPpietc.) The main goal here is to get more control over issues that involve screen coordinates and HiDpi (4K, Retina.)$$.Env.summary()now returns these extra infos.
- BasicScript module. Added
changeLocaleTo()in the public API. Allows to reactivate Yalt to a different locale, making sure the UI is accordingly rebuilt.
- Added
Dialog.prototype.changeUnitKey()from Dom.Dialog. Useful to dynamically update theeditUnitsproperty of a measurementUnits box, for example, if you want your dialog units to match those indocument.viewPreferences. - Added
$$.Env.isUnit(<any>), a little method that checks whether the passed argument refers to aMeasurementUnitsnumber, key, or Enumerator, in whatever InDesign version. BTW, I madeisUnitavailable straight in$$using<fct>.copy('..').
- Introducing BasicScript and its child modules Context, UserInterface, and Server. Read the notice first! (Concrete examples coming soon.)
- Added
Dialog.prototype.changeListKey()from Dom.Dialog. Useful to dynamically update thestringListproperty of a widget. The routine tries to maintain a consistent item index if possible (that is, if the new list still contains the current string.)
- Settings module. Added the
hasKey(str)method so one can check whether some key is actually declared (before activation.) Added a BACKGROUND text that should make this (great) module more intelligible ;-) - Created a private
ELOG()routine inRoot/errorsto make error logs more modular.
- Added the Dom.Dialog module in the
etc/branch. Provides a simple API for creating and managing DOM dialogs using XML descriptors.
- Yalt module. Various fixes and improvements.
- Settings module. Added the
hasScopemethod to quickly answers questions like, is there a SESSION-scoped parameter among my settings?, etc. - MD5 module. Slight enhancement of the trace: it now shows the input string if it has less than 50 characters.
- File module. Changed the default temp file suffix into
txt(sincetmpmay cause the OS to simply ignore theexecutemethod.) Also,File.temp()now provides a fallback mechanism in caseexecute()returnsfalse.
- Added the Complex class for making easy to deal with complex numbers. Many operators and methods are available.
- BigInt. Better implementation of the
+operator when aBigIntis mixed with a string. Now interpreted as aconcatoperation. So"Result: " + BigInt(1000)will promptResult: 1000as (likely) expected. Idem withBigInt + str.
Ext/numbernow performs a polyfill forNumber's static members specified in ECMAScript 2015. Namely:EPSILON,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER; and the methodsisInteger()andisSafeInteger(). From now you can use code likeif(Number.isInteger(x)){...}in your project.- Important fix in the BigInt module. In
prototype['<']andprototype['<=']the reversed argument wasn't listened to, so the schemenumber < thiswas improperly parsed asthis['<'](number), leading to serious problems! For example,999 < BigInt(1000)was said false. (Detail.)
Settingsupdated. Various bugs fixed. Now supports session-persistent keys :-)
Ext/regexpnow provides the static methodRegExp.escape(), inspired by Benjamin Gruenbaum. Basically, you can inject the result ofRegExp.escape(myString)into a regex with no edge effect. This implementation offers a 2nd parameter,intent, in order to fine-tune the process in special contexts, in particular those that may involve literal regexes.Ext/patterns: added regexes intended to deal with escape issues:RegExp.RESC(canonical escaping class),RegExp.RSAF(stronger security),RegExp.RLIT(literal intent.)Ext/strings: our greatString.prototype.toSourcemethod now allows thequotesparam to befalse(strictly), so that the result is not nested within quotes and does not backslash inner quotes. Handy in special cases (playing with literal regexes, etc.)
Ext/fileadded, intended to extendFile.prototype. So far it only introduces the methodnudeName()which just returns the file name without its extension. (REM: Do not confuseExt/filewith the File module.)- Exposed the
stamp()utility in the API of the File module. It basically invokes the private~.STMPfunction, which builds a unique name for temporary files. Call$$.File.stamp()to use this feature from anywhere.
- Updated the File module to keep it in sync with local changes, but still working on making it cleaner...
- Added the Markov module (
/etc), a simple (and fast) implementation of Markov chain.
- Various unnotified changes in JSON. The
lavefunction now supports a third paramFORCE_OBJthat allows to browse special objects (such thatScriptUI,BridgeTalk…) which otherwise wouldn't expand. Also, theDOM_ACCESSparam can be set to-1. Ext/number: Implementation notes and small fixes.
Ext/enum: therevSourcemethod had no name. Fixed.Ext/regexp: the==operator had no name. Fixed.Ext/string: thecharSetmethod had no name. Fixed.
- Added the
$$.help()utility. Seecore/Root/$$.help.jsxinc. Display all API infos available from the included modules. - Added the
Function.prototype.sendutility, available at including stage. Provides to any public or private method being declared the ability to invoke<context>[<meth>](this,x,y)then return itself. - Enhancement of function signatures (casting) in various
etc/modules (Random, SHA, BigInt).
Ext/patterns: Added a regex for capturing ExtendScript operators (RegExp.EXOP).
- Added the
__core__property inMODULEandCLASSmacros ($$.jsxinc).
- Added the
/toolssubdir (intended for extra dev tools.) Not part of the framework.
- The entry point (
$$.jsxinc) now calculates the engine state before$$.load(). - Typo fixed in
$$.Env.engineState. $$.loadupdated (Root). In case IdExtenso's name is not"$$", remove the key$$from[[global]]. This cleanup step was previously done from~.ISCL(), but it is better to keep$$available up to this point.
- Env now exposes the
runningScriptproperty (URI pathname to the running script file.) - Log: Added an explicit
typeof logLeveltest, since ExtendScript wrongly regardsundefined < 0as true! - Added
$$.isModule()in Root. Tells whether a path, or a function, refers to a module. $$.error()entirely rewritten.- Web module: Added an error case in
get(). - Various unnotified changes.
Web.get()now supports https on Win platforms (through VBS, non-modal state assumed.) See~.ALTGin/etc/$$.Web.jsxlib.
- 'JSON Hook' mechanism introduced to allow any IdExtenso-compliant module or class to inject its own method for generating a source string. Details in
/core/$$.JSON.jsxlib. - Added
toSource()in BigInt prototype (/etc/$$.BigInt.jsxlib), and implemented its own JSON hook (see the privateJSONmethod) in compliance with JSON module. As a result,$$.JSON(BigInt(123456),0)outputs the compact string'BigInt("123456")', while$$.JSON(BigInt(123456),1)returns the expanded object source with noBigIntreference, that is,'{ "neg" : 0, "size" : 1, "0" : 123456 }'.
- Added a few comments to the JSON module (core), pending to address a design issue, namely, how is JSON supposed to deal with IdExtenso-based entities, such as modules or BigInt instances?… Ongoing reflection.
- Introducing the SHA class (
/etc/$$.SHA.jsxlib), the complete family of Secure Hash Algorithms as defined in FIPS PUB 180-4, FIPS PUB 202, and FIPS PUB 198a (HMAC). Implements: SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-3-224, SHA-3-256, SHA-3-384, SHA-3-512, SHAKE128, and SHAKE256. The subclass Int64 (/etc/SHA/$$.Int64.jsxlib) encapsulates 64-bit integer structure for bitwise calculations (taking advantage of ExtendScript's operator overloading.)
- Cosmetic addition: background & notice of the MD5 module (
/etc/$$.MD5.jsxlib).
- Added the Random class (
/etc/Random.jsxlib) and its dependencies, cf./etc/Random/directory.
- Major additions in both the entry point
/$$.jsxinc, the root module/core/$$.Root.jsxlib, and the function extension/core/Ext/$$.function.jsxinc. A new macro is introduced,CLASS, which allows to declare the underlying module as a constructor (i.e, it can instantiate things) while preserving the overall paradigm of the framework ([PUBLIC]vs.[PRIVATE]zones.) Unlike regular MODULE entities, a CLASS module supports the keys[STATIC](equiv. to[PUBLIC]) and a specific one,[PROTO]. The latter is used for prototyped members. A class builds instances through acreate()method which, if available, is automatically invoked by the constructor (that's something of a factory.) - Added a (single) call to
$.hiresTimerin$$.load()for the purpose of storing a load timestamp in microseconds. Made public via$$.getLoadStamp(). To be used by entropy collectors. - Introducing the extra module
/etc/BigInt.jsxlib, aka BigInt, a huge piece of code which implements in pure ExtendScript the famous BigInteger interface. Once included, just use$$.BigInt("123456789123456")to handle an immutable arbitrary-precision integer. BigInt operators are overloaded so that you can compute expressions such as(X*9999)%Y-(Z+1234), whereX,Y,ZareBigInt.
- Fixed integer code (
U53 -> I53) in$$.casting.jsxres.
- Major update of the Env module now including a Windows version checker based on
File.batchToString("VER > %1"). Allows to fix OS signature in ExtendScript versions that return a wrong$.osstring. - Updated
File.batchToString()in the File module. Now requires a%1placeholder for the temporary output. - Added
readUTF16(),writeUTF16(), andappendUTF16().
- Added
File.batchToString(/*str*/myCommand)in the File module. For the time being this method is only available to Windows platforms. It allows to quickly send a batch command that supports> fileoutput, and returns the result as a string. For example,$$.File.batchToString("VER")returns the result of the command> VER. Handy and transparent!
- Added the byte type (i.e
int8) in$$.casting.jsxres.
- Better type checking in
$$.success()—making sure it treats the relevant params as strings.
- Added the Window.update() trick in
~.SLMG()(sleep message), thanks to forums.adobe.com.
- Slight improvement of
JSONmodule: saferNaNstring no longer relying on[[global]].NaN(which is writable.)
- Included the messaging API (quick prompts etc.) in the Root module. Method:
$$.success(message). - Added
$$.Web.browse(url)(in the Web module), which allows to open an url in the client-side browser.
- Added
File.macLineFeed(),File.winLineFeed(), andFile.unixLineFeed()to control newline character(s) during file creation.
- Web: Bug fixed in
Web.get()whenisTextoption was turned ON. (No data were returned.)
- Yalt: Added
Yalt.hasKey()(check whether a translation key is present); fixedYalt.onLoad()signature.
Ext/$$.number.jsxinc: addedprefixandzeroPadparams toNumber.prototype.toHexa.
- Various unnotified changes in JSON, Env, etc.
- IdExtenso alpha release.

