hanzi-rails 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/hanzi.js +737 -455
- data/app/assets/stylesheets/hanzi.css.erb +560 -584
- data/lib/hanzi-rails/version.rb +2 -2
- metadata +5 -25
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* 漢字標準格式 v3.2.
|
2
|
+
* 漢字標準格式 v3.2.7 | MIT License | css.hanzi.co
|
3
3
|
* Han.css: the CSS typography framework optimised for Hanzi
|
4
4
|
*/
|
5
5
|
|
@@ -8,6 +8,10 @@ void function( global, factory ) {
|
|
8
8
|
// CommonJS
|
9
9
|
if ( typeof module === 'object' && typeof module.exports === 'object' ) {
|
10
10
|
module.exports = factory( global, true )
|
11
|
+
// AMD
|
12
|
+
} else if ( typeof define === 'function' && define.amd ) {
|
13
|
+
define(function() { return factory( global, true ) })
|
14
|
+
// Global namespace
|
11
15
|
} else {
|
12
16
|
factory( global )
|
13
17
|
}
|
@@ -22,28 +26,34 @@ var root = document.documentElement
|
|
22
26
|
|
23
27
|
var body = document.body
|
24
28
|
|
25
|
-
var VERSION = '3.2.
|
29
|
+
var VERSION = '3.2.7'
|
26
30
|
|
27
31
|
var ROUTINE = [
|
28
32
|
// Initialise the condition with feature-detecting
|
29
33
|
// classes (Modernizr-alike), binding onto the root
|
30
34
|
// element, possibly `<html>`.
|
31
35
|
'initCond',
|
36
|
+
|
32
37
|
// Address element normalisation
|
33
38
|
'renderElem',
|
39
|
+
|
34
40
|
// Handle Biaodian
|
35
|
-
|
41
|
+
/* 'jinzify', */
|
36
42
|
'renderHanging',
|
37
43
|
'renderJiya',
|
44
|
+
|
38
45
|
// Address Hanzi and Western script mixed spacing
|
39
46
|
'renderHWS',
|
47
|
+
|
40
48
|
// Address Basic Biaodian correction in Firefox
|
41
49
|
'correctBasicBD',
|
50
|
+
|
42
51
|
// Address presentational correction to combining ligatures
|
43
52
|
'substCombLigaWithPUA'
|
53
|
+
|
44
54
|
// Address semantic correction to inaccurate characters
|
45
55
|
// **Note:** inactivated by default
|
46
|
-
|
56
|
+
/* 'substInaccurateChar', */
|
47
57
|
]
|
48
58
|
|
49
59
|
// Define Han
|
@@ -289,12 +299,10 @@ var UNICODE = {
|
|
289
299
|
*
|
290
300
|
* 1. 國語注音、方言音符號:[\u3105-\u312D][\u31A0-\u31BA]
|
291
301
|
Bopomofo phonetic symbols
|
292
|
-
* 2.
|
293
|
-
|
294
|
-
* 3.
|
295
|
-
|
296
|
-
* 4. 方言音陰、陽入韻:[\u31B4-\u31B7][\u0358\u030d]?
|
297
|
-
Checked tones in dialects
|
302
|
+
* 2. 平上去聲調號:[\u02D9\u02CA\u02C5\u02C7\u02EA\u02EB\u02CB] (**註:**國語三聲包含乙個不合規範的符號)
|
303
|
+
Level, rising, departing tones
|
304
|
+
* 3. 入聲調號:[\u31B4-\u31B7][\u0358\u030d]?
|
305
|
+
Checked (entering) tones
|
298
306
|
*/
|
299
307
|
zhuyin: {
|
300
308
|
base: '[\u3105-\u312D\u31A0-\u31BA]',
|
@@ -302,7 +310,7 @@ var UNICODE = {
|
|
302
310
|
medial: '[\u3127-\u3129]',
|
303
311
|
final: '[\u311A-\u3129\u312D\u31A4-\u31B3\u31B8-\u31BA]',
|
304
312
|
tone: '[\u02D9\u02CA\u02C5\u02C7\u02CB\u02EA\u02EB]',
|
305
|
-
|
313
|
+
checked: '[\u31B4-\u31B7][\u0358\u030d]?'
|
306
314
|
}
|
307
315
|
}
|
308
316
|
|
@@ -349,7 +357,7 @@ var TYPESET = (function() {
|
|
349
357
|
var rZyS = UNICODE.zhuyin.initial
|
350
358
|
var rZyJ = UNICODE.zhuyin.medial
|
351
359
|
var rZyY = UNICODE.zhuyin.final
|
352
|
-
var rZyD = UNICODE.zhuyin.tone + '|' + UNICODE.zhuyin.
|
360
|
+
var rZyD = UNICODE.zhuyin.tone + '|' + UNICODE.zhuyin.checked
|
353
361
|
|
354
362
|
return {
|
355
363
|
/* Character-level selector (字級選擇器)
|
@@ -384,20 +392,20 @@ var TYPESET = (function() {
|
|
384
392
|
*/
|
385
393
|
group: {
|
386
394
|
biaodian: [
|
387
|
-
new RegExp( '(' + rBd + '){2,}', 'g' ),
|
395
|
+
new RegExp( '((' + rBd + '){2,})', 'g' ),
|
388
396
|
new RegExp( '(' + rBdLiga + rBdOpen + ')', 'g' )
|
389
397
|
],
|
390
398
|
punct: null,
|
391
399
|
hanzi: new RegExp( '(' + rHan + ')+', 'g' ),
|
392
400
|
western: new RegExp( '(' + rLatn + '|' + rGk + '|' + rCy + '|' + rPt + ')+', 'ig' ),
|
393
401
|
kana: new RegExp( '(' + rKana + '|' + rKanaS + '|' + rKanaH + ')+', 'g' ),
|
394
|
-
eonmun: new RegExp( '(' + rEon + '|' + rEonH + ')+', 'g' )
|
402
|
+
eonmun: new RegExp( '(' + rEon + '|' + rEonH + '|' + rPt + ')+', 'g' )
|
395
403
|
},
|
396
404
|
|
397
405
|
/* Punctuation Rules (禁則)
|
398
406
|
*/
|
399
407
|
jinze: {
|
400
|
-
hanging: new RegExp( '(' +
|
408
|
+
hanging: new RegExp( '(' + rBdClose + '*|[…⋯]*)([、,。.])(?!' + rBdEnd + ')', 'ig' ),
|
401
409
|
touwei: new RegExp( '(' + rBdOpen + '+)(' + rChar + ')(' + rBdEnd + '+)', 'ig' ),
|
402
410
|
tou: new RegExp( '(' + rBdOpen + '+)(' + rChar + ')', 'ig' ),
|
403
411
|
wei: new RegExp( '(' + rChar + ')(' + rBdEnd + '+)', 'ig' ),
|
@@ -415,13 +423,13 @@ var TYPESET = (function() {
|
|
415
423
|
*/
|
416
424
|
hws: {
|
417
425
|
base: [
|
418
|
-
new RegExp( '('+ rHan +')(' + rAlph + '|' + rPtOpen + ')', 'ig' ),
|
419
|
-
new RegExp( '('+ rAlph+ '|' + rPtEnd +')(' + rHan + ')', 'ig' )
|
426
|
+
new RegExp( '('+ rHan + ')(' + rAlph + '|' + rPtOpen + ')', 'ig' ),
|
427
|
+
new RegExp( '('+ rAlph + '|' + rPtEnd + ')(' + rHan + ')', 'ig' )
|
420
428
|
],
|
421
429
|
|
422
430
|
strict: [
|
423
|
-
new RegExp( '('+ rHan +')' + rWhite + '?(' + rAlph + '|' + rPtOpen + ')', 'ig' ),
|
424
|
-
new RegExp( '('+ rAlph+ '|' + rPtEnd +')' + rWhite + '?(' + rHan + ')', 'ig' )
|
431
|
+
new RegExp( '('+ rHan + ')' + rWhite + '?(' + rAlph + '|' + rPtOpen + ')', 'ig' ),
|
432
|
+
new RegExp( '('+ rAlph + '|' + rPtEnd + ')' + rWhite + '?(' + rHan + ')', 'ig' )
|
425
433
|
]
|
426
434
|
},
|
427
435
|
|
@@ -446,6 +454,21 @@ var TYPESET = (function() {
|
|
446
454
|
[ '\u006F[\u030d\u0358]', '\uDB80\uDC6F' ],
|
447
455
|
[ '\u0075[\u030d\u0358]', '\uDB80\uDC75' ],
|
448
456
|
|
457
|
+
[ '\u31B4[\u030d\u0358]', '\uDB8C\uDDB4' ],
|
458
|
+
[ '\u31B5[\u030d\u0358]', '\uDB8C\uDDB5' ],
|
459
|
+
[ '\u31B6[\u030d\u0358]', '\uDB8C\uDDB6' ],
|
460
|
+
[ '\u31B7[\u030d\u0358]', '\uDB8C\uDDB7' ]
|
461
|
+
],
|
462
|
+
|
463
|
+
'comb-liga-vowel': [
|
464
|
+
[ '\u0061[\u030d\u0358]', '\uDB80\uDC61' ],
|
465
|
+
[ '\u0065[\u030d\u0358]', '\uDB80\uDC65' ],
|
466
|
+
[ '\u0069[\u030d\u0358]', '\uDB80\uDC69' ],
|
467
|
+
[ '\u006F[\u030d\u0358]', '\uDB80\uDC6F' ],
|
468
|
+
[ '\u0075[\u030d\u0358]', '\uDB80\uDC75' ]
|
469
|
+
],
|
470
|
+
|
471
|
+
'comb-liga-zhuyin': [
|
449
472
|
[ '\u31B4[\u030d\u0358]', '\uDB8C\uDDB4' ],
|
450
473
|
[ '\u31B5[\u030d\u0358]', '\uDB8C\uDDB5' ],
|
451
474
|
[ '\u31B6[\u030d\u0358]', '\uDB8C\uDDB6' ],
|
@@ -477,6 +500,7 @@ Han.UNICODE.cjk = Han.UNICODE.hanzi
|
|
477
500
|
Han.UNICODE.greek = Han.UNICODE.ellinika
|
478
501
|
Han.UNICODE.cyrillic = Han.UNICODE.kirillica
|
479
502
|
Han.UNICODE.hangul = Han.UNICODE.eonmun
|
503
|
+
Han.UNICODE.zhuyin.ruyun = Han.UNICODE.zhuyin.checked
|
480
504
|
|
481
505
|
Han.TYPESET.char.cjk = Han.TYPESET.char.hanzi
|
482
506
|
Han.TYPESET.char.greek = Han.TYPESET.char.ellinika
|
@@ -523,12 +547,12 @@ var $ = {
|
|
523
547
|
// Clone a node (text, element or fragment) deeply or
|
524
548
|
// childlessly
|
525
549
|
clone: function( node, deep ) {
|
526
|
-
return node.cloneNode( deep
|
550
|
+
return node.cloneNode( typeof deep === 'boolean' ? deep : true )
|
527
551
|
},
|
528
552
|
|
529
553
|
// Remove a node (text, element or fragment)
|
530
|
-
remove: function( node
|
531
|
-
return
|
554
|
+
remove: function( node ) {
|
555
|
+
return node.parentNode.removeChild( node )
|
532
556
|
},
|
533
557
|
|
534
558
|
// Set attributes all in once with an object
|
@@ -586,7 +610,7 @@ var $ = {
|
|
586
610
|
|
587
611
|
var Fibre =
|
588
612
|
/*!
|
589
|
-
* Fibre.js v0.1
|
613
|
+
* Fibre.js v0.2.1 | MIT License | github.com/ethantw/fibre.js
|
590
614
|
* Based on findAndReplaceDOMText
|
591
615
|
*/
|
592
616
|
|
@@ -594,8 +618,9 @@ function( Finder ) {
|
|
594
618
|
|
595
619
|
'use strict'
|
596
620
|
|
597
|
-
var VERSION = '0.1
|
598
|
-
var
|
621
|
+
var VERSION = '0.2.1'
|
622
|
+
var NON_INLINE_PROSE = Finder.NON_INLINE_PROSE
|
623
|
+
var AVOID_NON_PROSE = Finder.PRESETS.prose.filterElements
|
599
624
|
|
600
625
|
var global = window || {}
|
601
626
|
var document = global.document || undefined
|
@@ -614,8 +639,8 @@ function matches( node, selector, bypassNodeType39 ) {
|
|
614
639
|
|
615
640
|
if ( typeof document === 'undefined' ) throw new Error( 'Fibre requires a DOM-supported environment.' )
|
616
641
|
|
617
|
-
var Fibre = function( context ) {
|
618
|
-
return new Fibre.fn.init( context )
|
642
|
+
var Fibre = function( context, preset ) {
|
643
|
+
return new Fibre.fn.init( context, preset )
|
619
644
|
}
|
620
645
|
|
621
646
|
Fibre.version = VERSION
|
@@ -626,87 +651,128 @@ Fibre.fn = Fibre.prototype = {
|
|
626
651
|
|
627
652
|
version: VERSION,
|
628
653
|
|
654
|
+
finder: [],
|
655
|
+
|
629
656
|
context: undefined,
|
630
657
|
|
631
|
-
|
658
|
+
portionMode: 'retain',
|
632
659
|
|
633
|
-
|
660
|
+
selector: {},
|
661
|
+
|
662
|
+
preset: 'prose',
|
634
663
|
|
635
|
-
init: function( context ) {
|
636
|
-
if (
|
664
|
+
init: function( context, noPreset ) {
|
665
|
+
if ( !!noPreset ) this.preset = null
|
637
666
|
|
638
|
-
|
639
|
-
|
667
|
+
this.selector = {
|
668
|
+
context: null,
|
669
|
+
filter: [],
|
670
|
+
avoid: [],
|
671
|
+
boundary: []
|
672
|
+
}
|
673
|
+
|
674
|
+
if ( !context ) {
|
675
|
+
throw new Error( 'A context is required for Fibre to initialise.' )
|
676
|
+
} else if ( context instanceof Node ) {
|
677
|
+
if ( context instanceof Document ) this.context = context.body || context
|
678
|
+
else this.context = context
|
640
679
|
} else if ( typeof context === 'string' ) {
|
641
|
-
this.contextSelector = context
|
642
680
|
this.context = document.querySelector( context )
|
681
|
+
this.selector.context = context
|
643
682
|
}
|
644
|
-
|
645
683
|
return this
|
646
684
|
},
|
647
685
|
|
648
|
-
|
649
|
-
|
650
|
-
|
686
|
+
filterFn: function( node ) {
|
687
|
+
var filter = this.selector.filter.join( ', ' ) || '*'
|
688
|
+
var avoid = this.selector.avoid.join( ', ' ) || null
|
689
|
+
var result = matches( node, filter, true ) && !matches( node, avoid )
|
690
|
+
return ( this.preset === 'prose' ) ? AVOID_NON_PROSE( node ) && result : result
|
651
691
|
},
|
652
692
|
|
653
|
-
|
693
|
+
boundaryFn: function( node ) {
|
694
|
+
var boundary = this.selector.boundary.join( ', ' ) || null
|
695
|
+
var result = matches( node, boundary )
|
696
|
+
return ( this.preset === 'prose' ) ? NON_INLINE_PROSE( node ) || result : result
|
697
|
+
},
|
654
698
|
|
655
699
|
filter: function( selector ) {
|
656
|
-
|
657
|
-
|
658
|
-
this.filterSelector = selector
|
659
|
-
break
|
660
|
-
case 'function':
|
661
|
-
this.filterElemFn = selector
|
662
|
-
break
|
663
|
-
default:
|
664
|
-
return this
|
700
|
+
if ( typeof selector === 'string' ) {
|
701
|
+
this.selector.filter.push( selector )
|
665
702
|
}
|
666
703
|
return this
|
667
704
|
},
|
668
705
|
|
669
|
-
|
706
|
+
endFilter: function( all ) {
|
707
|
+
if ( all ) {
|
708
|
+
this.selector.filter = []
|
709
|
+
} else {
|
710
|
+
this.selector.filter.pop()
|
711
|
+
}
|
712
|
+
return this
|
713
|
+
},
|
670
714
|
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
715
|
+
avoid: function( selector ) {
|
716
|
+
if ( typeof selector === 'string' ) {
|
717
|
+
this.selector.avoid.push( selector )
|
718
|
+
}
|
719
|
+
return this
|
720
|
+
},
|
721
|
+
|
722
|
+
endAvoid: function( all ) {
|
723
|
+
if ( all ) {
|
724
|
+
this.selector.avoid = []
|
725
|
+
} else {
|
726
|
+
this.selector.avoid.pop()
|
682
727
|
}
|
683
728
|
return this
|
684
729
|
},
|
685
730
|
|
686
|
-
|
731
|
+
addBoundary: function( selector ) {
|
732
|
+
if ( typeof selector === 'string' ) {
|
733
|
+
this.selector.boundary.push( selector )
|
734
|
+
}
|
735
|
+
return this
|
736
|
+
},
|
737
|
+
|
738
|
+
removeBoundary: function() {
|
739
|
+
this.selector.boundary = []
|
740
|
+
return this
|
741
|
+
},
|
742
|
+
|
743
|
+
setMode: function( portionMode ) {
|
744
|
+
this.portionMode = portionMode === 'first' ? 'first' : 'retain'
|
745
|
+
return this
|
746
|
+
},
|
747
|
+
|
748
|
+
replace: function( regexp, newSubStr ) {
|
687
749
|
var it = this
|
688
|
-
var portionMode = portionMode || 'retain'
|
689
750
|
it.finder.push(Finder( it.context, {
|
690
751
|
find: regexp,
|
691
752
|
replace: newSubStr,
|
692
753
|
filterElements: function( currentNode ) {
|
693
|
-
return it.
|
754
|
+
return it.filterFn( currentNode )
|
694
755
|
},
|
695
|
-
|
756
|
+
forceContext: function( currentNode ) {
|
757
|
+
return it.boundaryFn( currentNode )
|
758
|
+
},
|
759
|
+
portionMode: it.portionMode
|
696
760
|
}))
|
697
761
|
return it
|
698
762
|
},
|
699
763
|
|
700
|
-
wrap: function( regexp, strElemName
|
764
|
+
wrap: function( regexp, strElemName ) {
|
701
765
|
var it = this
|
702
|
-
var portionMode = portionMode || 'retain'
|
703
766
|
it.finder.push(Finder( it.context, {
|
704
767
|
find: regexp,
|
705
768
|
wrap: strElemName,
|
706
769
|
filterElements: function( currentNode ) {
|
707
|
-
return it.
|
770
|
+
return it.filterFn( currentNode )
|
708
771
|
},
|
709
|
-
|
772
|
+
forceContext: function( currentNode ) {
|
773
|
+
return it.boundaryFn( currentNode )
|
774
|
+
},
|
775
|
+
portionMode: it.portionMode
|
710
776
|
}))
|
711
777
|
return it
|
712
778
|
},
|
@@ -726,6 +792,10 @@ Fibre.fn = Fibre.prototype = {
|
|
726
792
|
}
|
727
793
|
}
|
728
794
|
|
795
|
+
// Deprecated API(s)
|
796
|
+
Fibre.fn.filterOut = Fibre.fn.avoid
|
797
|
+
|
798
|
+
// Make sure init() inherit from Fibre()
|
729
799
|
Fibre.fn.init.prototype = Fibre.fn
|
730
800
|
|
731
801
|
return Fibre
|
@@ -733,7 +803,7 @@ return Fibre
|
|
733
803
|
}(
|
734
804
|
|
735
805
|
/**
|
736
|
-
* findAndReplaceDOMText v 0.4.
|
806
|
+
* findAndReplaceDOMText v 0.4.3
|
737
807
|
* @author James Padolsey http://james.padolsey.com
|
738
808
|
* @license http://unlicense.org/UNLICENSE
|
739
809
|
*
|
@@ -747,6 +817,7 @@ return Fibre
|
|
747
817
|
var PORTION_MODE_FIRST = 'first'
|
748
818
|
var doc = document
|
749
819
|
var toString = {}.toString
|
820
|
+
var hasOwn = {}.hasOwnProperty
|
750
821
|
function isArray(a) {
|
751
822
|
return toString.call(a) == '[object Array]'
|
752
823
|
}
|
@@ -822,13 +893,61 @@ return Fibre
|
|
822
893
|
return new Finder(node, options)
|
823
894
|
}
|
824
895
|
|
896
|
+
exposed.NON_PROSE_ELEMENTS = {
|
897
|
+
br:1, hr:1,
|
898
|
+
// Media / Source elements:
|
899
|
+
script:1, style:1, img:1, video:1, audio:1, canvas:1, svg:1, map:1, object:1,
|
900
|
+
// Input elements
|
901
|
+
input:1, textarea:1, select:1, option:1, optgroup: 1, button:1
|
902
|
+
}
|
903
|
+
exposed.NON_CONTIGUOUS_PROSE_ELEMENTS = {
|
904
|
+
|
905
|
+
// Elements that will not contain prose or block elements where we don't
|
906
|
+
// want prose to be matches across element borders:
|
907
|
+
|
908
|
+
// Block Elements
|
909
|
+
address:1, article:1, aside:1, blockquote:1, dd:1, div:1,
|
910
|
+
dl:1, fieldset:1, figcaption:1, figure:1, footer:1, form:1, h1:1, h2:1, h3:1,
|
911
|
+
h4:1, h5:1, h6:1, header:1, hgroup:1, hr:1, main:1, nav:1, noscript:1, ol:1,
|
912
|
+
output:1, p:1, pre:1, section:1, ul:1,
|
913
|
+
// Other misc. elements that are not part of continuous inline prose:
|
914
|
+
br:1, li: 1, summary: 1, dt:1, details:1, rp:1, rt:1, rtc:1,
|
915
|
+
// Media / Source elements:
|
916
|
+
script:1, style:1, img:1, video:1, audio:1, canvas:1, svg:1, map:1, object:1,
|
917
|
+
// Input elements
|
918
|
+
input:1, textarea:1, select:1, option:1, optgroup: 1, button:1,
|
919
|
+
// Table related elements:
|
920
|
+
table:1, tbody:1, thead:1, th:1, tr:1, td:1, caption:1, col:1, tfoot:1, colgroup:1
|
921
|
+
|
922
|
+
}
|
923
|
+
exposed.NON_INLINE_PROSE = function(el) {
|
924
|
+
return hasOwn.call(exposed.NON_CONTIGUOUS_PROSE_ELEMENTS, el.nodeName.toLowerCase())
|
925
|
+
}
|
926
|
+
// Presets accessed via `options.preset` when calling findAndReplaceDOMText():
|
927
|
+
exposed.PRESETS = {
|
928
|
+
prose: {
|
929
|
+
forceContext: exposed.NON_INLINE_PROSE,
|
930
|
+
filterElements: function(el) {
|
931
|
+
return !hasOwn.call(exposed.NON_PROSE_ELEMENTS, el.nodeName.toLowerCase())
|
932
|
+
}
|
933
|
+
}
|
934
|
+
}
|
825
935
|
exposed.Finder = Finder
|
826
936
|
/**
|
827
937
|
* Finder -- encapsulates logic to find and replace.
|
828
938
|
*/
|
829
939
|
function Finder(node, options) {
|
830
940
|
|
941
|
+
var preset = options.preset && exposed.PRESETS[options.preset]
|
831
942
|
options.portionMode = options.portionMode || PORTION_MODE_RETAIN
|
943
|
+
if (preset) {
|
944
|
+
for (var i in preset) {
|
945
|
+
if (hasOwn.call(preset, i) && !hasOwn.call(options, i)) {
|
946
|
+
options[i] = preset[i]
|
947
|
+
}
|
948
|
+
}
|
949
|
+
}
|
950
|
+
|
832
951
|
this.node = node
|
833
952
|
this.options = options
|
834
953
|
// ENable match-preparation method to be passed as option:
|
@@ -850,17 +969,34 @@ return Fibre
|
|
850
969
|
|
851
970
|
var match
|
852
971
|
var matchIndex = 0
|
972
|
+
var offset = 0
|
853
973
|
var regex = this.options.find
|
854
|
-
var
|
974
|
+
var textAggregation = this.getAggregateText()
|
855
975
|
var matches = []
|
976
|
+
var self = this
|
856
977
|
regex = typeof regex === 'string' ? RegExp(escapeRegExp(regex), 'g') : regex
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
978
|
+
matchAggregation(textAggregation)
|
979
|
+
function matchAggregation(textAggregation) {
|
980
|
+
for (var i = 0, l = textAggregation.length; i < l; ++i) {
|
981
|
+
|
982
|
+
var text = textAggregation[i]
|
983
|
+
if (typeof text !== 'string') {
|
984
|
+
// Deal with nested contexts: (recursive)
|
985
|
+
matchAggregation(text)
|
986
|
+
continue
|
987
|
+
}
|
988
|
+
|
989
|
+
if (regex.global) {
|
990
|
+
while (match = regex.exec(text)) {
|
991
|
+
matches.push(self.prepMatch(match, matchIndex++, offset))
|
992
|
+
}
|
993
|
+
} else {
|
994
|
+
if (match = text.match(regex)) {
|
995
|
+
matches.push(self.prepMatch(match, 0, offset))
|
996
|
+
}
|
997
|
+
}
|
998
|
+
|
999
|
+
offset += text.length
|
864
1000
|
}
|
865
1001
|
}
|
866
1002
|
|
@@ -870,14 +1006,14 @@ return Fibre
|
|
870
1006
|
/**
|
871
1007
|
* Prepares a single match with useful meta info:
|
872
1008
|
*/
|
873
|
-
prepMatch: function(match, matchIndex) {
|
1009
|
+
prepMatch: function(match, matchIndex, characterOffset) {
|
874
1010
|
|
875
1011
|
if (!match[0]) {
|
876
1012
|
throw new Error('findAndReplaceDOMText cannot handle zero-length matches')
|
877
1013
|
}
|
878
1014
|
|
879
|
-
match.endIndex = match.index + match[0].length
|
880
|
-
match.startIndex = match.index
|
1015
|
+
match.endIndex = characterOffset + match.index + match[0].length
|
1016
|
+
match.startIndex = characterOffset + match.index
|
881
1017
|
match.index = matchIndex
|
882
1018
|
return match
|
883
1019
|
},
|
@@ -888,28 +1024,55 @@ return Fibre
|
|
888
1024
|
getAggregateText: function() {
|
889
1025
|
|
890
1026
|
var elementFilter = this.options.filterElements
|
1027
|
+
var forceContext = this.options.forceContext
|
891
1028
|
return getText(this.node)
|
892
1029
|
/**
|
893
1030
|
* Gets aggregate text of a node without resorting
|
894
1031
|
* to broken innerText/textContent
|
895
1032
|
*/
|
896
|
-
function getText(node) {
|
1033
|
+
function getText(node, txt) {
|
897
1034
|
|
898
1035
|
if (node.nodeType === 3) {
|
899
|
-
return node.data
|
1036
|
+
return [node.data]
|
900
1037
|
}
|
901
1038
|
|
902
1039
|
if (elementFilter && !elementFilter(node)) {
|
903
|
-
return
|
1040
|
+
return []
|
904
1041
|
}
|
905
1042
|
|
906
|
-
var txt = ''
|
1043
|
+
var txt = ['']
|
1044
|
+
var i = 0
|
907
1045
|
if (node = node.firstChild) do {
|
908
|
-
|
1046
|
+
|
1047
|
+
if (node.nodeType === 3) {
|
1048
|
+
txt[i] += node.data
|
1049
|
+
continue
|
1050
|
+
}
|
1051
|
+
|
1052
|
+
var innerText = getText(node)
|
1053
|
+
if (
|
1054
|
+
forceContext &&
|
1055
|
+
node.nodeType === 1 &&
|
1056
|
+
(forceContext === true || forceContext(node))
|
1057
|
+
) {
|
1058
|
+
txt[++i] = innerText
|
1059
|
+
txt[++i] = ''
|
1060
|
+
} else {
|
1061
|
+
if (typeof innerText[0] === 'string') {
|
1062
|
+
// Bridge nested text-node data so that they're
|
1063
|
+
// not considered their own contexts:
|
1064
|
+
// I.e. ['some', ['thing']] -> ['something']
|
1065
|
+
txt[i] += innerText.shift()
|
1066
|
+
}
|
1067
|
+
if (innerText.length) {
|
1068
|
+
txt[++i] = innerText
|
1069
|
+
txt[++i] = ''
|
1070
|
+
}
|
1071
|
+
}
|
909
1072
|
} while (node = node.nextSibling)
|
910
1073
|
return txt
|
911
1074
|
}
|
912
|
-
|
1075
|
+
|
913
1076
|
},
|
914
1077
|
|
915
1078
|
/**
|
@@ -1197,15 +1360,34 @@ return Fibre
|
|
1197
1360
|
}
|
1198
1361
|
return exposed
|
1199
1362
|
}())
|
1363
|
+
|
1200
1364
|
);
|
1201
1365
|
|
1366
|
+
function createBdGroup( portion, match ) {
|
1367
|
+
var elem = $.create( 'h-char-group', 'biaodian cjk' )
|
1368
|
+
|
1369
|
+
if ( portion.index === 0 && portion.isEnd ) {
|
1370
|
+
elem.innerHTML = match[0]
|
1371
|
+
} else {
|
1372
|
+
elem.innerHTML = portion.text
|
1373
|
+
elem.classList.add( 'portion' )
|
1374
|
+
|
1375
|
+
if ( portion.index === 0 ) {
|
1376
|
+
elem.classList.add( 'isFirst' )
|
1377
|
+
} else if ( portion.isEnd ) {
|
1378
|
+
elem.classList.add( 'isEnd' )
|
1379
|
+
}
|
1380
|
+
}
|
1381
|
+
return elem
|
1382
|
+
}
|
1383
|
+
|
1202
1384
|
function createBdChar( char ) {
|
1203
1385
|
var div = $.create( 'div' )
|
1204
1386
|
var unicode = char.charCodeAt( 0 ).toString( 16 )
|
1205
|
-
var clazz = 'biaodian cjk ' + ( char.match( TYPESET.char.biaodian.open ) ? 'open' :
|
1206
|
-
char.match( TYPESET.char.biaodian.close ) ? 'close end' :
|
1207
|
-
char.match( TYPESET.char.biaodian.end ) ? 'end' :
|
1208
|
-
char.match( new RegExp( '(' + UNICODE.biaodian.liga + ')' )) ? 'liga' : '' )
|
1387
|
+
var clazz = 'biaodian cjk ' + ( char.match( TYPESET.char.biaodian.open ) ? 'bd-open' :
|
1388
|
+
char.match( TYPESET.char.biaodian.close ) ? 'bd-close bd-end' :
|
1389
|
+
char.match( TYPESET.char.biaodian.end ) ? 'bd-end' :
|
1390
|
+
char.match( new RegExp( '(' + UNICODE.biaodian.liga + ')' )) ? 'bd-liga' : '' )
|
1209
1391
|
|
1210
1392
|
div.innerHTML = '<h-char unicode="' + unicode + '" class="' + clazz + '">' + char + '</h-char>'
|
1211
1393
|
return div.firstChild
|
@@ -1213,18 +1395,17 @@ function createBdChar( char ) {
|
|
1213
1395
|
|
1214
1396
|
$.extend( Fibre.fn, {
|
1215
1397
|
// Force punctuation & biaodian typesetting rules to be applied.
|
1216
|
-
jinzify: function() {
|
1217
|
-
|
1218
|
-
this.filterOutSelector += ', h-jinze'
|
1219
|
-
|
1398
|
+
jinzify: function( selector ) {
|
1399
|
+
return (
|
1220
1400
|
this
|
1401
|
+
.filter( selector || null )
|
1402
|
+
.avoid( 'h-jinze' )
|
1221
1403
|
.replace(
|
1222
1404
|
TYPESET.jinze.touwei,
|
1223
1405
|
function( portion, match ) {
|
1224
1406
|
var elem = $.create( 'h-jinze', 'touwei' )
|
1225
1407
|
elem.innerHTML = match[0]
|
1226
|
-
return (( portion.index === 0 && portion.isEnd ) || portion.index === 1 )
|
1227
|
-
? elem : ''
|
1408
|
+
return (( portion.index === 0 && portion.isEnd ) || portion.index === 1 ) ? elem : ''
|
1228
1409
|
}
|
1229
1410
|
)
|
1230
1411
|
.replace(
|
@@ -1253,13 +1434,12 @@ $.extend( Fibre.fn, {
|
|
1253
1434
|
? elem : ''
|
1254
1435
|
}
|
1255
1436
|
)
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1437
|
+
.endAvoid()
|
1438
|
+
.endFilter()
|
1439
|
+
)
|
1259
1440
|
},
|
1260
1441
|
|
1261
1442
|
groupify: function( option ) {
|
1262
|
-
var origFilterOutSelector = this.filterOutSelector
|
1263
1443
|
var option = $.extend({
|
1264
1444
|
biaodian: false,
|
1265
1445
|
//punct: false,
|
@@ -1269,16 +1449,16 @@ $.extend( Fibre.fn, {
|
|
1269
1449
|
western: false // Includes Latin, Greek and Cyrillic
|
1270
1450
|
}, option || {})
|
1271
1451
|
|
1272
|
-
this.
|
1452
|
+
this.avoid( 'h-hangable, h-char-group, h-word' )
|
1273
1453
|
|
1274
1454
|
if ( option.biaodian ) {
|
1275
|
-
this.
|
1276
|
-
TYPESET.group.biaodian[ 0 ],
|
1277
|
-
).
|
1278
|
-
TYPESET.group.biaodian[ 1 ],
|
1455
|
+
this.replace(
|
1456
|
+
TYPESET.group.biaodian[ 0 ], createBdGroup
|
1457
|
+
).replace(
|
1458
|
+
TYPESET.group.biaodian[ 1 ], createBdGroup
|
1279
1459
|
)
|
1280
1460
|
}
|
1281
|
-
if ( option.hanzi ) {
|
1461
|
+
if ( option.hanzi || option.cjk ) {
|
1282
1462
|
this.wrap(
|
1283
1463
|
TYPESET.group.hanzi, $.clone( $.create( 'h-char-group', 'hanzi cjk' ))
|
1284
1464
|
)
|
@@ -1293,20 +1473,17 @@ $.extend( Fibre.fn, {
|
|
1293
1473
|
TYPESET.group.kana, $.clone( $.create( 'h-char-group', 'kana' ))
|
1294
1474
|
)
|
1295
1475
|
}
|
1296
|
-
if ( option.eonmun ) {
|
1476
|
+
if ( option.eonmun || option.hangul ) {
|
1297
1477
|
this.wrap(
|
1298
1478
|
TYPESET.group.eonmun, $.clone( $.create( 'h-word', 'eonmun hangul' ))
|
1299
1479
|
)
|
1300
1480
|
}
|
1301
1481
|
|
1302
|
-
this.
|
1482
|
+
this.endAvoid()
|
1303
1483
|
return this
|
1304
1484
|
},
|
1305
1485
|
|
1306
|
-
// Implementation of character-level selector
|
1307
|
-
// (字元級選擇器)
|
1308
1486
|
charify: function( option ) {
|
1309
|
-
var origFilterOutSelector = this.filterOutSelector
|
1310
1487
|
var option = $.extend({
|
1311
1488
|
biaodian: false,
|
1312
1489
|
punct: false,
|
@@ -1318,7 +1495,7 @@ $.extend( Fibre.fn, {
|
|
1318
1495
|
eonmun: false
|
1319
1496
|
}, option || {})
|
1320
1497
|
|
1321
|
-
this.
|
1498
|
+
this.avoid( 'h-char' )
|
1322
1499
|
|
1323
1500
|
if ( option.biaodian ) {
|
1324
1501
|
this.replace(
|
@@ -1329,7 +1506,7 @@ $.extend( Fibre.fn, {
|
|
1329
1506
|
function( portion, match ) { return createBdChar( match[0] ) }
|
1330
1507
|
)
|
1331
1508
|
}
|
1332
|
-
if ( option.hanzi ) {
|
1509
|
+
if ( option.hanzi || option.cjk ) {
|
1333
1510
|
this.wrap(
|
1334
1511
|
TYPESET.char.hanzi, $.clone( $.create( 'h-char', 'hanzi cjk' ))
|
1335
1512
|
)
|
@@ -1344,12 +1521,12 @@ $.extend( Fibre.fn, {
|
|
1344
1521
|
TYPESET.char.latin, $.clone( $.create( 'h-char', 'alphabet latin' ))
|
1345
1522
|
)
|
1346
1523
|
}
|
1347
|
-
if ( option.ellinika ) {
|
1524
|
+
if ( option.ellinika || option.greek ) {
|
1348
1525
|
this.wrap(
|
1349
1526
|
TYPESET.char.ellinika, $.clone( $.create( 'h-char', 'alphabet ellinika greek' ))
|
1350
1527
|
)
|
1351
1528
|
}
|
1352
|
-
if ( option.kirillica ) {
|
1529
|
+
if ( option.kirillica || option.cyrillic ) {
|
1353
1530
|
this.wrap(
|
1354
1531
|
TYPESET.char.kirillica, $.clone( $.create( 'h-char', 'alphabet kirillica cyrillic' ))
|
1355
1532
|
)
|
@@ -1359,13 +1536,13 @@ $.extend( Fibre.fn, {
|
|
1359
1536
|
TYPESET.char.kana, $.clone( $.create( 'h-char', 'kana' ))
|
1360
1537
|
)
|
1361
1538
|
}
|
1362
|
-
if ( option.eonmun ) {
|
1539
|
+
if ( option.eonmun || option.hangul ) {
|
1363
1540
|
this.wrap(
|
1364
1541
|
TYPESET.char.eonmun, $.clone( $.create( 'h-char', 'eonmun hangul' ))
|
1365
1542
|
)
|
1366
1543
|
}
|
1367
1544
|
|
1368
|
-
this.
|
1545
|
+
this.endAvoid()
|
1369
1546
|
return this
|
1370
1547
|
}
|
1371
1548
|
})
|
@@ -1373,12 +1550,12 @@ $.extend( Fibre.fn, {
|
|
1373
1550
|
Han.find = Fibre
|
1374
1551
|
|
1375
1552
|
void [
|
1376
|
-
'
|
1377
|
-
'wrap',
|
1378
|
-
'
|
1379
|
-
'
|
1380
|
-
'
|
1381
|
-
'charify'
|
1553
|
+
'setMode',
|
1554
|
+
'wrap', 'replace', 'revert',
|
1555
|
+
'addBoundary', 'removeBoundary',
|
1556
|
+
'avoid', 'endAvoid',
|
1557
|
+
'filter', 'endFilter',
|
1558
|
+
'jinzify', 'groupify', 'charify'
|
1382
1559
|
].forEach(function( method ) {
|
1383
1560
|
Han.fn[ method ] = function() {
|
1384
1561
|
if ( !this.finder ) {
|
@@ -1477,7 +1654,6 @@ Locale.support = (function() {
|
|
1477
1654
|
// Create an element for feature detecting
|
1478
1655
|
// (in `testCSSProp`)
|
1479
1656
|
var elem = $.create( 'h-test' )
|
1480
|
-
var exposed = {}
|
1481
1657
|
|
1482
1658
|
function testCSSProp( prop ) {
|
1483
1659
|
var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1)
|
@@ -1496,7 +1672,7 @@ Locale.support = (function() {
|
|
1496
1672
|
var fakeBody = body || $.create( 'body' )
|
1497
1673
|
var div = $.create( 'div' )
|
1498
1674
|
var container = body ? div : fakeBody
|
1499
|
-
var
|
1675
|
+
var callback = typeof callback === 'function' ? callback : function() {}
|
1500
1676
|
var style, ret, docOverflow
|
1501
1677
|
|
1502
1678
|
style = [ '<style>', rule, '</style>' ].join('')
|
@@ -1537,6 +1713,29 @@ Locale.support = (function() {
|
|
1537
1713
|
}
|
1538
1714
|
|
1539
1715
|
return {
|
1716
|
+
columnwidth: testCSSProp( 'columnWidth' ),
|
1717
|
+
|
1718
|
+
fontface: (function() {
|
1719
|
+
var ret
|
1720
|
+
|
1721
|
+
injectElementWithStyle(
|
1722
|
+
'@font-face { font-family: font; src: url("//"); }',
|
1723
|
+
function( node, rule ) {
|
1724
|
+
var style = $.qsa( 'style', node )[0]
|
1725
|
+
var sheet = style.sheet || style.styleSheet
|
1726
|
+
var cssText = sheet ?
|
1727
|
+
( sheet.cssRules && sheet.cssRules[0] ?
|
1728
|
+
sheet.cssRules[0].cssText : sheet.cssText || ''
|
1729
|
+
) : ''
|
1730
|
+
|
1731
|
+
ret = /src/i.test( cssText ) &&
|
1732
|
+
cssText.indexOf( rule.split(' ')[0] ) === 0
|
1733
|
+
}
|
1734
|
+
)
|
1735
|
+
|
1736
|
+
return ret
|
1737
|
+
})(),
|
1738
|
+
|
1540
1739
|
ruby: (function() {
|
1541
1740
|
var ruby = $.create( 'ruby' )
|
1542
1741
|
var rt = $.create( 'rt' )
|
@@ -1550,8 +1749,7 @@ Locale.support = (function() {
|
|
1550
1749
|
// Browsers that support ruby hide the `<rp>` via `display: none`
|
1551
1750
|
ret = (
|
1552
1751
|
getStyle( rp, 'display' ) === 'none' ||
|
1553
|
-
// but in IE, `<rp>` has `display: inline
|
1554
|
-
// so, the test needs other conditions:
|
1752
|
+
// but in IE, `<rp>` has `display: inline`, so the test needs other conditions:
|
1555
1753
|
getStyle( ruby, 'display' ) === 'ruby' &&
|
1556
1754
|
getStyle( rt, 'display' ) === 'ruby-text'
|
1557
1755
|
) ? true : false
|
@@ -1565,27 +1763,25 @@ Locale.support = (function() {
|
|
1565
1763
|
return ret
|
1566
1764
|
})(),
|
1567
1765
|
|
1568
|
-
|
1569
|
-
var
|
1766
|
+
'ruby-display': (function() {
|
1767
|
+
var div = $.create( 'div' )
|
1570
1768
|
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
var style = $.qsa( 'style', node )[0]
|
1575
|
-
var sheet = style.sheet || style.styleSheet
|
1576
|
-
var cssText = sheet ?
|
1577
|
-
( sheet.cssRules && sheet.cssRules[0] ?
|
1578
|
-
sheet.cssRules[0].cssText : sheet.cssText || ''
|
1579
|
-
) : ''
|
1769
|
+
div.innerHTML = '<h-test-a style="display: ruby;"></h-test-a><h-test-b style="display: ruby-text-container;"></h-test-b>'
|
1770
|
+
return div.querySelector( 'h-test-a' ).style.display === 'ruby' && div.querySelector( 'h-test-b' ).style.display === 'ruby-text-container'
|
1771
|
+
})(),
|
1580
1772
|
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1773
|
+
'ruby-interchar': (function() {
|
1774
|
+
var IC = 'inter-character'
|
1775
|
+
var div = $.create( 'div' )
|
1776
|
+
var css
|
1585
1777
|
|
1586
|
-
|
1778
|
+
div.innerHTML = '<h-test style="-moz-ruby-position:' + IC + ';-ms-ruby-position:' + IC + ';-webkit-ruby-position:' + IC + ';ruby-position:' + IC + ';"></h-test>'
|
1779
|
+
css = div.querySelector( 'h-test' ).style
|
1780
|
+
return css.rubyPosition === IC || css.WebkitRubyPosition === IC || css.MozRubyPosition === IC || css.msRubyPosition === IC
|
1587
1781
|
})(),
|
1588
1782
|
|
1783
|
+
textemphasis: testCSSProp( 'textEmphasis' ),
|
1784
|
+
|
1589
1785
|
// Address feature support test for `unicode-range` via
|
1590
1786
|
// detecting whether it's Arial (supported) or
|
1591
1787
|
// Times New Roman (not supported).
|
@@ -1605,19 +1801,10 @@ Locale.support = (function() {
|
|
1605
1801
|
return ret
|
1606
1802
|
})(),
|
1607
1803
|
|
1608
|
-
columnwidth: testCSSProp( 'columnWidth' ),
|
1609
|
-
|
1610
|
-
textemphasis: testCSSProp( 'textEmphasis' ),
|
1611
|
-
|
1612
1804
|
writingmode: testCSSProp( 'writingMode' )
|
1613
1805
|
}
|
1614
1806
|
})()
|
1615
1807
|
|
1616
|
-
var UA = window.navigator.userAgent || null
|
1617
|
-
var isIE = /Trident/i.test( UA )
|
1618
|
-
|
1619
|
-
Locale.support['pseudo-element-clipboard'] = isIE ? true : false
|
1620
|
-
|
1621
1808
|
Locale.initCond = function( target ) {
|
1622
1809
|
var target = target || root
|
1623
1810
|
var ret = ''
|
@@ -1632,6 +1819,195 @@ Locale.initCond = function( target ) {
|
|
1632
1819
|
return ret
|
1633
1820
|
}
|
1634
1821
|
|
1822
|
+
var SUPPORT_IC = Locale.support[ 'ruby-interchar' ]
|
1823
|
+
|
1824
|
+
// 1. Simple ruby polyfill;
|
1825
|
+
// 2. Inter-character polyfill for Zhuyin
|
1826
|
+
function renderSimpleRuby( $ruby ) {
|
1827
|
+
var frag = $.create( '!' )
|
1828
|
+
var clazz = $ruby.classList
|
1829
|
+
var $rb, $ru
|
1830
|
+
|
1831
|
+
frag.appendChild( $.clone( $ruby ))
|
1832
|
+
|
1833
|
+
$
|
1834
|
+
.tag( 'rt', frag.firstChild )
|
1835
|
+
.forEach(function( $rt ) {
|
1836
|
+
var $rb = $.create( '!' )
|
1837
|
+
var airb = []
|
1838
|
+
var irb
|
1839
|
+
|
1840
|
+
// Consider the previous nodes the implied
|
1841
|
+
// ruby base
|
1842
|
+
do {
|
1843
|
+
irb = ( irb || $rt ).previousSibling
|
1844
|
+
if ( !irb || irb.nodeName.match( /((?:h\-)?r[ubt])/i )) break
|
1845
|
+
|
1846
|
+
$rb.insertBefore( $.clone( irb ), $rb.firstChild )
|
1847
|
+
airb.push( irb )
|
1848
|
+
} while ( !irb.nodeName.match( /((?:h\-)?r[ubt])/i ))
|
1849
|
+
|
1850
|
+
// Create a real `<h-ru>` to append.
|
1851
|
+
$ru = clazz.contains( 'zhuyin' ) ? createZhuyinRu( $rb, $rt ) : createNormalRu( $rb, $rt )
|
1852
|
+
|
1853
|
+
// Replace the ruby text with the new `<h-ru>`,
|
1854
|
+
// and remove the original implied ruby base(s)
|
1855
|
+
try {
|
1856
|
+
$rt.parentNode.replaceChild( $ru, $rt )
|
1857
|
+
airb.map( $.remove )
|
1858
|
+
} catch ( e ) {}
|
1859
|
+
})
|
1860
|
+
return createCustomRuby( frag )
|
1861
|
+
}
|
1862
|
+
|
1863
|
+
function renderInterCharRuby( $ruby ) {
|
1864
|
+
var frag = $.create( '!' )
|
1865
|
+
frag.appendChild( $.clone( $ruby ))
|
1866
|
+
|
1867
|
+
$
|
1868
|
+
.tag( 'rt', frag.firstChild )
|
1869
|
+
.forEach(function( $rt ) {
|
1870
|
+
var $rb = $.create( '!' )
|
1871
|
+
var airb = []
|
1872
|
+
var irb, $zhuyin
|
1873
|
+
|
1874
|
+
// Consider the previous nodes the implied
|
1875
|
+
// ruby base
|
1876
|
+
do {
|
1877
|
+
irb = ( irb || $rt ).previousSibling
|
1878
|
+
if ( !irb || irb.nodeName.match( /((?:h\-)?r[ubt])/i )) break
|
1879
|
+
|
1880
|
+
$rb.insertBefore( $.clone( irb ), $rb.firstChild )
|
1881
|
+
airb.push( irb )
|
1882
|
+
} while ( !irb.nodeName.match( /((?:h\-)?r[ubt])/i ))
|
1883
|
+
|
1884
|
+
$zhuyin = $.create( 'rt' )
|
1885
|
+
$zhuyin.innerHTML = getZhuyinHTML( $rt )
|
1886
|
+
$rt.parentNode.replaceChild( $zhuyin, $rt )
|
1887
|
+
})
|
1888
|
+
return frag.firstChild
|
1889
|
+
}
|
1890
|
+
|
1891
|
+
// 3. Complex ruby polyfill
|
1892
|
+
// - Double-lined annotation;
|
1893
|
+
// - Right-angled annotation.
|
1894
|
+
function renderComplexRuby( $ruby ) {
|
1895
|
+
var frag = $.create( '!' )
|
1896
|
+
var clazz = $ruby.classList
|
1897
|
+
var $cloned, $rb, $ru, maxspan
|
1898
|
+
|
1899
|
+
frag.appendChild( $.clone( $ruby ))
|
1900
|
+
$cloned = frag.firstChild
|
1901
|
+
|
1902
|
+
$rb = $ru = $.tag( 'rb', $cloned )
|
1903
|
+
maxspan = $rb.length
|
1904
|
+
|
1905
|
+
// First of all, deal with Zhuyin containers
|
1906
|
+
// individually
|
1907
|
+
//
|
1908
|
+
// Note that we only support one single Zhuyin
|
1909
|
+
// container in each complex ruby
|
1910
|
+
void function( $rtc ) {
|
1911
|
+
if ( !$rtc ) return
|
1912
|
+
|
1913
|
+
$ru = $
|
1914
|
+
.tag( 'rt', $rtc )
|
1915
|
+
.map(function( $rt, i ) {
|
1916
|
+
if ( !$rb[ i ] ) return
|
1917
|
+
var ret = createZhuyinRu( $rb[ i ], $rt )
|
1918
|
+
|
1919
|
+
try {
|
1920
|
+
$rb[ i ].parentNode.replaceChild( ret, $rb[ i ] )
|
1921
|
+
} catch ( e ) {}
|
1922
|
+
return ret
|
1923
|
+
})
|
1924
|
+
|
1925
|
+
// Remove the container once it's useless
|
1926
|
+
$.remove( $rtc )
|
1927
|
+
$cloned.setAttribute( 'rightangle', 'true' )
|
1928
|
+
}( $cloned.querySelector( 'rtc.zhuyin' ))
|
1929
|
+
|
1930
|
+
// Then, normal annotations other than Zhuyin
|
1931
|
+
$
|
1932
|
+
.qsa( 'rtc:not(.zhuyin)', $cloned )
|
1933
|
+
.forEach(function( $rtc, order ) {
|
1934
|
+
var ret
|
1935
|
+
ret = $
|
1936
|
+
.tag( 'rt', $rtc )
|
1937
|
+
.map(function( $rt, i ) {
|
1938
|
+
var rbspan = Number( $rt.getAttribute( 'rbspan' ) || 1 )
|
1939
|
+
var span = 0
|
1940
|
+
var aRb = []
|
1941
|
+
var $rb, ret
|
1942
|
+
|
1943
|
+
if ( rbspan > maxspan ) rbspan = maxspan
|
1944
|
+
|
1945
|
+
do {
|
1946
|
+
try {
|
1947
|
+
$rb = $ru.shift()
|
1948
|
+
aRb.push( $rb )
|
1949
|
+
} catch (e) {}
|
1950
|
+
|
1951
|
+
if ( typeof $rb === 'undefined' ) break
|
1952
|
+
span += Number( $rb.getAttribute( 'span' ) || 1 )
|
1953
|
+
} while ( rbspan > span )
|
1954
|
+
|
1955
|
+
if ( rbspan < span ) {
|
1956
|
+
if ( aRb.length > 1 ) {
|
1957
|
+
console.error( 'An impossible `rbspan` value detected.', ruby )
|
1958
|
+
return
|
1959
|
+
}
|
1960
|
+
aRb = $.tag( 'rb', aRb[0] )
|
1961
|
+
$ru = aRb.slice( rbspan ).concat( $ru )
|
1962
|
+
aRb = aRb.slice( 0, rbspan )
|
1963
|
+
span = rbspan
|
1964
|
+
}
|
1965
|
+
|
1966
|
+
ret = createNormalRu( aRb, $rt, {
|
1967
|
+
'class': clazz,
|
1968
|
+
span: span,
|
1969
|
+
order: order
|
1970
|
+
})
|
1971
|
+
|
1972
|
+
try {
|
1973
|
+
aRb[0].parentNode.replaceChild( ret, aRb.shift() )
|
1974
|
+
aRb.map( $.remove )
|
1975
|
+
} catch (e) {}
|
1976
|
+
return ret
|
1977
|
+
})
|
1978
|
+
$ru = ret
|
1979
|
+
if ( order === 1 ) $cloned.setAttribute( 'doubleline', 'true' )
|
1980
|
+
|
1981
|
+
// Remove the container once it's useless
|
1982
|
+
$.remove( $rtc )
|
1983
|
+
})
|
1984
|
+
return createCustomRuby( frag )
|
1985
|
+
}
|
1986
|
+
|
1987
|
+
// Create a new fake `<h-ruby>` element so the
|
1988
|
+
// style sheets will render it as a polyfill,
|
1989
|
+
// which also helps to avoid the UA style.
|
1990
|
+
function createCustomRuby( frag ) {
|
1991
|
+
var $ruby = frag.firstChild
|
1992
|
+
var hruby = $.create( 'h-ruby' )
|
1993
|
+
|
1994
|
+
hruby.innerHTML = $ruby.innerHTML
|
1995
|
+
$.setAttr( hruby, $ruby.attributes )
|
1996
|
+
hruby.normalize()
|
1997
|
+
return hruby
|
1998
|
+
}
|
1999
|
+
|
2000
|
+
function simplifyRubyClass( elem ) {
|
2001
|
+
if ( !elem instanceof Element ) return elem
|
2002
|
+
var clazz = elem.classList
|
2003
|
+
|
2004
|
+
if ( clazz.contains( 'pinyin' )) clazz.add( 'romanization' )
|
2005
|
+
else if ( clazz.contains( 'romanization' )) clazz.add( 'annotation' )
|
2006
|
+
else if ( clazz.contains( 'mps' )) clazz.add( 'zhuyin' )
|
2007
|
+
else if ( clazz.contains( 'rightangle' )) clazz.add( 'complex' )
|
2008
|
+
return elem
|
2009
|
+
}
|
2010
|
+
|
1635
2011
|
/**
|
1636
2012
|
* Create and return a new `<h-ru>` element
|
1637
2013
|
* according to the given contents
|
@@ -1640,7 +2016,7 @@ function createNormalRu( $rb, $rt, attr ) {
|
|
1640
2016
|
var $ru = $.create( 'h-ru' )
|
1641
2017
|
var $rt = $.clone( $rt )
|
1642
2018
|
var attr = attr || {}
|
1643
|
-
attr.annotation =
|
2019
|
+
attr.annotation = 'true'
|
1644
2020
|
|
1645
2021
|
if ( Array.isArray( $rb )) {
|
1646
2022
|
$ru.innerHTML = $rb.map(function( rb ) {
|
@@ -1657,7 +2033,7 @@ function createNormalRu( $rb, $rt, attr ) {
|
|
1657
2033
|
}
|
1658
2034
|
|
1659
2035
|
/**
|
1660
|
-
* Create and return a new `<ru>` element
|
2036
|
+
* Create and return a new `<h-ru>` element
|
1661
2037
|
* in Zhuyin form
|
1662
2038
|
*/
|
1663
2039
|
function createZhuyinRu( $rb, $rt ) {
|
@@ -1665,15 +2041,31 @@ function createZhuyinRu( $rb, $rt ) {
|
|
1665
2041
|
|
1666
2042
|
// Create an element to return
|
1667
2043
|
var $ru = $.create( 'h-ru' )
|
2044
|
+
$ru.setAttribute( 'zhuyin', true )
|
1668
2045
|
|
2046
|
+
// - <h-ru zhuyin>
|
2047
|
+
// - <rb><rb/>
|
2048
|
+
// - <h-zhuyin>
|
2049
|
+
// - <h-yin></h-yin>
|
2050
|
+
// - <h-diao></h-diao>
|
2051
|
+
// - </h-zhuyin>
|
2052
|
+
// - </h-ru>
|
2053
|
+
$ru.appendChild( $rb )
|
2054
|
+
$ru.innerHTML += getZhuyinHTML( $rt )
|
2055
|
+
return $ru
|
2056
|
+
}
|
2057
|
+
|
2058
|
+
/**
|
2059
|
+
* Create a Zhuyin-form HTML string
|
2060
|
+
*/
|
2061
|
+
function getZhuyinHTML( rt ) {
|
1669
2062
|
// #### Explanation ####
|
1670
2063
|
// * `zhuyin`: the entire phonetic annotation
|
1671
2064
|
// * `yin`: the plain pronunciation (w/out tone)
|
1672
2065
|
// * `diao`: the tone
|
1673
|
-
// * `
|
1674
|
-
|
1675
|
-
var
|
1676
|
-
var yin, diao, form, len
|
2066
|
+
// * `len`: the length of the plain pronunciation (`yin`)
|
2067
|
+
var zhuyin = typeof rt === 'string' ? rt : rt.textContent
|
2068
|
+
var yin, diao, len
|
1677
2069
|
|
1678
2070
|
yin = zhuyin.replace( TYPESET.zhuyin.diao, '' )
|
1679
2071
|
len = yin ? yin.length : 0
|
@@ -1681,35 +2073,48 @@ function createZhuyinRu( $rb, $rt ) {
|
|
1681
2073
|
.replace( yin, '' )
|
1682
2074
|
.replace( /[\u02C5]/g, '\u02C7' )
|
1683
2075
|
.replace( /[\u030D]/g, '\u0358' )
|
1684
|
-
|
1685
|
-
form = zhuyin.replace( TYPESET.zhuyin.form, function( s, j, y ) {
|
1686
|
-
return [
|
1687
|
-
s ? 'S' : null,
|
1688
|
-
j ? 'J' : null,
|
1689
|
-
y ? 'Y' : null
|
1690
|
-
].join('')
|
1691
|
-
})
|
1692
|
-
// - <h-ru>
|
1693
|
-
// - <rb><rb/>
|
1694
|
-
// - <h-zhuyin>
|
1695
|
-
// - <h-yin></h-yin>
|
1696
|
-
// - <h-diao></h-diao>
|
1697
|
-
// - </h-zhuyin>
|
1698
|
-
// - </h-ru>
|
1699
|
-
$ru.appendChild( $rb )
|
1700
|
-
$ru.innerHTML += '<h-zhuyin><h-yin>' + yin + '</h-yin><h-diao>' + diao + '</h-diao></h-zhuyin>'
|
1701
|
-
|
1702
|
-
// Finally, set up the necessary attribute
|
1703
|
-
// and return the new `<ru>`
|
1704
|
-
$.setAttr( $ru, {
|
1705
|
-
zhuyin: '',
|
1706
|
-
diao: diao,
|
1707
|
-
length: len,
|
1708
|
-
form: form
|
1709
|
-
})
|
1710
|
-
return $ru
|
2076
|
+
return len === 0 ? '' : '<h-zhuyin length="' + len + '" diao="' + diao + '"><h-yin>' + yin + '</h-yin><h-diao>' + diao + '</h-diao></h-zhuyin>'
|
1711
2077
|
}
|
1712
2078
|
|
2079
|
+
/**
|
2080
|
+
* Normalize `ruby` elements
|
2081
|
+
*/
|
2082
|
+
$.extend( Locale, {
|
2083
|
+
|
2084
|
+
// Address normalisation for both simple and complex
|
2085
|
+
// rubies (interlinear annotations)
|
2086
|
+
renderRuby: function( context, target ) {
|
2087
|
+
var target = target || 'ruby'
|
2088
|
+
var $target = $.qsa( target, context )
|
2089
|
+
|
2090
|
+
$.qsa( 'rtc', context )
|
2091
|
+
.concat( $target ).map( simplifyRubyClass )
|
2092
|
+
|
2093
|
+
$target
|
2094
|
+
.forEach(function( $ruby ) {
|
2095
|
+
var clazz = $ruby.classList
|
2096
|
+
var $new
|
2097
|
+
|
2098
|
+
if ( clazz.contains( 'complex' )) $new = renderComplexRuby( $ruby )
|
2099
|
+
else if ( clazz.contains( 'zhuyin' )) $new = SUPPORT_IC ? renderInterCharRuby( $ruby ) : renderSimpleRuby( $ruby )
|
2100
|
+
|
2101
|
+
// Finally, replace it
|
2102
|
+
if ( $new ) $ruby.parentNode.replaceChild( $new, $ruby )
|
2103
|
+
})
|
2104
|
+
},
|
2105
|
+
|
2106
|
+
simplifyRubyClass: simplifyRubyClass,
|
2107
|
+
getZhuyinHTML: getZhuyinHTML,
|
2108
|
+
renderComplexRuby: renderComplexRuby,
|
2109
|
+
renderSimpleRuby: renderSimpleRuby,
|
2110
|
+
renderInterCharRuby: renderInterCharRuby
|
2111
|
+
|
2112
|
+
// ### TODO list ###
|
2113
|
+
//
|
2114
|
+
// * Debug mode
|
2115
|
+
// * Better error-tolerance
|
2116
|
+
})
|
2117
|
+
|
1713
2118
|
/**
|
1714
2119
|
* Normalisation rendering mechanism
|
1715
2120
|
*/
|
@@ -1761,221 +2166,26 @@ $.extend( Locale, {
|
|
1761
2166
|
.forEach(function( elem ) {
|
1762
2167
|
var $elem = Han( elem )
|
1763
2168
|
|
1764
|
-
if (
|
2169
|
+
if ( Locale.support.textemphasis ) {
|
2170
|
+
$elem
|
2171
|
+
.avoid( 'rt, h-char, h-char-group' )
|
2172
|
+
.charify({ biaodian: true, punct: true })
|
2173
|
+
} else {
|
1765
2174
|
$elem
|
2175
|
+
.avoid( 'rt, h-char, h-char-group' )
|
1766
2176
|
.jinzify()
|
1767
|
-
.groupify({ western: true })
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
} : {
|
1776
|
-
hanzi: true,
|
1777
|
-
biaodian: true,
|
1778
|
-
punct: true,
|
1779
|
-
latin: true,
|
1780
|
-
ellinika: true,
|
1781
|
-
kirillica: true
|
1782
|
-
})
|
1783
|
-
})
|
1784
|
-
},
|
1785
|
-
|
1786
|
-
// Address normalisation for both simple and complex
|
1787
|
-
// rubies
|
1788
|
-
renderRuby: function( context, target ) {
|
1789
|
-
var method = target ? 'qsa' : 'tag'
|
1790
|
-
var target = target || 'ruby'
|
1791
|
-
var $target = $[ method ]( target, context )
|
1792
|
-
var $simpClaElem = $.qsa( target + ', rtc', context )
|
1793
|
-
|
1794
|
-
// First of all, simplify semantic classes
|
1795
|
-
$simpClaElem
|
1796
|
-
.forEach(function( elem ) {
|
1797
|
-
var clazz = elem.classList
|
1798
|
-
|
1799
|
-
if ( clazz.contains( 'pinyin' )) {
|
1800
|
-
clazz.add( 'romanization' )
|
1801
|
-
} else if ( clazz.contains( 'mps' )) {
|
1802
|
-
clazz.add( 'zhuyin' )
|
1803
|
-
}
|
1804
|
-
|
1805
|
-
if ( clazz.contains( 'romanization' )) {
|
1806
|
-
clazz.add( 'annotation' )
|
1807
|
-
}
|
1808
|
-
})
|
1809
|
-
|
1810
|
-
// Deal with `<ruby>`
|
1811
|
-
$target
|
1812
|
-
.forEach(function( ruby ) {
|
1813
|
-
var clazz = ruby.classList
|
1814
|
-
|
1815
|
-
var condition = (
|
1816
|
-
!Locale.support.ruby ||
|
1817
|
-
clazz.contains( 'zhuyin') ||
|
1818
|
-
clazz.contains( 'complex' ) ||
|
1819
|
-
clazz.contains( 'rightangle' )
|
1820
|
-
)
|
1821
|
-
|
1822
|
-
var frag, $cloned, $rb, $ru, maxspan, hruby
|
1823
|
-
|
1824
|
-
if ( !condition ) return
|
1825
|
-
|
1826
|
-
// Apply document fragment here to avoid
|
1827
|
-
// continuously pointless re-paint
|
1828
|
-
frag = $.create( '!' )
|
1829
|
-
frag.appendChild( $.clone( ruby ))
|
1830
|
-
$cloned = $.qsa( target, frag )[0]
|
1831
|
-
|
1832
|
-
// 1. Simple ruby polyfill for, um, Firefox;
|
1833
|
-
// 2. Zhuyin polyfill for all browsers.
|
1834
|
-
if ( !Locale.support.ruby || clazz.contains( 'zhuyin' )) {
|
1835
|
-
|
1836
|
-
$
|
1837
|
-
.tag( 'rt', $cloned )
|
1838
|
-
.forEach(function( rt ) {
|
1839
|
-
var $rb = $.create( '!' )
|
1840
|
-
var airb = []
|
1841
|
-
var irb
|
1842
|
-
|
1843
|
-
// Consider the previous nodes the implied
|
1844
|
-
// ruby base
|
1845
|
-
do {
|
1846
|
-
irb = ( irb || rt ).previousSibling
|
1847
|
-
|
1848
|
-
if ( !irb || irb.nodeName.match( /(r\-?[ubt])/i )) break
|
1849
|
-
|
1850
|
-
$rb.insertBefore( $.clone( irb ), $rb.firstChild )
|
1851
|
-
airb.push( irb )
|
1852
|
-
} while ( !irb.nodeName.match( /(r\-?[ubt])/i ))
|
1853
|
-
// Create a real `<h-ru>` to append.
|
1854
|
-
$ru = clazz.contains( 'zhuyin' ) ?
|
1855
|
-
createZhuyinRu( $rb, rt ) : createNormalRu( $rb, rt )
|
1856
|
-
|
1857
|
-
// Replace the ruby text with the new `<h-ru>`,
|
1858
|
-
// and remove the original implied ruby base(s)
|
1859
|
-
try {
|
1860
|
-
rt.parentNode.replaceChild( $ru, rt )
|
1861
|
-
|
1862
|
-
airb
|
1863
|
-
.forEach(function( irb ) {
|
1864
|
-
$.remove( irb )
|
1865
|
-
})
|
1866
|
-
} catch ( e ) {}
|
2177
|
+
.groupify({ western: true, biaodian: true })
|
2178
|
+
.charify({
|
2179
|
+
hanzi: true,
|
2180
|
+
biaodian: true,
|
2181
|
+
punct: true,
|
2182
|
+
latin: true,
|
2183
|
+
ellinika: true,
|
2184
|
+
kirillica: true
|
1867
2185
|
})
|
1868
2186
|
}
|
1869
|
-
|
1870
|
-
// 3. Complex ruby polyfill
|
1871
|
-
// - Double-lined annotation;
|
1872
|
-
// - Right-angled annotation.
|
1873
|
-
if ( clazz.contains( 'complex' ) || clazz.contains( 'rightangle' )) {
|
1874
|
-
$rb = $ru = $.tag( 'rb', $cloned )
|
1875
|
-
maxspan = $rb.length
|
1876
|
-
|
1877
|
-
// First of all, deal with Zhuyin containers
|
1878
|
-
// individually
|
1879
|
-
//
|
1880
|
-
// Note that we only support one single Zhuyin
|
1881
|
-
// container in each complex ruby
|
1882
|
-
void function( rtc ) {
|
1883
|
-
if ( !rtc ) return
|
1884
|
-
|
1885
|
-
$ru = $
|
1886
|
-
.tag( 'rt', rtc )
|
1887
|
-
.map(function( rt, i ) {
|
1888
|
-
if ( !$rb[ i ] ) return
|
1889
|
-
var ret = createZhuyinRu( $rb[ i ], rt )
|
1890
|
-
|
1891
|
-
try {
|
1892
|
-
$rb[ i ].parentNode.replaceChild( ret, $rb[ i ] )
|
1893
|
-
} catch ( e ) {}
|
1894
|
-
return ret
|
1895
|
-
})
|
1896
|
-
|
1897
|
-
// Remove the container once it's useless
|
1898
|
-
$.remove( rtc )
|
1899
|
-
ruby.setAttribute( 'rightangle', '' )
|
1900
|
-
}( $cloned.querySelector( 'rtc.zhuyin' ))
|
1901
|
-
|
1902
|
-
// Then, normal annotations other than Zhuyin
|
1903
|
-
$
|
1904
|
-
.qsa( 'rtc:not(.zhuyin)', $cloned )
|
1905
|
-
.forEach(function( rtc, order ) {
|
1906
|
-
var ret
|
1907
|
-
ret = $
|
1908
|
-
.tag( 'rt', rtc )
|
1909
|
-
.map(function( rt, i ) {
|
1910
|
-
var rbspan = Number( rt.getAttribute( 'rbspan' ) || 1 )
|
1911
|
-
var span = 0
|
1912
|
-
var aRb = []
|
1913
|
-
var rb, ret
|
1914
|
-
|
1915
|
-
if ( rbspan > maxspan ) {
|
1916
|
-
rbspan = maxspan
|
1917
|
-
}
|
1918
|
-
|
1919
|
-
do {
|
1920
|
-
try {
|
1921
|
-
rb = $ru.shift()
|
1922
|
-
aRb.push( rb )
|
1923
|
-
} catch (e) {}
|
1924
|
-
|
1925
|
-
if ( typeof rb === 'undefined' ) break
|
1926
|
-
span += Number( rb.getAttribute( 'span' ) || 1 )
|
1927
|
-
} while ( rbspan > span )
|
1928
|
-
|
1929
|
-
if ( rbspan < span ) {
|
1930
|
-
if ( aRb.length > 1 ) {
|
1931
|
-
console.error( 'An impossible `rbspan` value detected.', ruby )
|
1932
|
-
return
|
1933
|
-
}
|
1934
|
-
aRb = $.tag( 'h-rb', aRb[0] )
|
1935
|
-
$ru = aRb.slice( rbspan ).concat( $ru )
|
1936
|
-
aRb = aRb.slice( 0, rbspan )
|
1937
|
-
span = rbspan
|
1938
|
-
}
|
1939
|
-
|
1940
|
-
ret = createNormalRu( aRb, rt, {
|
1941
|
-
'class': clazz,
|
1942
|
-
span: span,
|
1943
|
-
order: order
|
1944
|
-
})
|
1945
|
-
|
1946
|
-
try {
|
1947
|
-
aRb[0].parentNode.replaceChild( ret, aRb.shift())
|
1948
|
-
aRb.forEach(function( rb ) {
|
1949
|
-
$.remove( rb )
|
1950
|
-
})
|
1951
|
-
} catch (e) {}
|
1952
|
-
|
1953
|
-
return ret
|
1954
|
-
})
|
1955
|
-
$ru = ret
|
1956
|
-
// Remove the container once it's useless
|
1957
|
-
$.remove( rtc )
|
1958
|
-
})
|
1959
|
-
}
|
1960
|
-
// Create a new fake `<h-ruby>` element so the
|
1961
|
-
// style sheets will render it as a polyfill,
|
1962
|
-
// which also helps to avoid the UA style.
|
1963
|
-
hruby = $.create( 'h-ruby' )
|
1964
|
-
hruby.innerHTML = frag.firstChild.innerHTML
|
1965
|
-
|
1966
|
-
// Copy all attributes onto it
|
1967
|
-
$.setAttr( hruby, ruby.attributes )
|
1968
|
-
hruby.normalize()
|
1969
|
-
|
1970
|
-
// Finally, replace it
|
1971
|
-
ruby.parentNode.replaceChild( hruby, ruby )
|
1972
2187
|
})
|
1973
2188
|
}
|
1974
|
-
|
1975
|
-
// ### TODO list ###
|
1976
|
-
//
|
1977
|
-
// * Debug mode
|
1978
|
-
// * Better error-tolerance
|
1979
2189
|
})
|
1980
2190
|
|
1981
2191
|
Han.normalize = Locale
|
@@ -2049,9 +2259,9 @@ $.extend( Han, {
|
|
2049
2259
|
// Elements to be filtered according to the
|
2050
2260
|
// HWS rendering mode
|
2051
2261
|
if ( strict ) {
|
2052
|
-
finder.
|
2262
|
+
finder.avoid( 'textarea, code, kbd, samp, pre' )
|
2053
2263
|
} else {
|
2054
|
-
finder.
|
2264
|
+
finder.avoid( 'textarea' )
|
2055
2265
|
}
|
2056
2266
|
|
2057
2267
|
finder
|
@@ -2138,7 +2348,7 @@ $.extend( Han.fn, {
|
|
2138
2348
|
}
|
2139
2349
|
})
|
2140
2350
|
|
2141
|
-
|
2351
|
+
function detectSpaceFont() {
|
2142
2352
|
var div = $.create( 'div' )
|
2143
2353
|
var ret
|
2144
2354
|
|
@@ -2147,23 +2357,26 @@ Han.isSpaceFontLoaded = (function() {
|
|
2147
2357
|
ret = div.firstChild.offsetWidth !== div.lastChild.offsetWidth
|
2148
2358
|
$.remove( div, body )
|
2149
2359
|
return ret
|
2150
|
-
}
|
2360
|
+
}
|
2151
2361
|
|
2152
|
-
Han
|
2362
|
+
$.extend( Han, {
|
2363
|
+
detectSpaceFont: detectSpaceFont,
|
2364
|
+
isSpaceFontLoaded: detectSpaceFont()
|
2365
|
+
})
|
2366
|
+
|
2367
|
+
Han.support['han-space'] = detectSpaceFont()
|
2153
2368
|
|
2154
2369
|
Han.renderHanging = function( context ) {
|
2155
2370
|
var context = context || document
|
2156
2371
|
var finder = Han.find( context )
|
2157
2372
|
|
2158
2373
|
finder
|
2159
|
-
.
|
2374
|
+
.avoid( 'textarea, code, kbd, samp, pre, h-hangable' )
|
2160
2375
|
.replace(
|
2161
2376
|
TYPESET.jinze.hanging,
|
2162
2377
|
function( portion, match ) {
|
2163
2378
|
var elem = $.create( 'h-hangable' )
|
2164
|
-
|
2165
|
-
|
2166
|
-
elem.innerHTML = match[2] + '<h-cs biaodian="' + match[3] + '"><h-inner hidden> </h-inner></h-cs><h-char class="biaodian cjk end" unicode="' + unicode + '">' + match[3] + '</h-char>'
|
2379
|
+
elem.innerHTML = match[1] + '<h-cs><h-inner hidden> </h-inner><h-char class="biaodian bd-close bd-end cjk">' + match[2] + '</h-char></h-cs>'
|
2167
2380
|
return portion.index === 0 ? elem : ''
|
2168
2381
|
}
|
2169
2382
|
)
|
@@ -2175,6 +2388,14 @@ $.extend( Han.fn, {
|
|
2175
2388
|
hanging: null,
|
2176
2389
|
|
2177
2390
|
renderHanging: function() {
|
2391
|
+
var condClazz = this.condition.classList
|
2392
|
+
var isSpaceFontLoaded = detectSpaceFont()
|
2393
|
+
|
2394
|
+
if ( isSpaceFontLoaded && condClazz.contains( 'no-han-space' )) {
|
2395
|
+
condClazz.remove( 'no-han-space' )
|
2396
|
+
condClazz.add( 'han-space' )
|
2397
|
+
}
|
2398
|
+
|
2178
2399
|
this.hanging = Han.renderHanging( this.context )
|
2179
2400
|
return this
|
2180
2401
|
},
|
@@ -2192,18 +2413,34 @@ Han.renderJiya = function( context ) {
|
|
2192
2413
|
var finder = Han.find( context )
|
2193
2414
|
|
2194
2415
|
finder
|
2195
|
-
.
|
2416
|
+
.avoid( 'textarea, code, kbd, samp, pre, h-char-group' )
|
2417
|
+
.replace(
|
2418
|
+
// This is a safeguard against hanging rendering
|
2419
|
+
new RegExp( '(' + UNICODE.biaodian.end + '+)(' + UNICODE.biaodian.open + '+)', 'g' ),
|
2420
|
+
function( portion, match ) {
|
2421
|
+
if ( portion.index === 0 ) return portion.isEnd ? match[0] : match[1]
|
2422
|
+
|
2423
|
+
var elem = $.create( 'h-char-group', 'biaodian cjk portion' )
|
2424
|
+
elem.innerHTML = match[2]
|
2425
|
+
return elem
|
2426
|
+
}
|
2427
|
+
)
|
2428
|
+
.endAvoid()
|
2429
|
+
|
2430
|
+
finder
|
2431
|
+
.avoid( 'textarea, code, kbd, samp, pre, h-char' )
|
2196
2432
|
.groupify({ biaodian: true })
|
2197
2433
|
.charify({ biaodian: true })
|
2198
2434
|
|
2199
2435
|
// The reason we're doing this instead of using pseudo elements in CSS
|
2200
2436
|
// is because WebKit has problem rendering pseudo elements containing only
|
2201
2437
|
// space.
|
2202
|
-
$.qsa( 'h-char.biaodian.open, h-char.biaodian.end', context )
|
2438
|
+
$.qsa( 'h-char.biaodian.bd-open, h-char.biaodian.bd-end', context )
|
2203
2439
|
.forEach(function( elem ) {
|
2440
|
+
if ( Han.find.matches( elem, 'h-cs *' )) return
|
2204
2441
|
var html = '<h-inner>' + elem.innerHTML + '</h-inner>'
|
2205
2442
|
var hcs = '<h-cs hidden> </h-cs>'
|
2206
|
-
var isOpen = elem.classList.contains( 'open' )
|
2443
|
+
var isOpen = elem.classList.contains( 'bd-open' )
|
2207
2444
|
elem.innerHTML = isOpen ? hcs + html : html + hcs
|
2208
2445
|
})
|
2209
2446
|
|
@@ -2228,11 +2465,11 @@ $.extend( Han.fn, {
|
|
2228
2465
|
|
2229
2466
|
var mdot
|
2230
2467
|
|
2231
|
-
mdot = $.create( 'h-char', 'biaodian cjk middle' )
|
2468
|
+
mdot = $.create( 'h-char', 'biaodian cjk bd-middle' )
|
2232
2469
|
mdot.setAttribute( 'unicode', 'b7' )
|
2233
2470
|
|
2234
2471
|
Han.correctBasicBD = function( context, all ) {
|
2235
|
-
if ( Han.support.unicoderange && !all )
|
2472
|
+
if ( Han.support.unicoderange && !all ) return
|
2236
2473
|
|
2237
2474
|
var context = context || document
|
2238
2475
|
var finder
|
@@ -2260,33 +2497,35 @@ $.extend( Han.fn, {
|
|
2260
2497
|
}
|
2261
2498
|
})
|
2262
2499
|
|
2263
|
-
var QUERY_RU_W_ANNO
|
2500
|
+
var QUERY_RU_W_ANNO = 'h-ru[annotation]'
|
2264
2501
|
var SELECTOR_TO_IGNORE = 'textarea, code, kbd, samp, pre'
|
2265
2502
|
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
2269
|
-
|
2270
|
-
|
2271
|
-
}
|
2272
|
-
|
2273
|
-
var aCombLiga = Han.TYPESET[ 'display-as' ][ 'comb-liga-pua' ]
|
2274
|
-
var aInaccurateChar = Han.TYPESET[ 'inaccurate-char' ]
|
2503
|
+
function createCompareFactory( font, treat, control ) {
|
2504
|
+
return function() {
|
2505
|
+
var a = Han.localize.writeOnCanvas( treat, font )
|
2506
|
+
var b = Han.localize.writeOnCanvas( control, font )
|
2507
|
+
return Han.localize.compareCanvases( a, b )
|
2508
|
+
}
|
2509
|
+
}
|
2275
2510
|
|
2276
|
-
|
2511
|
+
function isVowelCombLigaNormal() {
|
2512
|
+
return createCompareFactory( '"Romanization Sans"', '\u0061\u030D', '\uDB80\uDC61' )
|
2513
|
+
}
|
2277
2514
|
|
2278
|
-
|
2279
|
-
|
2515
|
+
function isVowelICombLigaNormal() {
|
2516
|
+
return createCompareFactory( '"Romanization Sans"', '\u0069\u030D', '\uDB80\uDC69' )
|
2517
|
+
}
|
2280
2518
|
|
2281
|
-
|
2282
|
-
|
2519
|
+
function isZhuyinCombLigaNormal() {
|
2520
|
+
return createCompareFactory( '"Zhuyin Kaiti"', '\u31B4\u0358', '\uDB8C\uDDB4' )
|
2521
|
+
}
|
2283
2522
|
|
2523
|
+
function createSubstFactory( regexToSubst ) {
|
2524
|
+
return function( context ) {
|
2284
2525
|
var context = context || document
|
2285
|
-
var finder
|
2286
|
-
|
2287
|
-
finder.filterOut( SELECTOR_TO_IGNORE, true )
|
2526
|
+
var finder = Han.find( context ).avoid( SELECTOR_TO_IGNORE )
|
2288
2527
|
|
2289
|
-
|
2528
|
+
regexToSubst
|
2290
2529
|
.forEach(function( pattern ) {
|
2291
2530
|
finder
|
2292
2531
|
.replace(
|
@@ -2302,31 +2541,30 @@ $.extend( Han, {
|
|
2302
2541
|
}
|
2303
2542
|
)
|
2304
2543
|
})
|
2305
|
-
|
2306
|
-
$
|
2307
|
-
.qsa( QUERY_RU_W_ANNO, context )
|
2308
|
-
.forEach(function( ru ) {
|
2309
|
-
var annotation = ru.getAttribute( 'annotation' )
|
2310
|
-
|
2311
|
-
aCombLiga
|
2312
|
-
// Latin vowels only
|
2313
|
-
.slice( 0, 5 )
|
2314
|
-
.forEach(function( pattern ) {
|
2315
|
-
annotation = annotation.replace(
|
2316
|
-
new RegExp( pattern[ 0 ], 'ig' ), pattern[ 1 ]
|
2317
|
-
)
|
2318
|
-
})
|
2319
|
-
ru.setAttribute( 'annotation', annotation )
|
2320
|
-
})
|
2321
2544
|
return finder
|
2322
|
-
}
|
2545
|
+
}
|
2546
|
+
}
|
2547
|
+
|
2548
|
+
var charCombLiga = $.create( 'h-char', 'comb-liga' )
|
2549
|
+
|
2550
|
+
$.extend( Han, {
|
2551
|
+
isVowelCombLigaNormal: isVowelCombLigaNormal(),
|
2552
|
+
isVowelICombLigaNormal: isVowelICombLigaNormal(),
|
2553
|
+
isZhuyinCombLigaNormal: isZhuyinCombLigaNormal(),
|
2554
|
+
|
2555
|
+
isCombLigaNormal: isVowelICombLigaNormal()(), // ### Deprecated
|
2556
|
+
|
2557
|
+
substVowelCombLiga: createSubstFactory( Han.TYPESET[ 'display-as' ][ 'comb-liga-vowel' ] ),
|
2558
|
+
substZhuyinCombLiga: createSubstFactory( Han.TYPESET[ 'display-as' ][ 'comb-liga-zhuyin' ] ),
|
2559
|
+
substCombLigaWithPUA: createSubstFactory( Han.TYPESET[ 'display-as' ][ 'comb-liga-pua' ] ),
|
2323
2560
|
|
2324
2561
|
substInaccurateChar: function( context ) {
|
2325
2562
|
var context = context || document
|
2326
2563
|
var finder = Han.find( context )
|
2327
2564
|
|
2328
|
-
finder.
|
2329
|
-
|
2565
|
+
finder.avoid( SELECTOR_TO_IGNORE )
|
2566
|
+
|
2567
|
+
Han.TYPESET[ 'inaccurate-char' ]
|
2330
2568
|
.forEach(function( pattern ) {
|
2331
2569
|
finder
|
2332
2570
|
.replace(
|
@@ -2338,17 +2576,65 @@ $.extend( Han, {
|
|
2338
2576
|
})
|
2339
2577
|
|
2340
2578
|
$.extend( Han.fn, {
|
2341
|
-
'comb-liga':
|
2342
|
-
'
|
2579
|
+
'comb-liga-vowel': null,
|
2580
|
+
'comb-liga-vowel-i': null,
|
2581
|
+
'comb-liga-zhuyin': null,
|
2582
|
+
'inaccurate-char': null,
|
2583
|
+
|
2584
|
+
substVowelCombLiga: function() {
|
2585
|
+
this['comb-liga-vowel'] = Han.substVowelCombLiga( this.context )
|
2586
|
+
return this
|
2587
|
+
},
|
2588
|
+
|
2589
|
+
substVowelICombLiga: function() {
|
2590
|
+
this['comb-liga-vowel-i'] = Han.substVowelICombLiga( this.context )
|
2591
|
+
return this
|
2592
|
+
},
|
2593
|
+
|
2594
|
+
substZhuyinCombLiga: function() {
|
2595
|
+
this['comb-liga-zhuyin'] = Han.substZhuyinCombLiga( this.context )
|
2596
|
+
return this
|
2597
|
+
},
|
2343
2598
|
|
2344
2599
|
substCombLigaWithPUA: function() {
|
2345
|
-
|
2600
|
+
if ( !Han.isVowelCombLigaNormal()) {
|
2601
|
+
this['comb-liga-vowel'] = Han.substVowelCombLiga( this.context )
|
2602
|
+
} else if ( !Han.isVowelICombLigaNormal()) {
|
2603
|
+
this['comb-liga-vowel-i'] = Han.substVowelICombLiga( this.context )
|
2604
|
+
}
|
2605
|
+
|
2606
|
+
if ( !Han.isZhuyinCombLigaNormal()) {
|
2607
|
+
this['comb-liga-zhuyin'] = Han.substZhuyinCombLiga( this.context )
|
2608
|
+
}
|
2609
|
+
return this
|
2610
|
+
},
|
2611
|
+
|
2612
|
+
revertVowelCombLiga: function() {
|
2613
|
+
try {
|
2614
|
+
this['comb-liga-vowel'].revert( 'all' )
|
2615
|
+
} catch (e) {}
|
2616
|
+
return this
|
2617
|
+
},
|
2618
|
+
|
2619
|
+
revertVowelICombLiga: function() {
|
2620
|
+
try {
|
2621
|
+
this['comb-liga-vowel-i'].revert( 'all' )
|
2622
|
+
} catch (e) {}
|
2623
|
+
return this
|
2624
|
+
},
|
2625
|
+
|
2626
|
+
revertZhuyinCombLiga: function() {
|
2627
|
+
try {
|
2628
|
+
this['comb-liga-zhuyin'].revert( 'all' )
|
2629
|
+
} catch (e) {}
|
2346
2630
|
return this
|
2347
2631
|
},
|
2348
2632
|
|
2349
2633
|
revertCombLigaWithPUA: function() {
|
2350
2634
|
try {
|
2351
|
-
this['comb-liga'].revert( 'all' )
|
2635
|
+
this['comb-liga-vowel'].revert( 'all' )
|
2636
|
+
this['comb-liga-vowel-i'].revert( 'all' )
|
2637
|
+
this['comb-liga-zhuyin'].revert( 'all' )
|
2352
2638
|
} catch (e) {}
|
2353
2639
|
return this
|
2354
2640
|
},
|
@@ -2382,12 +2668,8 @@ window.addEventListener( 'DOMContentLoaded', function() {
|
|
2382
2668
|
}
|
2383
2669
|
})
|
2384
2670
|
|
2385
|
-
// AMD
|
2386
|
-
if ( typeof define === 'function' && define.amd ) {
|
2387
|
-
define(function() { return Han })
|
2388
|
-
|
2389
2671
|
// Expose to global namespace
|
2390
|
-
|
2672
|
+
if ( typeof noGlobalNS === 'undefined' || noGlobalNS === false ) {
|
2391
2673
|
window.Han = Han
|
2392
2674
|
}
|
2393
2675
|
|