\documentclass[10ptj]{ltjsarticle}
\usepackage[width=40\zw, lines=40,centering]{geometry}
\usepackage{amsmath,luacode,xcolor}
\begin{luacode}
  lineskip = {}
do
  local insert = table.insert
  local rangedimensions, max = node.rangedimensions, math.max
  function lineskip.p_profile(before, after)
    local t = {}
    do
      local w_acc, d_before = 0, 0
      local x = before.head; local xn = x.next
      while x do
        local w, d
        if xn then w, _, d= rangedimensions(before,x,xn)
        else w, _, d= rangedimensions(before,x) end
        if d~=d_before then
          d_before = d; t[w_acc] = t[w_acc] or {}
          if t[w_acc][1] then t[w_acc][1]=max(t[w_acc][1],d)
          else t[w_acc][1]=d end
        end
        w_acc = w_acc + w
        x = xn; if x then xn = x.next end
      end
    end
    do
      local w_acc, h_before = 0, 0
      local x = after.head; local xn = x.next
      while x do
        local w, h
        if xn then w, h = rangedimensions(after,x,xn)
        else w, h = rangedimensions(after,x) end
        if h~=h_before then
          h_before = h; t[w_acc] = t[w_acc] or {}
          if t[w_acc][2] then t[w_acc][2]=max(t[w_acc][2],h)
          else t[w_acc][2]=h end
        end
        w_acc = w_acc + w
        x = xn; if x then xn = x.next end
      end
    end
    local t2 = {}
    for i,v in pairs(t) do insert(t2, { i, v[1], v[2] } ) end
    table.sort(t2, function(a,b) return a[1]<b[1] end)
    do
      local bls = tex.baselineskip.width
      local dmax, d, hmax, h, lmin = 0, 0, 0, 0, 1/0
      for i,v in ipairs(t2) do
        d, h = (v[2] or d), (v[3] or h)
        if d>dmax then dmax=d end
        if h>hmax then hmax=h end
        if (bls-h-d)<lmin then lmin=bls-h-d end
      end
      if lmin==1/0 then lmin = 0 end
      return lmin, bls - lmin - (before.depth+after.height)
    end
  end
  function lineskip.p_dummy(before, after)
    return nil, 0
  end
end
do
  local setglue = node.setglue
  local floor, max = math.floor, math.max
  function lineskip.l_dummy(dist, g, adj, normal)
    if dist < tex.lineskiplimit then
      local ng = tex.lineskip; g.subtype=1
      setglue(g, ng.width + adj, ng.stretch, ng.shrink, ng.stretch_order, ng.shrink_order)
    else
      local ng = tex.baselineskip; g.subtype=2
      setglue(g, normal, ng.stretch, ng.shrink, ng.stretch_order, ng.shrink_order)
    end
  end
  function lineskip.l_step(dist, g, adj, normal)
    if dist < tex.lineskiplimit then
      local ng = tex.baselineskip; g.subtype=1
      local f = max(1,ng.width*lineskip.step_factor)
      setglue(g,
        normal - f * floor((dist-tex.lineskip.width)/f),
        ng.stretch, ng.shrink, ng.stretch_order, ng.shrink_order)
    else
      local ng = tex.baselineskip; g.subtype=2
      setglue(g, normal, ng.stretch, ng.shrink, ng.stretch_order, ng.shrink_order)
    end
  end
end

  local l_profiler, l_skip = lineskip.p_dummy, lineskip.l_dummy
  function lineskip.setting(profiler, skip_method)
    l_profiler = lineskip['p_'..tostring(profiler)] or lineskip.p_dummy
    l_skip = lineskip['l_'..tostring(skip_method)] or lineskip.l_dummy
  end
  
do
  luatexbase.add_to_callback('post_linebreak_filter',
    function(h)
      for x in node.traverse_id(12, h) do
        if (x.subtype==1)or(x.subtype==2)then
          local p, n = x.prev, x.next
          if p then 
            while ((p.id==14)or(p.id==12)or(p.id==13)) and p.prev do p = p.prev end
            if p.id==0 and n.id==0 then
              local normal = tex.baselineskip.width - p.depth - n.height
              local lmin, adj; lmin, adj = l_profiler(p,n)
              l_skip(lmin or normal,x,adj, normal)
            end
          end
        end
      end
      return true
    end, 'test', 10000
  )
end

do
  local to_direct, to_node = node.direct.todirect, node.direct.tonode
  local make_dir_whatsit = luatexja.direction.make_dir_whatsit
  local get_dir_count = luatexja.direction.get_dir_count
  local function lineskip_append_vlist(b, loc, prev, mirrored)
     local new_b = to_node(loc=='box' and 
	   make_dir_whatsit(to_direct(b), to_direct(b), get_dir_count(), 'append_vlist')) or b
     local tail = tex.nest[tex.nest.ptr].tail
     if tail and tail.id==12 and tail.subtype==3 then
        tail = tail.prev
     end
     if tail and (prev > -65536000) then
        local normal = tex.baselineskip.width - prev - new_b.height
        local lmin, adj = nil, 0;
        if tail.id==0 and new_b.id==0 then
          if tail.depth==prev then lmin, adj = l_profiler(tail,new_b) end
        end
        local g = node.new(12); l_skip(lmin or normal, g, adj, normal)
        node.write(g)
      end
      node.write(new_b)
      tex.prevdepth = new_b.depth
      return nil -- do nothing on tex side
   end
   luatexbase.remove_from_callback('append_to_vlist_filter','ltj.direction')
   luatexja.base.add_to_callback('append_to_vlist_filter',
			lineskip_append_vlist,
			'line profile', 10000)
end  
\end{luacode}
\begin{document}
\directlua{%
  lineskip.step_factor = 0.5
}

% #1: null（TeX 既定） or profile（行の中身を考慮した行間測定）
% #2: null（TeX 既定）
%   or step（行送りが \baselineskip で十分でなかった場合，
%            lineskip.step_factor * \baselineskip の倍数だけ広げて
%            行間が \lineskip 以上になるようにする）
\def\R#1#2{\directlua{lineskip.setting('#1','#2')}%
\noindent\fbox{\parbox{25\zw}{%
\baselineskip14pt\noindent
\setbox2=\vtop{\noindent\hsize20\zw\textcolor{cyan!30!white}{%
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■□□□□■
 □□□□■□□□□■□□□□■□□□□■
}}\dp2=0pt\rlap{\copy2}\par\vspace*{-\baselineskip}
\textbf{#1, #2}\\
\vrule height 2pt depth 0pt width 10\zw\\
\vrule height 2pt depth 0pt width 10\zw\\
\the\baselineskip あああああああああああああああ\\
あああああああああ$X_{X_{X_X}}$ああああああ\\
ああああああああああああああああああ\\
……であるから$b=\dfrac1{X_2}$となる．\\
一方$\dfrac{A^A}{B_B}=21$なので……\\
……であるから$b=\dfrac1{X_2}$となる．\\%\vadjust{あああああ$\dfrac34$}\\
一方$\dfrac{A^A}{B_B}=21$なので……

あいであるから$b=\dfrac1{X_2}$となる．新段落！\\
一方$\dfrac{A^A}{B_B}=21$なので……

\hbox{感じ感じ$\displaystyle\int$}
ほげであるから$b=\dfrac1{X_2}$となる．新段落！\\
一方$\dfrac{A^A}{B_B}=21$なので……

\hrule
かきであるから$b=\dfrac1{X_2}$となる．hrule無効\\
一方$\dfrac{A^A}{B_B}=21$なので……

\prevdepth0pt
うえであるから$b=\dfrac1{X_2}$prevdepth設定のため無効\\
一方$\dfrac{A^A}{B_B}=21$なので……
}}\newpage}


\R{null}{null}
\R{profile}{null}
\R{null}{step}
\R{profile}{step}

\end{document}
