- 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 codenb
is 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.jsxres
output (sorted list.) - Collator.
$$.Collator
's tailoring rules andLING
map have been updated from$$.MetaCollator
. This basically reflects theno
→nb
change in$$.Linguist
: the Norwegian Bokmål language should now be accessed from thenb
key 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
pageMatch
method: you can now specify the first (resp. last) page of a section usingMySecIdentifier:<
(resp.MySecIdentifier:>
).
- Collator: Changed the logic of the
~.TMAP
routine: when processing a>n
operator 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 3zzV
structure. 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
$$.Collator
as a diacritical variant of Ее (U+0415/U+0435). ~.TLRM now provides a dedicated set of tailoring rules for Russian (ru
key). 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
forceRedraw
function (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 (theinputArr
argument). 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
UIColors
enumerators and alternate[r,g,b]
colors. Use theencode
/decode
methods to manage color assignments and translate data in common#RRGGBB
form.
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: thexyOutput
argument 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 dedicatedCONST
branch
it is safer (and required!) to explore each option when extracting existing settings from the declarator object.
- Dom.TextParcels:
getSamples
options now support a boolean property,unionStyles
, that tells whether target Character Styles and target Paragraph Styles (cfthis.options.csIds
andthis.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.Space
now 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 akeydown
event 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
/jump
settings).ScriptUI.EditIntegerFactory
now has a staticGroup()
function that can integrate a stepper with the EditInteger component.ScriptUI.StepperFactory
is 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:
forceRedraw
now 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_INTEGER
andNumber.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$$.Unit
can still convert and display those values in any other user-friendly unit.
- SUI/mini: Added the optional 2nd argument
TRY_NOTIFY
inScriptUI.forceRedraw
. In some environments—mostly CC versions—the commandmyWidget.notify('onDraw')
might work, although not 100% safe. TheTRY_NOTIFY
flag makesforceRedraw
try this approach first, using the schemetry{ wg.notify('onDraw'); retval=1; }catch(_){ retval=0; }
. If it fails, the regularforceRedraw
strategy is used.
Edit(Factory)
: Slight change in the watcher callback, thevalue
key is now re-normalized even ifthis.text
already 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 returnnv
in the valid value type.- Yalt: Added the key
"Invalid numeric value"
in the resource file. - Unit: The static
$$.Unit.DecimalChar
property 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.DecimalChar
when your script starts up (or whenever needed.)
- Unit: Fixed wrong formatting of zero in
$$.Unit.format()
when 'pc' or 'ci' unit is involved withUseTypographicNotation
turned 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 whateverMeasurementUnits
mode. Supportsfalse
as 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_VALUE
mode, 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
):append
can now digest most not-well formedEndnoteRanges
, based on a more general detection pattern:/\uFEFF[^\u0004\uFEFF]{0,2}\u0004/
. This reduces the cases whereDom.TextParcels
fails to parse document endnotes (in particular, imported notes that tend to alter the regularU+FEFF
U+0004
sequence.) 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,append
now 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
forceSectionPrefix
in 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
forceSectionPrefix
parameter in the constructor options (ini
argument). 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 (cfpagesMap
property) 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 supportingfalse
as 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_VALUE
mode, 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.measurementUnit
is 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 whateverMeasurementUnits
mode —you often need points— and automatically restores the original context when$$.Env
is unloading. In CS5/CS6/CC it's just a matter of setting and restoringapp.scriptPreferences.measurementUnit
; in CS4 we need to temporarily change theviewPreferences
property of the host object (active document assumed, if available). The whole mechanism is now implemented in the unit.jsxinc snippet (part of theEnv
module). 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 aMeasurementUnits
enum or the equivalent number; if no argument is supplied,MeasurementUnits.POINTS
is assumed.
Edit(Factory)
andEditInteger(Factory)
: These advancedEditText
factories 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.TextParcels
is 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.prototype
has been augmented from the client code:myArr.__count__
then mistakenly increases byArray.prototype.__count__
(natively 0), which led$$.JSON
to 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 patchindexOf
in 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~.BRKN
filter completely transparent (for almost two years!), which resulted in an InDesign crash whenever you had to stringifyapp
orDocument
objects :-/ (Reminder: The reason for this filter is to prevent browsing of buggy DOM properties likeapp.scriptPreferences
or.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.NoCharWidth
returning 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_SEL
argument 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~.CATG
map 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:CheckListFactory
tries 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
:startupAlias
fix. Solves the “tt.nudeName is not a function” error.- Ext/file:
nudeName
fix. - Added the method
File.prototype.fresh()
(returning a non-existing File instance based on the present File object). Env
: added theisHighContrast
property (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.elision
option. 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\x01
wasn'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 thestartupAlias
method. It could produce a runtime error “tt.nudeName is not a function” becauseFile.prototype.resolve()
can sometimes result in aFolder
object (!)
- 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$$.Settings
remains 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.Context
to 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
,$$.UserInterface
and$$.Server
to 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
MenuExtension
visible 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'sfactories
for handling the optionmore
. Do the same with your own factories if needed. -
Updated all existing factory components so they now support the option
more
when you call the factory. This must be anObject
having 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 amore
object: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
RectPack
module, 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 optionsreduxPair
andreduxMore
to theformat
method.
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, theonLoad
method 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)
.
Env
now exposes aisHighContrast
property (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$$.isDark
and$$.isHighContrast
allows 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$$.ScriptUIFactories
that connects any factory to IdExtenso'sonEngine
/onLoad
/onUnload
callback mechanism. Thus, you can declare a staticonLoad
method (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.onLoad
is 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,$$.isDark
may 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 theonLoad
callback: the components now fit dynamically the InDesign UI theme.)
- Added the module
Dom.Endnote
, the counterpart ofDom.Footnote
for endnotes. Both now rely on a common toolbox.
Check(Factory)
andDrawnCheck(Factory)
: Better detection of Ctrl+Click.
DrawnCheck(Factory)
. Technically, theonClickChange
handler of your DrawnCheck component receives as 1st argument a customclicked
event 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 theclicked
event. 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
#targetengine
directive. 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 is120
which merges the scopesENGI|SESS|OBJ|APP|HYB
and 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_SESSION
env 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
UNIQ
property inselect()
.
- Linguist: Made the
~.LNGS
map 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._OR
capturing 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
GREEK
andCYRILLIC
attractors 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
~.TMAP
routine. 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
~.WSYS
in 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.prototype
so 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.split
wasn't working as expected on strings that do not contain U+0000. It is now fixed. 2.RegExp.escape
wasn't supporting the empty string. Fixed! 3.RegExp.fromCodeRanges
had a logical bug related to surrogate pairs. Fixed! Also, the special escape sequence\-
is now used for U+002D, instead of\u002D
which is not properly handled in ExtendScript. In addition,fromCodeRanges
supports a new option as 2nd argument,OUT_MODE
(set it to-1
to 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 customizedonDraw
callback. Unlike PNG sprites (that consume more memory and undergo UI scaling issues in various environments),DrawnCheck
components are purely drawn from theScriptUIGraphics
canvas. 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 mainformat
method (see the specification of theoptions
argument.) In substance,singletons
allows 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$$.PageRange
to 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 theroot
option which tellsScriptUI.CheckListFactory()
to automatically prepend a root node on top of all supplied branches. If<yourOptions>.root
is 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,preCheck
keeps 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
app
is 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 likeFootnoteNumberingStyle
and 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
~.SCRI
mapping 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 commandsextractLabel
andinsertLabel
are 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.xyz
to the corresponding JSON string while saving the data. Note thatmyObj.xyz
should 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 aBook
on 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$$.Settings
methods 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 withModalScript
semantics regarding theSmartListItemGetter
option. 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.builder
resource 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\u002D
which is not properly handled in ExtendScript's RegExp classes. In addition,fromCodeRanges
supports a new option for its 2nd argumentOUT_MODE
: set it to-1
to 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
parse
andnormalize
now support themap
argument 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 theactive
property and could receive the focus, but you made it behave so that it does not respond to thefocus
event. In such case you want to informScriptUI.setFocus
that it should ignore your component. This is now possible usingmyComponent.__cantFocus__ = true
.
- Dom/items solves the issue of retrieving items (from any
Collection
or 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.LINE
in Ext/patterns, SUI/builder can optionally preventhelpTip
inheritance 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.
enabled
andvisible
properties) configurable at creation time forCheck(Factory)
,CheckGroup(Factory)
andCheckList(Factory)
. This allows you to predefine states straight from theoptions
object.
- Improving the
Popup(Factory)
. 1. Added a cache to avoid re-processing the same arguments from theupdate
method 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
CheckList
component 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
SideMenu
component 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/:
Check
implements a customizable checkbox that optionally supports three states and deals consistently with events. Can replace the nativeCheckbox
widget.CheckGroup
manages a set of uniformCheck
components. (Hence it requires theCheck
factory.)Popup
implements 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 incomingini
set 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 stringtext
when laid out in a multiline text widget (StaticText, EditText.)
- SUI/mini: added the
RETMAX
argument (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
helpTip
inheritance 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
KeyboardEvent
viaScriptUI.event('my_custom_type', 'K', originalKeyboardEvent)
. - Ext/patterns: Changed
RegExp.LINE = /\u000D|\u000A|\u000D\u000A/g
intoRegExp.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
~.SPLT
routine was killing CS4 if the input string was empty. Nows.length > 0
is a condition before callings.replace(callee.CUR_MTCH, F)
.
- YALT. Added automatic support of
...
terminator. That is, if the keyabc
is 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, cfsortNumbers
option. Any word boundary (incl..
) can now initiate a valid digit sequence:XYZ.123
is no longer interpreted as0.123
, and regular decimal point as inXYZ 123.45
is 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 aMenuItem
orSubmenu
instance.
- 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
, andMenuItem
objects.) In summary, the path solver had to avoid both.getElements()
,.constructor
and.parent
commands 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.$$.JSON
now 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~.EXTN
member introduced in AnyScript/run. Thanks to this extension mechanism, the Context/UI/Server model now supports an additionalMenuExtension
component 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 thebeforeDisplay
event occurs. If defined, this function must return TRUE (resp. FALSE) to enable (resp. disable) the menu item.beforeInvoke(runMode,parentModule,scriptMenuAction
: Called when thebeforeInvoke
event occurs.afterke(runMode,parentModule,scriptMenuAction
: Called when theafterInvoke
event occurs.
See full example in tests/BasicScriptMenuDemo.jsx
- Dom.Menu: Made
removeAction()
a bit safer using aisValid
checkpoint onScriptMenuAction
instance(s). - File: Added a generic
startupAlias()
method that will create, check or remove an alias of thetarget
script file in thestartup scripts
subfolder of the user branch.
- Added a preliminary step in AnyScript/run that checks whether the private member
~.EXTN
is defined and functional. In such case,~.EXTN(runMode)
is called and if the returned value isfalse
the 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~.EXTN
would 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 anisValid
test 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/script
snippet. 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
,MenuItem
instances, 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 sameEvent
instance twice, unless explicitly allowed. This is a tricky adjustment but definitely needed in advanced projects:$$.Env.globalEvent
recovers 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.evt
reference 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.evt
once processed (not tested though), but it sounds safer to address the issue from$$.Env.globalEvent
itself. The new code uses an internal event stamp that detects a previously returned event. In such case, the method returns0
instead of the oldEvent
reference, unless you supply a truthyALLOW_PREVIOUS_EVENT
argument 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_SCALING
should 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 -> https
redir is now supported. Relaxed the non-modalstate condition in InDesign >= CS5 (7.0) since it has been found thatapp.doScript
can 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/builder
now 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 return0
if 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$$.Log
can 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 thecharAt
method can pick a U+0000 character, e.g"x\0y".charAt(1)
returns"\0"
. But in ExtendScript an empty string is returned whenevercharAt
should output"\0"
.Ext/string
hacksString.prototype.charAt
in order to fix the problem.
- ScriptUI/events snippet added in the
etc
branch. Provides the functionScriptUI.event()
and advanced tools and tricks for manipulatingEvent
,UIEvent
,MouseEvent
, andKeyboardEvent
instances 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 theparentPage
property 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.min
andMath.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 buildRegExp
patterns 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
abc
part (prefix) will be considered while computing collation keys, the next characters being entirely ignored. - Only the
xyz
part (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!)
~.SPLT
routine. The separatorU+FFFD
is 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_MODE
ingetRichList()
. 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
Array
object 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, thoseundefined
variables 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 RU
date/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 theiLocale
arg 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 (fromLocaleStr
andtoLocaleStr
.)
- ByteStream: Added the
TAG
encoding (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/$$.jsxinc
into#include path/to/$$.spin.jsxinc
in your client script. The method$$.spin()
is otherwise transparent. - Recent additions in the
core
branch: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 eitherWindow
orLayoutWindow
type. So you can explicitly center a ScriptUI window (1st argument) relative to another one, or relative to a document window (LayoutWindow
instance.) 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.enableRedraw
temporarily set to true during the execution of that function. IfenableRedraw
is 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
DontClone
global option. Usually it's safer to let$$.Settings
perform a JSON clone while setting a key to an object reference (ss.myKey=myObj
), because that reference may be lost andss.myKey
is 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.DontClone
to 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..+1
on 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 cachedScriptUIPen
from a uint240xrrggbb
value. (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 cachedScriptUIBrush
based on both a colorValue0xRRGGBB
and 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.jsxres
andWIND.jsxres
snippets. The previous code was changing the input descriptor to adjust theproperties
object 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-alive
was 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 theenabled
property 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_REFRESH
subfunction 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 agetString
method, invoke it. Otherwise, stringify the value. ModalScript/UserInterface
: Added theCancelValue
attribute (uint, default:2) and fixed the treatment of the value returned from the SUI dialog. TheonClose
hook can now handle the dialog retval as such: theok
argument isfalse
only if retval===µ.CancelValue
.BasicScript/UserInterface
: The~._GO_
method wasn't supposed to returntrue
in case the user validates the dialog while noonClose
callback is available. Indeed,true
has the meaning “Skip the server”. This tiny bug had no critical impact in practice, because theonClose
hook is almost always implemented!
- Web: finally found a way to escape XMLHTTP
responseBody
in VBS and parse the returned string in JS. Should significantly reduce failures of yourhttps
requests (in Windows.)
- Ext/string: added
String.levenFilter(arr,str,max)
. Returns a subset ofarr
(string array) whose items are the most similar tostr
with 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 usesDate
timestamp, as this caused biases.
SUI/builder/SETK
: the special keyoptimalSize
can be used to set bothpreferredSize
ANDminimumSize
in one step. This is a useful shortcut, since many ScriptUI controls require both apreferredSize
and aminimumSize
to get properly aligned.- Env module: fixed a bug regarding
~.IDEX
and the public propertyidexEntryPath
(“URI path to IdExtenso Entry Folder, if available”). There was a mistake on the location$.fileName
refers 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.setFocus
improved and made smarter. SinceGroup
andPanel
objects don't provide theactive
property 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 anactive
property.
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..catch
block for nestingapp.activate()
. This bypasses a runtime error that sometimes occurs when multiple InDesign CC versions are running in parallel! - Due to
app.layoutWindows
access inEnv/screen
, theESTK
entry point wasn't working anymore! AddedA.layoutWindows = 0;
in$$.estk
to 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
$.screens
from within a function scope create an inexplicable(workspace)
instance which then alters actual function (workspace) count. A workaround is to access$.screens
only 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 aListBox
or aDropDownList
, depending on the flag...properties.dropdown
.
- Slight change in
ScriptUI.forceRedraw()
(cf SUI/mini) using specialized routines for list controls (ListBox
andDropDownList
).
- Enhanced Root/help, based on my recent study of multi-column
ListBox
control in ScriptUI. Improves the refresh mechanism of$$.help
's listbox.
- Settings: made the
backup
method JsxBlind-safe, using thecallee.ARG
trick. 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
Event
entry 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 aMenuAction
listener.) - Fixed non-declared
q
argument 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.activeWindow
exists. 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
show
event of the Window (unless the code explicitly invokes thelayout()
function at some point.) Hence, an interesting use of handling our fake_layout
event 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=true
doesn'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.jsxinc
contains basic extensions of theScriptUI
object: alignment shortcuts,ScriptUI.isWidget()
,ScriptUI.forceRedraw()
, etc.SUI/$$.builder.jsxinc
specifically 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
$$.Env
features 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
ScriptUI
to make background/foreground management easier and safer in cross-version scripts. NOTE: This is an optional snippet (etc
branch) 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
onDraw
handler (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.jsxinc
andExt/$$.object.jsxinc
now 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.jsxinc
takes advantage of the change mentioned above.$$.Root.jsxlib
declares$$.resolve()
and$$.isModule()
a bit sooner to make those features available when including inner snippets likeerrors
ormessaging
.- 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
IDAT
chunks...
- 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.jsxinc
is 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 thename
property of the output widget, provided a name is available and wouldn't override an existingname
property. 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, thehelpTip
property inherits from parent's help tip (inScriptUI.builder
.) Useful to spread a tip throughout a container.
- ModalScript: small fix in
~._SV_
(theitems
property 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 amode
argument 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.jsxinc
now 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.jsxinc
now implementsString.fromCodePoint()
as specified in ECMA-262 9.0, including the ability to supply anArray
of 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.jsxinc
added. 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.resolve
is OK. Thanks toPage
's API we can implement a fully functionalresolve
method 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~.BCKP
routine 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 (fullWindow
or 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 frommyFolder1
tomyFolder2
in"../../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 theCLASS
macro. (REM. - For technical and performance reasons, IdExtenso does not invoke thearguments
property ofFunction
instances. 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 (MeasurementEditbox
andMeasurementCombobox
instances.) In summary,SmartMeasurementBoxes==1
guarantees 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 ifSmartListItemGetter
is 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 someMeasurementUnits
enum, 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 howUnitData
instances are loaded. $$.Env.isUnit()
now supports numeral inputs, that is, strings having the form"2054187384"
or"0x7A696E63"
. (Useful in XML context.)
- Yalt : The
YALT
routine 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$$.jsxinc
to keep track of the entry point location. - Env : Added the
userName()
method. Added theidexEntryPath
property. 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 defaultminWidth
for 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
selected
for either Dropdown or RadiobuttonGroup widgets: it is interpretedselectedButton
in case of radio group, andselectedIndex
in 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.OR
etc.
- 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===null
is not reliable whenx
refers to aUnitValue
instance whose value is in the range )-1,1(. Indeed, due to an implementation error regarding the===
operator,UnitValue(0.5,'pt')===null
is true! TheLAVE
routine 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.DecimalChar
andNumber.ThousandsChar
.
Ext/$$.number.jsxinc
: AddedNumber.prototype.toDecimal()
, a variant oftoFixed
that 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.SPCE
for 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 thetrim
methods.
- 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
(mainMonitorPpi
etc.) 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 theeditUnits
property 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 aMeasurementUnits
number, key, or Enumerator, in whatever InDesign version. BTW, I madeisUnit
available 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 thestringList
property 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/errors
to 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
hasScope
method 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
(sincetmp
may cause the OS to simply ignore theexecute
method.) 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 aBigInt
is mixed with a string. Now interpreted as aconcat
operation. So"Result: " + BigInt(1000)
will promptResult: 1000
as (likely) expected. Idem withBigInt + str
.
Ext/number
now 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 < this
was improperly parsed asthis['<'](number)
, leading to serious problems! For example,999 < BigInt(1000)
was said false. (Detail.)
Settings
updated. Various bugs fixed. Now supports session-persistent keys :-)
Ext/regexp
now 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.toSource
method now allows thequotes
param 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/file
added, intended to extendFile.prototype
. So far it only introduces the methodnudeName()
which just returns the file name without its extension. (REM: Do not confuseExt/file
with the File module.)- Exposed the
stamp()
utility in the API of the File module. It basically invokes the private~.STMP
function, 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
lave
function now supports a third paramFORCE_OBJ
that allows to browse special objects (such thatScriptUI
,BridgeTalk
…) which otherwise wouldn't expand. Also, theDOM_ACCESS
param can be set to-1
. Ext/number
: Implementation notes and small fixes.
Ext/enum
: therevSource
method had no name. Fixed.Ext/regexp
: the==
operator had no name. Fixed.Ext/string
: thecharSet
method 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.send
utility, 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 inMODULE
andCLASS
macros ($$.jsxinc
).
- Added the
/tools
subdir (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
. $$.load
updated (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
runningScript
property (URI pathname to the running script file.) - Log: Added an explicit
typeof logLevel
test, since ExtendScript wrongly regardsundefined < 0
as 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~.ALTG
in/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 privateJSON
method) 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 noBigInt
reference, 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
$.hiresTimer
in$$.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,Z
areBigInt
.
- 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$.os
string. - Updated
File.batchToString()
in the File module. Now requires a%1
placeholder 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> file
output, 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
JSON
module: saferNaN
string 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()
whenisText
option was turned ON. (No data were returned.)
- Yalt: Added
Yalt.hasKey()
(check whether a translation key is present); fixedYalt.onLoad()
signature.
Ext/$$.number.jsxinc
: addedprefix
andzeroPad
params toNumber.prototype.toHexa
.
- Various unnotified changes in JSON, Env, etc.
- IdExtenso alpha release.