RE: 表單的 maxlength 屬性跟 non-BMP 字符支援(原: Re: JavaScript 的非基本多文種平面(non-BMP))


Kenny:



1. data:text/html; charset=utf-8,<input maxlength="2"
    value="&#131207;1"></input>


    2.
javascript:alert(document.getElementsByTagName("input")[0].checkValidity())



测试了下,ff4.0.1,xp sp3 简体中文环境,alert的也是true


Date: Fri, 17 Jun 2011 16:18:28 +0800
From: kennyluck@w3.org
To: timdream@gmail.com
CC: public-html-ig-zh@w3.org
Subject: 表單的 maxlength 屬性跟 non-BMP 字符支援(原: Re: JavaScript 的非基本多文種平面(non-BMP))



  


    
    
  
  
    花了不少時間多做了一點研究,分成兩篇,這篇講現象與實作。

    

    (11/06/08 10:13), Timothy Chien wrote:
    
      1. 我一定要特別指出來以表達我對 Twitter 竟然有考慮這個東西的震驚

    
    

    我也要對以下這個表達震驚:

    

        HTML5 規範裡表單的 maxlength 屬性[1]有考慮到這個東西(請參考代碼點長度(code-point
    length)的定義[2]),而且 webkit 也實作出來了。

    

    [1]
http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#the-maxlength-attribute


    [2]
http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#code-point-length


    

    測試方法就是在瀏覽器的 URL 條依序打入:

    

    1. data:text/html; charset=utf-8,<input maxlength="2"
    value="&#131207;1"></input>

    2.
javascript:alert(document.getElementsByTagName("input")[0].checkValidity())

    

    如果是 true 就是對的,false 就是錯的。

    

    結果:WebKit 沒問題、FF4 是錯的、Opera 11.50b1 (為了感謝阿菲(Philip
    Jägenstedt)的來信,特地載了最新版的 Opera 試驗 :p)是錯的

    

    如果用 JavaScript 測試 WebKit,有一些情形比較奇怪,不過大致上符合現在的 HTML5 標準:

    "&#131207;" 的代碼點長度是 1

    "\ud840\udc87" 的代碼點的長度是 1("&#131207;" 的兩個代理對(Surrogate pair))

    "\ud840" 的代碼點長度是 1(這比較奇怪,不過基本是符合標準的,下一篇再解釋)

    

    另外有一個有趣的情形是 <input value="&#xd840;&#xdc87;">。根據 HTML5
    規範,這雖然是不合法的內容(要寫 "&#131207;" 要用 "&#20087;"),但是瀏覽器規定必須要把它解析成兩個 U+FFFD REPLACEMENT CHARACTER[3],
    所以代碼點長度是 2。(Opera 11.50b1 沒有實作這個小細節,"&#xd840;&#xdc87;" 會變成一個
    "&")

    

    [3]
    http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference

    (Otherwise, if the number is in the range 0xD800 to 0xDFFF or is
    greater than 0x10FFFF, then this is a parse error. Return a U+FFFD
    REPLACEMENT CHARACTER.)

    

    但是,我看了 WebKit 一年半以前實作 maxlength 的報告[4]跟原始碼之後,發現到它是算一種叫做字素簇(grapheme
    cluster)[5]或是稱作使用者所見字符(user-perceived charcter)的個數。舉例來說,WebKit
    為了maxlength 在算

    

    "A\u0301"   // (A +  ́) = Á,一個字素簇

    

    的長度的時候,會把它算成 1,不合規範講的,因為這個狀況的代碼點長度是 2。

    

    [4] https://bugs.webkit.org/show_bug.cgi?id=29292


    [5] http://unicode.org/reports/tr29/


    

    WebKit 用了一個很大套的一個叫做 ICU 由 IBM 開發的國際化程式庫算字素簇的個數,在編譯 WebKit
    的時候如果沒連接這套程式庫似乎 non-BMP 的長度就會算成 2 了。Gecko 的 gfxTextRun
    有方法可以算字素簇(用來移動光標,選取用),不過 maxlength 的正確算法反正就是還沒有人做。

    

    
      2. str.codePointCount() 可以用 String.prototype 實做吧?Kenny 寫個 library
丟出來吧,哪天真的大家覺得不夠快就會被瀏覽器實做了?
(JSON,arr.forEach ... 等等好像都是這樣被實做的?)

    
    

    對是對啦,不過有需要用的人自己把上一篇都丟出來的 Twitter 的程式碼自己包不就好了 xd 

    真要做的話,我比較喜歡非函數形式,可以用 ECMAScript5 的
    Object.defineProperty(String.prototype, "codePointCount", {get:...})
    來做。另外,做 JavaScript 功能的原型好像可以用 JavaScript 發明人 Brendan Eich 他們在搞的
    Narcissus[6] fork 出來玩(不過這個新功能那麼小。。。)

    

    我留給比較會寫代碼 的 Web Developer 去玩吧,我的專長是看代碼跟讀信 xd

    

    說實在的,從標準那邊下手應該比較合理,不過我不太清楚 ECMA 的規則、、、

    

    [6] https://github.com/mozilla/narcissus/


    

    

    此致

    Kenny, W3C

    Twitter: http://twitter.com/kanghaolu


    Plurk: http://www.plurk.com/kennyluck

            

Received on Sunday, 19 June 2011 11:01:13 UTC