/ 最近 .rdf 追記 設定 本棚

log[正規表: 2013-11-01]



20131101() Kindleトアから大手アダトコミックが大量削除 - 電パブログ■ちんちんかもかもって辞書に載ってる単語だったりする知らね■紙の本でも独善によって一部をなき物にするアマゾンだけど Kindleではそれよりさらに厳しい基準でのぞんでいるとTSUTAYAと一緒消えろ(※強勢はなし付けると願い事みたいになってしまう平板に興味のないゴミカスに退場を許可するみたいに発音する)■ところでReader Storeでも Kinoppyでも最初から取り扱いがなかったりするわけですね終わってるやん(直販してる)フラス書院が正解ISBNのついた本を100%カバーすることを目標に掲げた電書書店はないのか?■こんなんのまま紙が廃れたら悲劇だなあ分を弁えへん私企業に所有させていいもんやないでこんなところに利益をくれてやるのは同時に人質を差し出すようなものあとで後悔することになる@2013-11-18「あとで後悔が二重表現の例として挙げられていてそうかと思って書き直そうとしたがどうもしっくりしないこれは未来のある時点において後悔することを動詞(の付属部)だけでなく副詞も使って示しているのであってつまり後悔の対象が必ずその時点における過去の事象であることと後悔するのがいつであるかは別物なので二重表現にはならないのではないだろう「今後悔してるに対す「あとで後悔する(ことになる)は不自然じゃないと思う

最終更: 2016-11-18T12:59+0900

[tDiary][Firefox][正規表現][javascript] Firefoxが句点を行頭に送ってしまうのがあまりに目障りでもう耐えられないので~正規表現(Rubyに劣るECMAScript仕様)~禁則処理(IE完璧Firefox/Safariに指導)~両端揃え(IE完璧Firefox満足*Safariを補完)~画像とCSSDPI~字詰め

tDiaryのプラグインとして今回追加したのは auto_nobrの部分だ

add_title_proc {|date, title|
  auto_nobr = lambda{|src|
    return src.gsub(/[^{}\[\]()*#"!'`=:|][、。」』!?!?)]+|[「『(]+[^{}\[\]()*#"!'`=:|]/u){ %{{{'<nobr>'}}#{$&}{{'</nobr>'}}} }
  }
  inline_or_nil = lambda{|src|
    lines = src.split(/\r?\n/)
    return nil if 1 < lines.length
    html = WikiSection.new(auto_nobr.call lines.first).body_to_html
    return html.gsub!(/\A\s*<p>/, '') && html.gsub!(/<\/p>\s*\z/, '')
  }
  if title.index('<')
    title.sub(/<span class="title">([^<>]+)<\/span>/){|_0|
      html = inline_or_nil.call(CGI.unescapeHTML $1)
      html ? %/<span class="title">#{html}<\/span>/ : _0
    }
  else
    inline_or_nil.call(CGI.unescapeHTML title) or title
  end rescue title
}

一応Firefoxの挙動は word-break: break-allが指定された結果であるであるがだからといって行頭の句点句点だけの行(ぽつーん)はありえないだろうと思うのです。

 っつけ仕様

 1.標準に存在しない<nobr>タグの使用

かといって空白が関係するわけではないから white-space:nowrap とか使えないし使えたとして FONTタグを <span style="font:"></span>に置き換えるようなことに意味を見いだせたのはそれが 2000年頃のことだったからだし段落全体を一行で表示したいわけでもないので Pタグに対してルールを追加することもできず代替案が見つからない

 2.ーなテキト置換

HikiDocで意味を持ってそうな記号を避けつつ句点+1文字を<nobr>で囲ってる整形式でないというエラーが出るパターンがまだ残ってるかもしれないfootnoteプラグインとかわりと文章を渡すから危険だ

 3.対象がタトル欄だけ

全体を対象にするなら JavaScriptでやるでもテキトを対象にしつつタグをインジトする方法がわからなかった

ッチしたテキドキュメトフラグメ(テキ+NOBRエレメ+テキ)と置き換えればよかったのか?具体的方法が見えたところだがレイアトが変わってしまう変更を読み込み完了間際にスクリトで行うというのはやっぱりよくないかもフラグメト付きの URLでアクセスしたときターゲトが画面外に逃げてしまいかねない

 4.表示を確認したのは Firefox(23.0.1)IE9だけ

Operaは独自のレンダリングエンジンを放棄したしWindowsSafariはアップデトが止まったしGoogle Chromeはイール場所がキモいから(今でもそうかは知らない当然やめるだろうと予想するほどにそして一瞬でアンイールしてしまうほどにキモかったということだ)

 CSS 3におけるテキトの自動改行と禁則処理の定義 - builder by ZDNet Japan

break-all

任意の位置で自動改行を行うが日本語のテキトでline-break:normalと指定したときと同じようにゆるい禁則処理を行う

これを期待して待ってたんだけど

 アポラボロ: Firefox 15 の禁則処理を修正

word-breakというスタイルシトは文の改行の仕方を指定するものでもともと Internet Explorer 独自の物だったようなのですが最近になって Firefox もこれを採用したらしいのです。そのため以前の Firefox では無効化されることを想定してこのスタイルシトが指定されていたと考えられます。

ト制作者の想定としては IE のみにこのスタイルシトを指定したつもりが意図せず Firefox でも有効化されてしまい禁則処理のされない読みづらい記事が発生してしまったということだと思います。おそらくIE の場合はこのスタイルシトが指定されていても禁則処理には影響がなかったのではないでしょう

先行する IEはまとも後追いの Firefoxはバカ日本人の貢献が足りないのか?

 GeckoWebkitword-break:break-all; ってこれでいいの? « やおよろグッ!

良くないと思います。

 word-break: break-all;W3COKになってるし|ぼくんちのバックステージ

余談:Googleの検索仕様変更について

1ヶ月ほど前からGoogle検索の左メニーが無くなっちゃいましたねえ

スクリトを無効にしてると今でも出てくるんですよ畳まれたメニーをクリックしなくても大体の選択肢が羅列されてるんですよールバックが機能してるのをほめる前にスクリトを使って使いにくくしてることにあきれる

 @2013-11-02 正規表現パターンについて

auto_nobr処理の中の

/[^{}\[\]()*#"!'`=:|][、。」』!?!?)]+|[「『(]+[^{}\[\]()*#"!'`=:|]/u

というパターンは要するに

HikiDocで特別な意味を持たない1文字+行頭禁則文字、または、行末禁則文字+HikiDocで特別な意味を持たない1文字

という意味なんだけどHikiDocで~という部分が重複(ょうふく)してるパターンの中にパターンを展開する方法を持たない JavaScriptこの重複をどう取り除けるか?

文字列を組み合わせて RegExpのコトラクタに渡すのは文字列を Functionトラクタに渡すこと(evalと同じ)文字列から SQLを組み立てるのに似て好きではない一面でわかりにくくなるのを承知で書き直すとこうなる

/(?=([「『(]+)?([^{}\[\]()*#"!'`=:|])([、。」』!?!?)]+)?)(?:\1\2|\2\3)/u

前半の先読み部分は次のような意味の1~3個のキャプチャを含む

(行末禁則文字)?(HikiDocで~)(行頭禁則文字)?

後半の対象文字列と実際にマッチする部分はキャプチャを参照するだけの単純な二択

(?:\1\2|\2\3)

っこによるグループ化がないと先読みが最初の選択肢にしかかからないことに注意| の結合は一番弱い

ャプチャや分岐が増えてるがパターンの繰り返しはないしトリッキーに見えてもひとたび構造がわかると簡単だと思うがどうだろう

最終的にこの日記で使用するパターンは \3? を付け加えてこうなった

/(?=([「『(]+)?([^{}\[\]()*#"!'`=:|])([、。」』!?!?)]+)?)(?:\1\2\3?|\2\3)/u

これでっこで1文字だけを囲った 『目みたいなテキトがひとかたまりとして扱われて折り返されることがなくなる

ひとつ心配なのは?によって存在しないことにされたキャプチャを参照することが必ずマッチの失敗を意味するのかどう参照が空の文字列に展開されるなら必ず成功すると判断されてもしかたがないたとえそれが NULLと空文字列の混同だとしてもありそうな話ではある

 禁則処理がおかしい - Ronten

ここまで書いてから見つけたのがこれ

 word-break: break-all;

から

 word-break: normal;
 word-wrap: break-word;

に変更元々英数だけの文字がdivをはみ出す現象の防止の為にword-break: break-all; を指定していたがそれだと日本語の句読点が行頭に来てしまうっぽい

word-break: normal;だけだと英数だけの文字がはみ出すが上のように二つ指定すると日本語も英語も両方うまくいった

ええええええくやしいから本文の方だけ CSSで対応する

/* chiffon_leafgreen.css 183行目 */
div.day {
  word-break: break-all;
  word-wrap : break-word;
}

/* に追加して */
div.section {
  word-break: normal;
}

思い出した。word-break:break-allと word-break:normal(+word-wrap:break-word)での英字折り返しの違い。normalだとスペースでの折り返しが優先される結果、word-break:break-allしたかった目的

#箱の端から端まで文字を満たしたい。
#句読点など1文字程度の段差なら許容できる。
#やりすぎた字間調整(text-justify)は見苦しいからやらない。

が実現できないのだった。はみだすのも嫌だが右端がガタガタでカタマリ感がないのも嫌なのだった。これは word-wrap:break-wordでは補えない。

a ab abc abcd abcde abcdef abcdefg abcdefgh abcdefghi abcdefghij abcdefghijk abcdefghijkl abcdefghijklm abcdefghijklmn abcdefghijklmno abcdefghijklmnop abcdefghijklmnopq abcdefghijklmnopqr abcdefghijklmnopqrs abcdefghijklmnopqrst abcdefghijklmnopqrstu abcdefghijklmnopqrstuv abcdefghijklmnopqrstuvw abcdefghijklmnopqrstuvwx abcdefghijklmnopqrstuvwxy abcdefghijklmnopqrstuvwxyz

方針は変更せずトルではきっちり右端での折り返しを優先し本文では禁則処理を優先しようそもそもは word-break:break-allで禁則処理が行われるのが本当でそれこそが望みの結果なのに

 @2013-11-04 朝令暮改

2.ーなテキト置換が予想以上にプロブレマックだった二重ブラケトで囲った URLの中の ?NOBRタグで囲おうとして URLを破壊し XHTMLを破壊していた既に書いたように footnoteプラグインに引数として渡す文章に NOBRタグを挿入する問題もあるトル欄で footnoteプラグインは使わない(セクション末尾に脚注を挿入しようとしても無理だから)同じような問題が続出するということだ

というわけで目途をつけておいた JavaScriptでの実装に切り替えた

// Firefox(ver.15-23現在まで)が word-break:break-allで禁則処理を
// してくれないので NOBRタグで強制的に特定の折り返しを禁止する。
function auto_nobr(textNode)
{
	var create_nobr = function(text){
		var d = textNode.ownerDocument;
		var nobr = d.createElement("nobr");
		if (text) {
			nobr.appendChild(d.createTextNode(text));
		}
		return nobr;
	};
	var m, re = /[「『((]+.[))』」、。!!??]*|.[))』」、。!!??]+/;
	while (m = re.exec(textNode.nodeValue)) {
		/* assert 0 < match.length in case of infinite loop. */
		nobrText = textNode.splitText(m.index);
		textNode = nobrText.splitText(m[0].length);
		nobrText.parentNode.replaceChild(create_nobr(m[0]), nobrText);
	}
	return textNode; // the last Node of splitted textNodes.
}

function apply_auto_nobr_recursively(node)
{
	var except_tags = {
		"textarea":"タグの包含が許可されていないのか<nobr>で囲ったテキストが消えてしまう。",
		"nobr"    :"二重適用防止"
	};
	for (var child = node.firstChild; child; child = child.nextSibling){
		if ((child.tagName||"").toLowerCase() in except_tags) {
			// skip blacklist-ed elements.
		} else if (child.nodeType == Node.TEXT_NODE) {
			child = auto_nobr(child);
		} else if (child.firstChild) {
			apply_auto_nobr_recursively(child);
		}
	}
}

var h2 = document.getElementsByTagName("h2");
for (var i = 0; i < h2.length; ++i) {
	var root = h2[i].parentElement;
	if (! root || root.tagName.toLowerCase() != "div" || -1 == (" "+root.className+" ").indexOf(" day ")) {
		continue;
	}
	// now root is a div.day.
	apply_auto_nobr_recursively(root);
}

それから

ひとつ心配なのは?によって存在しないことにされたキャプチャを参照することが必ずマッチの失敗を意味するのかどう参照が空の文字列に展開されるなら必ず成功すると判断されてもしかたがないたとえそれが NULLと空文字列の混同だとしてもありそうな話ではある

と書いておいた懸念は現実のものだったFirefox(23.0.1)でも IE9でも次のスクリトは true(ッチした)を表示する(ちなみに ruby1.8nil(ッチ無し)を返)

alert(/(?=(A)?)\1/.test("B"));

これと区別できた方が応用が広がるのに

alert(/(?=(A?))\1/.test("B"));

 @2013-11-05 Safari(5.1.7)の微妙に異なる振る舞いとやり残し

Safariでは <nobr>で囲った直前の文字までがひとかたまりになるのか句点+2文字が次行に送られている読みやすくはあるがなんでこうなる? Safariのユーザー・ージト・スタイルシトに nobr{white-space:nowrap}があるこれを normalで上書きすると NOBRタグによる禁則が無効になる空白による分かち書きを行わない日本語文章において white-space指定は空白だけを対象にしたものではなかったそういえば全角文字だけの文章と全半角混在の文章で Safariの処理が異なるという報告もあった<NOBR>でも white-space:nowrapでもSafariが対象要素の外側にある1文字を余分に巻き込む理由にはならないとおもうけどパターンから行頭禁則文字手前の1文字にマッチすトを取り除くと Safariの挙動に対応した禁則処理が行えるがそうすると Firefoxで行頭禁則が効かなくなるおかしな Safariに合わせたりはしない

既にタグで囲まれているテキトと交差するように <nobr>で囲うことはできないということは、<a>テキ</a>とか <a>テキ</a>みたいなよくあるマークアップ済みテキトに禁則処理を適用できないということだ(むしろこれに対処したくて Safariは直前の文字(要素)を巻き込んでるのか?という疑いもわいてきたが直前の文字ならぬ直前の要素にくっついたりはしなかった残念Safari残念)これは後付けスクリトでなんとかできるとは思えないFirefoxword-break:break-all完全対応待ち

 @2013-11-06 両端揃え

1.箱の端から端まで文字を満たしたい

を徹底するためにスタイル指定を足して完成

.day .section, .day .title > * {
  text-align: justify;           /* 両端揃え */
  text-justify: inter-ideograph; /* 日本語両端揃え(IE向けに字間の調整方法を指定する。CSS3?) */
}

Firefox(23.0.1)IE9は期待通りSafari(5.1.7)は英字手前のスペースだけを使って両端揃えをしようとして英字混じり文が不自然に分断されるこれは

3.やりすぎた字間調整(text-justify)は見苦しいからやらない

に反するけどSafariだけの問題なので知らない時間が解決するでしょう

<追記@2013-11-11>WebKit向けに面白いことをしてる人がいますね【目指せePub出版】Webkittext-align:justifyに挑戦する | 高橋文樹.com俺だったら表示されない空白SPAN要素を挿入するんでなく Unicodeの幅0スペースのどれかを挿入するかな結果が期待通りになるかは確かめる必要があるしいずれにしろコピペがひどいことになりそうでコンテンツを改変しない方策が望まれる</追記>

<追記@2013-11-12>こういう指iOS5Mobile Safariでは日本語でも両端揃えができるようになりました | BALLOGもあるが提示された例から判断する限りiOS4で行われていの禁則処理が iOS5で行われなくなった結果行末が揃っただけに見える字間調整が行われた結果ではなくむしろ退化してないか?それから全角文字だけで文章を書くならスペースに頼らない字間調整が行われるとの報告もある>webkit系ブラウChrome/Safariで両端揃えはできないの?jQueryで検証 | 株式会社LIG</追記>

 @2013-11-07CSS Text Module Level 3 (www.w3.org)

 text-justify

W3C Last Call Working Draft 10 October 2013

The following features are at risk and may be cut from the spec during its CR period if there are no (correct) implementations:

  • thetext-justifyproperty

Value: auto | none | inter-word | distribute

先月出た文書text-justify(とその他いくつか)が名指しで消滅の危機後がないinter-ideographに代えて distributeを指定しといた方が先々有効かも(属性自体が消えてなければ)

 word-break, line-break

word-breakline-breakを統合するのはなくなったんだろうline-breakの項目があるうまくないとは思ってたので歓迎でも句読点の禁則が line-breakの3つのレベル:strict-normal-looseのどこかわからない

句点は U+3002;CL # IDEOGRAPHIC FULL STOPかぎかっこ()U+300C;OP # LEFT CORNER BRACKETUAX #14 (www.unicode.org)では CLOPも言及されてるけどCSS5.1. Line Breaking Detailsではそれらを含まないクラスに限定して UAX #14を参照してるから CLOPも位置づけが明確にならない要はline-break属性で具体的に挙げられてるのは最低限の要件であってその他の線引きは User-Agentまかせということだった書いてありました

CSS distinguishes between three levels of strictness in the rules for text wrapping. The precise set of rules in effect for each level is up to the UA and should follow language conventions. However, this specification does require that:

将来組み版向けに細かい制御が必要だろうとも(別の場所で)ってるが当面満足できないということはline-breakを緩くしておいて必要な部分に<nobr>というアプローチもなくはないのかな?

KADOKAWAEPUBの取り扱いに関する文書を公開していたなとダウンロドしてみたKADOKAWA-EPUB PORTAL

■3点リーダや2倍ダーシがつづく際の禁則の抑制について

3点リーダや2倍ダーシナカグロなどは前後の文字と分離禁止禁則が行われるためあまり長いと直前の文字から改行されて意図せぬ表示になることがあるそのようなときは4文字以上連続する場合を目安に以下のようword-break-break-allを該当箇所にのみ指定すること未対応の RS もあるが指定があって表示が崩れることはないので挿入しておく

【参考】分離禁止される可能性の高い文字について

CSS3 line-breakの項には頭・行末で前後の文字との分離が禁止になる文字についての記載がある詳細http://www.w3.org/TR/2012/WD-css3-text-20121113/」のline-breakの項を参照

実際にはまだ禁則処理については RS 次第でありline-break の指定が反映されることも期待できないのでこれらに依存するような記述は避ける

制作仕様ver.1.0.1

基本は word-break:normal必要に応じて一部を word-break:break-all包む(くるむ)っかで見たような文書(だがちっと古い)へのリンクもあるぞ

この PDFでも見たし数日前自炊ePubのためのあれこれ覚え書き - 道具眼日誌:古田-私的記録でも見たのだけどtcyというクラス名をっぱりアレをタテチュウヨコと読むんだってことだよね検索したら例によって Wikipediaが一番読み「たてちゅうよこであり「たてなかよこではなJIS X 4051で規定腹腔といい縦中横といいーカルルールでもこうと決めたからには正解!みたいなのってどうなん?

 @2013-11-09 ECMAScript(3rd&5th ed.)Rubyとは異なる残念正規表現仕様

20131101p01.08の最後の方に書いてたことFirefoxでも IEでも Safariでも同じ挙動――?をキャプチャの中に付けても外に付けても trueを返すこと――を示すので ECMAScriptとして規定されてるんだろうと探してみた以下該当部引用太字強調は失われたり付け足したりしてます。

The form (?! Disjunction ) specifies a zero-width negative lookahead. In order for it to succeed, the pattern inside Disjunction must fail to match at the current position. The current position is not advanced before matching the sequel. Disjunction can contain capturing parentheses, but backreferences to them only make sense from within Disjunction itself. Backreferences to these capturing parentheses from elsewhere in the pattern always return undefined because the negative lookahead must fail for the pattern to succeed. For example,

 /(.*?)a(?!(a+)b\2c)\2(.*)/.exec("baaabaac")

looks for an a not immediately followed by some positive number n of a's, a b, another n a's (specified by the first \2) and a c. The second \2 is outside the negative lookahead, so it matches against undefined and therefore always succeeds. The whole expression returns the array:

 ["baaabaac", "ba", undefined, "abaac"]
Microsoft Word - Ecma-262.doc / Standard ECMA-262 3rd Edition - December 1999 / 15.10.2.8 Atom / 139ージ

こちらでも "always succeeds"と書いてある

Informative comments: An escape sequence of the form \ followed by a nonzero decimal number n matches the result of the nth set of capturing parentheses (see 15.10.2.11). It is an error if the regularexpression has fewer than n capturing parentheses. If the regular expression has n or more capturing parentheses but the nth one is undefined because it hasn't captured anything, then the backreference always succeeds.

15.10.2.9 AtomEscape / 140ージ

残念だthereforeとかあっさり書いちまいやがってそれはまったく自明ではないぞ

空パターン(JavaScriptPerlと違ってダブルスラッシュがコメトになってしまうので作るのに小細工が必要)が必ず成功するのはわかるでもそれに対応するのはキャプチャが空文字列を保存していてそれを後から(その文字列そのものにマッチする)パターンとして参照した場合であって参照すべきキャプチャ・参照すべきパターンが存在しない(=undefinedである空文字列ではない)ときは必ず失敗して欲しかった理由はすでに書いたようにこの二つを区別できなくなるのが困るからだ

/(?=(A)?)\1/.test("B"))
/(?=(A?))\1/.test("B"))

っと実際的な不利益は 20131101p01.06に書いた書き換えが通用しないことだこれって C++11にも影響する(してる)んでしょ? *SIGH*

 @2013-11-12 Safari(Win5.1.7)で満遍なく字間調整

Safariでは全半角混在文章に対しては自動的に text-justify:inter-wordに相当する字間調整が選択されるらしく日本語文章にわずかに含まれる空白が過剰に引き延ばされた見苦しい表示になってしまうことをもう書いた>20131101p01.10

実は word-break:break-allを指定しているとほとんど任意の場所で折り返しができるので(Safariの場合禁則処理も行わないので)わずかなスペースに調整のしわ寄せがいっても問題にならない(といっても切り落としたような右端のラインは得られないが)でも禁則処理を施した場合 Safariはなぜか3文字を次行に送ってしまうので(20131101p01.09)全角1文字分以上の空白が文章を分断してしまうのが問題になる

どうするこれに対処し<span style="width:0; font-size:0; overflow:hidden"> </span>を挿入した人が唯一見つけられるvisibility:hiddenを指定した空白なら挿入してもコピペに影響しないのを SafariIEFirefoxで確認した()ので自分はこうした.textContentには影響するかも.innerTextには影響しないかも

// Windows版Safari(5.1.7)の字間調整は全半角混在文章でスペースに対してしか働かず文が不自然に分断されてしまう。
// 不可視の空白を挿入することでさらなる字間調整ポイントを Safariに対して教える。
// 相当うざい結果になる(なにせほぼ任意の2文字の間に SPAN要素が挿入される)ので、Safariでだけ実行するように。
function textfunc2_safari_whitespace_distribution_inter_ideograph(textNode)
{
	var _xp, new_xp = function() { // XP = expansion point
		if (! _xp) {
			var d = textNode.ownerDocument;
			_xp = d.createElement("span");
			_xp.style.fontSize      =
			_xp.style.letterSpacing = "0px";
			_xp.style.visibility    = "hidden";
			_xp.appendChild(d.createTextNode(" "));
		}
		return _xp.cloneNode(true);
	};
	var p = textNode.parentNode;
	var m, re = /\S(?=\S)/;
	while (m = re.exec(textNode.nodeValue)) {
		/* assert 0 < match.length in case of infinite loop. */
		textNode = textNode.splitText(m.index + m[0].length);
		p.insertBefore(new_xp(), textNode);
	}
	// ついでに、Safariが <nobr>の直前直後の2文字を接着して字間調整も折り返しも行わないのを矯正する。
	try { if (textNode.nextSibling.tagName.toLowerCase() == "nobr") {
		p.insertBefore(new_xp(), textNode.nextSibling);
	} } catch(e) {}
	return textNode; // the last Node of splitted textNodes.
}

スクリトの全体はページのソースを参照のこと結構重い処理なのでページの表示後しばらくして文字が移動するのが見えてしまうかもでも Safariだけの問題なので()

Safariで表示したこのページでテキトを選択してみると文字と文字の間に白い縦線が入ってるのが見えるんじゃないだろうそれが visibility:hiddenなスペースだと思われる行末から行頭に向かって1文字1文字の間に1ピクセルの字間を配ってるかんじ行頭に着いても分配する字間が余ってる場合は2ピクセル目をまた行末から配るたまに2文字くっついたままになってるのは禁則処理のために挿入した NOBR(開き)タグの直前と直後の文字Safariはなんでこの2文字を接着してしまって字間調整も折り返しも行わないんだろう<NOBR>の直前に字間調整用の SPANを挿入するとめでたく接着が解けたがSPAN挿入の二重適用を避けつつ NOBRに限ったドホックな処理を追加せずに済む方法は……。<追記@2013-11-14>上のスクリトは Safariを特定したものなのだしNOBR要素狙い打ちで字間調整用の SPANを注入することにした </追記>

<追記@2013-11-21>見えないクリップボドにコピーされないとはいえスペースを挿入してるのは間違いないのでスタイルシトを切ると空白入りのテキトが表示されるしージ内検索も空白を入れないとヒトしないタグの意味的にもこれらの副作用を避ける目的でも WBRタグを使いたいんだけど字間を挿入する効果がないんよね。</追記>

<追記@2013-11-25>分離禁止と分割禁止の2つの概念分離禁止は分割禁止を含むより強い拘束―と―の間に改行(折り返し)はもちろん空白も挿入してはいけないというのが分離禁止の例WBRは分割(改行(折り返し)の挿入)を許可する要素だから自動的に字間の挿入も許可しているはず。期待して待っていていいかな?</追記>

 W3C日本語組版トとCSS3 - JAGAT

WebKit以外は禁則に対応しているCSSには禁則ルール「通常「厳しくする3段階の設定がある両端揃えについては実装依存「どういう実装をしてもいいただ日本語ではJLREQを参照するといいとしているEPUB仕様も同様である

Firefoxword-break:break-allを指定すると禁則処理が行われなくなるのが問題(対応してるが適用)

Safariが全半角混在文章に対して日本語向けの両端揃えを選ばないのが問題(xml:lang="ja-JP"なのに JLREQを参照すべき場面だと思われていな)

 public-html-ig-jp@w3.org Mail Archives

 @2013-11-14 PS3泥ケー・Opera

PS3のインターネトブラウザも今では WebKitースだとか(実際そう名乗っていた。診断くん)なかなかきれいなフトレンダリングで(でもズームするともやっとする)禁則処理字間調整の方法まで含めて Safariによく似た結果スクリトを有効にすることでこのページも期待通りの表示になった

もうひとつブラウザドロケ(URBANO L01)で表示すると中心線近くでせせこましく折り返したり折り返さなかったりする現象()が見られたんだけどgoogle/京セラのせいにして放置していいのかDPIの高さにこのページが対応できていなかったりするの

※スクリト実行中は画面に見えてる3日分のタトルがせせこましく折り返してた実行後は先頭の1日だけがせせこましく折り返したままだった

またナビゲーションリンクをクリックすると再現性なく HTTPステータスコ505 HTTP Version not supportedが返ってくることがわずかな時間に何度もあったっぱりブラウザ(GCかどうか知らないが)が信用ならんのかなLTE経由やったから auがいらん茶々入れてたんかな

Opera17も試してみたんだけどトの設定がないのんな開発者プレビーにはあったみたいだけどその場所にもなかった閲覧者が読みやすいと感じるフトは閲覧者が知っている(そして設定している)だろうと思って HTML/CSSではフトファミリを指定してないんだけどその結果がMS Pゴシックのビトマップフ3段階ほど文字を大きくするとベクタデータに切り替わるのか見られる表示になるけどMS Pゴシックをあえて指定してすら文字が美しい Safariとは雲泥の差見るに堪えない

 @2013-11-15ーマ画像DPI

URBANOのブラウザは Google Chromeではなかったージョンが4.XXXだということがかろうじてわかったがまったく素性が知れないこれは不自由ゆえか不慣れゆえ

スマホの Google Chromeで表示してみると PCで見るより一行の文字数が少ない固定サイズの背景画像を基準にして横幅をピクセルで指定しているためにひと文字ひと文字をより多くのピクセルを使って精細に描画する(DPIってこと)スマホでは文字数が減るんだろうこういうのってベクタ画像をスケーリングしたり左上角+辺の繰り返し+右上角の画像3枚構成で横幅を可変にしたりするのだろうそういうことができるのかどうかも知らないけどそれかこういうときにこそ画像の DPI(JPEGにそういう値がなかった?)が役目を果たしてブラウザが勝手にリサイズしてくれたりするんじゃないんだろうDPIとピクセル数で現実世界の長さがわかるわけでそれを共通の尺度にしてブラウザが再度スマホにおいて画像を表示するのに使うべきピクセル数を求められるはずでは?でも現実世界の長さを共通の尺度にするとスマホの画面サイズは PCのモニタと比べて小さすぎるのでもそれはスマホが DPI設定をそれなりの高さに抑えておいてズームを駆使すればいいだけのことじゃないWindowsDPI設定がモニタのピクセル密度を全然反映していないのだから何を考えても机上の空論そもそも日記のテーマ(chiffon_leafgreen)で使われてる画像が DPI値をセトできない GIF(ジフ)った画像にだけ DPIが指定してあってもというのもある画像のピクセル数を基準にして div.day要素の横幅が 510pxと指定してあるからこちらも画像が何ピクセルを使って表示されるのかに合わせて変換されないとつじつまが合わないそのへんはまた CSSpx単位が論理的/相対的な単位であるとかが関係してきて……これかなpxpixels; 1px is equal to 1/96th of 1inDPIを固定して定義されてるから pxと現実世界の長さがいつでも1:1対応するその結果 CSS1pxとモニタの画素とは1:1対応しないーマ(※ライセスはGPL)で使われてる画像を 96×96DPI指定した PNG(pingと同じピンではないの?)に変換するだけで解決するといいなあ(儚い希望)

 PCでなんちってRetinaFirefoxSafariにつく差(@2013-11-22)

WindowsDPI設定を2倍(192dpi)にするとなんちってRetina(300overにはまだまだ届かない)を体験できる贅沢なピクセルの使い方の代償は画面の仮想的な広がりが面積比4分の1に狭くなること24.1インチ・WUXGA(1920×1200)モニタは今となってはでかいばっかりで粗いもんだ4Kなんかより QUXGA Wide(3840×2400)27インチまでで出ないかな

Firefoxは高DPI設定に応じて滑らかな質感すら感じさせる文字を表示するSafari自分の管理外なのであろうドウのタトルバーの文字だけがきれいでメニーから文字から他の全てが滲んでぼやけている(もちろんズームはしていない)Safariの普段の美しさは最適化(切り捨て)の結果なのだった。<< .exeのプロパ「高 DPI設定では画面のスケーリングを無効にするにチックを入れるとまた結果が違うかも。(@2015-11-24)

仮想的に DPIを上げたからといってスマホの Google Chromeで見たようにこの日記の1行が16文字になったりはしないんだよねームでなく文字サイズだけを拡大すると行あたりの文字数が減っていくからこれかな? 対策は画面が小さくて文字が読めないときは文字サイズそのままでズームしろ<<改めてスマホのGCで確認した既に述べた状態は文字サイズ100%でのもの60%PCより少し1行の文字が多いくらいになるそれでタップしてズームすると左右の余白がほぼゼロになって精細で美しい文字の文章が難なく読める物理的には PCモニタより小さいんだろうけどカンマとピリドを見分けるのにも苦労しない文字サイズ100%PCと同じレイアトになって欲しいんだけど……

 追記@2014-02-16 ドロケーのブラウザ60%PCより少し1行の文字が多いくらいになることに関係するかもしれない話

Androidの密度非依存ピクセdp

Density-independent Pixel / dipともいう

このdpという単位はAndroidアプリを作る際に使われる単位でAndroidの開発者向けウェブサトではDevice-independent Pixel(密度非依存ピクセル)という単位を定義しています。これは160dpiのピクセル密度を持つスプレイで表示される1px1dpとしたものでたとえば320dpiの場合1dp = 2px480dpiの場合1dp = 3pxになります。

いまさら聞けないRetina対応のため「ピクセルの話 – Rriver

Androidでは WindowsCSS3に準拠した 96dpiではなく160dpiに固定して論理ピクセdpを定義したと160:96 = 1:0.6だから文字の描画に使用する画素数を 60%()×60%()に減らしたときに PCとレイアトが同じになることに納得できる

 訂正@2014-03-17 CSS31pxが1対1対応するのは CSS31inであった

そして1inが現実の 1インチに対応するパターンの他に1px"reference pixel"に結びつけられるパターンが認められているAndroidGoogle Chromeでは reference pixelを媒介にして CSS3 pxdpが一致してるってことなのかも

 @2013-11-19HTMLで文字詰めするタイポグラー用JS | fladdict

これは字詰め禁則とも字間調整(広げる方)ともかち合うのでこれを適用しようとするとタグの交差に対処する方法を真剣に考えないといけないでもやりたいなあ読点とかぎ括弧中黒は全角だと間延びしすぎだしだからって半角文字を使うのも違う気がするしああでもトを知らないと盲撃ち(めくらうち)になってしまうのか……Webトが救世主なんだろうけど文字サイズを決めないのと同様にフトもこちらで決めたくはないのだなといいつつ…リニーアルした(www.hsbt.org) www.ruby-lang.org/en/ の文字が見なれないきれいさだなと思ってイスペトすると Noto Sunsという Googleが提供する(?)トが使われていたりして結局は受けとり手が満足できるかどうかが問題なのだった

<link href='https://fonts.googleapis.com/css?family=Noto+Sans:400,700,400italic,700italic&amp;subset=latin,cyrillic,greek,vietnamese' rel='stylesheet' type='text/css'>

 @2013-11-20 字詰め

ったほとんど昨日貼ったリンク先のスクリ(FLAutoKerning.js)の移植行頭の約物の処理だけ省いた折り返しでの天付きをせずにそれだけするのもどうかと思っていい加減長いので詳細はソースの textfunc4_jizume

 問題点
  • さらに重くなった重たい字間処理と重なる WebKit系が悲惨
  • MS Pゴシックだと詰まりすぎるつまりーザーがフトを指定できない Opera17で詰まりすぎる今日のこの日記を長々と書き継いでいるうちにリリースされた Opera18ではフトの指定ができましためでたいOperaすばらしい(もちろん皮)
  • Safariでは一部の記号の一部()が元々詰まっていてそこに字詰め処理が入ると詰まりすぎるCODEタグによってプロポーショナルと等幅が切り替わる所だったこれは特殊だし難しいケースだ(ある程度はタグを乗り越えて)隣の文字を見て詰める量を決めるけど隣の文字からフトが変わってるとは思わないもんなあタグを乗り越える理由は禁則のための NOBRタグを無視したいからなので要素の終端で打ち切る選択肢はない
  • 適用先の要素に 0以外の letter-spacingが指定されていた場合はそれに加算した letter-spacingを設定すべきではないか?

まとめるとトにメイリオを指定した Firefox(25.0)Internet Explorer(9)以外お断り仕様になってしまいました

Firefox25での表示(ベンチマーク)> 20131101p01.pdf(610KiB)

スクリーンシト追加@2013-12-05

  • Firefox19 on Mountain Lionのスクリーンシ(5.2MiB)>macml_firefox_19.0.png
    • Fx23 on Vistaとの違い

      1. text-align:justifyにも関わらず右端が揃っていない(その割に文字間が調整されたような疎密の波がある)
      2. PRE内の文字が font-size:100%指定にも関わらず 90%ほどになってる(IEとか他のブラウザでなら見たことあるけど)
  • iPhone5でのスクリーンシ(5.0MiB)>ios_iPhone-5_6.0_landscape.jpg
    • Fx23 on Vistaとの違い

      1. PRE内の文字が font-size:100%指定にも関わらず 90%ほどになってる
      2. 他は完璧というか感覚的な読みやすさで凌駕してるのでは?

プロポーショナルフトにはもともと余分な空白はないし()等幅フトが指定してあるなら等幅であることを尊重すべきだし実質ほとんど等幅のプロポーショナルフトであるメイリオでしか見るべき効果がない

※参考にすること(トリクスカーニングとオプカルカーニング)@2013-12-05デザイナーは文字詰めに命をかけよう ~和文と欧文のフーマトの違いから考える~ | 企業ソーシャルメア運用・ーシャルデータ分析・YouTubeャンネル運用の株式会社アトゼロ

SVGの方に measureTextとか text-renderingがあるらしい(DOMスペクタを覗いていたら見つかった)CSS Fonts Module Level 3にも font-kerningとか font-variant-east-asian:proportional-width(胡散臭い……)とかあった追い追いどうにかなるでしょう


といいつつっかく書いたコドを捨てきれないのだなあ簡易に等幅とプロポーショナルフトを見分けてプロポーショナルの場合は字詰めの対象を絞ることにしたメイリオMS PゴシックSH G30-MSH G30-Pでまあまあ破綻せずに表示できてると思うトするときはトを切り替えた後にリロドしないとフトにあった処理が行われないことに注意

長いけど貼りますよージョン管理されてませんからログを残さないとね

// 全角の約物・句読点などの連続すると過剰になる余白を詰める。プロポーショナルフォントはもともと
// 余白が調整されているから、主にメイリオと等幅フォントが対象になる。
// textfunc2/textfunc3で字間調整のための見えないスペースを挿入した後だと全く
// 効果がないのでその前に実行すること。
//
// アイディアと実装とカーニングペアの定義の下敷きはこちら。
// http://fladdict.net/blog/2011/02/auto-kerning.html
function textfunc4_jizume(textNode)
{
	var is_proportional = function() {// ¿等幅フォントもしくはほぼ等幅のメイリオではない? フォントごとにカーニングペアのひとつひとつについてテストするのもいいかもね。
		try {
			var canvas = textNode.ownerDocument.createElement("canvas");
			textNode.parentNode.appendChild(canvas);
			var ctx = canvas.getContext("2d");
			ctx.font = "100% "+getComputedStyle(textNode.parentElement||textNode.parentNode).getPropertyValue("font-family"); // If returned value is the used value, appendChild may be removed.
			//console.log(""+ctx.measureText("」「").width+" "+ctx.measureText("@@").width);
			return ctx.measureText("」「").width < ctx.measureText("@@").width;
		} catch(e) {
			return true; /* 字詰めをやりすぎないように無難な方を返す。*/
		} finally {
			if (canvas) {
				textNode.parentNode.removeChild(canvas);
			}
		}
	};
	var ki = is_proportional() ? textfunc4_jizume.kerning_info_for_all : textfunc4_jizume.kerning_info_for_monospace;
	var enclose_in_letterspacing_span = function(textNode, em) {
		var span = textNode.ownerDocument.createElement("span");
		span.style.letterSpacing = ""+em+"em";
		span.appendChild(textNode.parentNode.replaceChild(span, textNode));
	};
	var next_element_char_or_empty = function(textNode) {
		var skip_blankTextNode = function(node) {
			for (;node && node.nodeType == Node.TEXT_NODE && /^\s*$/.test(node.nodeValue); node = node.nextSibling) {
				// empty loop-body;
			}
			return node;
		};
		var nextNode = skip_blankTextNode(textNode.nextSibling) || skip_blankTextNode(textNode.parentNode.nextSibling);
		for (; nextNode && nextNode.nodeType != Node.TEXT_NODE; nextNode = skip_blankTextNode(nextNode.firstChild)) {
			// empty loop-body.
		}
		return (nextNode && nextNode.nodeType == Node.TEXT_NODE) ? nextNode.nodeValue.charAt(0) : "";
		// あんまり先の方の文字を読んで letter-spacingを設定しても意味ないかもね。
		// 何もしないか、むしろ先の文字に負の marginなりを設定したほうが意味があるかも。
	};
	for (var i = 0; i < textNode.nodeValue.length;) {
		var     char = textNode.nodeValue.charAt(i);
		var nextChar = textNode.nodeValue.charAt(i+1) || next_element_char_or_empty(textNode) || "*";
		var space = (ki[char+nextChar] || (ki[char+"*"]||0)+(ki["*"+nextChar]||0));
		if (space) {
			var charNode = textNode.splitText(i);
			    textNode = charNode.splitText(1);
			enclose_in_letterspacing_span(charNode, space);
			i = 0;
		} else {
			i += 1;
		}
	}
	return textNode; // the last Node of splitted textNodes.
}
/*
	カーニングペアの定義
	単位はem。 -0.5(em) でボックス0.5個分詰まる。
	"*く" と定義した場合、"あく"、"いく"、"うく"、というように、全ての"○く"の組み合わせにカーニングが設定される。
	"あく" と定義をした場合、 "あく"という文字のペアのみにカーニングが設定される。
	ワイルドカードペアと直接指定のペアが衝突する場合、直接指定のペアが優先される。
*/
textfunc4_jizume.kerning_info_for_all = { // プロポーショナルフォントでも削られていない(であろう)余白に関して設定する。
// 直接指定のカーニングペア
"か。":-0.05,
"が。":-0.10,
"け。":-0.10,
"げ。":-0.15,
"す。":-0.15,
"ず。":-0.15,
"み。":-0.05,
"。」":-0.25
};

textfunc4_jizume.kerning_info_for_monospace = { // プロポーショナルフォントでは削られている(ことが多い)余白に関して設定する。
// 前後の文字をワイルドカード指定した汎用のカーニングペア
"*ト":-0.10,
"*ド":-0.10,
"*「":-0.25,
"」*":-0.25,
"*(":-0.25,
")*":-0.25,
"、*":-0.25,
"。*":-0.25,
"・*":-0.25,
"*・":-0.25,
"*:":-0.25,
":*":-0.25,

// 直接指定のカーニングペア
"」「":-0.75,
"」。":-0.50,
"」、":-0.25,
"、「":-0.75,
"。「":-0.75,
"、『":-0.75,
"。『":-0.75,
"、(":-0.75,
"。(":-0.75
};
for (var k in textfunc4_jizume.kerning_info_for_all) {
	textfunc4_jizume.kerning_info_for_monospace[k] = textfunc4_jizume.kerning_info_for_all[k];
}
 getComputedStyle(textNode.parentElement||textNode.parentNode)に関して

IE9がテキドに parentElementを定義していないらしいまさにこれですよ

一部のブラウザーではparentElement プロパElement ドでのみ定義されており特にテキドに対して定義されていない場合がある点に注意して下さい

Node.parentElement - Web API リファレ| MDN

parentNodeでなく parentElementを呼んでるのは getComputedStyleの第一引数が Elementでないといけないと書いてあるからで

The first argument must be an Element, not a Node (as in a #text Node).

window.getComputedStyle - MDN

IEの場合だけ parentNodeで誤魔化します。parentである Nodeはいつでも Elementであるという仮定は確かめてないけどほぼ正しいでしょう

 @2013-11-25Mozilla, Opera でも日本語を均等割付(deztec.jp)

ってドメインだけど 11年前の記事とあって読んだことはなかった2番目に見つかった空白挿入で均等割り付けをやった人ただし対象は WebKitでなく OperaMozilla今の Firefox(1.5から?)は日本語文字間に調整用の字間を挿入してくれる英字間にまったく配分しないのが行内の疎密の偏りとなって時々目立つというのが現在の問題

 スピドアップ

is_proportionalが全体の50%の時間を使っていたので結果をメモすることにした読み込み完了直前に一回だけ実行する処理だからスタイルやフトの変更について行けなくても構わないよね関数の消費時間の40%が削減できたので全体では2割の削減

 @2013-11-27 defer, async. ねえ waitは?

スピドアップの一環SCRIPTタグに deferやら asyncを付けようと思うたびに未定義の関数を呼び出すエラーに悩まされて結局諦めるこういう非同期・遅延属性を付けたいのは完全自動の後付けスクリトか共有ライブラリのどちらかだ完全自動タイプは問題ないdeferasnycを両方付けて非同期・最速で実行してもらえればいい完全自動だけどイベントドリブンではないなら対象要素の登場後に配置するなり deferだけを付けるなりすればいい(※あれもこれも deferにすると一部の非常に遅い外部スクリトが以降の deferスクリトの実行をブロックしかねない?)ライブラリの場合はライブラリ関数を呼び出すコドがどこかにあるそれが独立した .jsァイルであればライブラリ共々 defer属性だけを付けると順番に実行されることが期待される(HTML5に限って?)でもページやその内容に依存して呼び出しコドが変化する場合は?ページの一部として HTML内に埋め込まれている場合は? src属性がない SCRIPTタグには deferasyncも付けてはいけないという

ライブラリは非同期・最速で読み込んでほしいそれを待って実行したい HTML埋め込みスクリトはどうやって待つ?

DOMContentLoadedイベトの発火は Blink Opera(18)で非同期スクリトの読み込み・実行より早いことがある仕様がどうあれ画像やスタイルシトの読み込みがまだかもしれないのと同様スクリトの読み込みが完了しているとは期待できないのが現状

答えは jQueryのソースとかこのへんに(丸投げた)><script>タグのasync属性を使わずに非同期でJavaScriptを読み込む方法 | さくらたんどっとびーずscript.onloadを使ってJavaScriptがロドされた時の処理を記述する | さくらたんどっとびーず

ってらんない非常に保守的で asyncdeferを付けすぎても全然問題を起こさない(でも読み込みは並列でやって) Firefoxに限って script.onloadだとか document.currentScriptdocument.onafterscriptexecuteといったお役立ち手段が充実しているというってらんない

<追記@2013-12-02>Promiseという名前/概念を仕入れたasyncSCRIPT要素が Promiseを返してくれればPromise.every(これとこれとこのスクリ).then(function(scripts){ 指定したスクリトに依存した処理 })とか書けそうscriptsが何の配列なのかという疑問は残る</追記>


一番遅いのはスクリトによるブロック(HTML解釈DOM構築中断。スタイルシト読み込み完了待ち(ただし Operaはインチキしてたらし))ではなくtDiaryスポスなんだけどね静的ファイル書き出しには抗いがたい魅力がある.htaccessにはこういう記述があるんだけど

# Rewrite rule1
#  shows static html, if exists.
RewriteCond /home/vvvvvv/www/cgi_file/ds14050/diary/snap/$1.html -f
#RewriteCond %{REQUEST_METHOD} =GET [OR]
RewriteCond %{REQUEST_METHOD} =HEAD
RewriteCond %{HTTP:Cache-Control} !=no-cache [nocase]
RewriteRule ^([0-9]{8})\.html$ /cgi_file/ds14050/diary/snap/$1.html [L]

なんでやめた(GETの場合を除外した)んだっけ<ーマがまだら模様になるからだコメトやらなにやらで更新のあった日は隣の書きっぱなしの日とは異なる更新日時点のテーマをまとって新たに書き出される常に現在のテーマで表示されるも良し12月に書いた日記がいつまでも12月のテーマで表示されるも良しでもモザイクはいただけないSSIででも対処したらいいんだけど1行コメトアトする方が簡単だったとか単体で完結しない .htmlァイルを書き出すことへの抵抗だとか(SSIがサーバーを選ぶことは気にしない)

Latestドや Monthドでスポスを一日一日順番に出力していくとかでもブラウザの助けになるんではないかと思うけどどうだろう思い立ったが吉日でちっとやってみよう<<ETagとか Content-Lengthッダをどうするんだって

ETagは必ずしもスポスボから生成する必要はなかった>ETagをどう生成するか - 岩本隆史の日記帳

Content-Lengthはどう

  • 転送コングが施されている場合Content-Lengthッダは送られてはならないし仮に送られてもこれを無視しなければならない
  • 転送コングが施されていない場合Content-Lengthッダは送られなければならないがこれはメッセージボ中のオクテト数と正確に一致しなければならない
  • Content-Lengthッダが送られない場合は接続の終了を持ってエンィテの終末を判断する事ができるがリクエトボにおいてこの手法は推奨されないしーバは 411 スポスを持って明示的に拒否する事ができる
[Studying HTTP] HTTP Header Fields

スポスの場合は接続を閉じることで内容・転送の終了を告げることができるので必ずしも Content-Lengthが必要ではないのかな?

body = tdiary.eval_rhtml

tdiary.write_to($stdout)

みたいな形にする方向でやってみる


いろいろのバッファの他に HTTPDが間に入って実際のところどうなってるんでし

 @2013-12-06 字間調整・そして独立分離している文字列処理を実行時に効率的に融合する方法

WBRタグでは効果を得られない不可視の空白を挿入する方法ではスタイルシトを切ったときに空白が見えるまたページ内検索でも単語の文字と文字の間に空白を挿入しないと見つけられなくなる第3の方法は CSS content属性を使うことスタイルシトを切ると空白ごと消えるしージ内検索でも挿入された空白は無視されるまたどのブラウザでも字間挿入効果があることは確認済

実装の問題は要素の挿入ではなく要素で文字を包むことになるのを他の文字列処理(, 字詰め)が知って対処する必要があること実際のところそれはもう済んでいてさらに以前は禁則と字詰めと字間調整がバングする場面(ABなど)で字詰めが効いていなかったのだがこれも解決した解決していないのは各々の文字列処理がテキトをぶった切るのだが2番目3番目の処理は細切れのテキドを相手にしなければならないがためにメソドの呼び出しとメソドの固定された初期処理とタグを乗り越えて文字を先読みすることの回数が増え効率が著しく低下すること2段3段の文字列処理を加えるなら切断は一度で済ませたい

対象が共通操作も若干のバリエーションはあるものの大枠は同じ対象と操作を選び組み合わせるところが固有固有部分を分けながら実行時に効率的に融合させる方法マニピュレータ付きのコンテクトを引き回す。操作を一旦ため込んでージしてから実行に移す。

  • style_to_range(begin, end, style) // letter-spacingなど
  • unbreakable_style_to_range(begin, end, style) // white-space:nowrapなど
  • unbreakable_tag_to_range(begin, end, tag) //NOBRで囲むのを white-space:nowrapに替えるなら今のところ不要
  • 要素挿入メソ幅のないrangeに対する unbreakable_xxxとして扱えるはず。でも字間調整のためにはもう不要

あとで

 @2013-12-08ップロドした>textfunc.ver2.js@2015-03-04

いいかげん HTMLに埋め込むには長々しいので独立した .jsァイルにtextfuncX_*はより簡素になったがそれを走らせる基礎を新しく書いた過去の記録>textfunc.ver1.jsーバーヘドは ver2の方が大きい多段のテキト処理を前提にするなら組み合わせによる所要時間の増大は ver2の方が抑えられていると思う誤算がひとつIE9visibility:hiddencontent属性値をクリップボドにコピーしてしまうそれでもスタイルシOFFで挿入した空白が見えてしまうことやページ内検索がほとんど不可能になってしまうことに比べればずっとマシではある

 TODO: 高速なフト判別ブラウザ判別によらないテキトレイアトの妥当性検証混植?

ト判別(is_proportional)が一番コト高なのは変わらず。テキトレイア(則・間・字詰め)が満足できるものかどうかをブラウザ判別に頼らず機能検出によって判断する(jQuery.browserがなくなり代わりに現れた jQuery.supportの使用が推奨されるらしいjQuery.supportでのブラウザ判別という面白記事の登場は避けられない世の流れ(惰性)ブラウザを判別したいその理由ブラウザ間の差異を検出するロジックを jQuery.supportに追加するのが本道だろうに)方法は(より軽量な)ト判別にもつながっているように思う.offsetWidthとかね結局のところ初めて見つけた .measureTextを使ってみたかったというのが is_proportionalを構成する理由の8割だから中身を置き換えると存在理由までが消えてしまいかねないのだ

<追記@2013-12-22>is_proportionalが遅いのは先送りされていたブラウザの処理が getComputedStyleをきっかけにして実行に移されるからis_proportionalから getComputedStyleを取り除くと処理時間のほぼすべてが is_inline_element(これも getComputedStyleを呼んでいる)へと移るDOM操作のコトが getComputedStyleをきっかけにして噴出してるとみるのが正しい例えば関連するスタイル(wbrクラス)の定義をスクリト実行の後ろに移すことでわずかに改善する。</追記>


混植だってWebデザイナーのためのタイポグラと文字組Reloaded)」鷹野 雅(スイッチやろうと思えば正規表現で文字を拾い出して最小限の SPAN要素でフト指定ができますよ他の処理を有効にしたままで……と思ったらここに衝突の種

トを変更する処理とフトに依存する字詰めを並行して行うことはできない一段目としてフトを変更する処理を単独で(テキドの分割を最小限に抑えながら)行い二段目にその他の処理をまとめて行うワークアラウドが必要になるだろう


上の方でリンクした MLで名前を見た人達がいたのでおもしろい

 @2013-12-11 .offsetWidthによるトルネック(is_proportional)の解消&テキトレイアトの検証……のはずだったけど

.offsetWidthを使った is_proportionalFirefox23.measureTextの倍の 1.4秒かかったOperaでも .measureTextの消費時間が2桁ミリ秒のところ .offsetWidthは4桁ミリ秒を消費する意外にも canvasを作って .measureTextする方が早かった

is_proportionalのテト過程で気が付いたんだけどOpera18Safari5.1.7で等幅フトとして欧文フConsolasを指定すると日本語用のフールバックがFontLinkではメイリオを指定してるにも関わらず MS Pゴシックになるfont-family:monospaceを指定してるのに台無しだよ!

.offsetWidth/.offsetHeightを使ったテキトレイアトの検証は function TextLayoutInfo() として textfunc.ver2.js@2015-03-04に追加した


結果が出てから調べる奴

Text measurement: element vs. canvas · jsPerf

Firefox23での実行結果
Measure text in span is 78% slower than Canvas measureText().
Internet Explorer9での実行結果
Measure text in span is 95% slower than Canvas measureText().
Opera18での実行結果
Measure text in span is 93% slower than Canvas measureText().
Safari5.1.7での実行結果
Measure text in span is 91% slower than Canvas measureText().

圧倒的じゃあない


まだ高速化をあきらめないis_proportionalの結果を要素にメモするのでなく font-familyの値をキーにしたメモをどこかに作ればいい気がしたでもそれには computed valueの定義の新旧を乗り越えないといけない(関連:used value)


Fx23で1割しか改善しないgetComputedStyleで時間を食ってるのかも(Operaだと組み込み関数のプロファイルもとれるんだけどFxでは?)

これね(またしても後手)

測りごとの罠 - EfficientJavaScript - Dev.Opera

前に読んでたけoffsetWidth のようなプロパを使ったり getComputedStyle のようなメソドを呼ぶとなんてそのものズバリの具体例が頭に残ってなかった


 そろそろおしまい

経緯をふり返ってみる

  1. URLが折り返されなくてはみ出したり長い単語がごっそり次の行へ送られて右端が余ったりするのが嫌で word-break:break-allを指定する(横幅に制限のあるテーマだったから word-wrap:break-wordとともに最初から指定してあった)
  2. Firefox(と Safari)で禁則処理が行われないのがありえない(word-break:break-allが原)
  3. NOBRタグを使って全てとはいわないが大部分の禁則処理を補完する
  4. 右端が揃ってないのが気になってきた(禁則処理が悪化させ)
  5. text-align:justify, text-justify:distribute(inter-ideograph)で行末を揃える
  6. FirefoxSafariで生じる字間の偏りが気になる(IEと違い text-justifyで行末揃えの具体的方法を指定できないのが原)
  7. 不可視の空白を分離許可・分割許可の目印として挿入することで是正する
  8. 字詰め(ーニング)も同じ仕組みで実現できそうなのでやってみた
  9. あれ?分離許可・分割許可の空白を挿入してるなら word-break:break-allする必要なくね?
  10. word-break:normalにしてブラウザの禁則処理を利用するとタグをまたいだ禁則も有効になって嬉しい<<imkk
  11. (これか) IE以外で英単語がぶった切られる結果になるのは問題があると思ってるword-break:break-allword-wrap:break-wordや無差別な分離許可・分割許可の挿入にかえてtext-justify:distribute, line-break:loose, hyphens:autoが使える日を待ってる日本語か英語しか書けないのだしハイフンを挿入できる位置を自分で調べるという手もあるにはあるが……(機械的にできるのか利用可能な辞書があるのかまったく不明)

word-break:break-allから始まる一連のもぐらたたきの結末はword-break:break-allをやめて自分で分離分割許可ポイトをブラウザに提示することだった

一般的に参考になるのはこちらの記事でしょうね自分の場合は優先順位が異なるので紆余曲折を経る必要があったわけだけど

長い英単語を途中で折り返したいときの CSS の指定方: Days on the Moon


検索したら TeXとクヌース先生に行き着くのですねハイフネーションは第一義にはデータ圧縮問題だそうです。packed trieとかなんとか出てきた(そこに至るまでに linked trie, indexed trie, compressed trieなど勉強になるなあWEB+DB PRESS vol.42で読ん『高速文字列解析の世界の人の記事はそれ自体が圧縮されていて何度読み返しても難しかった)いつもの書いたからやる羽目に陥ってるような気がしないでもない&shy;によるソトハイフンは一番遅かった FirefoxでもとっくにサポトされてるらしいURLみたいなのにはコピーには影響しないとしても折り返し点でハイフンが表示されてほしくないなうまく無視して word-wrap:break-wordに任せるか代わりに WBRタグを挿入する字間調整のために挿入するスペース(.wbr:before{content:" "})の代わりに &shy;(.wbr:before{content:"\0000AD"})を挿入してみたけど Firefoxでは期待通りのソトハイフンSafari5.1.7/Opera18では異常な空間が生じるIE9は単語間調整を優先して折り返してくれないャスァイのやり過ぎが嫌でいろいろやってるのに調整幅の最大値を制限できないせいでぐぬぬ

 @2013-12-27 text-justify: distribute

まだやっていましたtextfunc5_nobr_over_asciiwordを追加これは textfunc2, textfunc3から英単語を分割する効果のみを取り除くもの分離効果が残ってるのがミソで英字間に両端揃えのためのスペースを分配はするが英単語の途中で折り返しはしなくなるこれは要するに word-break: normal; text-align: justify; text-justify: distribute を指定して得られるはずの結果と同じ

  • 日本語文ではほぼすべての文字間隔が調整対象で禁則を例外としてどこでも折り返せるので違和感なく両端揃えが行われる
  • 英文では単語間隔と文字間隔をバラス良く調整対象にすることで単語や文字が散漫に散らばる印象を抑えることができる
    • ハイフネーションによっても同じ効果が得られるがこれはまた別の話
    • TODO: WebKit系の字間分配アルゴリズム「右端から順番になので行末がルーズになりがち
  • 日本語英語混じり文では日本語文に対しては英単語内で折り返せないことで英文に対しては英単語間のスペースの数が限られていることで字間調整量が過大になりがちでところどころ散漫な行が目につく混合文に限って word-break: break-all でぶった切るのが無難だと思うがlang属性を積極的に活用する運用になってないので見分けられないこれの満足のいく表示が一番難しい

見苦しい部分が少ないながら残るものの総合的にみて満足してるFirefoxでスクリトを切ってこの日記を表示するとより多くの散漫な行が目に入るOpera18でスクリトを切って見ると行末が揃わないっかり数文字分の空白がそこここに現れるIE9でスクリトを切って見ると何も変わらない……IE9は英語でも日本語でもありえない表示は行わないしtext-justifyによって選択肢を提供してくれるけどスクリトによってそれを逸脱するような操作を行う余地がない(何をしても効果が見られない)いじれなくてももともと見られない表示ではないので構いません字詰めに関してはどのブラウザでも同じように効果を発揮してるかぎ括弧の余白が削れて満足

 @2014-01-05 JSLint

jslint.comtextfunc.ver2.jsのクリーンさをチックタブインデトをオプションで許してもらうとったエラーは4つ

  • Missing 'use strict' statement. line 19 character 55

    var sorted_unbreakables = [];
  • Unexpected '--'. line 25 character 60

    for (begin_first = this.length; 0 <= begin_first-1; --begin_first) {
  • Unexpected '++'. line 30 character 8

    for (begin_last = begin_first; begin_last < this.length; ++begin_last) {
  • Move 'var' declarations to the top of the function.

    for (var pos = begin_first; pos <= begin_last; ++pos) {

for文に関するものはスタイルの問題なので変えない(そういえば前に別のスクリトで jslint.jsを試したときも forまわりが多かった>20080212p01.02.01)間違ってるのは JavaScriptの仕様です(letがデメリト無しで使えるなら varから乗り換えるけども)"use strict"; は早速ファイルの先頭に置いてみたけど何も変わらなかったvarを1か所取り除いて暗黙のグローバル変数を作ってみたらエラーが出たので無視はされてないみたい未来への保険/保障/保証*4としてそのまま置いておく

 @2014-03-07 FLAutoKerning.jsの亜種

jquery.kerning.jshttp://karappoinc.github.io/jquery.kerning.js/

Notice

使用するにはトに合わせたカーニングデータの作成が必要です。 現時点ではースコドに付属しているテンプレトを参考に使用するフトに合わせたカーニングデータを別途作成する必要があります。

※ フトデータから自動的にjsonータを生成するツールを試作中です。

こういうのはカーニングデータの重要度が9割以上だと思うそしてカーニングデータはフトに固有そして使用されているフトをほぼ確実に知るためには Webトが必要字詰めの実装方法が letter-spacingであるとかdisplay:inline-blockmargin-leftmargin-rightの組み合わせであるとかは些細な違い(といいながら興味津々でソースをのぞいてるわけだ俺の関心はそっち)

 @2015-01-19音声出力環境における擬似要素(::before, ::after)の内容(content)の読み上げについて|Web制作 W3G

content属性値は読まれてしまうそうです。空白文字に関しては単語としての認識を阻害し息継ぎが発生するらしい

 @2015-02-17WebトサービFONTPLUSに文字詰め機能を実装|ソトバンク・テクノロジー株式会社のプスリリース

提供するフトから余白に関するデータを一括で削除しそこに CSSで余白を付けるという手順ト間の差異を一度リセトすることで共通のカーニングデータを利用できるようにする試みなんだろう

  • 同じ字でもあまり形が違うとフト間でカーニングデータを流用できない
  • どうせ Webトを使うなら最終的にはフト固有のカーニングに行き着く

だろうとはいえ悪くはない手抜きでも完璧でもないほどほどを狙ったサービスじゃないかと

 一だったり十だったりする人の日記でも字詰め(@2015-04-25)

中里一日: Mobile SafariJavascriptで約物のアキ調整 Posted by hajime at 2011092915:21

イカしたスクリ>tsume.js

文字列って元をたどれば文字配列であってっきとしたデータ構造でありしかもただの配列より便利なメソドがいっぱい生えてるんだってことを思い出させてくれる

日本語識別子って読む分にはいいけどIMEを切り替えて入力するのはすんごく面倒なんだぜ

 @2015-03-22 Opera28がやった!

百聞は一見に如かず>20131101.html rendered by Opera28.pdf(1.5MiB)<スクリトなしで右端が揃っている

いくつか前のバージョンでは日本語英語交じり文の字間を暗黙の text-justify:inter-word で調整した結果(IEと違い text-justifyで他の調整方法を指定させてくれなかった)わずかな空白文字が何文字分にも引き延ばされたりまったく調整できていなかったりしたOpera28では選択肢がないのは同じだが英字部分が text-justify:inter-word日本語部分が text-justify:distribute(inter-ideograph) 相当で調整されているらしくこれ以上を求めるなら個別に手作業するしかないんじゃないだろうかというまともな表示になっている

英字部分が inter-word相当(distributeではない)ということで英単語の中のアルファベト間には調整字間が分配されないなので行の大部分を英単語が占める場合に日本語部分が散らかってしまうことがある俺は日本語をメインに考えてるのでtextfunc.jk.jsでは英字部分にもスペースを散らして所々英単語を間延びさせていた(とはいえ調整箇所が増えると目に見える影響は減ることが期待されるあくまでも期待>20140607)優劣ではなく優先度の問題これ以上の完璧を求めるなら手作業が必要だということの理由

他の Blink搭載ブラウザはどうなんだろ(ールしてないから確認できない)

@2015-04-15 Google Chromeだけでなく WebKitSafariでも改善していたみたいったね

角・半角が混在したテキトにおける CSS text-align: justify | アカベコマイリ

 TextLayoutInfo, ブラウザ検出と機能検出

textfunc.jk.jsが読み込まれてるページ(たとえばここ)でコンソールを開いて

new TextLayoutInfo

と打ってみると複数のプロパを持つオブジトが返ってくるその名前と値の表がこう

TextLayoutInfobrowserFirefox 22Opera 28
fontsize_zero_is_availabletruetrue
no_kinsoku_under_wordbreak_breakalltruefalse
no_whitespace_distribution_inter_asciicharactertruetrue
no_whitespace_distribution_inter_ideographfalsefalse

trueになっている項目(fontsize_zero...以外)textfunc.jk.jsによる修正対象以前の Operano_whitespace_distribution_inter_ideographtrueになっていたはずだがいつの間にか falseになっているその結果 Firefoxの場合と同等の処理の対象を英字のみに絞った低負荷バージョンが選択される自動的にこれがブラウザ検出ではなく機能検出を使う理由>>HTML5 - ブラウザーと機能検出(msdn.microsoft.com)

TextLayoutInfoによれば(※自作なのでいまいち信用できない)句読点の禁則にも改善があったみたいword-break:break-allでの禁則を無視したありえない表示がなくなったのではないだろうこれに関しては一貫して IEがすぐれていたしFirefoxword-break:break-allに対応した15以来ダメな点だ(この日記のタトルを見よ)

 textfunc.ver2.js (12.1KiB, 2015-05-14) + textfunc.jk.js (19.8KiB, 2015-03-22)

 何であるか

word-break:break-alltext-align:justifyで各ブラウザに起こる諸問題を解決し未だサポトされない text-justify:distributeを実現するためのスクリ

 具体的に
  • word-break:break-allでも(タグ境界を除いて)禁則(Fx, Safari, Blink Opera)
  • WebKit系でも justify. (Safari, Blink Opera)
  • word-break:normal(=折り返しが制限されて justifyの調整量が過大になりがち)でもなるべく調整の余白が目立たないように(Fx, Safari, Blink Opera)
  • (同じ仕組みを利用したおま) メイリオの約物の等幅チックな余白を詰める(IE, Fx, Safari, Blink Opera)
 備考
  • 各ブラウザのバージョンは IE9, Firefox23, Safari5.1.7, Opera18.
  • Presto Operaでは最小フトサイズ設定が災いして文字が散らばってしまうのでTextLayoutInfo.fontsize_zero_is_availableでこれを検知して処理を諦める(諦めちゃいます。先のない Presto限定なので)
  • Opera 28で禁則とジャスァイに改善がありました。20131101p01.34
  • Opera 31(現在の最新版)textfunk.jk.jsis_proportional関数が満足に機能していないたぶんこれの影響で判定と表示でフトのフールバックが一致してないとかじゃないChrome 42でフトがMS Pゴシックからメイリオに変更&元に戻す方法 | What I Know ~ワッタイナ
  • CSSunicode-rangeデスクリプタで特定の文字範囲にだけ有効なフト指定がしてある場合に要素を対象にする is_proportional関数は対応できない
 変更履歴
2015-05-14
コメト追加
2015-04-10
バグ修正文字列をSPAN要素で囲ってスタイルをセトする時に無関係な属性に undefined をセトしていた(単に無視されて無害だがコンソールがうるさい)副作用で1割くらい速くなった
2015-03-17
Firefoxで実行時間の短縮このページでいうと2000msから1200msへ。詳細
2015-03-11
unbreakable_element_to_rangeunbreakable_class_to_rangeを廃止しunbreakable_style_to_rangeに統合
2015-03-10
unbreakable_element_to_range追加(textfunc.ver2.js)
textfunc6_non_strict_kinsoku追加(textfunc.jk.js)
2015-03-04
構成変更「本来別ファイルに分離すべきものとコメトしてた部分を textfunc.ver2.js から textfunc.jk.js として分離した
2015-02-19
action_to_range追加 (js/textfunc.kururi.jsで利用するた)
textfuncに渡されるテキトが前から順番になるように深さ優先で

* 全角文字の字間は拡大するが英字はそのままなので一部は間延びして一部は詰まって見える全体に散らした方が目立たないのに@2013-11-19 Safariと同じ方法をより限定された対象に適用するだけで矯正できるのでやってしまった対象を限定しなくても副作用はないけど処理負荷を考えて限定したコピペコド率高し(だが構わない分岐直後なので当然のことールファンクションは共有してもいいけど)@2013-12-16 ■の連続も分割されないなどういう Unicodeプロパを参照してるんだろ

 @2013-11-09 勘違いしてたけどこの部分は Rubyなのでパターンの中にパターンを埋め込む方法で繰り返しをなくせるそれに後に明らかになったようにこの後の書き換えは各種ブラウザの JavaScriptで無効なRubyでしか使えない方法だったECMAScriptとしてあまりありがたくない動作が規定されてるのかも

 雰囲気で動詞化してみました

@2015-03-04,(2) textfunc.ver2.js の一部を textfunc.jk.js に分離した

 今は無駄だけど将来のうっかりな変更にそなえて

 うっかりな変更を許さない

*4 うっかりしたコドが存在しないこと

詳細 getComputedStyletextfunc内から取り除くことは機能低下を招いてできないので中間データをすべてため込んで DOM操作を最後にまとめて行うことにしたそれだ副作用で GCできない使用中のメモリが一時的に増えるちなみに Blink(Opera28)では悪化も改善もしないFirefox(23)には最適化の余地があるってことだ


20100907()

最終更: 2010-09-15T20:40+0900

[SakuraEditor][正規表現] 検索置換

Command_REPLACE(置換)Command_REPLACE_ALL(すべて置換)Command_SEARCH_NEXT(下検索)を呼ぶのをやめたい連携手段がレイアト座標を基にした選択範囲しかなく一文字で表現される CRLFLFだけがマッチしたときに情報が欠落するしCommand_SEARCH_NEXTが持つ検索以外の事前・事後処理が無駄になるし正規表現検索が BMatch(), BSubst(検索&置換)の計二回行われるのも無駄

wchar_t単位で検索を行う CSearchAgent::SearchWord検索結果をレイアト座標に変換する際の誤差(前述)を考慮してマッチ範囲を拡大し結果を不正確なものにするのは誤りだと思うそれより上の層でこれを呼び出している CLayoutMgr::SearchWordがその配慮を行うべきでは

 ったらいい操作

Match
対象文字列の対象範囲全体がパターンに一致するか調べる
Search
対象文字列の対象範囲からパターンに一致する部分を探す。
Replace
対象文字列の対象範囲からパターンに一致する部分を探し与えられたフーマトの文字列に置き換えた文字列を返す。(返るのは対象文字列の対象範囲に相当する文字)
Expand
MatchSearchの結果を用いッチ全体($0)を与えられたフーマトの文字列に置き換えた文字列を返す。
パターン
BREGEXP.DLLm/pattern/flags/pattern/replace/flag も同じ一つのパターンとして扱うので検索用のパターンと置換用のパターンに互換性がないそうではなく、Search(Compile("pattern", flag), "target", startindex), Replace(Compile("pattern", flag), "target", startIndex, "replace")ったら良かった( "pattern""target""replace" は実際は二つの引数で表)

bregonig.dllbregexp.dllを使いながらパターンの共通化や Expandの不足に対処するにはどうする自分で Expandを実装しdllが用意した置換機能(置換パターン)を使わないで済ませるでもねえ実装の数だけ仕様がある状態を避けたいから Expand機能をライブラリに用意して欲しいわけで(置換文字列の $$$に展開されなかったり\1 が展開されたり$1が展開されなかったり色々あるんよ)


 @2010-09-10 悪夢のよう「クリップボドから貼り付ける置換オプション(本当は矩形選択)

  • CRLFCRだけや LFだけをクリップボドの内容で置き換えることができない
  • 正規表現検索のとき検索始点(終点)挿入オプションがきかない
  • クリップボドの形式が矩形テキトだったときに検索条件によっては無限ループ

    例えばクリップボドに

    789
    456
    123

    という 39文字(改行文字はない)がおさめられているときッチと置き換えられるのは 789 であり、456 123 はそれぞれ次行次々行に挿入されるつまり、456 123 はこれから検索対象になるということだ検索条件が \d{3}ったり ^ったり矩形テキトの二行目以降にマッチするものだったら無限ループ

置換操作が二階層潜らないとロジック単位にならないというのも悩みの種検索はロジック単位で行えてるのにそれをレイアト単位に変換してそれがさらにロジック単位に変換されて一対一対応じゃないからごにょごにょしないと思い通りに置換されなくて

 @2010-09-15

どうして最上層のレイアトを基準にして文字列処理を行わなければいけない文書(wchar_t列としておく)の変更を LayoutMgrに通知する仕組みを整備するのを怠ってLayoutMgrを通して文書の変更を行うことで通知を不要にしていることが背景にあるのでは? GUIを通しての文字列操作に限ってはそれで十分だからそうなるのも仕方ないし必要に迫られた人間(俺とか)がより汎用的な手段を整備せずにダック*に頼る方が罪は重いかも

* 挿入位置・置換範囲を文字レイアト境界まで拡大して入・置換文字列も同じだけ拡張する


20100709() Windows Confidential: The Third Rail of Keyboard Shortcuts | TechNet Magazineを読んでの違和感レイモド チェンは Win+Eがどこを開くかの話をしているおれは Win+Eがどこを開くかなんて確かめたことがなくWindows Explorer――フォルダを表示するときに利用される簡易表示ではなくフォルダツリーが付いた正式版――を起動するためのシトカトだと思っていたそんでだから使ってない

最終更: 2014-01-02T18:04+0900

[SakuraEditor][正規表現] 「鬼車と bregonighitEnd(20100531p01)機能が搭載されることを願う他力本願日記

なんてことをこの日記の冒頭に掲げたもんだから自分でやってみた(どういうこと?)

 更新履歴

rev3 (2010-09-05, そのうち書)
(サクラエ) 複数行検索を利用した複数行置換を実装(複数行全置換はまだ似たようなコドだし必要なのは手間だけだけ)
rev2.1 (2011-01-29)
(サクラエ) バグ修正複数行検索モドでマッチ位置をバッファ内インデックスから(,)に変換する際にミスった検索結果が表示されることがあった
rev2 (2010-08-27)
(サクラエ) 複数行検索モド実装(正規表現を使った下検索の50MiB制限あり制限による探索打ち切り・ッチ範囲切り上げの通知な)
トバイナリ+変更点(test_multiine_search.zip)
rev1
() 普通のマッチなしと入力次第でマッチする可能性のあるマッチなしに異なる戻り値を割り当てた
(bregonig) 入力不足のときに BMatchの戻り値を 0(正常終了,ッチなし)にしてエラーメッセージで入力延長によるマッチ成功の可能性を伝えている
(サクラエ) 下検索での入力不足によるマッチ失敗をステータスバーで通知

 bregonig

既存アプリに影響があるので良くないけどbregonigへの暫定的な変更はこう

 regexec_onig(bregonig.cpp)
	} else {
		/* ERROR */
		onig_err_to_bregexp_msg(err_code, NULL, msg);
-		return -1;
+		return err_code == ONIG_MISMATCH_INPUTSHORTAGE ? 0 : -1;
	}

入力が足りなくてマッチしなかったときはエラーメッセージをセトするけど戻り値は負数(エラ)ではなく 0(ッチなし)

 鬼車

鬼車(5.9.2)K.Takata's software : bregonig.dllで手に入る onig-5.9.2-mod.diffを適用したものをさらに変更ッチに失敗したときのエラーの種類で hitendしたかどうかを伝えるゃんと動くのか非常にあやしい代物TODOもいっぱいある

  • 特定のパターンのパターンに向けた最適化を無効にしている(そこまで手が回らな)
  • backward searchに対していつ hitendフラグを立てていいのかわからない(ので未対)
  • "aaaaa\n" という文字列から [a\r\n]+a というパターンを検索したときにバトラックにより "aaaaa" がマッチするわけだがその次の行にも "aaaa.." という文字が続いていた場合は……一応マッチは見つかっているが hitendフラグも立てたい
  • [\w\W\s\S] というようなパターンでメタ文字の登場順([\W\S\w\s]とか)に 依存しておかしな結果になる(もちろん俺のミス原因は解らな)

っぱり鬼車は手に負えないかも

 サクラエ

なんのことはない影響を受ける既存アプリにはサクラエタが含まれている正規表現のコンパイルエラーと入力不足によるマッチなしを区別するためにちっと変更した

 複数行検索モ

一行検索(従来動作)してみてッチが行末まで続いていたり次の行の内容次第でマッチが成功に変わりそうなときはとりあえず二行ぶん検索してみるそれでも状況が同じなら 50MiBのバッファを埋めてから三度目の検索を行う50MiBって大きすぎるだろう大きさの問題だろうかか

実装は CSearchAgent::SearchWord()これって単語検索専用のメソドではなかったのですよ。CGrepAgentもこれを利用したらよかった

ッファの実体は std::wstring文字列を比較するにも wmemcmpなりを使おうとして結局 std::wstring("hoge") == L"hoge" を使ったへたれなのでstr系のライブラリ関数は恐ろしくて毎回すぐに投げ出します。(あれを使いこなせる人は VBPHPも使いこなせると思うんです)

 TODO
  • 上検索
  • 検索語ハイラトの処理がたぶん一行ごとに行われている一行ずつ進みながら複数行を対象に検索を行ってるってわ無駄だし目に見えて遅い
  • ッファ長の制限によりッチ範囲が途中で切られたりマッチの探索が打ち切られたりしても何も言わないのをなんと(制限をなくすかメッセージで)
  • SourceForge.net: Sakura Editor: Detail: 2309002 - 正規表現による複数行検索対(簡易版のコメトを見ると検索語ハイラトのほか「すべて置換にもパッチが必要そうッチを流し読みしてたら BookmarkManager(::MarkSearchWord)までが GrepAgentが持ってたような検索の勝手実装を持ってるらしSearchAgentを使ってよね(いやSearchAgentは当時なかったんだ)
  • (複数行)検索にマッチしたなかでも最初の行がマッチに含まれているか含まれていないかというのは区別する価値があるサクラエタの既存の実装は行指向が強いだろうから「マッチした(ただし先のほうの行で)ということを勘違いしかねない(SearchAgentや選択範囲にはそういう指向がないから運良く複数行検索が自然に実装できただ)
  • (@2011-08-01) [\s\S]*$ というパターン最後の行の末尾までマッチして欲しいのに一行目の改行直前で止まってしまうッチに成功したときの hitEndフラグの扱い

 @2010-07-12 鬼車 for Java

hitEnd()の実装の参考になるか?と思ったけどそうもいかなそう

Revision  74 hitEnd()の実装(但し仕様は満たしていない)。
Revision  85 useAnchoringBounds()及びuseTransparentBounds()に対応。→hitEnd()の実装を修正。
Revision 103 hitEnd()に@Deprecatedを追加。
    /**
     * This method is experimentation phase, and implementation has not been completed yet.
     * @return
     * @deprecated
     */
    @Deprecated
    public boolean hitEnd() {
        return (hasAnchoringBounds ? (range == region.end(0)) : (input.length() == end()));
    }
Matcher.java(rev166)

hasAnchoringBoundsが設定されてる場合は無視するとしてそうでないときは入力の長さとマッチの末尾(end())が一致してることをテトしてるだけに見えるそれって hitEnd()とは違うよね。531日の日記文字列 aa に対してパターン aa を適用したときに hitEnd()falseになった事例を引用した

そうそうこれこそが hitEnd()の使い道 >Check if string is a prefix of a Javascript RegExp - Stack Overflow コメトの最後に見たことのある名前が☺


 @2010-07-12 PCRE

PCRE(現在 ver. 8.10)は戻り読みも再帰も(パターンのコンパイル時の)改行指定オプションもスキャナー的に使うための hitEnd()のような機能(read pcrepartial)およそ欲しいものをすべて備えている悪名高いスタックオーバーフローにも1.スタック使用量を減らす。2.代替メモリ確保関数を使う(汎用ゆえに遅いmalloc/freeか自作)3.pcre_exec()の代わりに pcre_dfa_exec()を使うみたいな各種対策があるらしい


20100531()

最終更: 2010-07-10T01:01+0900

[正規表現] requireEnd(), hitEnd()

hitEnd

public boolean hitEnd()

このマッチーが行なった最前のマッチング操作によって入力シーケスの終わりに達していたらtrueを返します。

このメソドがtrueを返したときはさらに新たな入力を加えると最後のマッチの結果が変わる可能性があります。

requireEnd

public boolean requireEnd()

入力を新たに増やすことによってそれまでのマッチが不成功に変わるならtrueを返します。

ッチが見つかっていたときにこのメソドがtrueを返したらさら入力を増やすとそのマッチがなくなることを意味します。ッチが見つかっていたときにこのメソドがfalseを返したらさらに入力を増やすとマッチが変わるかもしれないがッチがなくなることはないことを意味します。ッチが見つかっていないときにrequireEndを呼ぶことは無意味です。

java.util.regex クラス Matcher

まず 1.5 で導入された hitEnd メソドと requireEnd メソドですが hitEnd メソドキュメトでは入力の末尾がヒトした場合にtrueを返すとありますが入力というのは領域を指しているようなのですが末尾というのが最後の文字なのか末尾の位置なのかよく分かりませんでした例えば aa をマッチング対象の入力シーケスとして正規表現 aa でマッチングを行った場合入力シーケス全体にマッチしますがこの場合に hitEndfalse を返します。つまり最後の文字がマッチしていても true にはならないようです。ところが正規表現 a+a* でマッチングを行うと aa と同様に入力シーケス全体にマッチしますがこの場合は hitEndtrue となります。つまりマッチした部分だけでなく正規表現パターン自体も hitEnd の返す値に影響するようです。

Java 正規表現アプリケーション

どちらも入力が一つの文字列におさまっていないときに役に立つメソ

  1. 二番目の引用内容と
  2. requireEnd()trueを返した場合と hitEnd()trueを返した場合の対比と
  3. 自分が行文字列のリトを対象に鬼車でマッチングを行うときに欲しい機能から

hitEnd()について想像するなら

search engineが遷移先を残したまま入力を消費し尽くしたときに hitEnd()trueになるそれの意味することは直前のマッチが成功していたのならさらなる入力によりマッチの範囲が延長される可能性があるということ直前のマッチが失敗していたのならさらなる入力によりマッチが成功するかもしれないということ

ところでhitEnd()trueかつ requireEnd()trueの場合って存在するだろうあるとしてどんな入力とパターンになるだろう

requireEnd()はなくても困りはしないッチの範囲が入力の末尾まで続いていれば無条件に入力を増やしてトライすることで requireEnd()trueったのか falseったのかは確かめられる

hitEnd()ッチが成功していたときは重要ではない真価は、ッチが不成功だったときに hitEnd()falseを返した場合はさらなる入力をつなげてもマッチが成功に変わることがないと確かにいえることhitEnd()がなければすべての入力を連結せずにはマッチが存在しないことを断定できない


そうそうこれこれ>http://www.mail-archive.com/classpath-patches@gnu.org/msg08501.html

さらにっちドキュメトは詳細だしバグにも触れてある上のスレドで報告されてるのとは別のバグみたいだけど

boolean hitEnd()

(This method is unreliable in Java 1.5; a workaround is presented on page 392.)

This method indicates whether the regex engine tried to inspect beyond the trailing end of the input during the previous match attempt (regardless of whether that attempt was ultimately successful). This includes the inspection done by boundaries such as \b and $.

If hitEnd returns true, more input could have changed the result (changed failure to success, changed success to failure, or changed the span of text matched). On the other hand, false means that the results from the previous attempt were derived solely from the input the regex engine had to work with, and, as such, appending additional text could not have changed the result.

The common application is that if you have a successful match after which hitEnd is true, you need to wait for more input before committing to a decision. If you have a failed match attempt and hitEnd is true, you'll want to allow more input to come in, rather than aborting with a syntax error.

Section 8.4.  The Matcher Object
本日のツッコミ(4) ッコミを入れる

ds14050>ところでhitEnd()trueかつ requireEnd()trueの場合って存在するだろう a..

ds14050なぜだか上のコメトがスパム扱い@data_path/log/debug.logを見た >I, [2012-0..

ds14050>[\/url] ではなく \[\/url] が正しい 正真正銘正しいのは \[\/url\]った しか..

ds14050>requireEnd()はなくても困りはしないッチの範囲が入力の末尾まで続いていれば無条件に入力を増やして..


20100519() [SakuraEditor]ドブロックの折りたたみっていうのはトライン解析の結果(ツリ)を別窓でなくエタ自体に表示するようなものなのですねbyte_stream>char_stream(codepoint>glyph)>line_stream>layoutline_streamの上にさらに folding_streamを乗っけるイメージ?

最終更: 2010-05-19T16:21+0900

[正規表現] 鬼車条件付き選択

348 nobodyさん 2008/07/27(日) 01:11:32 ID:sEx2Pn85
    質問させてください。

    サクラエディタに鬼車5.9.1を搭載して正規表現の勉強をしているのですが、手元にある詳説正規表現には

    (<)?\w+(?(1)>)

    このような例があり、<があれば>のマッチを試みる?ということができるみたいです。

    ただ、鬼車はこの表現をサポートしていないみたいです。
    http://www.geocities.jp/kosako3/oniguruma/doc/RE.ja.txt

    同様のことを鬼車でも実現する方法ってあるのでしょうか? 
正規表現道場

鬼車は条件付き選択をサポトしていないのが玉に瑕だと以前から思っているなんとかできないかと上の例で考えてみたらこうなった

(<|)\w+(\1{100}|>)

せこい姑息だ100ってなんだよこんなの( <abc<<<...(94個の<を省略)...<<<> )にもマッチするじゃね


20100329() XRegExp-1.5.0がでている

最終更: 2010-04-04T07:43+0900

[正規表現] 正規表現の空の文字クラスのブラウザ実装 > 文字クラス(suika.fam.cx)

まとめはリンク先に任せるとして最新の Opera(10.51)ではどうかねと思ってスバーに javascript……と打ち込んだら空の文字クラスのテトスクリトと思しきまさに今打ち込もうとしていたものが補完された笑える(他に Operaの使い道はないのか)このときの履歴だろうさておき結果は

// Opera10.51
/[]/.test("a") //=> false
/[^]/.test("a") //=> true

9.61のときとは違って一般に期待される結果になっているよう次いで IE8の結果は……どちらもスクリトエラ

// IE8
/[]/.test("a") //=> "正規表現の中に ']' を指定してください。" (Perlと同じ。だけど IEのバージョンももう 8だよ)
/[^]/.test("a") //=> "正規表現の中に ']' を指定してください。" (Perlと同じ。だけど IEのバージョンももう 8だよ)

// このエラーが導くのは、パターンのこういう解釈と結果。
/[]]/.test("]") //=> true
/[^]]/.test("]") //=> false

変わっていないECMAScript3に準拠するならマッチ結果の食い違いはともかくエラーはないはずだけど

っと前にニースになった IE9 Preview(IEBlog : About the Platform Preview)もせっかくだしイールして試してみたIEBlog : The New JavaScript Engine in Internet Explorer 9なんて記事も見つけたし結果は /[]/.test("a")/[^]/.test("a") もクラッシ残念至極


20090922() [790FX-GD70] BIOS v1.5

最終更: 2016-03-05T00:30+0900

[SakuraEditor][正規表現] 正規表現を使った検索・置換で改行の意味を LFのみから CRも含むように

経緯 > サクラエBBS[r7030]

差分 > fix_cr_handling_of_regex(下に修正版があ)

お試し > sakuraW.zip (547KiB)(下に修正版があ) (正規表現検索・置換を試すには bregonig.dll(Unicode対応)が別途必)

検索置換を数度試したが機能しているみたいただ$ が本当に改行の手前でマッチする関係で

^.*$

を空文字列に置換するという最初に提起されたケースでは置換後の空行までが置換対象になってしまう(置換回数が 2)目的に適うより適切なパターンは

^.+$

あるいはタの行置換機能を使っているのだからっと単純に

.+

で良い


 @2009-09-24

正規表現 - SakuraEditorWikiを見ていて気付いた。\c[\c]\c$\c. という制御文字のひとつを表すパターンが存在する鬼車 正規表現 Version 5.9.1によれば \C-[\C-]\C-$\C-.\M-[\M-]\M-$\M-. も存在しうる。\M-\C-[ なども存在しそうに思ったけどこれはこういう結果になった

irb(main):001:0> /\M-\C-[/
SyntaxError: (irb):1: too short escaped multibyte character: /\M-\C-[/
        from c:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>'
irb(main):002:0

制御文字なんて扱ったことがないからなあ(もはや relicだという認識)対処の必要性がさっぱり感じられないけど……


 @2009-09-25

一括置換で $CRLFCR直前LF直前LF直後(正規表現DLLに与えた文字列末尾)の三カ所にマッチしてしまうとの指摘 >サクラエBBS[r7039]

逐一置換を実行した場合は問題ないことを確認していたのだが一括置換はライブラリに全部お任せで検索開始位置を調整することもできないから動作が違っていたのだろう$CRLFの間にマッチするのはわかっていたが明示的に \r を食べた場合にだけ影響があると思っていた一括置換なんてありふれた操作でそれが明るみに出るとは思いもせず。

急いで修正 > fix_cr_handling_of_regex.rev2sakuraW.rev2.zip (547KiB)(さらなる修正版 rev3が下)

初めて戻り読みを使ったなんとなく反則的な手段の気がして使わないですむ方法をいつも考えるのだけど無理だったこれで bregonig.dll依存が決定的になった[] の入れ子のことだけなら ] が見つかったときに charset_levelを一気に 0 にするだけで BREGEXP.DLL対応もできたのだ


\C-X\M-X というのは Ruby向けなのかもサクラエ(+bregonig.dll)\C-[ を検索しようとするpremature end of char-classというメッセージが出るとなれば\cX だけが引っかかった小骨ということになる

対処 > fix_cr_handling_of_regex.rev3sakuraW.rev3.zip

<追記>bregonig.dllでは \c\X\cX の意味になるともう知らねー。</追記>


個人プロジトでもないと色々大変そうッグフドでも食べながら様子見します。とりあえず反応だ

 2.非対応となっているBREGEXP.DLL(ANSI版)への対処方法
 ANSI版とUNICODE版は別仕様としてしまうのか?

使用できる正規表現自体が別物なので BREGEXP.DLLCBregexp::MakePattern()でよいかとーザーを驚かさないための変更なので.\r にマッチすることを期待していた人以外に影響はないつもりでいる

<追記>ANSI+bregonig.dll向けのパッチを用意したので別仕様は ANSI+(BREGEXP.DLL/bregonig.dll)Unicode+bregonig.dllの間または ANSI+BREGEXP.dll (ANSI/Unicode)+bregonig.dllの間のどちらでも選べるBREGEXP.DLLのサポトするオックスな(戻り読みをサポトしない)正規表現で$を改行直後の行文字列終端にマッチさせない方法が見つからない限り BREGEXP.DLL対応は無理。</追記>

<追記>BREGEXP.DLL版も用意した>_ANSI.rev2 >_ANSI.rev3</追記>

 3.$ が改行なし最終行のEOF手前ともマッチするように改善すること
 $ を (?=\r\n?|(?<!\r)\n|(?<[^\r\n])$) に置き換える方法を試してみたけどエラーで動きませんでした。

肯定の戻り読みは (?<=) でした(なにせ使用経験がないもので)気を取り直してパターンを (?=\r\n?|(?<!\r)\n|(?<=[^\r\n])$)* に置き換えたところ検索は予想通り最終行がEOFのみの場合を除いて文書末にマッチするようになったのだけど置換が行われない(以前は行われていたのだろうか? マッチのインデックスが文書の長さと同じ(=1つはみ出した状態)になっているはずだから特別な対処が必要なのだろ)

「以前は行われていたのだろうか?< 行われていなかったなら(間違ってるけど)おいておこう

 4.検索強調表示が検索時の選択反転表示と一致すること
 $ を (?=\r\n?|(?<!\r)\n) に置き換えた版で $ を検索すると、改行文字自体は選択反転表示にはならない(マッチしない)のに検索強調表示されている。
 また、なぜか上方向検索では改行文字自体にマッチしたかのように選択反転表示になる。

$で検索したときに改行文字が強調表示されるのは0のハイラトには意味がないので実用面から今のように最低でも幅 1を保つべきだと思っていた

上検索で改行が選択されてしまうのは間違いなので修正したいこれまでが知らず $ が改行にマッチする仕様に依存していたのかもしれずこういう修正は正しい方向に向かうためのものだと考えている

修正した(rev4)無限ループを避けるためにマッチ幅が 0のときに検索開始位置を特別にインクリメトするんだけどそのタイミングが悪くて検索開始位置だけでなくマッチの範囲までがインクリメトされていたのが原因

 5.正規表現キーワードでの $, . 指定も検索・置換と挙動が一致すること
 現状、正規表現キーワードには $, . に検索・置換でやっているような細工が入っておらず、素の正規表現ライブラリ挙動になっている模様。
 検索・置換時の . の細工([^\r\n]への置換)が追加されると、今よりも差異が大きくなって混乱しそう。

すでに書いたように.\r にマッチすること$CRLF の真ん中にマッチすることを期待していた人(いるのか?)以外は違いに気付かないだろう

\r\n$ みたいな書き方をしていた場合にマッチしなくなるこのケースはなくはないかも

 6.検索・置換や正規表現キーワードの複数行対応への順応性

ーチックsフラグが含まれる( . があらゆる文字にマッチするようになる)ときには . を置き換えないようにするmフラグが含まれない( ^$ が行頭行末にマッチしなくなる)ときには $ を置き換えないようにするとか?


>fix_cr_handling_of_regex.rev4sakuraW.rev4.zip


2ch民は 1.6.5.0をつかうのね♥マークはいらないんだConsolasも使いたくないんだ(これは俺の理由だけ) r1663を使おうぜ


 @2009-09-28

UnicodeRevision1662>http://sakura-editor.svn.sourceforge.net/viewvc/sakura-editor?view=rev&sortby=date&revision=1662

AnsiPatch>http://sourceforge.net/tracker/?func=detail&aid=2869238&group_id=12488&atid=312488


勘違いしていたUnicode版のサクラエタで使用できる正規表現ライブラリは bregonig.dll(Unicode)だけだという事実がいつの間にかbregonig.dllUnicode版専用だという思い込みにすり替わっていた

ったら採用の可否はともかくAnsi(trunk2(Release|Debug)_Ansiドのことでなく trunkのビド産物のことだろう)向けのパッチを作成する意味はあるわけだCBregexpのイスタスがその寿命を通じて 1つの DLLだけを扱うのであればトを初回に払うだけで処理の振り分けを行うことができるっちかな?

>>> DLL初期化時に呼ばれる仮想関数がありました(そのたびにチックを行えばいい実際は 1回しか呼ばれないだろ)


CheckRegexpSyntax() は癌だ検索ボタンを押すたびに DLLのロドからはじめて文法をチックしたら使い捨てるって何事文法チックは Compile()で十分その後の Match()のための準備にもなってちょうどいいもろもろの手順を共通化したいのなら引数として CBregexpを受け取るべきだ正規表現のチックをしたい(=正規表現を利用したい)部分ではもちろん CBregexpなりなんなりをすでに持っているだろうCheckRegexpSyntax()がこんな重量級のローカル変数をもつ必要はない無効な検索パターンを履歴に追加したくないがために検索の主体でない検索ダイアログが利用しているのかもしれないけど


 @2009-09-29

っつけで一応これで昨日書い「コトを初回に払うだけで処理の振り分けを行うことができるが事実になった昨日の段階では検索ボタンを押すたびに DLLがサポトする文法をチックする関数が実行されていた(初回どころではない)これでもまだ検索ボタンを押すたびに Compile()2回走るのは変わっていない

おまけとしてbregexp.dllだけが sakura.exeの隣にある状態でエタを起動しその後 bregonig.dllを配置したとき検索ダイアログでは bregonig.dll Ver....と表示されbregonig.dllしかサポトしない戻り読みを使用しても正規表現エラーにはならないものの実際の検索には bregexp.dllが使用されるためだろう戻り読みが機能していればマッチするはずの条件でもマッチ無しになってしまうこういう説明もややこしい起こりづらい状況が起こらなくなる(文法チックと実際の検索が CBregexpの同じイスタスによって行われるようになるか)

本当は CBregexpCDllHandlerを継承するのをやめて分離して1つの CDllHandler(DLLスタ)を多数の CBregexp(BREGEXP構造体)から参照するのがいいのかもっといえばBREGEXP構造体もコンパイル済みパターンとマッチ結果に分離したいサポトする文法の情報はもちろん DLL付きの情報CDllHandlerは汎用的すぎるからその任にはCDllHandlerを継承したいまの CBregexpから BREGEXP構造体だけを追い出したものを充てればいい

いまの CBregexpInitDll()を呼び出されて途中で違う正規表現ライブラリを読み込まされたときコンパイル済みの BREGEXP構造体を正しく解放できるのだろうか?


 @2009-10-01

BREGEXP.DLLでも .$ を置き換えるようにしてみた > fix_cr_handling_of_regex_ANSI.rev2(下に rev3)

副作用があってXYZ(CR)(LF) という行に対して XYZを検索すると XYZ(CR)(LF) がマッチするッチ結果が改行に隣接しているとき改行がマッチに含められます。$を検索すると (CR)(LF) がマッチするのは以前からの通りここが変わらないのは一括置換での過剰な置換を防ぐ手立てがこれしか BREGEXP.DLLからは与えられていないということ

ついでに気になった\r\n を検索したときステータスバーに 1 bytes selected. と表示されるのを修正>fix_selection_area_and_selected_byte_count_ANSI 選択領域が中途半端なサイズだったのも直ったそれもこれも CLayoutEOLの長さを常に 1とカウトしていたせいッチ範囲が勝手に 1切り詰められていた

表示としては ↵ も ⇠ も ⇣ も同じ一字だから CLayoutのすることにも一理あるのかもしれないそれなら改行文字の部分の選択領域をせめて全角幅にして検索結果のハイラト部分と大きさをそろえよう

ANSI版の View関連のソースを見てたら気が遠くなるUnicode版で

  • CRLFを全角幅で表示
  • CRLFCRLFのみハイラ選択
  • LFCRの全角表示全角幅選択(or半角幅ハイラ)
  • 行頭マッチ(^)でキャレト描画

あたりなんとかならんかな検索結果の選択範囲とハイラト領域のずれが気になる


 @2009-10-03

ANSI版を BREGEXP.DLLと組み合わせているときに不必要に改行が検索結果に含まれてしまう場合を rev2より大幅に減らした意地悪なパターンを与えられたときにどうなるかは把握しきれていない

> fix_cr_handling_of_regex_ANSI.rev3(rev2rev3にバグ発覚rev4)


fix_cr_handling_of_regex_ANSI.rev4

どういうバグだったかというと一括置換をしたときに改行や行文字列末尾付近で過剰に置換が行われないように戻り読みが使えない BREGEXP.DLLのときは検索パターンと置換文字列に細工を施すのだけど検索パターンの置き換え方がまずかった

 誤: /A|B/ -> /A|B((?:\r\n?|\n\r?)?)/
 正: /A|B/ -> /(?:A|B)((?:\r\n?|\n\r?)?)/

選択 | の結合順位は一番低いのでした


バグは CBregexp.cppを好き勝手にいじっていた結果をテトしている最中にたまたま見つかった

  • メンバ関数に constをつけたり
  • 正規表現フラグを指定する引数の型を intから専用のものに変えたり
  • CBregexp::IsLookAhead(const char *pattern)が内部状態を変更してCBregexp::Match()の結果に意図しない影響を与える可能性を排除したり

していたこれは単なる自己満足


 @2009-10-04

不必要に選択範囲が改行にかかっていたケースををさらに減少> fix_cr_handling_of_regex_ANSI.rev5 検索パターンが LF直前や文字列末尾に幅0ッチしそうなときにだけ細工を行うことにしたなんというか盆栽趣味?

バイナリ>sakura.zip


 @2009-11-25

AINI版では LFCRLFCRの間に幅0ッチしそうなときも細工を行わないといけないだろうなやらないけど(LFCR?なにそれ?という立)

* あえて (?<=[^\r\n])$ を使ったつもりでいたけど実は (?<![\r\n])$ の方が最適だった可能性二者の違いは>[[20080528p01]]ただしサクラエタ的には EOFのみの行は存在しない(行番号も表示しない)ものらしいのでどちらのパターンを使っても実際の違いは生じない

 扱うファイルが ASCII onlyという可能性FontLinkッチ<https://sourceforge.net/tracker/?func=detail&aid=1832567&group_id=12488&atid=312488>を自分で当てている可能性はある


20090703() 時計回り反時計回りはわかる右回り左回りはどっちがどっちかわからない目の付け所が恣意的ではないかと小学生のころ思っていた<< 円を正面から見るのでなく中心に立ってみればよかったのだ(っと訪れた理)

最終更: 2009-08-25T02:45+0900

[正規表現][Firefox] XRegExp-1.0.1Firefox/(?!)/

20090628p01で書いた Firefoxのバグっぽいものが XRegExpに影響するみたい

// Firefox 3.0.11 + XRegExp 1.0.1 での実行結果
alert( XRegExp("[]").test("a") ); //=> true
alert(  RegExp("[]").test("a") ); //=> false

[][^] の意味するところってなんでしょうね[] は空の文字集合だか「どれでもない一文字とマッチする(=空文字列にもマッチせず必ず失敗する)[^] は空の文字集合の補集合だか「任意の一文字だろう

参考ページを見つけた > 文字クラス(http://suika.fam.cx)

結局こういうことだ

  • 主要 4ブラウザのうち [][^] が使えないのは IE
  • Opera(9.61)[][^] がおかしい(他と違う)
  • Firefox(3.0.11, 3.5RC3)(?!)(?=) がおかしい(他と違うし自分自身の (?!|)(?=|) とも違う)

(IEの件を除いて)どのパターンも規格上の正解やデフトスタンダドがなくて混乱してんじゃないかなあこういうのには近づかないに限る


 追記@2009-07-04 04:44: 内容確認

正しくコメが読めてるといいんだけど……

IEが空の文字セ[] を処理しないのは(ECMAScriptの仕様をすっとばし) Perlその他JavaScript以外の多くの実装にならっているもので、[ に続く最初の文字を文字通りの文字 ] だとしているからだから []][\]] と同じ意味になる

Firefox(?!) の代わりに (?!|)(?=) の代わりに (?=|) を使うのは良くなくてつまりこれらの結果は同じになるべきだけどどちらになるかは将来の Firefox次第だからトラックの発生にもつながって効率的にも不利だから (?!) の代わりは \b\B(?=) の代わりは (?:) が良い

\b\B というのは覚えておこう


 追記@2009-07-04: はずしてた

冒頭の指摘ははずしてる考える前に気付いたことをただ書いたせいだ

XRegExpの目的の一つはブラウザごとにまちまちな挙動を見せる JavaScriptの正規表現に関するメソドを仕様に準拠させることだったと思う(String.split()とか RegExp.lastIndexとか)

だから空の文字セ( [][^] )を提供する第一の目的は 5ブラウザ(IE, Fx, Opera, Safari, Google Chrome)のうち不当にこれを受け付けない IEにおいて仕様で許された正規表現パターンを利用可能にすることかもしれない

その過程でFirefoxがネイブに処理する空の文字セトとXRegExpの提供する空の文字セトの挙動が食い違ってしまっている(1行目 12)というのが冒頭の指摘でもこれは重要ではないし同様の指摘を Operaについても行うことができる(3行目 12列と 34)

そうではなくてライブラリ利用者とし「仕様に準拠した「ブラウザ間で統一された機能を望む視点からXRegExpの提供する空の文字セトが Firefoxにおいてのみ違う意味になること(2列目)をこそ指摘すべきだった(実際そうしたんだけど日記の内容だけが古かったのでこうして追記してい)

1列目2列目3列目4列目
RegExp("[]")XRegExp("[]")RegExp("[^]")XRegExp("[^]")
1行目Firefox(3.0.11, 3.5RC3)必ず失敗必ず成功成功したり失敗したり()任意の一文字任意の一文字
2行目IE(8.0)例外必ず失敗例外任意の一文字
3行目Opera(9.64)任意の一文字必ず失敗必ず失敗任意の一文字
4行目Safari(4.0)必ず失敗必ず失敗任意の一文字任意の一文字
5行目Chrome(2.0.172.33)必ず失敗必ず失敗任意の一文字任意の一文字
 すごくおかしな Firefox(3.0.11)(?!)

全てのパターンに (?!) が含まれているから本当は全て falseになってほしい

/(?!)/.test("abc")     //=> true!
/(?!)(?!)/.test("abc") //=> false

/^(?!)/.test("abc")    //=> false
/(?!)$/.test("abc")    //=> true!

/a(?!)/.test("abc")    //=> false
/(?!)a/.test("abc")    //=> true!

/\b(?!)/.test("abc")   //=> false
/(?!)\b/.test("abc")   //=> true!

/(?:)(?!)/.test("abc") //=> true!
/(?!)(?:)/.test("abc") //=> true!

(?!) が実質的にパターンの先頭にあるときだけ存在しないかのように振る舞っているようなすごく限定された状況でのみ発動するんだったんだ

ここまで書いてなかったことに気付いたけどこれが XRegExp("[]") に影響するのはこのパターンが内部的に (?!) に書き換えられるから。XRegExp (1.1.0, 2009-07-04)では \b\B に置き換えられるようになっていてFirefoxのおかしな挙動に影響されて他のブラウザと違う結果になることはなくなっている


もう書かれてた! > http://blog.stevenlevithan.com/archives/xregexp-1-0/comment-page-1#comment-37653


 追記@2009-07-05 04:40: XRegExp-1.0の設計の良さを示す好例 > 20090703c02

自身の機能を XRegExp.addToken()で提供しておりーザーも同じ方法で拡張できるークンの有効範囲が文字セ[] の内か外かその両方かは addToken()の第3引数のビトフラグ( XRegExp.INSIDE_CLASS, XRegExp.OUTSIDE_CLASS )で指定できるしエスケープシークスは予め処理されているので \(?!)\\b\B に置き換えてしまう心配もない簡単でしょう

でも鬼車の \g を追加しようとして名前付きキャプチャ内部のパターンを手に入れられず中断


 追記@2009-07-05 04:40: \gの実装サンプルを見てみた

その \gの利用例が次

XRegExp("(?<any_backref>\\3|\\4){0}     \
         (?<smiles>(?::-[D)])+){0}      \
         ([ab]) ([12]) \\g<any_backref>+\
         \\g<smiles>                    ", "x").test("a22aaa:-):-D"); // true
http://xregexp.com/api/addtoken_examples/

解説するとまず名前付きキャプチャを使って再利用を前提としたパターンを定義する(any_backrefsmiles)ポイトは量指定子{0}の存在で現状ではこれが必ず必要になるこれによりこの名前付きキャプチャはマッチに参加せず一文字も消費せずに成功するその存在意義は \g<smiles> のように後で名前を使ってパターンを再利用できること

上の例で実際に文字を消費するパターンは後半分次の部分だ

    /([ab])([12])\g<any_backref>+\g<smiles>/

Rubyで同じ意図を持って書くとこういうふうになる

irb> any_backref = /\1|\2/
=> /\1|\2/
irb> smiles = /(?::-[D)])+/
=> /(?::-[D)])+/
irb> re = /([ab])([12])#{any_backref}+#{smiles}/
=> /([ab])([12])(?-mix:\1|\2)+(?-mix:(?::-[D)])+)/
irb> re.match( "a22aaa:-):-D" ).to_a
=> ["a22aaa:-):-D", "a", "2"]

さてパターンの再利用が \g の利用法だけど個人的にそれが最大の効果を発揮するのはパターン定義の中でパターンを呼び出したとき再帰的なパターンを定義できることだと思っている。20080111p01で既に書いているが

 /%[Qq]?(?<brace>\{[^\{}]*(?:\g<brace>[^\{}]*)*})/

名前付きキャプチ(?<brace>) の中に \g<brace> があるこういう GNUの命名のような再帰的定義ができてこそ \g を利用する価値があると個人的には思う

addToken()\g を定義する方法として考えていたの「パターン文字列を上限を決めて再帰的に展開するというものこのように

  1. (?<brace>{\g<brace>})
  2. (?<brace>{(?:{\g<brace>})})
  3. (?<brace>{(?:{(?:{(?:{\g<brace>})}))})
  4. (?<brace>{(?:{(?:{(?:{(?:)})}))})

実際の手順は addTokenの第二引数が文字列を返す代わりに toString()を定義したオブジトを返しxregexp.jsの下の引用部分、output.join("") の時点で名前付きキャプチャ内のパターンを参照してパターン文字列を返そうというもの

75
76
77
            regex = RegExp(output.join(""), real.replace.call(flags, /[^gimy]+/g, ""));
            regex._xregexp = {
                source:       pattern,
xregexp.js (1.0.1)

ドの枠組みはこんなのもちろんこのままでは動かない

function PatternOfNamedCapture(name) {
	this.name = name;
}
PatternOfNamedCapture.prototype.toString = function(){
	// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
	if(MAX_RECURSION < count++) {
		return "(?:)";
	} else {
		return output.slice(
			defs[this.name].start,
			defs[this.name].end
		).join("");
	}
	// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
};
XRegExp.addToken(
	/\\g<([$\w]+)>/,
	function(match) {
		return new PatternOfNamedCapture(match[1]);
	}
);
本日のツッコミ(4) ッコミを入れる

Steven LevithanActually, IE treats [] and [^] like Perl and almost every ..

Steven LevithanThanks for finding and documenting the Firefox (?!) bugs. ..

Steven LevithanRegarding your latest update (dated 2009-07-05 04:40), Oni..

Steven LevithanI just updated the example page I linked to so that the so..


20090628()

最終更: 2009-10-28T01:40+0900

[正規表現][Firefox] .NETの正規表現の再帰について(20080111p01の補足)

再帰っていっていいのかな?鬼車は明らかに再帰だったけど

.NETの正規表現を利用した経験はありません(念のため)想像です。

.NETの再帰に関係した部分ドキュメがあまりにわかりにくかったので整理(実はわかりにくさの半分は日本語のせいだった英語の方ドキュメトを読みまし)

 1.スタックされる名前付きキャプチャグル: (?<name1>), (?'name1')

ャプチャ内容を読み出す従来の記法が \1, \2名前付きキャプチャの場合は \k<name1>, \k'name1'など(実装ごとに異なる)ャプチャグループに量指定子がくっついている場合これらで読み出せるのは最後のキャプチャ内容だだけどキャプチャの記憶領域はキャプチャグループごとに一つではなくスタックになっていてその一番上の内容を読み出していると考える(.NETだか Javaだかではプログラムからこのスタックにアクセスできたはず)

 2.名前付きキャプチname1のスタックを POP: (?<name2-name1>)

まずこれは name2という名前付きキャプチャグループと同時にname1のキャプチャスタックを POPするname2を省略して name1POPするだけも可能MSDNの日本ドキュメトを名前の部分だけこちらに合うように書きかえたのが次

既に定義されていたグループ name1 の定義を削除し既に定義されていた name1 グループと現在のグループの間隔をグループ name2 に格納します。

実際に name2のキャプチャ内容がどういうものになるのか(直前の name1のキャプチャ内容name2の……にマッチした部分その間がそれぞれ含まれるのかどうか)は読み取れないけど直前の name1ャプチャをなかったことにしname1のキャプチャ部分から ……までを name2に保存するという(覚え: name2は直前の name1から……ま)

当然のことname1のキャプチャスタックが空のとき name2のキャプチャは ……のマッチ正否に関わらず失敗する

 3.名前付きキャプチname1のスタックが空であることをテトするイ: (?(name1)(?!))

name1のキャプチャに成功しているかどうかで適用するパターンを変化させる条件分岐 (?(name1)truepattern|falsepattern)必ず失敗するパターン (?!) の組み合わせによりname1のキャプチャスタックが空でないと必ず失敗する逆に name1のキャプチャスタックが空のときは(省略された空の falsepatternが何にでもマッチして)必ず成功する(はず)

(?(name1)(?!)) が成功する(=name1のキャプチャスタックが空である)とはname1に含まれるパターンが開きかっこname2のパターンが閉じかっこにマッチしその間のパターンが開き閉じどちらのかっこにもマッチしないとき開きかっこと閉じかっこがバラスしているということ(MSDNの例がこれ)

なんてこったい

// Firefox 3.0.11と 3.5RC3のロケーションバーでの実行結果。
javascript:alert(/(?!)/.test("")) //=> true (falseであってほしい)
javascript:alert(/(?=)/.test("")) //=> false (trueであってほしい)
javascript:alert(/(?:)/.test("")) //=>
// Windows Vistaでの JScript(WSH)実行結果。
WScript.Echo(""+ /(?!)/.test("")) //=> false (期待通り)
WScript.Echo(""+ /(?=)/.test("")) //=> true (期待通り)
WScript.Echo(""+ /(?:)/.test("")) //=> true (期待通り)

必ず失敗するパターンを試してみたら Firefoxで真逆の結果が出てしまったFirefoxが間違っててくれないと困るよ(ブラウザにより逆の結果がでていることがもう困るけ)

(参考)間違いなく失敗する* > 詳説正規表現第3- Googleック検索, 詳説正規表現第3- Googleック検索

Internet Explorer 8.0.6001.18783 64-bit EditionSafari 4.0.530.17Opera 9.64Google Chrome 2.0.172.33 でもみんな Firefoxとは逆の結果になるFirefoxだけが 3.0から 3.5RC3になっても違っているのは悪夢だ

Firefoxに理がないことは次の例からも判断できない空のパターンを空と空の選択パターンにするだけで結果がひっくり返ってる

// Firefox 3.0.11のロケーションバーでの実行結果。
javascript:alert(/(?!)/.test("")) //=> true (下と同じであるべき)
javascript:alert(/(?!|)/.test("")) //=> false (期待通り)

javascript:alert(/(?=)/.test("")) //=> false (下と同じであるべき)
javascript:alert(/(?=|)/.test("")) //=> true (期待通り)

javascript:alert(/(?:)/.test("")) //=> true (期待通り)
javascript:alert(/(?:|)/.test("")) //=> true (期待通り)

* 念のため断っておくと書籍の文脈ではこの断定は Perl.NETの正規表現に(ゃんと)限られている


20090317() XRegExp(シンプルな正規表現しか使えない JavaScriptにモダンな拡張機能を提供する JavaScriptライブラリ)の作者Regular Expressions Cookbookを書いた(共著)って気になるけどクックブックってどんなんなんだろう「読める本ではないような不安があるんだけど

[][正規表現] [ーパーバ] Jan Goyvaerts, Steven LevithanRegular Expression CookbookOreilly & Associates Inc

Regular Expression Cookbook Regular Expression Cookbook
Jan Goyvaerts/Steven Levithan
Oreilly & Associates Inc
4,073

XRegExp: JavaScript regex librarySyntaxHighlighter(Ver.2.0)で使われていたので知ったXRegExpの作者が本の著者の一人Steven Levithan

XRegExp(Ver.0.6.1)Firefox 2,3Internet Explorer 5.5-8β1Safari 3.1Opera 9.27JavaScriptに付け加えて利用可能にする正規表現の機能は

  •  名前付きキャプチャグループ

    後方参照も可String.replace()での使用も可

  •  s(singleline)フラグ

    .が改行にもマッチ

  •  x(extended)フラグ

    ほとんどの空白を無意味なものにしたり(=パターンを自由にインデトできる)行コメ(#から改行まで)を利用可能にする

  •  インラインコメ

    (?#ここにコメ)

  •  Unicode Properties & Blocks サポ

    こんなの\p{L}, \p{M}, \p{N}, \p{InHiragana}, \p{InKatakana}否定は大文字のP\P{}

    文字集合の中で使えないという制限があるが若干の工夫でなんとかなる

使い所が限定されていそうだったり使い方が難しそうな機能として

  •  XRegExp.matchRecursive(string, left, right, modifiers, options)

    (独り) 名前付きキャプチャグループをサポトしたならそのキャプチャ結果をスタックしてそこにパターンを繰り返し適用する書き方を用意することでmatchRecursive()なんてスペシャルメソドは不要にできるのでは? <何を言ってるのか自分でわかってないよ

    XRegExpのコトラクタlog[2008-01-11-p01] 鬼車すごい正規表現で再帰ができるで書いたようなパターン文字列を渡して再帰を認識するマッチングを行いたいです。

正規表現に関連するいくつかのメソドを上書きしブラウザ間の差異を吸収するとともに仕様通りの動作に統一したりもする

  •  /pattern/g.lastIndex

    IEなどが0の文字にマッチしたときに lastIndexを不当にインクリメトするのを修正

  •  String.split(separator, limit)

    • 分割パターン中のキャプチャグループを戻り値の配列に挿入する
    • ッチに参加しなかったキャプチャグループの位置に undefinedを挿入する
    • 連続するセパレータの間などに存在する空文字列を省略せずに戻り値の配列に含める

    (独り) limitを指定したときに戻ってくる配列の要素数が limitと一致しないXRegExpのバグ? もちろん separatorにキャプチャグループは使っていない


 再帰パターン

例えば再帰の深さの上限を 1020と決めてしまってXRegExpのコトラクタでごにょごにょパターン文字列を展開してみればどうだろうJavaScriptで正規表現を一から実装しようというプロジトではないから自ずと制限が定まってしまうのだけど上限付きでもそれが 20もあれば十分という気がする


 追記@2009-06-25: XRegExp 1.0がリリースされている(2009-06-24)

驚いた大部分がライブラリの機能紹介という退屈な(<作者本人が一番よく知っているから)文章に紛れ込んだバグ報告(とも呼べそうにないもの)を不自由な Google翻訳から見つけ出すとは

1.0のソースも眺めてみたいけれど巨大な変更履歴にちっと後込そのうちね

本日のツッコミ(1) ッコミを入れる

Steven LevithanHi. I translated this page using Google Translate. The la..


20081110() 自動二輪でデュアルパーパス車(ュアルといいつつ実質オフ寄り)を嗜好し自転車ではクロスバイク(の中でもロド寄り)を好むのに共通点はどこにあるのかと思えば軽くて扱いやすい所だったらしいトバイにラトウトスポーツというカテゴリはないのーパーモタドだけなの(それでいいんだけ)

[正規表現] >Ruby 初心者スレPart 22 >>861 (http://www.kt.rim.or.jp/%7ekbk/zakkicho/08/zakkicho0811a.html#D20081109-6)

if line =~ /.*Sector:<.*(Basic Materials|Conglomerates|Consumer Goods|Financial|Healthcare|Industrial Goods|Services|Technology|Utilities)/
    p $1
end 

HTMLをその場その場の正規表現で処理したくはないけどそれはそれとしてこうするSector:HOGEHOGEというテキトにタグがいろいろ付いていてそれらを無視してセクタ名を取り出したいということかと

   /Sector:(?:<[^>]+>)*(Basic Materials|Conglomerates|Consumer Goods|Financial|Healthcare|Industrial Goods|Services|Technology|Utilities)/

元のパターン冒頭の .* は全く無駄一度文字列全部を食べてしまうことに無駄以外の意味はない(後ろかSector:を探すか前かSector:を探すかという違いはあったりし)

二番目の .* が以降の文字列すべてを食べてしまうのも無駄それにそれじSector:から最も離れたセクタ名と同じ単語に一番最初にマッチしてしまう

以上お目汚しでしたそれよりこの質問への最初の回答は金言良いなあ(こんなスがすぐに付くなんて)

 正規表現は書き方を覚えないと駄目
 なぜなら、ほんの少し変えようと思っただけで別物になるから
 コピペでやろうとすると異常に遠回りになる

基本的に覚えることは

  • 文字クラスとメタ文字(\w,\n,\s,...)
  • アンカ(^,$,\b,...)と先読み(戻り読)
  • パターンのグルーピングと選択
  • 量指定子(これは文字にもグループにも付けられ)

だけだもの


20080528() コンテトネゴシエイションによる表示言語の切り替えはうまくない内容が同じなら日本語で表示された方が読みやすいが英語の方が情報が新しいのが常Accept-Languageを切り替えるより URLを書き換える方が圧倒的に楽でしょう読み手に選択肢を! >>>>>>http://www.mozilla.com/firefox/

[正規表現] 今日やられた正規表現

/^(?=\W)/
/^(?!\w)/

二つの違いは? (ト:空文字列/)


/^(?=\W)/  //=> 単語に使われる以外の文字から始まる行の頭にマッチ
/^(?!\w)/  //=> 単語に使われる文字から始まらない行の頭にマッチ
           //   (最初のパターンと違い、一文字もない場合(空行)にもマッチする)

20080515() 正規表現の存在を知りその文法を知ったのは JScript5.5HTMLヘルプだったほんとう役に立ドキュメトだった(>20080215p01) 「だったといいつつ今も持っていて参照もしているけれど

[Ruby][正規表現] /n, /s, /e, /u, $KCODEのもやっとを解消

正規表現リテラルの /nseuフラグは正規表現のマッチ動作に影響を与える(/nseuフラグのいずれも指定しなかった場合は実行時の $KCODEに従)

/nが指定されていたり $KCODE='NONE'のとき.は改行を除いたり改行を含んだりする 1にマッチするメタ文字だが/seuフラグが指定されていたり $KCODESsEeUuのいずれかで始まる文字列のとき.は日本語を含むShift_JISEUC-JPUTF-8一文字(1-3?)にマッチする

/nseuフラグや $KCODEは正規表現のパターンの解釈にも影響を与える

Shift_JISで保存したスクリトファイルに /w/ というパターンと 'w' という文字列リテラルがありッチを行った場合実行時に $KCODE='NONE'であればパターンは /\225\w/ と解釈され"\225"の後にメタ文字 \wにマッチする文字を探し失敗する$KCODE='SJIS'であればパターンは /w/ と解釈され""のあとに "w"を探し成功する

irb(main)> /表w/n =~ '表w'
=> nil
irb(main)> /表w/s =~ '表w'
=> 0

正規表現パターンの中のマルチバト文字は文字列の場合と同じくあくまでバト列であり/nseuフラグや $KCODEがどうであれ EUC-JPで保存されたスクリトの中の正規表現リテラル //Shift_JIS「あを表すバト列 "\202\240" にマッチすることはない