[latex3-commits] [git/LaTeX3-latex3-babel] master: Arabic kashida, with user definable rules. 'step' in transforms. (ea7b112)
Javier
email at dante.de
Sat May 8 16:35:36 CEST 2021
Repository : https://github.com/latex3/babel
On branch : master
Link : https://github.com/latex3/babel/commit/ea7b1122763c1cfc1eabe1dec4f8cef06ac66156
>---------------------------------------------------------------
commit ea7b1122763c1cfc1eabe1dec4f8cef06ac66156
Author: Javier <email at localhost>
Date: Sat May 8 16:35:36 2021 +0200
Arabic kashida, with user definable rules. 'step' in transforms.
>---------------------------------------------------------------
ea7b1122763c1cfc1eabe1dec4f8cef06ac66156
README.md | 20 +-
babel.dtx | 300 +++++++++++++++++++++++++---
babel.ins | 2 +-
babel.pdf | Bin 832617 -> 843054 bytes
bbcompat.dtx | 2 +-
locale/ar/babel-ar.ini | 5 +
locale/ar/babel-arabic.tex | 83 --------
news-guides/news/whats-new-in-babel-3.59.md | 63 ++++++
samples/lua-arabic.pdf | Bin 117183 -> 85278 bytes
samples/lua-arabic.tex | 11 +
10 files changed, 364 insertions(+), 122 deletions(-)
diff --git a/README.md b/README.md
index 8a954ea..70766fd 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-## Babel 3.58
+## Babel 3.58.2366
This package manages culturally-determined typographical (and other)
rules, and hyphenation patterns for a wide range of languages. Many
@@ -8,9 +8,9 @@ is a set of ini files for about 250 languages.
The latest stable version is available on <https://ctan.org/pkg/babel>.
-Changes in version 3.58 are described in:
+Changes in version 3.59 are described in:
-https://github.com/latex3/babel/blob/master/news-guides/news/whats-new-in-babel-3.58.md
+https://github.com/latex3/babel/blob/master/news-guides/news/whats-new-in-babel-3.59.md
Apart from the manual, you can find information on some aspects of babel at:
@@ -46,6 +46,9 @@ respective authors.
### Summary of Latest changes
```
+3.59 2021-05-??
+ * Kashida with user-definable rules (via transforms).
+
3.58 2021-04-26
* More predefined transforms (lua):
- doubleletter.hyphen: Norsk
@@ -59,17 +62,6 @@ respective authors.
* Fix: \shorthandoff*{^} was not revertible (#126).
* Experimental code for Arabic justification (with elongated
forms: lua).
-
-3.57 2021-04-07
- * Predefined transforms (lua):
- - Arabic: transliteration.dad
- - Croatian: digraphs.ligatures
- - Greek: diaeresis.hyphen
- - Hindi: transliteration.hk
- - Hungarian: digraphs.hyphen
- * Transforms: {xxxx} syntax also in string=.
- * Preliminary code for Uyghur hyphenation (lua).
- * magyar as alternative to hungarian in \babelprovide.
```
### Previous changes
diff --git a/babel.dtx b/babel.dtx
index 745cf11..b6eb2ba 100644
--- a/babel.dtx
+++ b/babel.dtx
@@ -31,7 +31,7 @@
%
% \iffalse
%<*filedriver>
-\ProvidesFile{babel.dtx}[2021/04/26 v3.58 The Babel package]
+\ProvidesFile{babel.dtx}[2021/05/08 v3.58.2366 The Babel package]
\documentclass{ltxdoc}
\GetFileInfo{babel.dtx}
\usepackage{fontspec}
@@ -4958,8 +4958,8 @@ help from Bernd Raichle, for which I am grateful.
% \section{Tools}
%
% \begin{macrocode}
-%<<version=3.58>>
-%<<date=2021/04/26>>
+%<<version=3.58.2366>>
+%<<date=2021/05/08>>
% \end{macrocode}
%
% \textbf{Do not use the following macros in \texttt{ldf} files. They
@@ -7653,14 +7653,19 @@ help from Bernd Raichle, for which I am grateful.
\else
\edef\bbl at tempa{\bbl at cl{lnbrk}}%
\fi
+ % linebreaking - handle u, e, k (v in the future)
\bbl at xin@{/u}{/\bbl at tempa}%
+ \ifin@\else\bbl at xin@{/e}{/\bbl at tempa}\fi % elongated forms
+ \ifin@\else\bbl at xin@{/k}{/\bbl at tempa}\fi % only kashida
+ \ifin@\else\bbl at xin@{/v}{/\bbl at tempa}\fi % variable font
\ifin@
- % 'unhyphenated' = allow stretching
+ % unhyphenated/kashida/elongated = allow stretching
\language\l at unhyphenated
\babel at savevariable\emergencystretch
\emergencystretch\maxdimen
\babel at savevariable\hbadness
\hbadness\@M
+ \hfuzz=10pt
\else
% other = select patterns
\bbl at patterns{#1}%
@@ -10968,6 +10973,10 @@ help from Bernd Raichle, for which I am grateful.
\bbl at csarg\edef{intsp@#2}{\bbl at KVP@intraspace}%
\fi
\bbl at provide@intraspace
+ %
+ \bbl at xin@{/e}{/\bbl at cl{lnbrk}}
+ \ifin@\else\bbl at xin@{/k}{/\bbl at cl{lnbrk}}\fi
+ \ifin@\bbl at arabicjust\fi
% == Line breaking: hyphenate.other.locale/.script==
\ifx\bbl at lbkflag\@empty
\bbl at ifunset{bbl at hyotl@\languagename}{}%
@@ -12126,6 +12135,10 @@ help from Bernd Raichle, for which I am grateful.
\bbl at adjust@lua{linebreak}{cjk_enabled=true}}
\@namedef{bbl at ADJ@linebreak.cjk at off}{%
\bbl at adjust@lua{linebreak}{cjk_enabled=false}}
+\@namedef{bbl at ADJ@justify.arabic at on}{%
+ \bbl at adjust@lua{linebreak}{arabic.justify_enabled=true}}
+\@namedef{bbl at ADJ@justify.arabic at off}{%
+ \bbl at adjust@lua{linebreak}{arabic.justify_enabled=false}}
%
\def\bbl at adjust@layout#1{%
\ifvmode
@@ -13572,6 +13585,22 @@ help from Bernd Raichle, for which I am grateful.
end
}^^
\bbl at luahyphenate}
+% \end{macrocode}
+%
+% \subsection{CJK line breaking}
+%
+% Minimal line breaking for CJK scripts, mainly intended for simple
+% documents and short texts as a secundary language. Only line
+% breaking, with a little stretching for justification, without any
+% attempt to adjust the spacing. It is based on (but does not strictly
+% follow) the Unicode algorithm.
+%
+% We first need a little table with the corresponding line breaking
+% properties. A few characters have an additional key for the width
+% (fullwidth \textit{vs.} halfwidth), not yet used. There is a separate
+% file, defined below.
+%
+% \begin{macrocode}
\catcode`\%=14
\gdef\bbl at cjkintraspace{%
\let\bbl at cjkintraspace\relax
@@ -13696,22 +13725,214 @@ help from Bernd Raichle, for which I am grateful.
\fi}}
% \end{macrocode}
%
-% \subsection{CJK line breaking}
+% \subsection{Arabic justification}
%
-% Minimal line breaking for CJK scripts, mainly intended for simple
-% documents and short texts as a secundary language. Only line
-% breaking, with a little stretching for justification, without any
-% attempt to adjust the spacing. It is based on (but does not strictly
-% follow) the Unicode algorithm.
-%
-% We first need a little table with the corresponding line breaking
-% properties. A few characters have an additional key for the width
-% (fullwidth \textit{vs.} halfwidth), not yet used. There is a separate
-% file, defined below.
+% \begin{macrocode}
+\ifnum\bbl at bidimode>100 \ifnum\bbl at bidimode<200
+\def\bblar at chars{%
+ 0628,0629,062A,062B,062C,062D,062E,062F,0630,0631,0632,0633,%
+ 0634,0635,0636,0637,0638,0639,063A,063B,063C,063D,063E,063F,%
+ 0640,0641,0642,0643,0644,0645,0646,0647,0649}
+\def\bblar at elongated{%
+ 0626,0628,062A,062B,0633,0634,0635,0636,063B,%
+ 063C,063D,063E,063F,0641,0642,0643,0644,0646,%
+ 0649,064A}
+\begingroup
+ \catcode`_=11 \catcode`:=11
+ \gdef\bblar at nofswarn{\gdef\msg_warning:nnx##1##2##3{}}
+\endgroup
+\gdef\bbl at arabicjust{%
+ \let\bbl at arabicjust\relax
+ \newattribute\bblar at kashida
+ \bblar at kashida=\z@
+ \expandafter\bbl at add\csname selectfont \endcsname{{\bbl at parsejalt}}%
+ \directlua{
+ Babel.arabic.elong_map = Babel.arabic.elong_map or {}
+ Babel.arabic.elong_map[\the\localeid] = {}
+ luatexbase.add_to_callback('post_linebreak_filter',
+ Babel.arabic.justify, 'Babel.arabic.justify')
+ }}%
+% Save both node lists to make replacement. TODO. Save also widths to
+% make computations
+\def\bblar at fetchjalt#1#2#3#4{%
+ \bbl at exp{\\\bbl at foreach{#1}}{%
+ \bbl at ifunset{bblar at JE@##1}%
+ {\setbox\z@\hbox{^^^^200d\char"##1#2}}%
+ {\setbox\z@\hbox{^^^^200d\char"\@nameuse{bblar at JE@##1}#2}}%
+ \directlua{%
+ local last = nil
+ for item in node.traverse(tex.box[0].head) do
+ if item.id == node.id'glyph' and item.char > 0x600 and
+ not (item.char == 0x200D) then
+ last = item
+ end
+ end
+ Babel.arabic.#3['##1#4'] = last.char
+ }}}
+% Brute force. No rules at all, yet. The ideal: look at jalt table. And
+% perhaps other tables (falt?, cswh?). What about kaf? And diacritic
+% positioning?
+\gdef\bbl at parsejalt{%
+ \ifx\addfontfeature\@undefined\else
+ \bbl at xin@{/e}{/\bbl at cl{lnbrk}}%
+ \ifin@
+ \directlua{%
+ if Babel.arabic.elong_map[\the\localeid][\fontid\font] == nil then
+ Babel.arabic.elong_map[\the\localeid][\fontid\font] = {}
+ tex.print([[\string\csname\space bbl at parsejalti\endcsname]])
+ end
+ }%
+ \fi
+ \fi}
+\gdef\bbl at parsejalti{%
+ \begingroup
+ \let\bbl at parsejalt\relax % To avoid infinite loop
+ \edef\bbl at tempb{\fontid\font}%
+ \bblar at nofswarn
+ \bblar at fetchjalt\bblar at elongated{}{from}{}%
+ \bblar at fetchjalt\bblar at chars{^^^^064a}{from}{a}% Alef maksura
+ \bblar at fetchjalt\bblar at chars{^^^^0649}{from}{y}% Yeh
+ \addfontfeature{RawFeature=+jalt}%
+ % \@namedef{bblar at JE@0643}{06AA}% todo: catch medial kaf
+ \bblar at fetchjalt\bblar at elongated{}{dest}{}%
+ \bblar at fetchjalt\bblar at chars{^^^^064a}{dest}{a}%
+ \bblar at fetchjalt\bblar at chars{^^^^0649}{dest}{y}%
+ \directlua{%
+ for k, v in pairs(Babel.arabic.from) do
+ if Babel.arabic.dest[k] and
+ not (Babel.arabic.from[k] == Babel.arabic.dest[k]) then
+ Babel.arabic.elong_map[\the\localeid][\bbl at tempb]
+ [Babel.arabic.from[k]] = Babel.arabic.dest[k]
+ end
+ end
+ }%
+ \endgroup}
%
-% \textit{Work in progress.}
+\begingroup
+\catcode`#=11
+\catcode`~=11
+\directlua{
+
+Babel.arabic = Babel.arabic or {}
+Babel.arabic.from = {}
+Babel.arabic.dest = {}
+Babel.arabic.justify_factor = 0.95
+Babel.arabic.justify_enabled = true
+
+function Babel.arabic.justify(head)
+ if not Babel.arabic.justify_enabled then return head end
+ local d, new
+ local k_list, k_item, pos_inline
+ local width, width_new, full, k_curr, wt_pos, goal
+ local subst_done = false
+ local elong_map = Babel.arabic.elong_map
+ local last_line
+ local GLYPH = node.id'glyph'
+ local KASHIDA = luatexbase.registernumber'bblar at kashida'
+ local LOCALE = luatexbase.registernumber'bbl at attr@locale'
+
+ for line in node.traverse_id(node.id'hlist', head) do
+ % Exclude last line. todo. But-- it discards one-word lines, too!
+ if (line.glue_sign == 1 and line.glue_order == 0) then
+ elongs = {} % Stores elongated candidates of each line
+ k_list = {} % And all letters with kashida
+ pos_inline = 0 % Not yet used
+
+ for n in node.traverse_id(GLYPH, line.head) do
+ pos_inline = pos_inline + 1 % To find where it is. Not used.
+
+ % Elongated glyphs
+ if elong_map then
+ local locale = node.get_attribute(n, LOCALE)
+ if elong_map[locale] and elong_map[locale][n.font] and
+ elong_map[locale][n.font][n.char] then
+ table.insert(elongs, {node = n, locale = locale} )
+ node.set_attribute(n.prev, KASHIDA, 0)
+ end
+ end
+
+ % Tatwil
+ if Babel.kashida_wts then
+ local k_wt = node.get_attribute(n, KASHIDA)
+ if k_wt > 0 then
+ table.insert(k_list, {node = n, weight = k_wt, pos = pos_inline})
+ end
+ end
+
+ end % of node.traverse_id
+
+ if #elongs == 0 and #k_list == 0 then goto next_line end
+
+ full = line.width
+ goal = full * Babel.arabic.justify_factor % A bit crude
+ width = node.dimensions(line.head) % The 'natural' width
+
+ % == Elongated ==
+ % Original idea taken from 'chikenize'
+ while (#elongs > 0 and width < goal) do
+ subst_done = true
+ local x = #elongs
+ local curr = elongs[x].node
+ local oldchar = curr.char
+ curr.char = elong_map[elongs[x].locale][curr.font][curr.char]
+ width = node.dimensions(line.head) % Check if the line is too wide
+ % Substitute back if the line would be too wide and break:
+ if width > goal then
+ curr.char = oldchar
+ break
+ end
+ % If continue, pop the just substituted node from the list:
+ table.remove(elongs, x)
+ end
+
+ % == Tatwil ==
+ if #k_list == 0 then goto next_line end
+
+ width = node.dimensions(line.head) % The 'natural' width
+ k_curr = #k_list
+ wt_pos = 1
+
+ while width < goal do
+ subst_done = true
+ k_item = k_list[k_curr].node
+ if k_list[k_curr].weight == Babel.kashida_wts[wt_pos] then
+ d = node.copy(k_item)
+ d.char = 0x0640
+ line.head, new = node.insert_after(line.head, k_item, d)
+ width_new = node.dimensions(line.head)
+ if width > goal or width == width_new then
+ node.remove(line.head, new) % Better compute before
+ break
+ end
+ width = width_new
+ end
+ if k_curr == 1 then
+ k_curr = #k_list
+ wt_pos = (wt_pos >= table.getn(Babel.kashida_wts)) and 1 or wt_pos+1
+ else
+ k_curr = k_curr - 1
+ end
+ end
+
+ ::next_line::
+
+ % Must take into account marks and ins, see luatex manual.
+ % Have to be executed only if there are changes. Investigate
+ % what's going on exactly.
+ if subst_done then
+ node.insert_before(head, line, node.hpack(line.head, full, 'exactly'))
+ node.remove(head, line)
+ end
+ end % if process line
+ end % for lines
+ return head
+end
+}
+\endgroup
+\fi\fi % Arabic just block
+% \end{macrocode}
%
-% Common stuff.
+% \subsection{Common stuff}
%
% \begin{macrocode}
\AddBabelHook{babel-fontspec}{afterextras}{\bbl at switchfont}
@@ -14136,6 +14357,7 @@ end
&% after the match, either as found by u.match (faster) or the
&% computed position based on sc if w has changed.
local last_match = 0
+ local step = 0
&% For every match.
while true do
@@ -14143,9 +14365,9 @@ end
print('=====')
end
local new &% used when inserting and removing nodes
- local refetch = false
local matches = { u.match(w, p, last_match) }
+
if #matches < 2 then break end
&% Get and remove empty captures (with ()'s, which return a
@@ -14211,6 +14433,10 @@ end
item_base = data_nodes[crep.data]
end
+ if crep then
+ step = crep.step or 0
+ end
+
if crep and next(crep) == nil then &% = {}
last_match = save_last &% Optimization
goto next
@@ -14220,7 +14446,14 @@ end
table.remove(w_nodes, sc)
w = u.sub(w, 1, sc-1) .. u.sub(w, sc+1)
sc = sc - 1 &% Nothing has been inserted.
- last_match = utf8.offset(w, sc+1)
+ last_match = utf8.offset(w, sc+1+step)
+ goto next
+
+ elseif crep and crep.kashida then &% Experimental
+ node.set_attribute(item,
+ luatexbase.registernumber'bblar at kashida',
+ crep.kashida)
+ last_match = utf8.offset(w, sc+1+step)
goto next
elseif crep and crep.string then
@@ -14256,7 +14489,7 @@ end
end &% for
node.remove(head, item)
end &% if ''
- last_match = utf8.offset(w, sc+1)
+ last_match = utf8.offset(w, sc+1+step)
goto next
elseif mode == 1 and crep and (crep.pre or crep.no or crep.post) then
@@ -14325,7 +14558,7 @@ end
w = u.sub(w, 1, sc-1) .. placeholder .. u.sub(w, sc+1)
end
- last_match = utf8.offset(w, sc+1)
+ last_match = utf8.offset(w, sc+1+step)
::next::
@@ -14395,6 +14628,26 @@ end
return "]]..Babel.capt_map(m[" .. capno .. "]," ..
(mlen) .. ").." .. "[["
end
+
+ &% Create/Extend reversed sorted list of kashida weights:
+ function Babel.capture_kashida(key, wt)
+ wt = tonumber(wt)
+ if Babel.kashida_wts then
+ for p, q in ipairs(Babel.kashida_wts) do
+ if wt == q then
+ break
+ elseif wt > q then
+ table.insert(Babel.kashida_wts, p, wt)
+ break
+ elseif table.getn(Babel.kashida_wts) == p then
+ table.insert(Babel.kashida_wts, wt)
+ end
+ end
+ else
+ Babel.kashida_wts = { wt }
+ end
+ return 'kashida = ' .. wt
+ end
}
% \end{macrocode}
%
@@ -14473,10 +14726,11 @@ end
rep = rep:gsub('^%s*(remove)%s*$', 'remove = true')
rep = rep:gsub('^%s*(insert)%s*,', 'insert = true, ')
rep = rep:gsub('(string)%s*=%s*([^%s,]*)', Babel.capture_func)
- rep = rep:gsub( '(space)%s*=%s*([%d%.]+)%s+([%d%.]+)%s+([%d%.]+)',
+ rep = rep:gsub('(space)%s*=%s*([%d%.]+)%s+([%d%.]+)%s+([%d%.]+)',
'space = {' .. '%2, %3, %4' .. '}')
- rep = rep:gsub( '(spacefactor)%s*=%s*([%d%.]+)%s+([%d%.]+)%s+([%d%.]+)',
+ rep = rep:gsub('(spacefactor)%s*=%s*([%d%.]+)%s+([%d%.]+)%s+([%d%.]+)',
'spacefactor = {' .. '%2, %3, %4' .. '}')
+ rep = rep:gsub('(kashida)%s*=%s*([^%s,]*)', Babel.capture_kashida)
tex.print([[\string\babeltempa{{]] .. rep .. [[}}]])
}}}&%
\directlua{
diff --git a/babel.ins b/babel.ins
index 3a07387..5d94d37 100644
--- a/babel.ins
+++ b/babel.ins
@@ -26,7 +26,7 @@
%% and covered by LPPL is defined by the unpacking scripts (with
%% extension .ins) which are part of the distribution.
%%
-\def\filedate{2021/04/26}
+\def\filedate{2021/05/08}
\def\batchfile{babel.ins}
\input docstrip.tex
diff --git a/babel.pdf b/babel.pdf
index 4eca976..2c6399c 100644
Binary files a/babel.pdf and b/babel.pdf differ
diff --git a/bbcompat.dtx b/bbcompat.dtx
index a69fa73..46f5169 100644
--- a/bbcompat.dtx
+++ b/bbcompat.dtx
@@ -30,7 +30,7 @@
%
% \iffalse
%<*dtx>
-\ProvidesFile{bbcompat.dtx}[2021/04/26 v3.58]
+\ProvidesFile{bbcompat.dtx}[2021/05/08 v3.58.2366]
%</dtx>
%
%% File 'bbcompat.dtx'
diff --git a/locale/ar/babel-ar.ini b/locale/ar/babel-ar.ini
index ca0c4ff..fd70acd 100644
--- a/locale/ar/babel-ar.ini
+++ b/locale/ar/babel-ar.ini
@@ -207,5 +207,10 @@ transliteration.dad.7.2 = { string = {1|AauiIbnf|آأؤإئٮںڡ} }
; 1-letter
transliteration.dad.8.0 = { ([{007C}AbtjHxdrzsSDTZ`RfqklmnhUIYaui+opCvgJe]) }
transliteration.dad.8.1 = { string = {1|{007C}AbtjHxdrzsSDTZ`RfqklmnhUIYaui+opCvgJe|ءابتجحخدرزسصضطظعغفقكلمنهوىيَُِّْپچڤگژۀ} }
+;
+kashida.plain.1.0 = { ()[يئهشسقفغعضصنمكلظطخحجثتب]()[يئهشسقفغعضصنمكلظطخحجثتباأإآوؤذدزرة] }
+kashida.plain.1.1 = { kashida = 500 }
+kashida.plain.2.0 = { ()ل()[اأإآ] }
+kashida.plain.2.1 = { kashida = 0 }
diff --git a/locale/ar/babel-arabic.tex b/locale/ar/babel-arabic.tex
index fbad883..5207dfd 100644
--- a/locale/ar/babel-arabic.tex
+++ b/locale/ar/babel-arabic.tex
@@ -10,87 +10,4 @@
\BabelBeforeIni{ar}{%
}
-\ifcase\bbl at engine\or
-
-\directlua{
-
-Babel.ar_tolong = {}
-
-function Babel.ar_justify(head)
- local substlist = Babel.ar_tolong
- local GLYPH = node.id'glyph'
- local substs, width, goal
- local subst_done = true % false
- math.randomseed(1)
- for line in node.traverse_id(node.id'hlist', head) do
- if (line.glue_sign == 1 and line.glue_order == 0) then % exclude last line!
- substs = {} % we store all “expandable” letters of each line
- for n in node.traverse_id(GLYPH, line.head) do
- if (substlist[n.char]) then
- table.insert(substs, n)
- end
- end
- line.glue_set = 0 % deactivate normal glue expansion
- width = node.dimensions(line.head) % check the new width
- goal = line.width
-
- while (width < goal and \string#substs > 0) do
- x = math.random(\string#substs) % choose randomly a glyph
- oldchar = substs[x].char
- substs[x].char = substlist[substs[x].char]
- subst_done = true
- width = node.dimensions(line.head) % check if the line is too wide
- % substitute back if the line would be too wide and break:
- if width > goal then substs[x].char = oldchar break end
- % if further substitutions have to be done, remove the just
- % substituted node from the list:
- table.remove(substs,x)
- end
- % Must take into account marks and ins, see luatex manual.
- % Have to be executed only if there are changes.
- if subst_done then
- line.head = node.hpack(line.head, goal, 'exactly')
- end
- end
- end
- return head
-end
-
-}
-
-\gdef\ArabicSetupJust{%
- \directlua{
- Babel.ar_tolong = {}
- luatexbase.add_to_callback('post_linebreak_filter',
- Babel.ar_justify, 'Babel.ar_justify')
- }%
- % It must be done for each font, and stored separately.
- % Locale must be taken into account too. Brute force.
- % No rules at all, yet. The ideal: look at jalt table.
- % And perhaps other tables (falt?, cswh?). What about kaf?
- \begingroup
- \bbl at foreach{%
- 0628,0629,062A,062B,062C,062D,062E,062F,0630,0631,0632,0633,%
- 0634,0635,0636,0637,0638,0639,063A,063B,063C,063D,063E,063F,%
- 0640,0641,0642,0643,0644,0645,0646,0647,0649}{%
- \setbox\z@\hbox{% Only final, for the moment
- ^^^^200d\char"##1=%
- \addfontfeature{RawFeature=+jalt}%
- ^^^^200d\char"##1}%
- \directlua{
- local chars = {}
- for item in node.traverse(tex.box[0].head) do
- if item.id == node.id'glyph' and item.char > 128 and
- not (item.char == 0x200D) then
- table.insert(chars, item.char)
- end
- end
- if not (chars[1] == chars[2]) then
- Babel.ar_tolong[chars[1]] = chars[2]
- end
- }}%
- \endgroup}
-
-\fi
-
\endinput
diff --git a/news-guides/news/whats-new-in-babel-3.59.md b/news-guides/news/whats-new-in-babel-3.59.md
new file mode 100644
index 0000000..96f4976
--- /dev/null
+++ b/news-guides/news/whats-new-in-babel-3.59.md
@@ -0,0 +1,63 @@
+# What's new in babel 3.59
+
+(Under development.)
+
+## More experimental Arabic justification
+
+But useable at your own rink, because the interface is unfinished and
+very likely will change. Note also there are still many pending issues –
+for example, lists just doesn't work.
+
+There are two modes: `elongated` and `kashida`. Actually the latter is the
+same as the former, but without real justification alternatives. If you
+only want elongated glyphs with ‘elongated’, just don’t define any
+kashida rule.
+
+For practical reasons, currently `bidi=basic` is required.
+
+The points were kashida have to be inserted if necessary are defined by
+means of ‘transforms’. In other words, they are not hardcoded and you
+can define you own rules with different weights (including rules for
+words matching some patterns). A very simple and basic transform is
+included for ’plain’ Arabic fonts, which attempts to distribute the
+tatwil as evenly as possible, starting at the end of the line. Its
+named `kashida.plain` and no ligature is taken into account (except, of
+course, for the lam-alif).
+
+So:
+```tex
+\usepackage[bidi=basic]{babel}
+
+\babelprovide[import, main,
+ typography/linebreaking = k, % This will change for sure!
+ transforms = kashida.plain
+ ]{arabic}
+
+\babelfont{rm}{FreeSerif}
+```
+
+An example of how to fine tune these rules is (with Sakkal Majalla):
+```
+\babelprehyphenation{arabic}{ () ب () ر }{ kashida = 0 }
+```
+Of course, these setting must be also font dependent, but for the
+moment this is what it is.
+
+As an example, the following rule is applied to words with at least 3
+letters. A (probably long) kashida is added to the last but one
+char with certain combinations.
+```
+\babelprehyphenation{arabic}{
+ {a}
+ () [ي ئ ه ش س ق ف غ ع ض ص ن م ك ظ ط خ ح ج ث ت ب ] () % ل
+ [ي ئ ه ق ن ك ث ت ب ا أ إ آ و ؤ ذ د ز ر ة]
+ [|،,.){]}] }
+{ kashida = 500 }
+\babelprehyphenation{arabic}{ () ل () [ ا أ إ آ] }{ kashida = 0 }
+```
+
+This feature can be deactivated with:
+```tex
+\babeladjust{ justify.arabic = off }
+```
+Use `on` to reactivate it.
diff --git a/samples/lua-arabic.pdf b/samples/lua-arabic.pdf
index 714831a..6ee50a0 100644
Binary files a/samples/lua-arabic.pdf and b/samples/lua-arabic.pdf differ
diff --git a/samples/lua-arabic.tex b/samples/lua-arabic.tex
index c09428c..b8e6bd8 100644
--- a/samples/lua-arabic.tex
+++ b/samples/lua-arabic.tex
@@ -1,10 +1,21 @@
%$LuaLaTeX -*- coding: utf-8 ; mode: latex; TeX-engine: luatex; -*-
\documentclass[a4paper]{book}
+% ===================
\usepackage[english, arabic, provide=*,
bidi=basic,
headfoot=arabic, % an alternative is layout=sectioning
layout=counters.tabular]{babel}
+% == Alternative for kashida ==
+% \usepackage[english,
+% bidi=basic,
+% headfoot=arabic, % an alternative is layout=sectioning
+% layout=counters.tabular]{babel}
+% \babelprovide[import, main,
+% % typography/linebreaking = k,
+% % transforms = kashida.plain
+% ]{arabic}
+% =====================
\babelfont{rm}
[ItalicFont=FreeSerif, Numbers=Arabic]
More information about the latex3-commits
mailing list.