hanzi-rails 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|