diff --git a/2015/05/02/2015-05-02-singleton/index.html b/2015/05/02/2015-05-02-singleton/index.html deleted file mode 100644 index f22ae8a..0000000 --- a/2015/05/02/2015-05-02-singleton/index.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - 单例模式的ARC和MRC实现 | CoderShmily's Blog - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
- -
- - -
- - -

- 单例模式的ARC和MRC实现 -

- - -
- -
- -

单例在整个工程中,就相当于一个全局变量,就是不论在哪里需要用到这个类的实例变量,都可以通过单例方法来取得,而且一旦你创建了一个单例类,不论你在多少个界面中初始化调用了这个单例方法取得对象,它们所有的对象都是指向的同一块内存存储空间(即单例类保证了该类的实力对象是唯一存在的一个).

- -

单例模式的作用

    -
  1. 可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问
  2. -
  3. 从而方便地控制了实例个数,并节约系统资源
  4. -
-
    -
  • ARC中,单例模式的实现
  • -
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 提供1个类方法让外界访问唯一的实例
+ (instancetype)sharedTools
{
return [[self alloc] init];
}
// 在.m中保留一个全局的static的实例
static Tools *_instance;
// 重写allocWithZone:方法,在这里创建唯一的实例
// 注意线程安全,判断是否为nil,可能多次创建
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
// 实现copyWithZone:方法
- (id)copyWithZone:(struct _NSZone *)zone
{
// 因为copy方法必须通过实例对象调用,所以可以直接返回_instance
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
-
    -
  • MRC中,单例模式的实现
  • -
-除了添加上面ARC实现的代码,再添加下面代码 - -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#pragma mark - MRC
#if __has_feature(objc_arc)
// 如果是ARC什么都不添加
#else
- (oneway void)release
{
}
- (instancetype)retain
{
return _instance;
}
- (NSUInteger)retainCount
{
return MAXFLOAT; //装逼格
}
#endif
-单例不能继承,类的静态变量只被初始化一次,子类和父类谁先调用,创建的就是哪种类型的变量,以后也不会改变 - - -

创建很多单例

    -
  • 利用宏定义
  • -
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//
// Single.h
// 01-掌握-单例ARC
//
// Created by apple on 15/8/6.
// Copyright (c) 2015年 CoderShmily. All rights reserved.
//
#define interfaceSingle(name) + (instancetype)share##name
#if __has_feature(objc_arc)
// 如果是ARC
#define implementationSingle(name) + (instancetype)share##name \
{ \
return [[self alloc] init]; \
} \
static id _instance; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
}
#else
// 如果不是ARC
#define implementationSingle(name) + (instancetype)share##name \
{ \
return [[self alloc] init]; \
} \
static id _instance; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
}\
- (oneway void)release \
{} \
- (instancetype)retain \
{ \
return _instance; \
} \
- (NSUInteger)retainCount \
{ \
return MAXFLOAT; \
}
#endif
-
    -
  • 使用宏定义
  • -
-
1
2
3
4
5
6
7
8
9
// FileTools.h
#import <Foundation/Foundation.h>
#import "Single.h"
@interface FileTools : NSObject
//+ (instancetype)shareFileTools;
interfaceSingle(FileTools);
@end
-
1
2
3
4
5
6
7
8
9
// FileTools.m
#import "FileTools.h"
@implementation FileTools
implementationSingle(FileTools)
@end
- - -
- -
- - - - - -
- -
- - - -
-
- -
- -
-
-
- - - - - - - - - - - - -
- - \ No newline at end of file diff --git a/2015/05/04/2015-05-04-runtime-dui-xiang-mo-xing/index.html b/2015/05/04/2015-05-04-runtime-dui-xiang-mo-xing/index.html deleted file mode 100644 index 959af91..0000000 --- a/2015/05/04/2015-05-04-runtime-dui-xiang-mo-xing/index.html +++ /dev/null @@ -1,280 +0,0 @@ - - - - - - Objective-C Runtime(二) 对象模型 | CoderShmily's Blog - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
- -
- - -
- - -

- Objective-C Runtime(二) 对象模型 -

- - -
- -
- -

Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一个方法的实现等。

-

这种特性意味着Objective-C不仅需要一个编译器,还需要一个运行时系统来执行编译的代码。对于Objective-C来说,这个运行时系统就像一个操作系统一样:它让所有的工作可以正常的运行。这个运行时系统即Objc Runtime。Objc Runtime其实是一个Runtime库,它基本上是用C和汇编写的,这个库使得C语言有了面向对象的能力。

- -

Runtime库主要做下面几件事:

-

1.封装:在这个库中,对象可以用C语言中的结构体表示,而方法可以用C函数来实现,另外再加上了一些额外的特性。这些结构体和函数被runtime函数封装后,我们就可以在程序运行时创建,检查,修改类、对象和它们的方法了。

-

2.找出方法的最终执行代码:当程序执行[object doSomething]时,会向消息接收者(object)发送一条消息(doSomething),runtime会根据消息接收者是否能响应该消息而做出不同的反应。这将在后面详细介绍。

-

在这一系列文章中,我们将介绍runtime的基本工作原理,以及如何利用它让我们的程序变得更加灵活。在本文中,我们先来介绍一下类与对象,这是面向对象的基础,我们看看在Runtime中,类是如何实现的。

-
-

类与对象基础数据结构

Class

-

Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针。它的定义如下:

1
typedef struct objc_class *Class;

-

查看objc/runtime.h中objc_class结构体的定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE; // 父类
const char *name OBJC2_UNAVAILABLE; // 类名
long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
#endif
} OBJC2_UNAVAILABLE;

-

在这个定义中,下面几个字段是我们感兴趣的

-

1.isa:需要注意的是在Objective-C中,所有的类自身也是一个对象,这个对象的Class里面也有一个isa指针,它指向metaClass(元类),我们会在后面介绍它。

-

2.super_class:指向该类的父类,如果该类已经是最顶层的根类(如NSObject或NSProxy),则super_class为NULL。

-

3.cache:用于缓存最近使用的方法。一个接收者对象接收到一个消息时,它会根据isa指针去查找能够响应这个消息的对象。在实际使用中,这个对象只有一部分方法是常用的,很多方法其实很少用或者根本用不上。这种情况下,如果每次消息来时,我们都是methodLists中遍历一遍,性能势必很差。这时,cache就派上用场了。在我们每次调用过一个方法后,这个方法就会被缓存到cache列表中,下次调用的时候runtime就会优先去cache中查找,如果cache没有,才去methodLists中查找方法。这样,对于那些经常用到的方法的调用,但提高了调用的效率。

-

4.version:我们可以使用这个字段来提供类的版本信息。这对于对象的序列化非常有用,它可是让我们识别出不同类定义版本中实例变量布局的改变。

-

针对cache,我们用下面例子来说明其执行过程:

1
NSArray *array = [[NSArray alloc] init];

-

其流程是:

-

1.[NSArray alloc]先被执行。因为NSArray没有+alloc方法,于是去父类NSObject去查找。

-

2.检测NSObject是否响应+alloc方法,发现响应,于是检测NSArray类,并根据其所需的内存空间大小开始分配内存空间,然后把isa指针指向NSArray类。同时,+alloc也被加进cache列表里面。

-

3.接着,执行-init方法,如果NSArray响应该方法,则直接将其加入cache;如果不响应,则去父类查找。

-

4.在后期的操作中,如果再以[[NSArray alloc] init]这种方式来创建数组,则会直接从cache中取出相应的方法,直接调用。

-
-

###objc_object与id

-

objc_object是表示一个类的实例的结构体,它的定义如下(objc/objc.h):

1
2
3
4
5
6
7
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;

-

可以看到,这个结构体只有一个字体,即指向其类的isa指针。这样,当我们向一个Objective-C对象发送消息时,运行时库会根据实例对象的isa指针找到这个实例对象所属的类。Runtime库会在类的方法列表及父类的方法列表中去寻找与消息对应的selector指向的方法。找到后即运行这个方法。

-

当创建一个特定类的实例对象时,分配的内存包含一个objc_object数据结构,然后是类的实例变量的数据。NSObject类的alloc和allocWithZone:方法使用函数class_createInstance来创建objc_object数据结构。

-

另外还有我们常见的id,它是一个objc_object结构类型的指针。它的存在可以让我们实现类似于C++中泛型的一些操作。该类型的对象可以转换为任何一种对象,有点类似于C语言中void *指针类型的作用。

-
-

###objc_cache

-

上面提到了objc_class结构体中的cache字段,它用于缓存调用过的方法。这个字段是一个指向objc_cache结构体的指针,其定义如下:

1
2
3
4
5
6
7
8
9
struct objc_cache {
unsigned int mask /* total = mask + 1 */ OBJC2_UNAVAILABLE;
unsigned int occupied OBJC2_UNAVAILABLE;
Method buckets[1] OBJC2_UNAVAILABLE;
};

-

该结构体的字段描述如下:

-

1.mask:一个整数,指定分配的缓存bucket的总数。在方法查找过程中,Objective-C runtime使用这个字段来确定开始线性查找数组的索引位置。指向方法selector的指针与该字段做一个AND位操作(index = (mask & selector))。这可以作为一个简单的hash散列算法。

-

2.occupied:一个整数,指定实际占用的缓存bucket的总数。

-

3.buckets:指向Method数据结构指针的数组。这个数组可能包含不超过mask+1个元素。需要注意的是,指针可能是NULL,表示这个缓存bucket没有被占用,另外被占用的bucket可能是不连续的。这个数组可能会随着时间而增长。

-

###元类(Meta Class)

-

在上面我们提到,所有的类自身也是一个对象,我们可以向这个对象发送消息(即调用类方法)。如:

1
NSArray *array = [NSArray array];

-

这个例子中,+array消息发送给了NSArray类,而这个NSArray也是一个对象。既然是对象,那么它也是一个objc_object指针,它包含一个指向其类的一个isa指针。那么这些就有一个问题了,这个isa指针指向什么呢?为了调用+array方法,这个类的isa指针必须指向一个包含这些类方法的一个objc_class结构体。这就引出了meta-class的概念

1
meta-class是一个类对象的类。

-

当我们向一个对象发送消息时,runtime会在这个对象所属的这个类的方法列表中查找方法;而向一个类发送消息时,会在这个类的meta-class的方法列表中查找。

-

meta-class之所以重要,是因为它存储着一个类的所有类方法。每个类都会有一个单独的meta-class,因为每个类的类方法基本不可能完全相同。

-

再深入一下,meta-class也是一个类,也可以向它发送一个消息,那么它的isa又是指向什么呢?为了不让这种结构无限延伸下去,Objective-C的设计者让所有的meta-class的isa指向基类的meta-class,以此作为它们的所属类。即,任何NSObject继承体系下的meta-class都使用NSObject的meta-class作为自己的所属类,而基类的meta-class的isa指针是指向它自己。这样就形成了一个完美的闭环。

-

通过上面的描述,再加上对objc_class结构体中super_class指针的分析,我们就可以描绘出类及相应meta-class类的一个继承体系了,

-
    -
  1. 类C的类对象(class object)的super_class都指向了类C父类的类对象(class object), NSObject的类对像的super_class指向0x0

    -
  2. -
  3. 类C的类对象(class object)的isa指针都指向他的元类对象(metaclass object)

    -
  4. -
  5. 类C的元类对象(metaclass object)的super_class指针指向父类的元类对象(metaclass object), 例外:NSObject的元类对象(metaclass object)的super_class指向NSObject的类对象(class object).

    -
  6. -
  7. 类C的元类对象(metaclass object)的isa指针指都指向NSObject的元类对象(metaclass object)

    -
  8. -
-

NSObject的实例对象(虽然它没有实例变量和实例方法但这个对象仍然存在)其super_class指向地址0x0,因为NSObject没有父类, 这满足上面的结论1。

-

NSObject的实例对象的isa指向了NSObject的元类对象(metaclass object),这满足上面结论2。

-

NSObject的元类对象(metaclass object)指向了自己,这也满足上面结论4。

- - -
- -
- - - - - -
- -
- - - -
-
- -
- -
-
-
- - - - - - - - - - - - -
- - \ No newline at end of file diff --git a/2015/05/05/2015-05-05-runtime-gai-shu/index.html "b/2015/05/05/Objective-C Runtime(\344\270\200) \346\246\202\350\277\260/index.html" similarity index 67% rename from 2015/05/05/2015-05-05-runtime-gai-shu/index.html rename to "2015/05/05/Objective-C Runtime(\344\270\200) \346\246\202\350\277\260/index.html" index c7f5893..9d06d4b 100644 --- a/2015/05/05/2015-05-05-runtime-gai-shu/index.html +++ "b/2015/05/05/Objective-C Runtime(\344\270\200) \346\246\202\350\277\260/index.html" @@ -1,97 +1,396 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + - Objective-C Runtime(一) 概述 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + Objective-C Runtime(一) 概述 | CoderShmily's Blog + + + + - - - - - + + + + + + + + + + + + + + - - + - +
+
- -
-
- + +
+
+
+
+ + +
-
- + + + + -

- Objective-C Runtime(一) 概述 -

+ + +
- + + + + + +
+ + + + +
- - +
+ - + + + -
+
+ +
+
+ + +
+ + +
+ +
- -
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - - - -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/2015/05/06/2015-05-06-objective-c-runtime-san-xiao-xi-chuan-di/index.html b/2015/05/06/2015-05-06-objective-c-runtime-san-xiao-xi-chuan-di/index.html deleted file mode 100644 index d3e3619..0000000 --- a/2015/05/06/2015-05-06-objective-c-runtime-san-xiao-xi-chuan-di/index.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - Objective-C Runtime(三) 消息传递 | CoderShmily's Blog - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
- -
- - -
- - -

- Objective-C Runtime(三) 消息传递 -

- - -
- -
- -

Objective-C Runtime的消息传递

-

###Objective-C – 消息传递
Objective-C 扩展了 C 语言,并加入了面向对象特性和 Smalltalk 式的消息传递机制。而这个扩展的核心是一个用 C 和 编译语言 写的 Runtime 库。它是 Objective-C 面向对象和动态机制的基石.

-

Objective-C 是一个动态语言,这意味着它不仅需要一个编译器,也需要一个运行时系统来动态得创建类和对象、进行消息传递和转发。理解 Objective-C 的 Runtime 机制可以帮我们更好的了解这个语言,适当的时候还能对语言进行扩展,从系统层面解决项目中的一些设计或技术问题。了解 Runtime ,要先了解它的核心 - 消息传递(Messaging)。

-
-

消息传递

在很多语言,比如 C ,调用一个方法其实就是跳到内存中的某一点并开始执行一段代码。没有任何动态的特性,因为这在编译时就决定好了。而在 Objective-C 中,[object foo] 语法并不会立即执行 foo 这个方法的代码。它是在运行时给 object 发送一条叫 foo 的消息。这个消息,也许会由 object 来处理,也许会被转发给另一个对象,或者不予理睬假装没收到这个消息。多条不同的消息也可以对应同一个方法实现。这些都是在程序运行的时候决定的。

-

事实上,在编译时你写的 Objective-C 函数调用的语法都会被翻译成一个 C 的函数调用- objc_msgSend() 。比如,下面两行代码就是等价的:

-
1
2
3
[array insertObject:foo atIndex:5];
objc_msgSend(array, @selector(insertObject:atIndex:), foo, 5);
-

消息传递的关键藏于 objc_object 中的 isa 指针和 objc_class 中的 class dispatch table。

-

objc_object, objc_class以及Ojbc_method

在 Objective-C 中,类、对象和方法都是一个 C 的结构体,从 objc/objc.h 头文件中,我们可以找到他们的定义:

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
**struct objc_method_list **methodLists**;
**struct objc_cache *cache**;
struct objc_protocol_list *protocols;
#endif
};
struct objc_method_list {
struct objc_method_list *obsolete;
int method_count;
#ifdef __LP64__
int space;
#endif
/* variable length structure */
struct objc_method method_list[1];
};
struct objc_method {
SEL method_name;
char *method_types; /* a string representing argument/return types */
IMP method_imp;
};
-

objc_method_list 本质是一个有 objc_method 元素的可变长度的数组。一个 objc_method 结构体中有函数名,也就是SEL,有表示函数类型的字符串 (见 Type Encoding) ,以及函数的实现IMP。

-

从这些定义中可以看出发送一条消息也就 objc_msgSend 做了什么事。举 objc_msgSend(obj, foo) 这个例子来说:

-

1.首先,通过 obj 的 isa 指针找到它的 class ;

-

2.在 class 的 method list 找 foo ;

-

3.如果 class 中没到 foo,继续往它的 superclass 中找 ;

-

4.一旦找到 foo 这个函数,就去执行它的实现IMP .

-

但这种实现有个问题,效率低。但一个 class 往往只有 20% 的函数会被经常调用,可能占总调用次数的 80% 。每个消息都需要遍历一次 objc_method_list 并不合理。如果把经常被调用的函数缓存下来,那可以大大提高函数查询的效率。这也就是 objc_class 中另一个重要成员 objc_cache 做的事情 - 再找到 foo 之后,把 foo 的 method_name 作为 key ,method_imp 作为 value 给存起来。当再次收到 foo 消息的时候,可以直接在 cache 里找到,避免去遍历 objc_method_list.

-
-

动态方法解析和转发

在上面的例子中,如果 foo 没有找到会发生什么?通常情况下,程序会在运行时挂掉并抛出 unrecognized selector sent to …的异常。但在异常抛出前,Objective-C 的运行时会给你三次拯救程序的机会:

-
    -
  • Method resolution
  • -
  • Fast forwarding
  • -
  • Normal forwarding
  • -
-

###Method Resolution

-

首先,Objective-C 运行时会调用+resolveInstanceMethod: 或者 +resolveClassMethod:,让你有机会提供一个函数实现。如果你添加了函数并返回 YES, 那运行时系统就会重新启动一次消息发送的过程。还是以 foo 为例,你可以这么实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
void fooMethod(id obj, SEL _cmd)
{
NSLog(@"Doing foo");
}
+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
if(aSEL == @selector(foo:)){
class_addMethod([self class], aSEL, (IMP)fooMethod, "v@:");
return YES;
}
return [super resolveInstanceMethod];
}

-

Core Data 有用到这个方法。NSManagedObjects 中 properties 的 getter 和 setter 就是在运行时动态添加的。

-

如果 resolve 方法返回 NO ,运行时就会移到下一步:消息转发(Message Forwarding)

-

上面的例子可以重写成:

1
2
3
4
5
IMP fooIMP = imp_implementationWithBlock(^(id _self) {
NSLog(@"Doing foo");
});
class_addMethod([self class], aSEL, fooIMP, "v@:");

-

Fast forwarding

如果目标对象实现了 -forwardingTargetForSelector: ,Runtime 这时就会调用这个方法,给你把这个消息转发给其他对象的机会。

1
2
3
4
5
6
7
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if(aSelector == @selector(foo:)){
return alternateObject;
}
return [super forwardingTargetForSelector:aSelector];
}

-

只要这个方法返回的不是 nil 和 self,整个消息发送的过程就会被重启,当然发送的对象会变成你返回的那个对象。否则,就会继续 Normal Fowarding 。

-

这里叫 Fast ,只是为了区别下一步的转发机制。因为这一步不会创建任何新的对象,但下一步转发会创建一个 NSInvocation 对象,所以相对更快点。

-

###Normal forwarding
这一步是 Runtime 最后一次给你挽救的机会。首先它会发送 -methodSignatureForSelector:消息获得函数的参数和返回值类型。如果 -methodSignatureForSelector:返回 nil ,Runtime 则会发出 -doesNotRecognizeSelector: 消息,程序这时也就挂掉了。如果返回了一个函数签名,Runtime 就会创建一个 NSInvocation 对象并发送 -forwardInvocation:消息给目标对象。

-

NSInvocation 实际上就是对一个消息的描述,包括selector 以及参数等信息。所以你可以在-forwardInvocation:里修改传进来的 NSInvocation 对象,然后发送-invokeWithTarget: 消息给它,传进去一个新的目标:

1
2
3
4
5
6
7
8
9
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature)
signature = [alternateObject methodSignatureForSelector:selector];
return signature;
}

-
1
2
3
4
5
6
7
8
9
10
11
- (void)forwardInvocation:(NSInvocation *)invocation
{
SEL sel = invocation.selector;
if([alternateObject respondsToSelector:sel]) {
[invocation invokeWithTarget:alternateObject];
}
else {
[self doesNotRecognizeSelector:sel];
}
}
-

Cocoa 里很多地方都利用到了消息传递机制来对语言进行扩展,如 Proxies、NSUndoManager 跟 Responder Chain。NSProxy 就是专门用来作为代理转发消息的;NSUndoManager 截取一个消息之后再发送;而 Responder Chain 保证一个消息转发给合适的响应者。

-
-

##总结
Objective-C 中给一个对象发送消息会经过以下几个步骤:

-

1.在对象类的 dispatch table 中尝试找到该消息。如果找到了,跳到相应的函数IMP去执行实现代码;

-

2.如果没有找到,Runtime 会发送 +resolveInstanceMethod:或者 +resolveClassMethod:尝试去 resolve 这个消息;

-

3.如果 resolve 方法返回 NO,Runtime 就发送-forwardingTargetForSelector: 允许你把这个消息转发给另一个对象;

-

4.如果没有新的目标对象返回, Runtime 就会发送-methodSignatureForSelector:-forwardInvocation:消息。你可以发送 -invokeWithTarget: 消息来手动转发消息或者发送-doesNotRecognizeSelector:抛出异常。

-

利用 Objective-C 的 runtime特性,我们可以自己来对语言进行扩展,解决项目开发中的一些设计和技术问题。下一篇文章,我会介绍 Method Swizzling 技术以及如何利用 Method Swizzling 做 Logging。

- - -
- -
- - - - - -
- -
- - - -
-
- -
- -
-
-
- - - - - - - - - - - - -
- - \ No newline at end of file diff --git "a/2015/05/06/Objective-C Runtime(\344\272\214) \345\257\271\350\261\241\346\250\241\345\236\213/index.html" "b/2015/05/06/Objective-C Runtime(\344\272\214) \345\257\271\350\261\241\346\250\241\345\236\213/index.html" new file mode 100644 index 0000000..9e6cf46 --- /dev/null +++ "b/2015/05/06/Objective-C Runtime(\344\272\214) \345\257\271\350\261\241\346\250\241\345\236\213/index.html" @@ -0,0 +1,875 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Objective-C Runtime(二) 对象模型 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
+
+
+ + +
+ + + + + + + + +
+ + + + + + + +
+ + + +

Objective-C Runtime(二) 对象模型

+ + + +
+ + +
+ + + + + +

Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一个方法的实现等。

+

这种特性意味着Objective-C不仅需要一个编译器,还需要一个运行时系统来执行编译的代码。对于Objective-C来说,这个运行时系统就像一个操作系统一样:它让所有的工作可以正常的运行。这个运行时系统即Objc Runtime。Objc Runtime其实是一个Runtime库,它基本上是用C和汇编写的,这个库使得C语言有了面向对象的能力。

+ +

Runtime库主要做下面几件事:

+

1.封装:在这个库中,对象可以用C语言中的结构体表示,而方法可以用C函数来实现,另外再加上了一些额外的特性。这些结构体和函数被runtime函数封装后,我们就可以在程序运行时创建,检查,修改类、对象和它们的方法了。

+

2.找出方法的最终执行代码:当程序执行[object doSomething]时,会向消息接收者(object)发送一条消息(doSomething),runtime会根据消息接收者是否能响应该消息而做出不同的反应。这将在后面详细介绍。

+

在这一系列文章中,我们将介绍runtime的基本工作原理,以及如何利用它让我们的程序变得更加灵活。在本文中,我们先来介绍一下类与对象,这是面向对象的基础,我们看看在Runtime中,类是如何实现的。

+
+

类与对象基础数据结构

Class

+

Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针。它的定义如下:

+
1
typedef struct objc_class *Class;
+

查看objc/runtime.h中objc_class结构体的定义如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE; // 父类
const char *name OBJC2_UNAVAILABLE; // 类名
long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
#endif
} OBJC2_UNAVAILABLE;
+

在这个定义中,下面几个字段是我们感兴趣的

+

1.isa:需要注意的是在Objective-C中,所有的类自身也是一个对象,这个对象的Class里面也有一个isa指针,它指向metaClass(元类),我们会在后面介绍它。

+

2.super_class:指向该类的父类,如果该类已经是最顶层的根类(如NSObject或NSProxy),则super_class为NULL。

+

3.cache:用于缓存最近使用的方法。一个接收者对象接收到一个消息时,它会根据isa指针去查找能够响应这个消息的对象。在实际使用中,这个对象只有一部分方法是常用的,很多方法其实很少用或者根本用不上。这种情况下,如果每次消息来时,我们都是methodLists中遍历一遍,性能势必很差。这时,cache就派上用场了。在我们每次调用过一个方法后,这个方法就会被缓存到cache列表中,下次调用的时候runtime就会优先去cache中查找,如果cache没有,才去methodLists中查找方法。这样,对于那些经常用到的方法的调用,但提高了调用的效率。

+

4.version:我们可以使用这个字段来提供类的版本信息。这对于对象的序列化非常有用,它可是让我们识别出不同类定义版本中实例变量布局的改变。

+

针对cache,我们用下面例子来说明其执行过程:

+
1
NSArray *array = [[NSArray alloc] init];
+

其流程是:

+

1.[NSArray alloc]先被执行。因为NSArray没有+alloc方法,于是去父类NSObject去查找。

+

2.检测NSObject是否响应+alloc方法,发现响应,于是检测NSArray类,并根据其所需的内存空间大小开始分配内存空间,然后把isa指针指向NSArray类。同时,+alloc也被加进cache列表里面。

+

3.接着,执行-init方法,如果NSArray响应该方法,则直接将其加入cache;如果不响应,则去父类查找。

+

4.在后期的操作中,如果再以[[NSArray alloc] init]这种方式来创建数组,则会直接从cache中取出相应的方法,直接调用。

+
+

objc_object与id

objc_object是表示一个类的实例的结构体,它的定义如下(objc/objc.h):

+
1
2
3
4
5
6
7
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;
+

可以看到,这个结构体只有一个字体,即指向其类的isa指针。这样,当我们向一个Objective-C对象发送消息时,运行时库会根据实例对象的isa指针找到这个实例对象所属的类。Runtime库会在类的方法列表及父类的方法列表中去寻找与消息对应的selector指向的方法。找到后即运行这个方法。

+

当创建一个特定类的实例对象时,分配的内存包含一个objc_object数据结构,然后是类的实例变量的数据。NSObject类的alloc和allocWithZone:方法使用函数class_createInstance来创建objc_object数据结构。

+

另外还有我们常见的id,它是一个objc_object结构类型的指针。它的存在可以让我们实现类似于C++中泛型的一些操作。该类型的对象可以转换为任何一种对象,有点类似于C语言中void *指针类型的作用。

+
+

objc_cache

上面提到了objc_class结构体中的cache字段,它用于缓存调用过的方法。这个字段是一个指向objc_cache结构体的指针,其定义如下:

+
1
2
3
4
5
6
7
8
9
struct objc_cache {
unsigned int mask /* total = mask + 1 */ OBJC2_UNAVAILABLE;
unsigned int occupied OBJC2_UNAVAILABLE;
Method buckets[1] OBJC2_UNAVAILABLE;
};
+

该结构体的字段描述如下:

+

1.mask:一个整数,指定分配的缓存bucket的总数。在方法查找过程中,Objective-C runtime使用这个字段来确定开始线性查找数组的索引位置。指向方法selector的指针与该字段做一个AND位操作(index = (mask & selector))。这可以作为一个简单的hash散列算法。

+

2.occupied:一个整数,指定实际占用的缓存bucket的总数。

+

3.buckets:指向Method数据结构指针的数组。这个数组可能包含不超过mask+1个元素。需要注意的是,指针可能是NULL,表示这个缓存bucket没有被占用,另外被占用的bucket可能是不连续的。这个数组可能会随着时间而增长。

+

元类(Meta Class)

在上面我们提到,所有的类自身也是一个对象,我们可以向这个对象发送消息(即调用类方法)。如:

+
1
NSArray *array = [NSArray array];
+

这个例子中,+array消息发送给了NSArray类,而这个NSArray也是一个对象。既然是对象,那么它也是一个objc_object指针,它包含一个指向其类的一个isa指针。那么这些就有一个问题了,这个isa指针指向什么呢?为了调用+array方法,这个类的isa指针必须指向一个包含这些类方法的一个objc_class结构体。这就引出了meta-class的概念

+
1
meta-class是一个类对象的类。
+

当我们向一个对象发送消息时,runtime会在这个对象所属的这个类的方法列表中查找方法;而向一个类发送消息时,会在这个类的meta-class的方法列表中查找。

+

meta-class之所以重要,是因为它存储着一个类的所有类方法。每个类都会有一个单独的meta-class,因为每个类的类方法基本不可能完全相同。

+

再深入一下,meta-class也是一个类,也可以向它发送一个消息,那么它的isa又是指向什么呢?为了不让这种结构无限延伸下去,Objective-C的设计者让所有的meta-class的isa指向基类的meta-class,以此作为它们的所属类。即,任何NSObject继承体系下的meta-class都使用NSObject的meta-class作为自己的所属类,而基类的meta-class的isa指针是指向它自己。这样就形成了一个完美的闭环。

+

通过上面的描述,再加上对objc_class结构体中super_class指针的分析,我们就可以描绘出类及相应meta-class类的一个继承体系了,

+
    +
  1. 类C的类对象(class object)的super_class都指向了类C父类的类对象(class object), NSObject的类对像的super_class指向0x0

    +
  2. +
  3. 类C的类对象(class object)的isa指针都指向他的元类对象(metaclass object)

    +
  4. +
  5. 类C的元类对象(metaclass object)的super_class指针指向父类的元类对象(metaclass object), 例外:NSObject的元类对象(metaclass object)的super_class指向NSObject的类对象(class object).

    +
  6. +
  7. 类C的元类对象(metaclass object)的isa指针指都指向NSObject的元类对象(metaclass object)

    +
  8. +
+

NSObject的实例对象(虽然它没有实例变量和实例方法但这个对象仍然存在)其super_class指向地址0x0,因为NSObject没有父类, 这满足上面的结论1。

+

NSObject的实例对象的isa指向了NSObject的元类对象(metaclass object),这满足上面结论2。

+

NSObject的元类对象(metaclass object)指向了自己,这也满足上面结论4。

+ + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ + +
+ + + +
+ + + + + +
+
+ + +
+ + + + +
+ +
+ +
+ +
+ + +
+ + + + + + + + + +
+
+ + + + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/2015/05/07/Objective-C Runtime(\344\270\211) \346\266\210\346\201\257\344\274\240\351\200\222/index.html" "b/2015/05/07/Objective-C Runtime(\344\270\211) \346\266\210\346\201\257\344\274\240\351\200\222/index.html" new file mode 100644 index 0000000..10a1f0a --- /dev/null +++ "b/2015/05/07/Objective-C Runtime(\344\270\211) \346\266\210\346\201\257\344\274\240\351\200\222/index.html" @@ -0,0 +1,859 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Objective-C Runtime(三) 消息传递 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
+
+
+ + +
+ + + + + + + + +
+ + + + + + + +
+ + + +

Objective-C Runtime(三) 消息传递

+ + + +
+ + +
+ + + + + +

Objective-C Runtime的消息传递

+

Objective-C – 消息传递

Objective-C 扩展了 C 语言,并加入了面向对象特性和 Smalltalk 式的消息传递机制。而这个扩展的核心是一个用 C 和 编译语言 写的 Runtime 库。它是 Objective-C 面向对象和动态机制的基石.

+

Objective-C 是一个动态语言,这意味着它不仅需要一个编译器,也需要一个运行时系统来动态得创建类和对象、进行消息传递和转发。理解 Objective-C 的 Runtime 机制可以帮我们更好的了解这个语言,适当的时候还能对语言进行扩展,从系统层面解决项目中的一些设计或技术问题。了解 Runtime ,要先了解它的核心 - 消息传递(Messaging)。

+
+

消息传递

在很多语言,比如 C ,调用一个方法其实就是跳到内存中的某一点并开始执行一段代码。没有任何动态的特性,因为这在编译时就决定好了。而在 Objective-C 中,[object foo] 语法并不会立即执行 foo 这个方法的代码。它是在运行时给 object 发送一条叫 foo 的消息。这个消息,也许会由 object 来处理,也许会被转发给另一个对象,或者不予理睬假装没收到这个消息。多条不同的消息也可以对应同一个方法实现。这些都是在程序运行的时候决定的。

+

事实上,在编译时你写的 Objective-C 函数调用的语法都会被翻译成一个 C 的函数调用- objc_msgSend() 。比如,下面两行代码就是等价的:

+
1
2
3
[array insertObject:foo atIndex:5];
objc_msgSend(array, @selector(insertObject:atIndex:), foo, 5);
+

消息传递的关键藏于 objc_object 中的 isa 指针和 objc_class 中的 class dispatch table。

+

objc_object, objc_class以及Ojbc_method

在 Objective-C 中,类、对象和方法都是一个 C 的结构体,从 objc/objc.h 头文件中,我们可以找到他们的定义:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
**struct objc_method_list **methodLists**;
**struct objc_cache *cache**;
struct objc_protocol_list *protocols;
#endif
};
struct objc_method_list {
struct objc_method_list *obsolete;
int method_count;
#ifdef __LP64__
int space;
#endif
/* variable length structure */
struct objc_method method_list[1];
};
struct objc_method {
SEL method_name;
char *method_types; /* a string representing argument/return types */
IMP method_imp;
};
+

objc_method_list 本质是一个有 objc_method 元素的可变长度的数组。一个 objc_method 结构体中有函数名,也就是SEL,有表示函数类型的字符串 (见 Type Encoding) ,以及函数的实现IMP。

+

从这些定义中可以看出发送一条消息也就 objc_msgSend 做了什么事。举 objc_msgSend(obj, foo) 这个例子来说:

+

1.首先,通过 obj 的 isa 指针找到它的 class ;

+

2.在 class 的 method list 找 foo ;

+

3.如果 class 中没到 foo,继续往它的 superclass 中找 ;

+

4.一旦找到 foo 这个函数,就去执行它的实现IMP .

+

但这种实现有个问题,效率低。但一个 class 往往只有 20% 的函数会被经常调用,可能占总调用次数的 80% 。每个消息都需要遍历一次 objc_method_list 并不合理。如果把经常被调用的函数缓存下来,那可以大大提高函数查询的效率。这也就是 objc_class 中另一个重要成员 objc_cache 做的事情 - 再找到 foo 之后,把 foo 的 method_name 作为 key ,method_imp 作为 value 给存起来。当再次收到 foo 消息的时候,可以直接在 cache 里找到,避免去遍历 objc_method_list.

+
+

动态方法解析和转发

在上面的例子中,如果 foo 没有找到会发生什么?通常情况下,程序会在运行时挂掉并抛出 unrecognized selector sent to …的异常。但在异常抛出前,Objective-C 的运行时会给你三次拯救程序的机会:

+
    +
  • Method resolution
  • +
  • Fast forwarding
  • +
  • Normal forwarding
  • +
+

Method Resolution

首先,Objective-C 运行时会调用+resolveInstanceMethod: 或者 +resolveClassMethod:,让你有机会提供一个函数实现。如果你添加了函数并返回 YES, 那运行时系统就会重新启动一次消息发送的过程。还是以 foo 为例,你可以这么实现:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
void fooMethod(id obj, SEL _cmd)
{
NSLog(@"Doing foo");
}
+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
if(aSEL == @selector(foo:)){
class_addMethod([self class], aSEL, (IMP)fooMethod, "v@:");
return YES;
}
return [super resolveInstanceMethod];
}
+

Core Data 有用到这个方法。NSManagedObjects 中 properties 的 getter 和 setter 就是在运行时动态添加的。

+

如果 resolve 方法返回 NO ,运行时就会移到下一步:消息转发(Message Forwarding)

+

上面的例子可以重写成:

+
1
2
3
4
5
IMP fooIMP = imp_implementationWithBlock(^(id _self) {
NSLog(@"Doing foo");
});
class_addMethod([self class], aSEL, fooIMP, "v@:");
+

Fast forwarding

如果目标对象实现了 -forwardingTargetForSelector: ,Runtime 这时就会调用这个方法,给你把这个消息转发给其他对象的机会。

+
1
2
3
4
5
6
7
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if(aSelector == @selector(foo:)){
return alternateObject;
}
return [super forwardingTargetForSelector:aSelector];
}
+

只要这个方法返回的不是 nil 和 self,整个消息发送的过程就会被重启,当然发送的对象会变成你返回的那个对象。否则,就会继续 Normal Fowarding 。

+

这里叫 Fast ,只是为了区别下一步的转发机制。因为这一步不会创建任何新的对象,但下一步转发会创建一个 NSInvocation 对象,所以相对更快点。

+

Normal forwarding

这一步是 Runtime 最后一次给你挽救的机会。首先它会发送 -methodSignatureForSelector:消息获得函数的参数和返回值类型。如果 -methodSignatureForSelector:返回 nil ,Runtime 则会发出 -doesNotRecognizeSelector: 消息,程序这时也就挂掉了。如果返回了一个函数签名,Runtime 就会创建一个 NSInvocation 对象并发送 -forwardInvocation:消息给目标对象。

+

NSInvocation 实际上就是对一个消息的描述,包括selector 以及参数等信息。所以你可以在-forwardInvocation:里修改传进来的 NSInvocation 对象,然后发送-invokeWithTarget: 消息给它,传进去一个新的目标:

+
1
2
3
4
5
6
7
8
9
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature)
signature = [alternateObject methodSignatureForSelector:selector];
return signature;
}
+
1
2
3
4
5
6
7
8
9
10
11
- (void)forwardInvocation:(NSInvocation *)invocation
{
SEL sel = invocation.selector;
if([alternateObject respondsToSelector:sel]) {
[invocation invokeWithTarget:alternateObject];
}
else {
[self doesNotRecognizeSelector:sel];
}
}
+

Cocoa 里很多地方都利用到了消息传递机制来对语言进行扩展,如 Proxies、NSUndoManager 跟 Responder Chain。NSProxy 就是专门用来作为代理转发消息的;NSUndoManager 截取一个消息之后再发送;而 Responder Chain 保证一个消息转发给合适的响应者。

+
+

总结

Objective-C 中给一个对象发送消息会经过以下几个步骤:

+

1.在对象类的 dispatch table 中尝试找到该消息。如果找到了,跳到相应的函数IMP去执行实现代码;

+

2.如果没有找到,Runtime 会发送 +resolveInstanceMethod:或者 +resolveClassMethod:尝试去 resolve 这个消息;

+

3.如果 resolve 方法返回 NO,Runtime 就发送-forwardingTargetForSelector: 允许你把这个消息转发给另一个对象;

+

4.如果没有新的目标对象返回, Runtime 就会发送-methodSignatureForSelector:-forwardInvocation:消息。你可以发送 -invokeWithTarget: 消息来手动转发消息或者发送-doesNotRecognizeSelector:抛出异常。

+

利用 Objective-C 的 runtime特性,我们可以自己来对语言进行扩展,解决项目开发中的一些设计和技术问题。下一篇文章,我会介绍 Method Swizzling 技术以及如何利用 Method Swizzling 做 Logging。

+ + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ + +
+ + + +
+ + + + + +
+
+ + +
+ + + + +
+ +
+ +
+ +
+ + +
+ + + + + + + + + +
+
+ + + + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2015/05/07/2015-05-07-objective-c-runtime-si-dong-tai-fang-fa-jue-yi-dynamic-method-resolution/index.html "b/2015/05/08/Objective-C Runtime(\345\233\233) \345\212\250\346\200\201\346\226\271\346\263\225\345\206\263\350\256\256/index.html" similarity index 70% rename from 2015/05/07/2015-05-07-objective-c-runtime-si-dong-tai-fang-fa-jue-yi-dynamic-method-resolution/index.html rename to "2015/05/08/Objective-C Runtime(\345\233\233) \345\212\250\346\200\201\346\226\271\346\263\225\345\206\263\350\256\256/index.html" index 7eaf212..c6f323d 100644 --- a/2015/05/07/2015-05-07-objective-c-runtime-si-dong-tai-fang-fa-jue-yi-dynamic-method-resolution/index.html +++ "b/2015/05/08/Objective-C Runtime(\345\233\233) \345\212\250\346\200\201\346\226\271\346\263\225\345\206\263\350\256\256/index.html" @@ -1,102 +1,425 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Objective-C Runtime(四) 动态方法决议 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - - - + + + + + + + + + + + + + + + Objective-C Runtime(四) 动态方法决议 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + - - + - +
+
- -
-
- + +
+
+
+
+ + +
-
- + + + + -

- Objective-C Runtime(四) 动态方法决议 -

+
+ + + + + + + +
+ + + +

Objective-C Runtime(四) 动态方法决议

+ + +
-
+ +
+ + + + -

Objective-C Runtime之动态方法决议

-
-

动态方法决议/动态方法解析(Dynamic Method Resolution)

-
+

动态方法决议/动态方法解析(Dynamic Method Resolution)

在声明property属性后,有2种实现选择

  • @synthesize
  • @@ -157,127 +480,419 @@

    总结 -
    - Share + +
    + + + + +
    + +
    + + + +
    + +
    -
    -

- - -
- - - - - Older -
Objective-C Runtime(三) 消息传递
-
- - + - -
+ +
+
+ + + +
+ + - +
+ + + +
+
+ + + + + + + + + +
+ -
+ - + + +
- +
+ +
-
-

归档

-
- - -
-

最新文章

-
-
    +
-
  • - Swift3.0学习笔记 + + + + +
  • + + - -
    -
    +
    + +
    +
    + + +
    + + +
    + +
    - -
    - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - - - -
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/2015/05/03/2015-05-03-kvc-he-kvoshen-ru/index.html "b/2015/05/10/KVC \345\222\214 KVO\346\267\261\345\205\245/index.html" similarity index 56% rename from 2015/05/03/2015-05-03-kvc-he-kvoshen-ru/index.html rename to "2015/05/10/KVC \345\222\214 KVO\346\267\261\345\205\245/index.html" index aabedc5..8510192 100644 --- a/2015/05/03/2015-05-03-kvc-he-kvoshen-ru/index.html +++ "b/2015/05/10/KVC \345\222\214 KVO\346\267\261\345\205\245/index.html" @@ -1,97 +1,396 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + - KVC 和 KVO深入 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + KVC 和 KVO深入 | CoderShmily's Blog + + + + - - - - - + + + + + + + + + + + + + + - - + - +
    +
    - -
    -
    - + +
    +
    +
    +
    + + +
    -
    - + + + + -

    - KVC 和 KVO深入 -

    + + +
    - + + + + + +
    + + + + +
    - - +
    + - + + +
    - +
    + +
    -
    -

    归档

    -
    - - - + + - -
    -
    +
    + +
    +
    + + +
    + + +
    + +
    - -
    - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - - - -
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git "a/2015/05/10/Objective-C Runtime(\344\272\224) \345\205\266\344\273\226\345\272\224\347\224\250/index.html" "b/2015/05/10/Objective-C Runtime(\344\272\224) \345\205\266\344\273\226\345\272\224\347\224\250/index.html" new file mode 100644 index 0000000..55d3b09 --- /dev/null +++ "b/2015/05/10/Objective-C Runtime(\344\272\224) \345\205\266\344\273\226\345\272\224\347\224\250/index.html" @@ -0,0 +1,866 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Objective-C Runtime(五) 其他应用 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    Objective-C Runtime(五) 其他应用

    + + + +
    + + +
    + + + + + +
      +
    • 动态添加方法
    • +
    • 给分类添加属性
    • +
    • 字典转模型
    • +
    + +

    1.动态添加方法

      +
    • 开发使用场景:如果一个类方法非常多,加载类到内存的时候也比较耗费资源,需要给每个方法生成映射表,可以使用动态给某个类,添加方法解决。
    • +
    • 经典面试题:有没有使用performSelector,其实主要想问你有没有动态添加过方法。
    • +
    • 简单使用
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    @implementation ViewController
    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    Person *p = [[Person alloc] init];
    // 默认person,没有实现eat方法,可以通过performSelector调用,但是会报错。
    // 动态添加方法就不会报错
    [p performSelector:@selector(eat)];
    }
    @end
    @implementation Person
    // void(*)()
    // 默认方法都有两个隐式参数,
    void eat(id self,SEL sel)
    {
    NSLog(@"%@ %@",self,NSStringFromSelector(sel));
    }
    // 当一个对象调用未实现的方法,会调用这个方法处理,并且会把对应的方法列表传过来.
    // 刚好可以用来判断,未实现的方法是不是我们想要动态添加的方法
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
    if (sel == @selector(eat)) {
    // 动态添加eat方法
    // 第一个参数:给哪个类添加方法
    // 第二个参数:添加方法的方法编号
    // 第三个参数:添加方法的函数实现(函数地址)
    // 第四个参数:函数的类型,(返回值+参数类型) v:void @:对象->self :表示SEL->_cmd
    class_addMethod(self, @selector(eat), eat, "v@:");
    }
    return [super resolveInstanceMethod:sel];
    }
    @end
    +

    2.给分类添加属性

      +
    • 原理:给一个类声明属性,其实本质就是给这个类添加关联,并不是直接把这个值的内存空间添加到类存空间。
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    @implementation ViewController
    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 给系统NSObject类动态添加属性name
    NSObject *objc = [[NSObject alloc] init];
    objc.name = @"hello";
    NSLog(@"%@",objc.name);
    }
    @end
    // 定义关联的key
    static const char *key = "name";
    @implementation NSObject (Property)
    - (NSString *)name
    {
    // 根据关联的key,获取关联的值。
    return objc_getAssociatedObject(self, key);
    }
    - (void)setName:(NSString *)name
    {
    // 第一个参数:给哪个对象添加关联
    // 第二个参数:关联的key,通过这个key获取
    // 第三个参数:关联的value
    // 第四个参数:关联的策略
    objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    @end
    +

    3.字典转模型

      +
    • 设计模型:字典转模型的第一步
        +
      • 模型属性,通常需要跟字典中的key一一对应
      • +
      • 问题:一个一个的生成模型属性,很慢?
      • +
      • 需求:能不能自动根据一个字典,生成对应的属性。
      • +
      • 解决:提供一个分类,专门根据字典生成对应的属性字符串。
      • +
      +
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    @implementation NSObject (Log)
    // 自动打印属性字符串
    + (void)resolveDict:(NSDictionary *)dict{
    // 拼接属性字符串代码
    NSMutableString *strM = [NSMutableString string];
    // 1.遍历字典,把字典中的所有key取出来,生成对应的属性代码
    [dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
    // 类型经常变,抽出来
    NSString *type;
    if ([obj isKindOfClass:NSClassFromString(@"__NSCFString")]) {
    type = @"NSString";
    }else if ([obj isKindOfClass:NSClassFromString(@"__NSCFArray")]){
    type = @"NSArray";
    }else if ([obj isKindOfClass:NSClassFromString(@"__NSCFNumber")]){
    type = @"int";
    }else if ([obj isKindOfClass:NSClassFromString(@"__NSCFDictionary")]){
    type = @"NSDictionary";
    }
    // 属性字符串
    NSString *str;
    if ([type containsString:@"NS"]) {
    str = [NSString stringWithFormat:@"@property (nonatomic, strong) %@ *%@;",type,key];
    }else{
    str = [NSString stringWithFormat:@"@property (nonatomic, assign) %@ %@;",type,key];
    }
    // 每生成属性字符串,就自动换行。
    [strM appendFormat:@"\n%@\n",str];
    }];
    // 把拼接好的字符串打印出来,就好了。
    NSLog(@"%@",strM);
    }
    @end
    +
      +
    • 字典转模型的方式一:KVC
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @implementation Status
    + (instancetype)statusWithDict:(NSDictionary *)dict
    {
    Status *status = [[self alloc] init];
    [status setValuesForKeysWithDictionary:dict];
    return status;
    }
    @end
    +
      +
    • KVC字典转模型弊端:必须保证,模型中的属性和字典中的key一一对应。
        +
      • 如果不一致,就会调用[<Status 0x7fa74b545d60> setValue:forUndefinedKey:]key找不到的错。
      • +
      • 分析:模型中的属性和字典的key不一一对应,系统就会调用setValue:forUndefinedKey:报错。
      • +
      • 解决:重写对象的setValue:forUndefinedKey:,把系统的方法覆盖, 就能继续使用KVC,字典转模型了。
      • +
      +
    • +
    +
    1
    2
    3
    4
    - (void)setValue:(id)value forUndefinedKey:(NSString *)key
    {
    }
    +
      +
    • 字典转模型的方式二:Runtime
        +
      • 思路:利用运行时,遍历模型中所有属性,根据模型的属性名,去字典中查找key,取出对应的值,给模型的属性赋值。
      • +
      • 步骤:提供一个NSObject分类,专门字典转模型,以后所有模型都可以通过这个分类转。
      • +
      +
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    @implementation ViewController
    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 解析Plist文件
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"status.plist" ofType:nil];
    NSDictionary *statusDict = [NSDictionary dictionaryWithContentsOfFile:filePath];
    // 获取字典数组
    NSArray *dictArr = statusDict[@"statuses"];
    // 自动生成模型的属性字符串
    // [NSObject resolveDict:dictArr[0][@"user"]];
    _statuses = [NSMutableArray array];
    // 遍历字典数组
    for (NSDictionary *dict in dictArr) {
    Status *status = [Status modelWithDict:dict];
    [_statuses addObject:status];
    }
    // 测试数据
    NSLog(@"%@ %@",_statuses,[_statuses[0] user]);
    }
    @end
    @implementation NSObject (Model)
    + (instancetype)modelWithDict:(NSDictionary *)dict
    {
    // 思路:遍历模型中所有属性-》使用运行时
    // 0.创建对应的对象
    id objc = [[self alloc] init];
    // 1.利用runtime给对象中的成员属性赋值
    // class_copyIvarList:获取类中的所有成员属性
    // Ivar:成员属性的意思
    // 第一个参数:表示获取哪个类中的成员属性
    // 第二个参数:表示这个类有多少成员属性,传入一个Int变量地址,会自动给这个变量赋值
    // 返回值Ivar *:指的是一个ivar数组,会把所有成员属性放在一个数组中,通过返回的数组就能全部获取到。
    /* 类似下面这种写法
    Ivar ivar;
    Ivar ivar1;
    Ivar ivar2;
    // 定义一个ivar的数组a
    Ivar a[] = {ivar,ivar1,ivar2};
    // 用一个Ivar *指针指向数组第一个元素
    Ivar *ivarList = a;
    // 根据指针访问数组第一个元素
    ivarList[0];
    */
    unsigned int count;
    // 获取类中的所有成员属性
    Ivar *ivarList = class_copyIvarList(self, &count);
    for (int i = 0; i < count; i++) {
    // 根据角标,从数组取出对应的成员属性
    Ivar ivar = ivarList[i];
    // 获取成员属性名
    NSString *name = [NSString stringWithUTF8String:ivar_getName(ivar)];
    // 处理成员属性名->字典中的key
    // 从第一个角标开始截取
    NSString *key = [name substringFromIndex:1];
    // 根据成员属性名去字典中查找对应的value
    id value = dict[key];
    // 二级转换:如果字典中还有字典,也需要把对应的字典转换成模型
    // 判断下value是否是字典
    if ([value isKindOfClass:[NSDictionary class]]) {
    // 字典转模型
    // 获取模型的类对象,调用modelWithDict
    // 模型的类名已知,就是成员属性的类型
    // 获取成员属性类型
    NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
    // 生成的是这种@"@\"User\"" 类型 -》 @"User" 在OC字符串中 \" -> ",\是转义的意思,不占用字符
    // 裁剪类型字符串
    NSRange range = [type rangeOfString:@"\""];
    type = [type substringFromIndex:range.location + range.length];
    range = [type rangeOfString:@"\""];
    // 裁剪到哪个角标,不包括当前角标
    type = [type substringToIndex:range.location];
    // 根据字符串类名生成类对象
    Class modelClass = NSClassFromString(type);
    if (modelClass) { // 有对应的模型才需要转
    // 把字典转模型
    value = [modelClass modelWithDict:value];
    }
    }
    // 三级转换:NSArray中也是字典,把数组中的字典转换成模型.
    // 判断值是否是数组
    if ([value isKindOfClass:[NSArray class]]) {
    // 判断对应类有没有实现字典数组转模型数组的协议
    if ([self respondsToSelector:@selector(arrayContainModelClass)]) {
    // 转换成id类型,就能调用任何对象的方法
    id idSelf = self;
    // 获取数组中字典对应的模型
    NSString *type = [idSelf arrayContainModelClass][key];
    // 生成模型
    Class classModel = NSClassFromString(type);
    NSMutableArray *arrM = [NSMutableArray array];
    // 遍历字典数组,生成模型数组
    for (NSDictionary *dict in value) {
    // 字典转模型
    id model = [classModel modelWithDict:dict];
    [arrM addObject:model];
    }
    // 把模型数组赋值给value
    value = arrM;
    }
    }
    if (value) { // 有值,才需要给模型的属性赋值
    // 利用KVC给模型中的属性赋值
    [objc setValue:value forKey:key];
    }
    }
    return objc;
    }
    @end
    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/2015/05/12/\345\215\225\344\276\213\346\250\241\345\274\217\347\232\204ARC\345\222\214MRC\345\256\236\347\216\260/index.html" "b/2015/05/12/\345\215\225\344\276\213\346\250\241\345\274\217\347\232\204ARC\345\222\214MRC\345\256\236\347\216\260/index.html" new file mode 100644 index 0000000..e7ffae9 --- /dev/null +++ "b/2015/05/12/\345\215\225\344\276\213\346\250\241\345\274\217\347\232\204ARC\345\222\214MRC\345\256\236\347\216\260/index.html" @@ -0,0 +1,841 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 单例模式的ARC和MRC实现 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    单例模式的ARC和MRC实现

    + + + +
    + + +
    + + + + + +

    单例在整个工程中,就相当于一个全局变量,就是不论在哪里需要用到这个类的实例变量,都可以通过单例方法来取得,而且一旦你创建了一个单例类,不论你在多少个界面中初始化调用了这个单例方法取得对象,它们所有的对象都是指向的同一块内存存储空间(即单例类保证了该类的实力对象是唯一存在的一个).

    + +

    单例模式的作用

      +
    1. 可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问
    2. +
    3. 从而方便地控制了实例个数,并节约系统资源
    4. +
    +
      +
    • ARC中,单例模式的实现
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    // 提供1个类方法让外界访问唯一的实例
    + (instancetype)sharedTools
    {
    return [[self alloc] init];
    }
    // 在.m中保留一个全局的static的实例
    static Tools *_instance;
    // 重写allocWithZone:方法,在这里创建唯一的实例
    // 注意线程安全,判断是否为nil,可能多次创建
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    _instance = [super allocWithZone:zone];
    });
    return _instance;
    }
    // 实现copyWithZone:方法
    - (id)copyWithZone:(struct _NSZone *)zone
    {
    // 因为copy方法必须通过实例对象调用,所以可以直接返回_instance
    return _instance;
    }
    - (id)mutableCopyWithZone:(NSZone *)zone
    {
    return _instance;
    }
    +
      +
    • MRC中,单例模式的实现
    • +
    +除了添加上面ARC实现的代码,再添加下面代码 + +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #pragma mark - MRC
    #if __has_feature(objc_arc)
    // 如果是ARC什么都不添加
    #else
    - (oneway void)release
    {
    }
    - (instancetype)retain
    {
    return _instance;
    }
    - (NSUInteger)retainCount
    {
    return MAXFLOAT; //装逼格
    }
    #endif
    +单例不能继承,类的静态变量只被初始化一次,子类和父类谁先调用,创建的就是哪种类型的变量,以后也不会改变 + + +

    创建很多单例

      +
    • 利用宏定义
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    //
    // Single.h
    // 01-掌握-单例ARC
    //
    // Created by apple on 15/8/6.
    // Copyright (c) 2015年 CoderShmily. All rights reserved.
    //
    #define interfaceSingle(name) + (instancetype)share##name
    #if __has_feature(objc_arc)
    // 如果是ARC
    #define implementationSingle(name) + (instancetype)share##name \
    { \
    return [[self alloc] init]; \
    } \
    static id _instance; \
    + (instancetype)allocWithZone:(struct _NSZone *)zone \
    { \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
    _instance = [super allocWithZone:zone]; \
    }); \
    return _instance; \
    } \
    - (id)copyWithZone:(NSZone *)zone \
    { \
    return _instance; \
    } \
    - (id)mutableCopyWithZone:(NSZone *)zone \
    { \
    return _instance; \
    }
    #else
    // 如果不是ARC
    #define implementationSingle(name) + (instancetype)share##name \
    { \
    return [[self alloc] init]; \
    } \
    static id _instance; \
    + (instancetype)allocWithZone:(struct _NSZone *)zone \
    { \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
    _instance = [super allocWithZone:zone]; \
    }); \
    return _instance; \
    } \
    - (id)copyWithZone:(NSZone *)zone \
    { \
    return _instance; \
    } \
    - (id)mutableCopyWithZone:(NSZone *)zone \
    { \
    return _instance; \
    }\
    - (oneway void)release \
    {} \
    - (instancetype)retain \
    { \
    return _instance; \
    } \
    - (NSUInteger)retainCount \
    { \
    return MAXFLOAT; \
    }
    #endif
    +
      +
    • 使用宏定义
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // FileTools.h
    #import <Foundation/Foundation.h>
    #import "Single.h"
    @interface FileTools : NSObject
    //+ (instancetype)shareFileTools;
    interfaceSingle(FileTools);
    @end
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // FileTools.m
    #import "FileTools.h"
    @implementation FileTools
    implementationSingle(FileTools)
    @end
    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2015/05/01/2015-05-01-Swift-ru-men/index.html "b/2015/05/13/Swift \345\205\245\351\227\250/index.html" similarity index 77% rename from 2015/05/01/2015-05-01-Swift-ru-men/index.html rename to "2015/05/13/Swift \345\205\245\351\227\250/index.html" index d351d8e..667b3c4 100644 --- a/2015/05/01/2015-05-01-Swift-ru-men/index.html +++ "b/2015/05/13/Swift \345\205\245\351\227\250/index.html" @@ -1,11 +1,96 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + - Swift 入门 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + Swift 入门 | CoderShmily's Blog + + + + - - - - - + + + + + + + + + + + + + + - - + - +
    +
    - -
    -
    - + +
    +
    +
    +
    + + +
    -
    - + + + + -

    - Swift 入门 -

    +
    + + + + + + + +
    + + + +

    Swift 入门

    + + +
    -
    + +
    + + + +

    特色

    • 苹果宣称 Swift 的特点是:快速、现代、安全、互动,而且明显优于 Objective-C 语言
    • @@ -359,122 +658,419 @@

      - -

    - - - - -
    + +
    + + + + + + +
    + + + + +
    - - +
    + - + + + + + + + + +
    -
    + + - -
    -
    - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/2015/05/15/2015-05-15-sdwebimageyuan-ma-jie-xi/index.html "b/2015/05/15/SDWebImage\346\272\220\347\240\201\350\247\243\346\236\220/index.html" similarity index 86% rename from 2015/05/15/2015-05-15-sdwebimageyuan-ma-jie-xi/index.html rename to "2015/05/15/SDWebImage\346\272\220\347\240\201\350\247\243\346\236\220/index.html" index af8ace3..32f7edf 100644 --- a/2015/05/15/2015-05-15-sdwebimageyuan-ma-jie-xi/index.html +++ "b/2015/05/15/SDWebImage\346\272\220\347\240\201\350\247\243\346\236\220/index.html" @@ -1,97 +1,396 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - SDWebImage源码解析 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + SDWebImage源码解析 | CoderShmily's Blog + + + + - - - - - + + + + + + + + + + + + + + - - + - +
    +
    - -
    -
    - + +
    +
    +
    +
    + + +
    -
    - + + + + -

    - SDWebImage源码解析 -

    +
    + + + + + + + +
    + + + +

    SDWebImage源码解析

    + + +
    -
    + +
    + + + +

    SDWebImage源码解析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    /*
    * This file is part of the SDWebImage package.
    * (c) Olivier Poitrey <rs@dailymotion.com>
    *
    * For the full copyright and license information, please view the LICENSE
    * file that was distributed with this source code.
    */
    #import "SDWebImageCompat.h"
    #import "SDWebImageOperation.h"
    #import "SDWebImageDownloader.h"
    #import "SDImageCache.h"
    typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
    /**
    * By default, when a URL fail to be downloaded, the URL is blacklisted so the library won't keep trying.
    * This flag disable this blacklisting.
    */
    /**
    *默认情况下,如果一个url在下载的时候失败了,那么这个url会被加入黑名单并且library不会尝试再次下载,这个flag会阻止library把失败的url加入黑名单(简单来说如果选择了这个flag,那么即使某个url下载失败了,sdwebimage还是会尝试再次下载他.)
    */
    SDWebImageRetryFailed = 1 << 0,
    /**
    * By default, image downloads are started during UI interactions, this flags disable this feature,
    * leading to delayed download on UIScrollView deceleration for instance.
    */
    /**
    *默认情况下,图片会在交互发生的时候下载(例如你滑动tableview的时候),这个flag会禁止这个特性,导致的结果就是在scrollview减速的时候
    *才会开始下载(也就是你滑动的时候scrollview不下载,你手从屏幕上移走,scrollview开始减速的时候才会开始下载图片)
    */
    SDWebImageLowPriority = 1 << 1,
    /**
    * This flag disables on-disk caching
    */
    /*
    *这个flag禁止磁盘缓存,只有内存缓存
    */
    SDWebImageCacheMemoryOnly = 1 << 2,
    /**
    * This flag enables progressive download, the image is displayed progressively during download as a browser would do.
    * By default, the image is only displayed once completely downloaded.
    */
    /*
    *这个flag会在图片下载的时候就显示(就像你用浏览器浏览网页的时候那种图片下载,一截一截的显示(待确认))
    *
    */
    SDWebImageProgressiveDownload = 1 << 3,
    /**
    * Even if the image is cached, respect the HTTP response cache control, and refresh the image from remote location if needed.
    * The disk caching will be handled by NSURLCache instead of SDWebImage leading to slight performance degradation.
    * This option helps deal with images changing behind the same request URL, e.g. Facebook graph api profile pics.
    * If a cached image is refreshed, the completion block is called once with the cached image and again with the final image.
    *
    * Use this flag only if you can't make your URLs static with embeded cache busting parameter.
    */
    /*
    *这个选项的意思看的不是很懂,大意是即使一个图片缓存了,还是会重新请求.并且缓存侧略依据NSURLCache而不是SDWebImage.
    *
    */
    SDWebImageRefreshCached = 1 << 4,
    /**
    * In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for
    * extra time in background to let the request finish. If the background task expires the operation will be cancelled.
    */
    /*
    *启动后台下载,加入你进入一个页面,有一张图片正在下载这时候你让app进入后台,图片还是会继续下载(这个估计要开backgroundfetch才有用)
    */
    SDWebImageContinueInBackground = 1 << 5,
    /**
    * Handles cookies stored in NSHTTPCookieStore by setting
    * NSMutableURLRequest.HTTPShouldHandleCookies = YES;
    */
    /*
    *可以控制存在NSHTTPCookieStore的cookies.(我没用过,等用过的人过来解释一下)
    */
    SDWebImageHandleCookies = 1 << 6,
    /**
    * Enable to allow untrusted SSL ceriticates.
    * Useful for testing purposes. Use with caution in production.
    */
    /*
    *允许不安全的SSL证书,在正式环境中慎用
    */
    SDWebImageAllowInvalidSSLCertificates = 1 << 7,
    /**
    * By default, image are loaded in the order they were queued. This flag move them to
    * the front of the queue and is loaded immediately instead of waiting for the current queue to be loaded (which
    * could take a while).
    */
    /*
    *默认情况下,image在装载的时候是按照他们在队列中的顺序装载的(就是先进先出).这个flag会把他们移动到队列的前端,并且立刻装载
    *而不是等到当前队列装载的时候再装载.
    */
    SDWebImageHighPriority = 1 << 8,
    /**
    * By default, placeholder images are loaded while the image is loading. This flag will delay the loading
    * of the placeholder image until after the image has finished loading.
    */
    /*
    *默认情况下,占位图会在图片下载的时候显示.这个flag开启会延迟占位图显示的时间,等到图片下载完成之后才会显示占位图.(等图片显示完了我干嘛还显示占位图?或许是我理解错了?)
    */
    SDWebImageDelayPlaceholder = 1 << 9,
    /**
    * We usually don't call transformDownloadedImage delegate method on animated images,
    * as most transformation code would mangle it.
    * Use this flag to transform them anyway.
    */
    /*
    *是否transform图片(没用过,还要再看,但是据我估计,是否是图片有可能方向不对需要调整方向,例如采用iPhone拍摄的照片如果不纠正方向,那么图片是向左旋转90度的.可能很多人不知道iPhone的摄像头并不是竖直的,而是向左偏了90度.具体请google.)
    */
    SDWebImageTransformAnimatedImage = 1 << 10,
    };
    typedef void(^SDWebImageCompletionBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL);
    typedef void(^SDWebImageCompletionWithFinishedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL);
    typedef NSString *(^SDWebImageCacheKeyFilterBlock)(NSURL *url);
    @class SDWebImageManager;
    @protocol SDWebImageManagerDelegate <NSObject>
    @optional
    /**
    * Controls which image should be downloaded when the image is not found in the cache.
    *
    * @param imageManager The current `SDWebImageManager`
    * @param imageURL The url of the image to be downloaded
    *
    * @return Return NO to prevent the downloading of the image on cache misses. If not implemented, YES is implied.
    */
    /*
    *主要作用是当缓存里没有发现某张图片的缓存时,是否选择下载这张图片(默认是yes),可以选择no,那么sdwebimage在缓存中没有找到这张图片的时候不会选择下载
    */
    - (BOOL)imageManager:(SDWebImageManager *)imageManager shouldDownloadImageForURL:(NSURL *)imageURL;
    /**
    * Allows to transform the image immediately after it has been downloaded and just before to cache it on disk and memory.
    * NOTE: This method is called from a global queue in order to not to block the main thread.
    *
    * @param imageManager The current `SDWebImageManager`
    * @param image The image to transform
    * @param imageURL The url of the image to transform
    *
    * @return The transformed image object.
    */
    /**
    *在图片下载完成并且还没有加入磁盘缓存或者内存缓存的时候就transform这个图片.这个方法是在异步线程执行的,防治阻塞主线程.
    *至于为什么在异步执行很简单,对一张图片纠正方向(也就是transform)是很耗资源的,一张2M大小的图片纠正方向你可以用instrument测试一下耗时.
    *很恐怖
    */
    - (UIImage *)imageManager:(SDWebImageManager *)imageManager transformDownloadedImage:(UIImage *)image withURL:(NSURL *)imageURL;
    @end
    /**
    * The SDWebImageManager is the class behind the UIImageView+WebCache category and likes.
    * It ties the asynchronous downloader (SDWebImageDownloader) with the image cache store (SDImageCache).
    * You can use this class directly to benefit from web image downloading with caching in another context than
    * a UIView.
    *
    * Here is a simple example of how to use SDWebImageManager:
    *
    * @code
    SDWebImageManager *manager = [SDWebImageManager sharedManager];
    [manager downloadImageWithURL:imageURL
    options:0
    progress:nil
    completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
    if (image) {
    // do something with image
    }
    }];
    * @endcode
    */
    /*
    *这一段是阐述SDWebImageManager是干嘛的.其实UIImageView+WebCache这个category背后执行操作的就是这个SDWebImageManager.他会绑定一个下载器也就是SDWebImageDownloader和一个缓存SDImageCache.后面的大意应该是讲你可以直接使用一个其他上下文环境的SDWebImageManager,而不是仅仅限于一个UIView.
    */
    @interface SDWebImageManager : NSObject
    @property (weak, nonatomic) id <SDWebImageManagerDelegate> delegate;
    /**
    *如同上文所说,一个SDWebImageManager会绑定一个imageCache和一个下载器.
    */
    @property (strong, nonatomic, readonly) SDImageCache *imageCache;
    @property (strong, nonatomic, readonly) SDWebImageDownloader *imageDownloader;
    /**
    * The cache filter is a block used each time SDWebImageManager need to convert an URL into a cache key. This can
    * be used to remove dynamic part of an image URL.
    *
    * The following example sets a filter in the application delegate that will remove any query-string from the
    * URL before to use it as a cache key:
    *
    * @code
    [[SDWebImageManager sharedManager] setCacheKeyFilter:^(NSURL *url) {
    url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path];
    return [url absoluteString];
    }];
    * @endcode
    */
    /*
    * 这个cacheKeyFilter是干嘛的呢?很简单.1他是一个block.2.这个block的作用就是生成一个image的key.因为sdwebimage的缓存原理你可以当成是一个字典,每一个字典的value就是一张image,那么这个value对应的key是什么呢?就是cacheKeyFilter根据某个规则对这个图片的url做一些操作生成的.上面的示例就显示了怎么利用这个block把image的url重新组合生成一个key.以后当sdwebimage检测到你
    */
    @property (nonatomic, copy) SDWebImageCacheKeyFilterBlock cacheKeyFilter;
    /**
    * Returns global SDWebImageManager instance.
    *
    * @return SDWebImageManager shared instance
    */
    /*
    *这个不用我解释了吧,生成一个SDWebImagemanager的单例.
    */
    + (SDWebImageManager *)sharedManager;
    /**
    * Downloads the image at the given URL if not present in cache or return the cached version otherwise.
    * 从给定的URL中下载一个之前没有被缓存的Image.
    *
    * @param url The URL to the image
    * @param options A mask to specify options to use for this request
    * @param progressBlock A block called while image is downloading
    * @param completedBlock A block called when operation has been completed.
    *
    * This parameter is required.
    *
    * This block has no return value and takes the requested UIImage as first parameter.
    * In case of error the image parameter is nil and the second parameter may contain an NSError.
    *
    * The third parameter is an `SDImageCacheType` enum indicating if the image was retrived from the local cache
    * or from the memory cache or from the network.
    *
    * The last parameter is set to NO when the SDWebImageProgressiveDownload option is used and the image is
    * downloading. This block is thus called repetidly with a partial image. When image is fully downloaded, the
    * block is called a last time with the full image and the last parameter set to YES.
    *
    * @return Returns an NSObject conforming to SDWebImageOperation. Should be an instance of SDWebImageDownloaderOperation
    */
    /*
    * 这个方法主要就是SDWebImage下载图片的方法了.
    * 第一个参数是必须要的,就是image的url
    * 第二个参数就是我们上面的Options,你可以定制化各种各样的操作.详情参上.
    * 第三个参数是一个回调block,用于图片在下载过程中的回调.(英文注释应该是有问题的.)
    * 第四个参数是一个下载完成的回调.会在图片下载完成后回调.
    * 返回值是一个NSObject类,并且这个NSObject类是conforming一个协议这个协议叫做SDWebImageOperation,这个协议很简单,就是一个cancel掉operation的协议.
    */
    - (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url
    options:(SDWebImageOptions)options
    progress:(SDWebImageDownloaderProgressBlock)progressBlock
    completed:(SDWebImageCompletionWithFinishedBlock)completedBlock;
    /**
    * Saves image to cache for given URL
    *
    * @param image The image to cache
    * @param url The URL to the image
    *
    */
    /*
    * 将图片存入cache的方法,类似于字典的setValue: forKey:
    */
    - (void)saveImageToCache:(UIImage *)image forURL:(NSURL *)url;
    /**
    * Cancel all current opreations
    */
    /*
    *取消掉当前所有的下载图片的operation
    */
    - (void)cancelAll;
    /**
    * Check one or more operations running
    */
    /*
    * check一下是否有一个或者多个operation正在执行(简单来说就是check是否有图片在下载)
    */
    - (BOOL)isRunning;
    /**
    * Check if image has already been cached
    *
    * @param url image url
    *
    * @return if the image was already cached
    */
    /*
    * 通过一个image的url是否已经存在,如果存在返回yes,否则返回no
    */
    - (BOOL)cachedImageExistsForURL:(NSURL *)url;
    /**
    * Check if image has already been cached on disk only
    *
    * @param url image url
    *
    * @return if the image was already cached (disk only)
    */
    /*
    * 检测一个image是否已经被缓存到磁盘(是否存且仅存在disk里).
    */
    - (BOOL)diskImageExistsForURL:(NSURL *)url;
    /**
    * Async check if image has already been cached
    *
    * @param url image url
    * @param completionBlock the block to be executed when the check is finished
    *
    * @note the completion block is always executed on the main queue
    */
    /*
    * 如果检测到图片已经被缓存,那么执行回调block.这个block会永远执行在主线程.也就是你可以在这个回调block里更新ui.
    */
    - (void)cachedImageExistsForURL:(NSURL *)url
    completion:(SDWebImageCheckCacheCompletionBlock)completionBlock;
    /**
    * Async check if image has already been cached on disk only
    *
    * @param url image url
    * @param completionBlock the block to be executed when the check is finished
    *
    * @note the completion block is always executed on the main queue
    */
    /*
    * 如果检测到图片已经被缓存在磁盘(存且仅存在disk),那么执行回调block.这个block会永远执行在主线程.也就是你可以在这个回调block里更新ui.
    */
    - (void)diskImageExistsForURL:(NSURL *)url
    completion:(SDWebImageCheckCacheCompletionBlock)completionBlock;
    /**
    *Return the cache key for a given URL
    */
    /*
    * 通过image的url返回image存在缓存里的key.有人会问了,为什么不直接把图片的url当做image的key来使用呢?而是非要对url做一些处理才能当做key.我的解释是,我也不太清楚.可能为了防止重复吧.
    */
    - (NSString *)cacheKeyForURL:(NSURL *)url;
    @end
    #pragma mark - Deprecated
    typedef void(^SDWebImageCompletedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType) __deprecated_msg("Block type deprecated. Use `SDWebImageCompletionBlock`");
    typedef void(^SDWebImageCompletedWithFinishedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished) __deprecated_msg("Block type deprecated. Use `SDWebImageCompletionWithFinishedBlock`");
    // 已被废弃
    @interface SDWebImageManager (Deprecated)
    /**
    * Downloads the image at the given URL if not present in cache or return the cached version otherwise.
    *
    * @deprecated This method has been deprecated. Use `downloadImageWithURL:options:progress:completed:`
    */
    - (id <SDWebImageOperation>)downloadWithURL:(NSURL *)url
    options:(SDWebImageOptions)options
    progress:(SDWebImageDownloaderProgressBlock)progressBlock
    completed:(SDWebImageCompletedWithFinishedBlock)completedBlock __deprecated_msg("Method deprecated. Use `downloadImageWithURL:options:progress:completed:`");
    @end
    @@ -99,127 +398,394 @@

    -
    - Share + +
    + + + +
    + +
    -
    -
    - - - - -
    + +
    + + + + + + +
    + + + + +
    - - +
    + - + + +
    - +
    + +
    -
    -

    归档

    -
    +
    + + - -
    -

    最新文章

    -
    - + + + + + + + +
    -
    + + - -
    -
    +
    + +
    +
    + + +
    + + +
    + +
    - -
    - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - - - -
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git "a/2015/06/03/const,static,extern\347\256\200\344\273\213/index.html" "b/2015/06/03/const,static,extern\347\256\200\344\273\213/index.html" new file mode 100644 index 0000000..1f3b25e --- /dev/null +++ "b/2015/06/03/const,static,extern\347\256\200\344\273\213/index.html" @@ -0,0 +1,886 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + const,static,extern简介 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    const,static,extern简介

    + + + +
    + + +
    + + + + + +

    const,static,extern简介

    + +

    一、const与宏的区别(面试题):

      +
    • const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量。

      +
        +
      • 编译时刻:宏是预编译(编译之前处理),const是编译阶段。
      • +
      • 编译检查:宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误。
      • +
      • 宏的好处:宏能定义一些函数,方法。 const不能。
      • +
      • 宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换。

        +

        注意:很多Blog都说使用宏,会消耗很多内存,我这验证并不会生成很多内存,宏定义的是常量,常量都放在常量区,只会生成一份内存。

        +
      • +
      +
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // 常见的常量:抽成宏
    #define TESTAccount @"account"
    #define TESTUserDefault [NSUserDefaults standardUserDefaults]
    // 字符串常量
    static NSString * const account = @"account";
    - (void)viewDidLoad {
    [super viewDidLoad];
    // 偏好设置存储
    // 使用宏
    [TESTUserDefault setValue:@"123" forKey:TESTAccount];
    // 使用const常量
    [[TESTUserDefault standardUserDefaults] setValue:@"123" forKey:account];
    }
    +

    二、const作用:限制类型

      +
    • 1.const仅仅用来修饰右边的变量(基本数据变量p,指针变量*p)
    • +
    • 2.被const修饰的变量是只读的。

      +
    • +
    • const基本使用

      +
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    - (void)viewDidLoad {
    [super viewDidLoad];
    // 定义变量
    int a = 1;
    // 允许修改值
    a = 20;
    // const两种用法
    // const:修饰基本变量p
    // 这两种写法是一样的,const只修饰右边的基本变量b
    const int b = 20; // b:只读变量
    int const b = 20; // b:只读变量
    // 不允许修改值
    b = 1;
    // const:修饰指针变量*p,带*的变量,就是指针变量.
    // 定义一个指向int类型的指针变量,指向a的地址
    int *p = &a;
    int c = 10;
    p = &c;
    // 允许修改p指向的地址,
    // 允许修改p访问内存空间的值
    *p = 20;
    // const修饰指针变量访问的内存空间,修饰的是右边*p1,
    // 两种方式一样
    const int *p1; // *p1:常量 p1:变量
    int const *p1; // *p1:常量 p1:变量
    // const修饰指针变量p1
    int * const p1; // *p1:变量 p1:常量
    // 第一个const修饰*p1 第二个const修饰 p1
    // 两种方式一样
    const int * const p1; // *p1:常量 p1:常量
    int const * const p1; // *p1:常量 p1:常量
    }
    +

    三、const开发中使用场景:

      +
    • 1.当一个方法参数只读
    • +
    • 2.定义只读全局变量
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    @implementation ViewController
    // 定义只读全局常量
    NSString * const str = @"123";
    // 当一个方法的参数,只读.
    - (void)test:(NSString * const)name
    {
    }
    // 指针只读,不能通过指针修改值
    - (void)test1:(int const *)a{
    // *a = 10;
    }
    // 基本数据类型只读
    - (void)test2:(int const)a{
    }
    @end
    +

    四、static和extern简单使用(要使用一个东西,先了解其作用)

      +
    • static作用:

      +
        +
      • 修饰局部变量:

        +

        1.延长局部变量的生命周期,程序结束才会销毁。

        +

        2.局部变量只会生成一份内存,只会初始化一次。

        +
      • +
      • 修饰全局变量

        +

        1.只能在本文件中访问,修改全局变量的作用域,生命周期不会改

        +
      • +
      +
    • +
    • extern作用:

      +
        +
      • 只是用来获取全局变量(包括全局静态变量)的值,不能用于定义变量
      • +
      +
    • +
    • extern工作原理:
        +
      • 先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找。
      • +
      +
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // 全局变量:只有一份内存,所有文件共享,与extern联合使用。
    int a = 20;
    // static修饰全局变量
    static int age = 20;
    - (void)test
    {
    // static修饰局部变量
    static int age = 0;
    age++;
    NSLog(@"%d",age);
    }
    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self test];
    [self test];
    extern int age;
    NSLog(@"%d",age);
    }
    I
    +

    五、static与const联合使用

      +
    • static与const作用:声明一个只读的静态变量
    • +
    • 开发使用场景:在一个文件中经常使用的字符串常量,可以使用static与const组合
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 开发中常用static修饰全局变量,只改变作用域
    // 为什么要改变全局变量作用域,防止重复声明全局变量。
    // 开发中声明的全局变量,有些不希望外界改动,只允许读取。
    // 比如一个基本数据类型不希望别人改动
    // 声明一个静态的全局只读常量
    static const int a = 20;
    // staic和const联合的作用:声明一个静态的全局只读常量
    // iOS中staic和const常用使用场景,是用来代替宏,把一个经常使用的字符串常量,定义成静态全局只读变量.
    // 开发中经常拿到key修改值,因此用const修饰key,表示key只读,不允许修改。
    static NSString * const key = @"name";
    // 如果 const修饰 *key1,表示*key1只读,key1还是能改变。
    static NSString const *key1 = @"name";
    +

    六、extern与const联合使用

      +
    • 开发中使用场景:在多个文件中经常使用的同一个字符串常量,可以使用extern与const组合。
    • +
    • 原因:
        +
      • static与const组合:在每个文件都需要定义一份静态全局变量。
      • +
      • extern与const组合:只需要定义一份全局变量,多个文件共享。
      • +
      +
    • +
    • 全局常量正规写法:开发中便于管理所有的全局变量,通常搞一个GlobeConst文件,里面专门定义全局变量,统一管理,要不然项目文件多不好找。

      +
    • +
    • GlobeConst.h

      +
    • +
    +
    1
    2
    3
    4
    5
    /*******************************首页****************************/
    extern NSString * const nameKey = @"name";
    /*******************************首页****************************/
    +
      +
    • GlobeConst.m
    • +
    +
    1
    2
    3
    4
    5
    6
    7
    #import <Foundation/Foundation.h>
    /*******************************首页****************************/
    NSString * const nameKey = @"name";
    /*******************************首页****************************/
    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/2015/06/10/React Native\344\273\213\347\273\215/index.html" "b/2015/06/10/React Native\344\273\213\347\273\215/index.html" new file mode 100644 index 0000000..e87a5ca --- /dev/null +++ "b/2015/06/10/React Native\344\273\213\347\273\215/index.html" @@ -0,0 +1,854 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + React Native介绍 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    React Native介绍

    + + + +
    + + +
    + + + + + +

    简介

    2015年9月15日,Facebook发布了 React Native for Android,把 Web 和原生平台的 JavaScript 开发技术扩展到了 Google 的流行移动平台

    +

    什么是React Native

    React Native 让开发者使用 JavaScript 和 React 编写应用,利用相同的核心代码就可以创建 Web,iOS 和 Android 平台的原生应用。React Native 的宗旨是,学习一次,高效编写跨平台原生应用。

    +

    官方的github地址为

    + +

    React Native有什么优点

      +
    • 提供了原生的控件支持
    • +
    +

    使用 React Native 你可以使用原生的控件,入在iOS平台我们可以使用UITabBar控件,在Android平台我们可以使用Drawer控件。这样,就让我们的App从使用上和视觉上拥有像原生App一样的体验。而且使用起来也非常简单。

    +
      +
    • 异步执行
    • +
    +

    所有的JavaScript逻辑与原生的代码逻辑都是在异步中执行的。原生的代码逻辑当然也可以添加自己的额外的线程。

    +

    这个特性意味着,我们可以将图片解码过程的线程从主线程中抽离出来,在后台线程将其保存在磁盘中,在不影响UI的情况下计算调整布局等等。
    所以,这些让React Native开发出来的App都是较为的流畅。

    +

    这个之间的通信过程也是有序列化来完成的,这个就让我们可以使用Chrome Developer Tools 来完成JavaScript逻辑的调试,当然我们也能够在模拟器和物理设备上调试。

    +
      +
    • 触屏处理
      React Native实现了高性能的图层点击与接触处理。

      +
    • +
    • Flexbox的布局样式
      使布局将变得更简单,这就使我们为什么要将网页的布局模式切换到React Native的Flexbox布局模式。Flexbox让UI布局变得简单,入使用margin和padding的嵌套模式。当然,React Native 同样也支持网页原生的一些属性布局模式,如FontWeight之类的。这些声明的布局和样式,都会存在内联的机制将其优化。

      +
    • +
    • Polyfills机制
      React Native也支持我们使用第三方的JavaScript库,来方便我们的开发。支持npm中的成千上万的模块。

      +
    • +
    • 基于React JS
      拥有React JS的优良特性。

      +
    • +
    +

    跨平台框架这么多?为什么重点关注React Native?

    如我们之前所介绍的,Android与IOS跨平台开发框架如此这多,如之前我们介绍的PhoneGap、Xamarin等,为什么我们重点的关注React Native呢?

    +
      +
    • Facebook所开源的框架
      我们知道,所有的开源框架,只有是一线的大公司研发出来的才能够保证框架的维护性、可用性。当然,这样也会吸引更多的开发者使用这个框架,才能够使我们在人才储备上有人可用。并不是说,框架多好就能够用的。如国内的CrossApp,虽然很好用,但是知名度不够,造成我们研发、bug反馈、人才招聘上的种种窘境。

      +
    • +
    • React JS技术的革命
      这个东西也就是国内的很多跨平台框架没有关注的地方,Facebook使用了React JS已经有了好几年的技术变革,特别是JSX与Virtual DOM的加入,给使用JavaScript来开发Native App简直是一个质的飞跃。

      +
    • +
    • BAT团队已经投入研发与使用
      如果很多中小型公司,看不清方向,这个我们倒是可以模仿BAT的脚步。现在的BAT公司内部,特别是A,已经投入了大量的人力在React Native上面,听说TMall App已经开始使用React 进行重构。

      +
    • +
    +

    原生控件

      +
    • Native的原生控件有更好的体验
    • +
    • Native有更好的手势识别
    • +
    • Native有更合适的线程模型,尽管Web Worker可以解决一部分问题,但如图像解码、文本渲染仍无法多线程渲染,这影响了Web的流畅性
    • +
    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/2015/06/15/\345\260\217\347\237\245\350\257\206\347\202\271\346\200\273\347\273\223/index.html" "b/2015/06/15/\345\260\217\347\237\245\350\257\206\347\202\271\346\200\273\347\273\223/index.html" new file mode 100644 index 0000000..0d39434 --- /dev/null +++ "b/2015/06/15/\345\260\217\347\237\245\350\257\206\347\202\271\346\200\273\347\273\223/index.html" @@ -0,0 +1,818 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 小知识点总结 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    小知识点总结

    + + + +
    + + +
    + + + + + +
      +
    • super,superClass,class
    • +
    + +

    super,superClass,class

    class:获取方法调用类名
    superclass:获取方法调用者的父类类名
    super:编译修饰符,不是指针,指向父类标志,
    本质还是拿到当前对象去调用父类的方法
    注意:super并不是拿到父类对象去调用父类方法

    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/2016/04/03/git \351\205\215\347\275\256\345\244\232\344\270\252SSH-Key/index.html" "b/2016/04/03/git \351\205\215\347\275\256\345\244\232\344\270\252SSH-Key/index.html" new file mode 100644 index 0000000..3a90416 --- /dev/null +++ "b/2016/04/03/git \351\205\215\347\275\256\345\244\232\344\270\252SSH-Key/index.html" @@ -0,0 +1,832 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    + + + +
    + + +
    + + + + + +

    我们在日常工作中会遇到公司有个gitlab,还有些自己的一些项目放在github上。这样就导致我们要配置不同的ssh-key对应不同的环境。下面我们来看看具体的操作

    + +

    生成一个公司用的SSH-Key

    1
    $ ssh-keygen -t rsa -C "youremail@yourcompany.com” -f ~/.ssh/id-rsa
    +

    在~/.ssh/目录会生成id-rsa和id-rsa.pub私钥和公钥。 我们将id-rsa.pub中的内容粘帖到公司gitlab服务器的SSH-key的配置中。

    +

    生成一个github用的SSH-Key

    1
    $ ssh-keygen -t rsa -C "youremail@your.com” -f ~/.ssh/github-rsa
    +

    在~/.ssh/目录会生成github-rsa和github-rsa.pub私钥和公钥。 我们将github-rsa.pub中的内容粘帖到github服务器的SSH-key的配置中。

    +

    添加私钥

    1
    $ ssh-add ~/.ssh/id_rsa $ ssh-add ~/.ssh/github_rsa
    +

    如果执行ssh-add时提示”Could not open a connection to your authentication agent”,可以现执行命令:

    +
    1
    $ ssh-agent bash
    +

    然后再运行ssh-add命令

    +
    1
    2
    3
    4
    # 可以通过 ssh-add -l 来确私钥列表
    $ ssh-add -l
    # 可以通过 ssh-add -D 来清空私钥列表
    $ ssh-add -D
    +

    修改配置文件

    在 ~/.ssh 目录下新建一个config文件

    +
    1
    touch config
    +

    添加内容:

    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # gitlab
    Host gitlab.com
    HostName gitlab.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa
    # github
    Host github.com
    HostName github.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/github_rsa
    +

    测试

    1
    $ ssh -T git@github.com
    +

    输出

    +
    1
    Hi XXX! You've successfully authenticated, but GitHub does not provide shell access.
    +

    就表示成功的连上github了.也可以试试链接公司的gitlab.

    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2016/11/15/2016-11-15-Swift3.0-jie-shao/index.html "b/2016/11/15/Swift3.0\345\255\246\344\271\240\347\254\224\350\256\260/index.html" similarity index 66% rename from 2016/11/15/2016-11-15-Swift3.0-jie-shao/index.html rename to "2016/11/15/Swift3.0\345\255\246\344\271\240\347\254\224\350\256\260/index.html" index 89871bf..8307b1f 100644 --- a/2016/11/15/2016-11-15-Swift3.0-jie-shao/index.html +++ "b/2016/11/15/Swift3.0\345\255\246\344\271\240\347\254\224\350\256\260/index.html" @@ -1,102 +1,400 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Swift3.0学习笔记 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - - - + + + + + + + + + + + + + + + Swift3.0学习笔记 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + - - + - +
    +
    - -
    -
    - + +
    +
    +
    +
    + + +
    -
    - + + + -

    - Swift3.0学习笔记 -

    + + +
    + + + + + + + +
    + + + +

    Swift3.0学习笔记

    + + +
    -
    + +
    + + -

    Swift3.0相关的语法介绍

    + + +

    总结一些 Swift3.0学习笔记

    -

    [TOC]

    -

    Any AnyObject NSObject

    Int Double String struct都是结构体

    +

    Any AnyObject NSObject

    Int Double String struct都是结构体
    s

    1. Any : 一个协议声明
    2. AnyObject : 一个具体的协议,协议里面没有内容,默认情况下,所有的类,都遵循了这个协议
    3. @@ -117,7 +415,7 @@

      循环

      1. for循环

      1
      2
      3
      4
      5
      6
      7
      8
      for i in 0 ..< 10 {
      print(i)
      }
      // _代表忽略的意思
      for _ in 0 ..< 10 {
      print("test")
      }

      2. while循环

      1. while循环

      1
      2
      3
      4
      5
      var i = 10
      while i 0 {
      i -= 1
      print(i)
      }

      2. repeat~while循环

      1
      2
      3
      4
      5
      // do 特殊含义,捕捉异常
      repeat {
      i += 1
      print(i)
      } while i < 10
      -

      字符串处理

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      let str2 = "123"
      let int4 = 10
      // 字符串拼接
      str2 + "\(int4)"
      // 遍历字符串
      for i in str2.characters {
      print(i)
      }
      str2.lengthOfBytes(using: String.Encoding.utf8)
      str2.characters.count
      String(format: "%02d", 1)
      // 截取字符串
      str2.substring(from: str2.startIndex)
      str2.substring(to: str2.index(after: str2.startIndex))
      str2.substring(from: str2.index(str2.startIndex, offsetBy: 2))
      str2.substring(from: str2.index(str2.endIndex, offsetBy: -1))
      let range = str2.startIndex ..< str2.endIndex
      str2.substring(with: range)
      str2.replaceSubrange(range, with: "sss")
      // 转为OC的NSString处理
      let str3 = (str2 as NSString).substring(to: 2)
      +

      字符串处理

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      let str2 = "123"
      let int4 = 10
      // 字符串拼接
      str2 + "\(int4)"
      // 遍历字符串
      for i in str2.characters {
      print(i)
      }
      str2.lengthOfBytes(using: String.Encoding.utf8)
      str2.characters.count
      String(format: "%02d", 1)
      // 截取字符串
      str2.substring(from: str2.startIndex)
      str2.substring(to: str2.index(after: str2.startIndex))
      str2.substring(from: str2.index(str2.startIndex, offsetBy: 2))
      str2.substring(from: str2.index(str2.endIndex, offsetBy: -1))
      let range = str2.startIndex ..< str2.endIndex
      str2.substring(with: range)
      str2.replaceSubrange(range, with: "sss")
      // 转为OC的NSString处理
      let str3 = (str2 as NSString).substring(to: 2)

      数组

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      // 数组的声明和初始化
      let arr1 = [2]
      var arr2 : [Any] = [1, 2, "ii", 11, "ss", "w"]
      let arr3 = [1, 1.1, "ss"] as [Any]
      // 相同类型的数组可以直接相加
      arr2 + arr3
      // 获取
      arr2.first
      arr2.last
      arr2[0]
      // 追加
      arr2.append(2.0)
      // 修改
      arr2[0] = 1
      // 插入
      arr2.insert("sww", at: 2)
      // 删除
      arr2.remove(at: 0)
      arr2.removeFirst()
      arr2.removeFirst(1)
      // 操作数组的区间
      let rang2 = 0 ..< 2
      arr2.removeSubrange(0 ..< 2)
      // 获取数组最大最小
      var arr = [1, 2]
      arr.min()
      arr.max()
      var arr4 = ["a", "3.3"]
      // 比的ASCII码
      arr4.min()
      arr4.max()
      // 数组的遍历
      for i in 0 ..< arr2.count {
      print(arr2[i])
      }
      // 利用元组获取数组的 角标+ 值
      for (key ,value) in arr2.enumerated() {
      print(key, value)
      }
      for i in arr2[0...2] {
      print(i)
      }
      // 转为OC数组的遍历
      (arr2 as NSArray).enumerateObjects({ (value, idx, stop) in
      print(value, idx)
      })

      字典

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      var dict : [String : Any] = ["key" : 1, "key2" : "value"]
      dict["key"] = 2
      let index = dict.index(forKey: "key")
      // index为nil报错
      dict.remove(at: index!)
      // 有则改,无则加
      dict.updateValue("value2", forKey: "key2")
      dict.removeValue(forKey: "key2")
      dict.removeAll()
      for value in dict.values {
      print(value)
      }
      for (key ,value) in dict {
      print(key, value)
      }
      // 类扩展---字典的相+
      extension Dictionary {
      static func +(dic : Dictionary, dic2 : Dictionary) - Dictionary
      {
      var result = dic
      for (key , value) in dic2 {
      result[key] = value
      }
      return result
      }
      }

      元组

      1
      2
      3
      4
      5
      6
      7
      // 元组类型 (name: String, Int, score: Int), 可以作为返回值
      let yz = (name : "zhangsan", _ : 18, score : 2)
      yz.0
      yz.name
      yz.score
      let(name, age, score) = ("zhangsan", 2, 2)
      @@ -130,20 +428,20 @@

      3. guard守护

      1
      2
      3
      4
      5
      6
      func funcl(tmp : Int?) {
      guard let test = tmp else {
      return
      }
      test
      }

      4. 空合运算符

      1
      2
      3
      // 如果sum == nil,那么取 ?? 后面的值
      // 如果 sum != nil, 取 sum! 强制解包后的值
      let tmp2 = sum ?? 0

      类型转换

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      var a = 8.8
      a is Int
      a is Double
      let str = "123"
      str as NSString
      str as Any
      // as! 代表,肯定可以转换成功,转换的结果,是非可选 不能为nil
      // as? 代表,系统尝试帮你进行转换,转失败了,就为nil
      -

      函数

      1. 函数的四种类型

      1. 无参数,无返回值

      1
      2
      3
      4
      5
      6
      7
      8
      9
      func func1() {
      }
      func func2() - Void {
      }
      func func3() - () {
      }
      -

      2. 无参数,有返回值

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      func func1() {
      }
      func func2() - Int {
      return 0
      }
      // 返回元组
      func func3() - (Int, String) {
      return (1, "123")
      }
      +

      函数

      1. 函数的四种类型

      1. 无参数,无返回值

      1
      2
      3
      4
      5
      6
      7
      8
      9
      func func1() {
      }
      func func2() -> Void {
      }
      func func3() -> () {
      }
      +

      2. 无参数,有返回值

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      func func1() {
      }
      func func2() -> Int {
      return 0
      }
      // 返回元组
      func func3() -> (Int, String) {
      return (1, "123")
      }

      3. 有参数,无返回值

      1
      2
      3
      func func1(age : Int) {
      }
      -

      4. 有参数,有返回值

      1
      2
      3
      func func3(age : Int) - (Int, String) {
      return (1, "123")
      }
      -

      函数其他注意

      1. 省略第一个外部参数的名字

      1
      2
      3
      4
      5
      // 省略第一个内部参数(函数内部可以使用的参数)
      // 从swift3.0开始默认第一个参数既是外部参数(函数调用时可以看到的参数)也是内部参数
      func func2(_ name : Int, name2 : Int) - Int {
      return 0
      }
      -

      2. 设置参数默认值

      1
      2
      3
      4
      // 设置默认值,会生成几种组合(带不带第二个参数的)
      func func2(name : Int, name2 : Int = 1) - Int {
      return 0
      }
      -

      3. 设置可变参数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      // 可变参数 类型...
      // 函数内部,把这个参数,当做数组来处理
      // 函数外部,直接可以传递多个值,用逗号隔开
      func addNum(nums : Int...) - Int {
      var result = 0
      for num in nums {
      result += num
      }
      return result
      }
      addNum(nums: 1, 2, 3)
      +

      4. 有参数,有返回值

      1
      2
      3
      func func3(age : Int) -> (Int, String) {
      return (1, "123")
      }
      +

      函数其他注意

      1. 省略第一个外部参数的名字

      1
      2
      3
      4
      5
      // 省略第一个内部参数(函数内部可以使用的参数)
      // 从swift3.0开始默认第一个参数既是外部参数(函数调用时可以看到的参数)也是内部参数
      func func2(_ name : Int, name2 : Int) -> Int {
      return 0
      }
      +

      2. 设置参数默认值

      1
      2
      3
      4
      // 设置默认值,会生成几种组合(带不带第二个参数的)
      func func2(name : Int, name2 : Int = 1) -> Int {
      return 0
      }
      +

      3. 设置可变参数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      // 可变参数 类型...
      // 函数内部,把这个参数,当做数组来处理
      // 函数外部,直接可以传递多个值,用逗号隔开
      func addNum(nums : Int...) -> Int {
      var result = 0
      for num in nums {
      result += num
      }
      return result
      }
      addNum(nums: 1, 2, 3)

      4. 修改内部参数的值

      1
      2
      3
      4
      5
      6
      7
      8
      // 默认不能修改内部参数的值
      func change(num : Int) {
      // num 为常亮,不能修改
      var num = num
      num = 3
      }
      let a = 0
      change(num: a)
      -

      5. 设置参数为地址传递

      1
      2
      3
      4
      // inout设置第一个参数为地址传递
      func func1(name : inout Int, name2 : Int) - Int {
      return 0
      }
      +

      5. 设置参数为地址传递

      1
      2
      3
      4
      // inout设置第一个参数为地址传递
      func func1(name : inout Int, name2 : Int) -> Int {
      return 0
      }

      6. 函数嵌套

      1
      2
      3
      4
      5
      func test() {
      func test2() {
      print("sss")
      }
      }
      -

      7. 函数的类型

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      // (Int, Int) - Int
      // 函数的类型 : 参数类型 和返回值类型
      func add(num : Int, num2 : Int) - Int{
      return num + num2
      }
      // (Int, Int) - Int
      // 函数的类型 : 参数类型 和返回值类型
      func jian(num : Int, num2 : Int) - Int{
      return num - num2
      }
      func exec(n1 : Int, n2 : Int, fun : (Int, Int) - Int) {
      let result = fun(n1 ,n2)
      print(result)
      }
      exec(n1: 3, n2: 2, fun: add)
      exec(n1: 3, n2: 2, fun: jian)
      -

      8. 区分不同函数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      func test() {
      }
      // 参数返回值不同
      func test() - Int {
      return 0
      }
      // 参数类型不同
      func test(age : Int) - Int {
      return 0
      }
      // 参数名字不同
      func test(_ age : Int) - Int {
      return 0
      }
      // 参数名字不同
      func test(name : Int) - Int {
      return 0
      }
      +

      7. 函数的类型

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      // (Int, Int) -> Int
      // 函数的类型 : 参数类型 和返回值类型
      func add(num : Int, num2 : Int) -> Int{
      return num + num2
      }
      // (Int, Int) -> Int
      // 函数的类型 : 参数类型 和返回值类型
      func jian(num : Int, num2 : Int) -> Int{
      return num - num2
      }
      func exec(n1 : Int, n2 : Int, fun : (Int, Int) -> Int) {
      let result = fun(n1 ,n2)
      print(result)
      }
      exec(n1: 3, n2: 2, fun: add)
      exec(n1: 3, n2: 2, fun: jian)
      +

      8. 区分不同函数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      func test() {
      }
      // 参数返回值不同
      func test() -> Int {
      return 0
      }
      // 参数类型不同
      func test(age : Int) -> Int {
      return 0
      }
      // 参数名字不同
      func test(_ age : Int) -> Int {
      return 0
      }
      // 参数名字不同
      func test(name : Int) -> Int {
      return 0
      }

      枚举

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      // 在swift里面,枚举类型,默认情况,不表示任何类型,就是一个标识
      // 类型首字母大写,元素小写
      enum Direction {
      case east
      case west
      }
      enum Direction2 {
      case east, west
      }
      enum Direction3 : Int {
      case east = 1
      case west = 3
      case north // Direction3.north.rawValue = 4 会自己累加
      case south
      }
      // 只有后边指定类型才能敲出rawValue
      // Direction4.left.rawValue 取出的值就是指定的类型
      enum Direction4 : String {
      case left = "left"
      case right = "right"
      case top
      case down
      func func1() {
      print("wwwww")
      }
      static func func2() {
      print("rrrr")
      }
      }
      let rv = Direction3.north.rawValue
      let rv2 = Direction3(rawValue: 1)
      let rv3 = Direction4(rawValue: "left")
      func test(path : Direction4) {
      if path == .left {
      print(path.rawValue)
      }
      }
      -

      结构体

      1. 结构体基本使用

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      // 类型方法 static func
      // 实例方法 func
      // 无论是枚举,还是结构体,都可以写方法
      struct Point {
      // 实例属性
      var x : Double
      var y : Double
      // 实例方法
      func distance() - Double {
      return x - y
      }
      mutating func distance2() - Double {
      x += 2 // 修改实例属性 方法要加mutating
      print(Point.z) // 访问类型属性
      return x - y
      }
      // 类型属性
      static var z : Double = 0 // 需要初始化
      // 类型方法
      static func dis() {
      // print(x) 不能直接访问x
      print(z)
      print(Point.z)
      }
      }
      +

      结构体

      1. 结构体基本使用

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      // 类型方法 static func
      // 实例方法 func
      // 无论是枚举,还是结构体,都可以写方法
      struct Point {
      // 实例属性
      var x : Double
      var y : Double
      // 实例方法
      func distance() -> Double {
      return x - y
      }
      mutating func distance2() -> Double {
      x += 2 // 修改实例属性 方法要加mutating
      print(Point.z) // 访问类型属性
      return x - y
      }
      // 类型属性
      static var z : Double = 0 // 需要初始化
      // 类型方法
      static func dis() {
      // print(x) 不能直接访问x
      print(z)
      print(Point.z)
      }
      }

      2. 结构体扩充构造函数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      struct Point {
      // 实例属性
      var x : Double
      var y : Double
      var z : Double?
      // 自定义 “构造函数” != 普通函数
      // 不加func,必须使用init作为名称
      // 在构造函数内部,必须要保证,所有的非可选属性,必须有值
      // 如果我们自定义了构造函数,那么系统生成的逐一构造器,就没有了
      init(x : Double, y : Double) {
      self.x = x
      self.y = y
      }
      init(x : Double, y : Double, z : Double) {
      self.x = x
      self.y = y
      self.z = z
      }
      }

      1. 类的声明初始化

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      // swift类,是可以不继承父类,那它本身就是rootClass
      // 可以写属性和方法
      // 属性:实例属性,类型属性
      // 方法:实例方法,类型方法
      // 类,默认情况下,不会生成逐一构造器(目的,保证所有的非可选属性有值)
      // 默认情况下,不能保证,所有的非可选属性有值
      // 一个实例对象被创建好以后,必须保证里面所有的非可选属性有值
      // 方案1:在构造函数中入手,给非可选属性初始化
      // 方案2:把非可选 - 可选
      // 方案3:给非可选的属性赋值默认值
      class Person {
      var age : Int
      init(age : Int) {
      // 为了不与age参数冲突才使用self
      self.age = age
      }
      init() {
      age = 2
      }
      }
      // 不会生成逐一构造器
      let p = Person()
      let p2 = Person(age: 3)

      2. 类的属性和方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      class Person {
      // 实例属性 - 存储属性(可以用来存储数值的属性)
      var score = 1
      var score2 : Int = 0 {
      willSet {
      score2 // old
      newValue // new
      }
      // willSet(changeName) {
      // score2 // old
      // changeName // new
      // }
      didSet {
      score2 // new
      oldValue // old
      }
      }
      // 实例属性 - 计算属性(并不是直接用来存储数值的,它是通过某些计算得来的数值)
      var b : Int {
      get {
      return score + score2
      }
      set {
      newValue
      }
      }
      // 类型属性
      static var c = 1
      static var d : Int?
      // 实例方法
      func func1() {
      self.score += 1
      }
      // 类型方法 - 不可以被子类重写override
      static func func2() {
      print("rrrr", c)
      }
      // 类型方法 - 可以被子类重写(结构体不能用class声明方法)
      class func func3() {
      print("sss")
      }
      // 结构体不能使用deinit析构函数
      // 析构函数只能被定义在class类中,不能在extension中
      deinit {
      print("类死了")
      }
      }
      @@ -179,13 +477,13 @@

      3. 协议中的可选

      协议中的可选,仅仅是OC的特性,Swift是不支持的
      解决方案:就是让Swift协议,拥有OC特性

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      @objc
      protocol work {
      @objc optional func run()
      }
      class Stu : work {
      func run() {
      print("Stu run2")
      }
      }

      #泛型

      -
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      // 泛化的类型,不是某一个具体的类型, <T中的T可以自定义名字
      func exchange<T(num1 : inout T, num2 : inout T) {
      let tmp = num1
      num1 = num2
      num2 = tmp
      }
      class Person {
      }
      // 限制 T 必须继承自 Person
      func exchange2<T(num1 : inout T, num2 : inout T) - Int where T : Person {
      let tmp = num1
      num1 = num2
      num2 = tmp
      return 0
      }
      var a = 3
      var b = 9
      var p1 = Person()
      var p2 = Person()
      exchange(num1: &a, num2: &b)
      // 参数必须继承自 Person
      exchange2(num1: &p1, num2: &p2)
      +
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      // 泛化的类型,不是某一个具体的类型, <T>中的T可以自定义名字
      func exchange<T>(num1 : inout T, num2 : inout T) {
      let tmp = num1
      num1 = num2
      num2 = tmp
      }
      class Person {
      }
      // 限制 T 必须继承自 Person
      func exchange2<T>(num1 : inout T, num2 : inout T) -> Int where T : Person {
      let tmp = num1
      num1 = num2
      num2 = tmp
      return 0
      }
      var a = 3
      var b = 9
      var p1 = Person()
      var p2 = Person()
      exchange(num1: &a, num2: &b)
      // 参数必须继承自 Person
      exchange2(num1: &p1, num2: &p2)

      闭包

      闭包 == 特殊的函数

      -

      1.闭包的基本使用

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      // 函数
      func add(num1 : Int, num2 : Int) - Int {
      return num1 + num2
      }
      // 简单的闭包
      // 如果闭包,参数是没有的,可以省略,in和in前面的内容
      var bibao : ()-() = {
      // ()-() in // 可以省略
      }
      // 带参数的闭包
      var bibao2 : (Int, Int)-(Int) = {
      // (varg1, varg2) in
      (varg1 : Int, varg2 : Int) in
      return varg1 + varg2
      }
      bibao2(10, 20)
      // 闭包当做参数
      func exec(n1 : Int, n2 : Int, block : (Int, Int)-(Int)) - Int {
      return block(n1, n2)
      }
      exec(n1: 20, n2: 30, block: add)
      exec(n1: 20, n2: 30, block: bibao2)
      exec(n1: 20, n2: 30, block: {
      (a : Int, b : Int)-(Int) in
      return a * b
      })
      -

      2. 尾随闭包和逃逸闭包

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      //尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。在使用尾随闭包时,你不用写出它的参数标签(此处是bb)
      // 如果一个函数的参数,是一个闭包类型,那么默认情况下,是一个“非逃逸”闭包;(闭包,生命周期,是函数)
      func test(a : Int, bb : (Int, Int)-(Int)) {
      let result = bb(a, 3)
      print(result)
      }
      test(a: 20) { (sum1, sum2) - (Int) in
      return sum1 - sum2
      }
      // @escaping : 代表,这个闭包,是逃逸闭包,以后,有可能,会被其他的闭包,延长生命周期(强引用)
      func test2(bb : @escaping (Int, Int)-(Int)) {
      bb(23, 3)
      let queue = DispatchQueue(label: "xx")
      let time = DispatchTime.now() + DispatchTimeInterval.seconds(2)
      queue.asyncAfter(deadline: time) {
      // 此处编译器会提示添加 @escaping
      _ = bb(10, 3)
      }
      }
      test2 { (sum, sum2) - (Int) in
      return sum * sum2
      }
      -

      3. 闭包的循环引用(4中解决方式)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      class Person {
      class Person {
      var resultBlock : (()-())?
      var age : Int = 0
      func test() {
      // weak 对象最后会被置为 nil,所以var
      weak var weakSelf = self
      resultBlock = {
      print("222",weakSelf?.age)
      }
      resultBlock?()
      }
      func test2() {
      resultBlock = {
      [weak self] in
      print(self?.age)
      }
      resultBlock?()
      }
      func test3() {
      // unowned == __unsafe_unretained 最后不会置为nil,编译器建议为let
      unowned let weakSelf = self
      resultBlock = {
      print(weakSelf.age)
      }
      resultBlock?()
      }
      func test4() {
      resultBlock = {
      [unowned self] in
      print(self.age)
      }
      resultBlock?()
      }
      deinit {
      print("人被释放了")
      }
      }
      var p : Person? = Person()
      p?.test()
      p = nil
      +

      1.闭包的基本使用

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      // 函数
      func add(num1 : Int, num2 : Int) -> Int {
      return num1 + num2
      }
      // 简单的闭包
      // 如果闭包,参数是没有的,可以省略,in和in前面的内容
      var bibao : ()->() = {
      // ()->() in // 可以省略
      }
      // 带参数的闭包
      var bibao2 : (Int, Int)->(Int) = {
      // (varg1, varg2) in
      (varg1 : Int, varg2 : Int) in
      return varg1 + varg2
      }
      bibao2(10, 20)
      // 闭包当做参数
      func exec(n1 : Int, n2 : Int, block : (Int, Int)->(Int)) -> Int {
      return block(n1, n2)
      }
      exec(n1: 20, n2: 30, block: add)
      exec(n1: 20, n2: 30, block: bibao2)
      exec(n1: 20, n2: 30, block: {
      (a : Int, b : Int)->(Int) in
      return a * b
      })
      +

      2. 尾随闭包和逃逸闭包

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      //尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。在使用尾随闭包时,你不用写出它的参数标签(此处是bb)
      // 如果一个函数的参数,是一个闭包类型,那么默认情况下,是一个“非逃逸”闭包;(闭包,生命周期,是函数)
      func test(a : Int, bb : (Int, Int)->(Int)) {
      let result = bb(a, 3)
      print(result)
      }
      test(a: 20) { (sum1, sum2) -> (Int) in
      return sum1 - sum2
      }
      // @escaping : 代表,这个闭包,是逃逸闭包,以后,有可能,会被其他的闭包,延长生命周期(强引用)
      func test2(bb : @escaping (Int, Int)->(Int)) {
      bb(23, 3)
      let queue = DispatchQueue(label: "xx")
      let time = DispatchTime.now() + DispatchTimeInterval.seconds(2)
      queue.asyncAfter(deadline: time) {
      // 此处编译器会提示添加 @escaping
      _ = bb(10, 3)
      }
      }
      test2 { (sum, sum2) -> (Int) in
      return sum * sum2
      }
      +

      3. 闭包的循环引用(4中解决方式)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      class Person {
      class Person {
      var resultBlock : (()->())?
      var age : Int = 0
      func test() {
      // weak 对象最后会被置为 nil,所以var
      weak var weakSelf = self
      resultBlock = {
      print("222",weakSelf?.age)
      }
      resultBlock?()
      }
      func test2() {
      resultBlock = {
      [weak self] in
      print(self?.age)
      }
      resultBlock?()
      }
      func test3() {
      // unowned == __unsafe_unretained 最后不会置为nil,编译器建议为let
      unowned let weakSelf = self
      resultBlock = {
      print(weakSelf.age)
      }
      resultBlock?()
      }
      func test4() {
      resultBlock = {
      [unowned self] in
      print(self.age)
      }
      resultBlock?()
      }
      deinit {
      print("人被释放了")
      }
      }
      var p : Person? = Person()
      p?.test()
      p = nil

      懒加载

      只是在第一次访问的时候,会调用相应的函数,获取实例,下次即使值为nil,也不会再次调用相应的函数,获取新的实例

      -
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      class Dog {
      var name : String = "wangcai"
      init() {
      print("创建了小狗")
      }
      }
      // 懒加载
      // 函数:构造函数,一般的函数,闭包
      // = 后面可以跟的值:具体的指,构造“函数”
      // 所谓的懒加载,是指,在用的时候,再通过后面的函数,获取相应的实例
      class Person {
      lazy var dog : Dog = Dog()
      // 这样的懒加载可以对创建的对象进行修改
      lazy var dog2 : Dog = Person.getDog()
      // 懒加载内容放到闭包,最后调用闭包
      lazy var dog3 : Dog = {
      let d = Dog()
      d.name = "dog3"
      return d
      }()
      lazy var dog4 : Dog = {
      $0.name = "dog4"
      return $0
      }(Dog())
      static func getDog() - Dog {
      let d = Dog()
      d.name = "getDog"
      return d
      }
      }
      +
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      class Dog {
      var name : String = "wangcai"
      init() {
      print("创建了小狗")
      }
      }
      // 懒加载
      // 函数:构造函数,一般的函数,闭包
      // = 后面可以跟的值:具体的指,构造“函数”
      // 所谓的懒加载,是指,在用的时候,再通过后面的函数,获取相应的实例
      class Person {
      lazy var dog : Dog = Dog()
      // 这样的懒加载可以对创建的对象进行修改
      lazy var dog2 : Dog = Person.getDog()
      // 懒加载内容放到闭包,最后调用闭包
      lazy var dog3 : Dog = {
      let d = Dog()
      d.name = "dog3"
      return d
      }()
      lazy var dog4 : Dog = {
      $0.name = "dog4"
      return $0
      }(Dog())
      static func getDog() -> Dog {
      let d = Dog()
      d.name = "getDog"
      return d
      }
      }

      注释

      1
      2
      3
      // MARK: - ARC
      // TODO: - todo
      // FIXME: 解决bug

      访问权限

      1. Swift中的访问控制模型基于模块和源文件、类这三个概念
      2. @@ -197,9 +495,10 @@

        方法抛出异常

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        // Error 就是在告诉编译器,这个枚举,可以充当具体的异常值
        enum FileError : Error{
        case notExists
        case notFormat
        case notContent
        }
        // path 不存在 nil
        // path存在,但是,路径对应的文件格式不对 .png
        func readFile(path : String) throws - String {
        // 1. 判断文件路径是否存在
        let isExists = FileManager.default.fileExists(atPath: path)
        if !isExists {
        // 在这里面,抛出,出现问题的原因
        // 如果想要成为,异常值,必须要遵循一个协议Error
        throw FileError.notExists
        // return
        }
        // 2. 读取文件内容
        // 判定,如果这个构造函数,出现了异常,一般都是格式不正确
        var content : String = ""
        do {
        content = try String(contentsOfFile: path)
        } catch {
        // 捕捉到异常,会执行这个闭包
        throw FileError.notFormat
        }
        if content.lengthOfBytes(using: String.Encoding.utf8) == 0 {
        throw FileError.notContent
        }
        return content
        }
        +

        方法抛出异常

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        // Error 就是在告诉编译器,这个枚举,可以充当具体的异常值
        enum FileError : Error{
        case notExists
        case notFormat
        case notContent
        }
        // path 不存在 nil
        // path存在,但是,路径对应的文件格式不对 .png
        func readFile(path : String) throws -> String {
        // 1. 判断文件路径是否存在
        let isExists = FileManager.default.fileExists(atPath: path)
        if !isExists {
        // 在这里面,抛出,出现问题的原因
        // 如果想要成为,异常值,必须要遵循一个协议Error
        throw FileError.notExists
        // return
        }
        // 2. 读取文件内容
        // 判定,如果这个构造函数,出现了异常,一般都是格式不正确
        var content : String = ""
        do {
        content = try String(contentsOfFile: path)
        } catch {
        // 捕捉到异常,会执行这个闭包
        throw FileError.notFormat
        }
        if content.lengthOfBytes(using: String.Encoding.utf8) == 0 {
        throw FileError.notContent
        }
        return content
        }

        Playground

        1. Playground异步执行

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        // Playground中的代码会从上到下执行,并在执行完毕之后立即停止,如果想要测试异步处理(比如网络请求)
        // 1. 导入PlaygroundSupport
        // import PlaygroundSupport
        // 2. 让Playground永远执行
        //PlaygroundPage.current.needsIndefiniteExecution = true
        // 3. 停止执行
        // PlaygroundPage.current.finishExecution()
        import PlaygroundSupport
        PlaygroundPage.current.needsIndefiniteExecution = true
        let queue = DispatchQueue(label: "xx")
        let time = DispatchTime.now() + DispatchTimeInterval.seconds(2)
        queue.asyncAfter(deadline: time) {
        print("finish")
        PlaygroundPage.current.finishExecution()
        }
        print("first")
        -

        2. MarkDown语法

        从Xcode右边文件属性,选中Render Documentation看渲染效果

        1
        2
        3
        4
        5
        //: [Previous](@previous)
        //: [Next](@next)
        //PageName为页名字不能有空格
        //: [Go to AnyPage](PageName)

        +

        2. MarkDown语法

        从Xcode右边文件属性,选中Render Documentation看渲染效果

        +
        1
        2
        3
        4
        5
        //: [Previous](@previous)
        //: [Next](@next)
        //PageName为页名字不能有空格
        //: [Go to AnyPage](PageName)

        3. TimeLine使用

        点击右上角双环(Show the Assistant editor),在代码中做的动画可以在TimeLine中预览

        4. Playground的Sources目录

        1. 放到Sources目录下的源文件会被编译成模块(module)并自动导入到Playground中,只会编译一次
        2. @@ -208,118 +507,419 @@

          -

    - - - +
    + - - - +
    + -
    + - + + +
    - +
    + +
    -
    -

    归档

    -
    - - -
    -

    最新文章

    -
    -
      +
    -
  • - Swift3.0学习笔记 + + + + +
  • + + - -
    -
    +
    + +
    +
    + + +
    + + +
    + +
    - -
    - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - - - -
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git "a/2016/12/03/iOS9\346\226\260\347\211\271\346\200\247\344\271\213\345\270\270\350\247\201\345\205\263\351\224\256\345\255\227/index.html" "b/2016/12/03/iOS9\346\226\260\347\211\271\346\200\247\344\271\213\345\270\270\350\247\201\345\205\263\351\224\256\345\255\227/index.html" new file mode 100644 index 0000000..533199c --- /dev/null +++ "b/2016/12/03/iOS9\346\226\260\347\211\271\346\200\247\344\271\213\345\270\270\350\247\201\345\205\263\351\224\256\345\255\227/index.html" @@ -0,0 +1,875 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + iOS9新特性之常见关键字 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    iOS9新特性之常见关键字

    + + + +
    + + +
    + + + + + +

    iOS9新出的关键字,用来修饰属性,或者方法的参数,方法的返回值
    好处:

    +
      +
    • 迎合swift
    • +
    • 提高我们开发人员开发规范,减少程序员之间的交流
    • +
    + +

    nullable和nonnull

    nullable:表示可以为空,nonnull为非空
    只能修饰对象,不能修饰int等,因为nil只能赋值给对象
    书写规范一样,以nullable为例:

    +
      +
    • 方式一:
    • +
    +
    1
    @property (nonatomic, strong, nullable) NSString *name;
    +
      +
    • 方式二:
    • +
    +
    1
    @property (nonatomic, strong) NSString *_Nullable name;
    +
      +
    • 方式三:
    • +
    +
    1
    @property (nonatomic, strong) NSString *__nullable name;
    +
      +
    • 方式四:修饰方法
    • +
    +
    1
    2
    - (nonnull NSString *)name:(nonnull NSString *)str;
    - (NSString *_Nonnull)name;
    +
      +
    • 方式五:
    • +
    +

    NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END之间定义的所有对象属性和方法默认都是nonnull

    +
    1
    2
    3
    NS_ASSUME_NONNULL_BEGIN
    @property (nonatomic, strong) NSString *name;
    NS_ASSUME_NONNULL_END
    +

    null_resettable

    1
    2
    // null_resettable:get不能返回空,set可以为空(比如控制器的view)
    @property (nonatomic, copy, null_resettable) NSString *name;
    +

    null_resettable必须重写setter或者getter方法,处理传递的值为空的情况(实际重写不判断为空警告也没了),不然会有警告。

    +

    null_unspecified

    null_unspecified不确定是否为空

    +
    1
    2
    @property (nonatomic, strong) NSString *_Null_unspecified name;
    @property (nonatomic, strong, null_unspecified) NSString *name;
    +

    泛型

    泛型:限制类型
    泛型使用场景:

    +
      +
    • 在集合(数组、字典、NSSet)中使用泛型比较常见。
    • +
    • 当声明一个类。类里面的某些属性的类型不确定,这时候我们才使用泛型。
    • +
    +

    泛型好处:

    +
      +
    • 提高开发规范,减少程序员之间交流
    • +
    • 通过集合取出来对象,直接当做泛型对象使用,可以直接使用点语法
    • +
    +
    1
    2
    3
    4
    @property (nonatomic, strong) NSArray<NSString *> *nameArr;
    // 后面使用时可以直接调出对应的方法
    self.nameArr[0].length;
    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // ObjectType可以自己指定名字
    @interface Person<ObjectType> : NSObject
    @property (nonatomic) ObjectType language;
    - (ObjectType)language;
    @end
    Person<NSString *> *p = [Person new];
    p.language = @"ss";
    +

    __covariant

    (协变): 用于泛型数据强转类型,可以向上强转,子类可以转成父类。

    +
    1
    2
    3
    4
    5
    6
    @interface Person<__covariant ObjectType> : NSObject
    @property (nonatomic) ObjectType language;
    - (ObjectType)language;
    @end
    +

    __contravariant

    (逆变): 用于泛型数据强转类型,可以向下强转,父类可以转成子类。

    1
    2
    @interface Person<__contravariant ObjectType> : NSObject
    @end

    +

    __kindof

    __kindof表示当前类或者它的子类
    好处:

    +
      +
    • 可以在编译的时候,检查真实类型
    • +
    • 返回值会有提示修饰的当前类
    • +
    +
    1
    2
    3
    @property (nonatomic, strong) NSArray<__kindof NSString *> *nameArr;
    - (__kindof NSString *)test;
    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/2017/04/02/iOS\351\200\206\345\220\221\345\267\245\345\205\267\346\216\250\350\215\220/index.html" "b/2017/04/02/iOS\351\200\206\345\220\221\345\267\245\345\205\267\346\216\250\350\215\220/index.html" new file mode 100644 index 0000000..6807ae1 --- /dev/null +++ "b/2017/04/02/iOS\351\200\206\345\220\221\345\267\245\345\205\267\346\216\250\350\215\220/index.html" @@ -0,0 +1,847 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + iOS逆向工具推荐 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    iOS逆向工具推荐

    + + + +
    + + +
    + + + + + +

    还原符号表(作者blog)
    https://github.com/tobefuturer/restore-symbol

    +

    转换成动态库(作者blog)
    https://github.com/tobefuturer/app2dylib

    +

    iOS逆向-静态分析

    OpenSSH (用于远程登录ssh和文件传输scp)
    class-dump(用于简单分析出工程中的类名和函数名)
    Hopper Disassembler(反编译工具)
    Reveal (对越狱后的设备查看任意app的布局)

    +

    iOS逆向-动态分析

    cycript (cycript是一个脚本语言,可以看做Objective-JavaScript,形容 的非常贴切。配合静态调试,可以调用运行中的app内的任意方法)

    +

    iOS逆向-内部钩子

      +
    1. CaptainHook文档 https://github.com/rpetrich/CaptainHook/wiki
    2. +
    3. https://github.com/steipete/Aspects
    4. +
    5. Theos创建Tweak工程,Logos语法写Tweak.xm
    6. +
    +

    其他

    debug server
    openssh

    +

    iOS逆向思路进展:使用InspectiveC来查看调用堆栈:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    跟踪一个程序,看看这个程序的执行流程是什么样的,以及某个函数的调用参数是什么。
    常规的方法是在汇编中寻找objc_msgSend,一层一层跟下去。这是比较笨的办法,而且不能动态查看函数的数。
    通过InspectiveC,我们可以动态的查看:
    * 某个类的所有方法调用情况
    * 某个类的某个方法的调用情况
    * 某个类的实例对象的所有方法的调用情况
    * 某个类的实例对象的某个方法的调用情况
    * 某个方法签名的调用情况
    +

    砸壳

      +
    1. dumpdecrypted https://github.com/stefanesser/dumpdecrypted
    2. +
    3. Clutch https://github.com/KJCracks/Clutch
    4. +
    5. pp助手直接下载越狱app
    6. +
    +
    1
    2
    3
    4
    5
    6
    7
    8
    * MobileHooker用于替换覆盖系统的方法,这个过程被称为Hooking(挂钩)
    * 它主要包含两个函数:
    void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP *result);
    void MSHookFunction(void*function,void* replacement,void** p_original);
    MSHookMessageEx 主要作用于Objective-C函数
    MSHookFunction 主要作用于C和C++函数
    Logos语法就是对此函数做了一层封装,让编写hook代码变的更直观,上面的例子用的就是logos语法。
    MSHookMessageEx 和MSHookFunction 使用方法这里就不介绍了,大家可去看书籍或者查询相关资料。
    +

    介绍几个互联网安全圈内比较知名的网站

    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/2017/04/03/iOS\351\200\206\345\220\221(1)class-dump\350\216\267\345\217\226\345\244\264\346\226\207\344\273\266/index.html" "b/2017/04/03/iOS\351\200\206\345\220\221(1)class-dump\350\216\267\345\217\226\345\244\264\346\226\207\344\273\266/index.html" new file mode 100644 index 0000000..2406a28 --- /dev/null +++ "b/2017/04/03/iOS\351\200\206\345\220\221(1)class-dump\350\216\267\345\217\226\345\244\264\346\226\207\344\273\266/index.html" @@ -0,0 +1,828 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + iOS逆向(1)class-dump获取头文件 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    iOS逆向(1)class-dump获取头文件

    + + + +
    + + +
    + + + + + +

    简述

      class-dump顾名思义,是用来dump目标对象class信息的工具。它根据oc的runtime特性,将存储在Mach-O文件中的头文件信息提取出来,生成对应的.h文件。

    +

    下载安装

    最新版本官网下载地址,下载后打开dmg文件,并将class-dump可执行文件放在/usr/bin目录下

    +

    在终端执行:

    +
    1
    sudo chmod 777 /usr/bin/class-dump
    +

    使用方法

    需要用到终端。在终端输入:

    1
    class-dump -H 要破解的可执行文件路径 -o 破解后的头文件存放路径

    +

    获取ipa后解压,用解压工具解压,找到.app文件(一般在Payload目录下),右键显示包内容,找到可执行文件,按照上边的指令得到.h文件。

    +

    iOS逆向工程之Theos-青玉伏案的博客
    iOS逆向工程工具之Theos

    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/2017/04/03/iOS\351\200\206\345\220\221class-dump\350\216\267\345\217\226\345\244\264\346\226\207\344\273\266/index.html" "b/2017/04/03/iOS\351\200\206\345\220\221class-dump\350\216\267\345\217\226\345\244\264\346\226\207\344\273\266/index.html" new file mode 100644 index 0000000..0fc0c00 --- /dev/null +++ "b/2017/04/03/iOS\351\200\206\345\220\221class-dump\350\216\267\345\217\226\345\244\264\346\226\207\344\273\266/index.html" @@ -0,0 +1,831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + iOS逆向class-dump获取头文件 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    iOS逆向class-dump获取头文件

    + + + +
    + + +
    + + + + + +

    简述

      class-dump顾名思义,是用来dump目标对象class信息的工具。它根据oc的runtime特性,将存储在Mach-O文件中的头文件信息提取出来,生成对应的.h文件。

    +

    下载安装

    最新版本官网下载地址,下载后打开dmg文件,并将class-dump可执行文件放在/usr/bin目录下

    +

    在终端执行:

    +
    1
    sudo chmod 777 /usr/bin/class-dump
    +

    使用方法

    需要用到终端。在终端输入:

    1
    class-dump -H 要破解的可执行文件路径 -o 破解后的头文件存放路径

    +

    获取ipa后解压,用解压工具解压,找到.app文件(一般在Payload目录下),右键显示包内容,找到可执行文件,按照上边的指令得到.h文件。

    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/2017/04/03/iOS\351\200\206\345\220\221\345\267\245\347\250\213\344\271\213Theos/index.html" "b/2017/04/03/iOS\351\200\206\345\220\221\345\267\245\347\250\213\344\271\213Theos/index.html" new file mode 100644 index 0000000..dce10ac --- /dev/null +++ "b/2017/04/03/iOS\351\200\206\345\220\221\345\267\245\347\250\213\344\271\213Theos/index.html" @@ -0,0 +1,922 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + iOS逆向之Theos基础到实战 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    +
    + + +
    + + + + + + + + +
    + + + + + + + +
    + + + +

    iOS逆向之Theos基础到实战

    + + + +
    + + +
    + + + + + +

    Theos是一个越狱开发工具包,Theos是越狱开发工具的首先,因为其最大的特点就是简单。大道至简,Theos的下载安装、编译发布都比较简单,越狱开发中另一个常用的工具是iOSOpenDev,因为本篇的主题是Theos,所以对iOSOpenDev不做过多赘述。本篇博客的主题是Thoes的安装及其使用。

    + +

    Theos的配置与安装

    Theos的配置与安装算是比较简单的,Theos的官方文档地址官方Wiki,当然进行该部分操作时,要保证你本地已经安装了Homebrew.

    +
    1
    2
    3
    4
    5
    # 官方推荐安装到/opt/目录下
    export THEOS=/opt/theos
    # 如果之前已经安装过 theos,请先删除,然后下载最新版
    rm -rf $THEOS
    sudo git clone --recursive https://github.com/theos/theos.git $THEOS
    +

    下载好Theos后,要修改一下文件的权限,如下命令

    +
    1
    sudo chown (id−u):(id−u):(id -g) theos
    +

    至此,Theos安装完毕

    +

    配置 dpkg-deb

    deb 是越狱开发安装包的标准格式,而 dpkg-deb 是操作 deb 文件的工具,有了这个工具,Theos 才能将工程正确地打包成 deb 包。

    +

    https://raw.githubusercontent.com/DHowett/dm.pl/master/dm.pl下载dm.pl,将其重命名为 dpkg-deb 后,放到 /opt/theos/bin/ 目录下

    +

    安装ldid

    在Theos开发插件中,iOS文件的签名是使用ldid工具来完成的,也就是说ldid取代了Xcode自带的Codesign。下方就是ldid的安装过程。

    +
    1
    brew install ldid
    +

    Theos创建deb包

    1
    $THEOS/bin/nic.pl
    +

    接下来我们就要使用theos来创建我们的工程了,创建工程也是比较简单的,就是调用我们theos目录中bin下的nic.pl命令。具体执行如下所示。在执行nic.pl命令后,会让你选择新建工程的模板,目前theos中内置的是12套模板,当然你可以从网上下载其他的模板。当然我们此处创建的是application_modern类型的工程,所以我们就选2即可,当然,如果你想创建tweak,那么就选11即可,下方我们选择的是第二个模板。

    +

    在选择模板后,紧接着会让你做一系列的操作,这一些列的操作和Xcode新建iOS工程的步骤类似。

    +

    (1)输入你的工程的名字(Project Name,必选项),此处我们工程的名字是FirstTheosApplication。

    +

    (2)输入包名(Package Name),包名的命名规则一般是你们公司域名的倒写,然后后边加上你的工程名字,此处我就随便写了一个,就是下方的com.ludashi.firsttheosapplication。

    +

    (3)输入作者的名字(Author/Maintainer Name), 此处我们输入的是Mr.LuDashi

    +

    (4)然后如数类名的前缀(Class name prefix), 此处我们输入的是CE。

    +

    经过上述配置后,我们的工程就创建好了。

    +

    下方是我们创建后的工程文件目录,当然packages文件夹是我们编译打包后才生成的文件,其中的deb就是我们的安装文件。可以将该安装包安装到我们的越狱手机上。

    接着我们要做一些编译打包前的准备工作,SDKVERSION是编译工程时所使用的SDK,因为本机Xcode中是9.3的SDK,所以我们知道的SDKVERSION是9.3。指定完编译所需的SDK后,我们需要指定打包后的文件所安装设备的IP地址,使用THEOS_DEVICE_IP来指定。下方的IP地址是一个越狱手机的IP地址。

    +

    在指定这个设备IP之前,你要保证你的越狱设备安装了OpenSSH,并且可以在Mac的终端上进行ssh登录。

    +

    编译打包前的准备工作

    1
    2
    export SDKVERSION=9.3
    export THEOS_DEVICE_IP=ios设备的ip
    +

    进行编译

    做好编译前的准备工作后,紧接着就是编译我们刚才创建的工程了。首先进入到我们的firsttheosapplication目录中,执行make命令进行编译.

    +
    1
    2
    cd firsttheosapplication
    make
    +

    进行打包

    1
    make package
    +

    Snip20170512_6

    +

    安装

    1
    make install
    +

    从Cydia中进行查看

    下方就是我们项目安装后的效果。打开Cydia,选择已安装Tab, 会看到我们刚才安装的FirstTheosApplication(实用工具),我们可以点进去进行查看,其中的一些信息大部分是我们刚才配置的信息。到此我们一个完整的流程就走完了。

    +

    Theos创建Tweak工程

    下方就是我们Tweak工程的创建,与上述工程的创建类似,不过我们在此选择的是Tweak模板。如下所示,我们将该Tweak工程命名为LockScreenAlter,其他配置项使用默认值即可。然后进入到我们的LockScreenAlter工程目录中,主要有下方四个文件。
    Tweak工程创建

    +

    Makefile文件

    该文件类似于配置文件,用来指定工程用到的文件、框架、库、使用的SDK等等,将整个编译、打包、安装的过程进行自动化。下方就是我们Makefile中的内容,下方红框中是创建完工程后默认的配置,上面红框中是后来我们添加的配置。这些项指定了编译、安装时所需的参数,使其自动化

    +

    Tweak.xm文件的编写

    分析这一步是至关重要的,因为这一步可以让你明白你的代码作用于何处。因为我们要在锁屏的页面进行弹框,所以我们要在相应的锁屏页面添加hook。下方就是我们的分析过程。经过浏览系统的头文件,我们从下方路径中找到了SBLockScreenManager.h这个文件,从文件名不难推测出该文件就是负责iPhone系统锁屏的文件,于是乎我们对其进行hook实现。

    +

    下方是上述头文件的内容,从内容我们更加坚信SBLockScreenManager类就是用来管理系统锁屏的,因为其中有个字段是用来表示是否已经锁屏的isUILocked。该头文件中还有一个类方法和一个对象方法。当然这个类方法明眼一看就是用来获取该类的单例的。而对象方法lockUIFromSource……应该是用来锁屏和解锁的。于是乎想要在锁屏中弹框就要在SBLockScreenManager类中的唯一的对象方法中进行操作了。

    +

    下方就是在Tweak.xm中的所有代码。是Logos语法,使用起来是比较简单的。%hook与%end成对出现,%hook后方跟的是我们要修改的类名,此处我们要对SBLockScreenManager进行修改,类似于OC中的继承操作。%orig,用来执行修改函数的原始函数,此处可以看做是OC语法中的super,类似于调用父类的方法。下方代码就用到这些Logos语法就足以在锁屏出进行弹框了。

    +

    常用Logos语法简介:

    +
    1
    2
    3
    4
    5
    6
    7
    8
    %hook 指定需要hook的类名,以%end结尾
    %log 用来打印log的,将信息输入到syslog中,如%log((NSString *)@"ZeluLi")
    %orig 执行被hook函数的原始代码,类似于super.method功能
    %group 该指令用于%hook的分组,%group后边跟的是组名,%group也是必须以%end结尾,其中可以包含多个%hook
    %init 该指令用来初始化某个%group,一个group只有被初始化后才可生效,init必须在hook中进行执行。
    %ctor tweak的构造器,用来初始化,如果不显式定义,Theos就会自动生成一个%ctor,并在其中调用%init(_ungrouped). 如:%ctor { %init(_ungrouped)}
    %new 该指令用来给现有的class添加一个新的函数。与Runtime中的class_addMethod相同。
    %c 该指令用来获取一个类的名称,类似于objc_getClass。
    +

    上述就先涉及这么多,更详细的请参加:http://iphonedevwiki.net/index.php/Logos

    +

    control文件

    control文件中存储的内容记录了deb包管理系统所需的基本信息,会被打包进deb包里。下方就是control中内容,其中存储的就是一些包名、工程名、版本、作者等等,与打包安装后在Cydia中看到的信息相同。

    +

    进行编译、打包、安装

    编译打包安装的过程与上一部分类型,在此就只展示一下过程,不做过多赘述了。

    +
      +
    • 编译 make
    • +
    • 打包make package
    • +
    • 安装到手机make install
    • +
    +

    从Cydia中进行查看

    下方就是我们成功安装后在Cydia中查看的截图,安装成功后,当你锁屏时就会弹出一个Alter。

    +

    免越狱安装注入dylib的App

    生成dylib

    创建完Tweak工程编译后,在.theos文件层级下面生成了dylib文件
    Snip20170512_8

    +

    检查依赖

    1
    otool -L Test.dylib
    +

    Snip20170512_10
    这里有对CydiaSubstrate的依赖 , 这是不行的 , 这个是theos在越狱机上特有的, 在非越狱机上需要更改此依赖

    +

    首先要找到libsubstrate.dylib文件,该文件应该在/opt/thoes/lib/目录下,没有了点击libsubstrate下载,然后将其拷贝到与你生成的的.dylib一个目录下,通过下面的指令修改依赖

    +
    1
    install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/libsubstrate.dylib Test.dylib
    +

    然后重新查看Test.dylib
    会发现依赖已经被修改完毕
    Snip20170512_11

    +

    获取砸壳版本的微信 ipa

    因为在 AppStore 上面下载得到的应用都是经过加密的,可以执行文件上已经被加过一层壳,所以我们需要先拿到砸过壳版本的微信应用。
    有两种方法:

    +
      +
    1. 直接在 PP 助手下载
    2. +
    3. 使用 Clutch 对越狱手机上应用进行砸壳
    4. +
    5. dumpdecrypted,使用方法请参考博客
    6. +
    +

    第一种方法没什么好说的,这里主要讲讲第二种方法。
    首先,将 Cluth 仓库 clone 到本地

    +
    1
    2
    git clone https://github.com/KJCracks/Clutch
    cd Clutch
    +

    接着,使用 Xcode 进行构建,得到可执行文件:

    +
    1
    xcodebuild -project Clutch.xcodeproj -configuration Release ARCHS="armv7 armv7s arm64" build
    +

    生成出来的可执行文件就在 Clutch 目录下,将其拷贝到手机上:

    +
    1
    scp Clutch/clutch root@<your.device.ip>:/usr/bin/
    +

    之后,就可以使用这个工具来进行砸壳了。

    +

    先 ssh 到越狱手机上,然后列出当前安装的应用:

    +
    1
    2
    3
    4
    5
    6
    ssh root@<your.device.ip>
    clutch -i
    # Installed apps:
    # 1: WeChat <com.tencent.xin>
    # 2: DingTalk <com.laiwang.DingTalk>
    # 3: 喜马拉雅FM(听书社区)电台有声小说相声英语 <com.gemd.iting>
    +

    可以得到 clutch 把相应的包名也显示出来了,这时我们就可以进行砸壳了:

    +
    1
    2
    3
    4
    5
    6
    7
    8
    9
    clutch -d com.tencent.xin
    # com.tencent.xin contains watchOS 2 compatible application. It's not possible to dump watchOS 2 apps with Clutch 2.0.4 at this moment.
    # Zipping WeChat.app
    # Swapping architectures..
    # ASLR slide: 0xb3000
    # ...
    # writing new checksum
    # DONE: /private/var/mobile/Documents/Dumped/com.tencent.xin-iOS7.0-(Clutch-2.0.4).ipa
    # Finished dumping com.tencent.xin in 76.9 seconds
    +

    可以看到,clutch 将砸过后的 ipa 文件放到了 /private/var/mobile/Documents/Dumped/ 目录下。

    +

    我们将它改成一个比较简单的名字,然后拷回电脑上:

    +
    1
    2
    mv /private/var/mobile/Documents/Dumped/com.tencent.xin-iOS7.0-\(Clutch-2.0.4\).ipa /private/var/mobile/Documents/Dumped/wechat.ipa
    scp root@<your.device.ip>:/private/var/mobile/Documents/Dumped/wechat.ipa ~/Desktop
    +

    将动态链接库注入二进制文件中

    接下来,就需要将我们的库注入到微信的二进制文件中,可以使用开源的 optool 工具。

    +

    编译安装 optool 工具:

    +
    1
    2
    3
    4
    因为 optool 添加了 submodule,因为需要使用 --recuresive 选项,将子模块全部 clone 下来
    git clone --recursive https://github.com/alexzielenski/optool.git
    cd optool
    xcodebuild -project optool.xcodeproj -configuration Release ARCHS="x86_64" build
    +
    1
    如果碰到类似 “error: There is no SDK with the name or path ‘/path/to/optool/macosx10.9’” 的错误,请使用 Xcode 打开工程,在 Build Setting 中选择正确的 SDK 版本。
    +

    将砸壳过的 ipa 文件解压,然后将 libsubstrate.dylib 与 Test.dylib 拷贝到解压后的WeChat.app 目录下。

    +
    1
    2
    # cd 到Test.dylib同级目录
    cp libsubstrate.dylib Test.dylib /Users/shmily/test/.theos/obj/debug/微信-6.5.7\(越狱应用\)/Payload/WeChat.app
    +

    Snip20170512_12

    +

    使用 optool 把 Test.dylib 注入到二进制文件中:

    +
    1
    optool install -c load -p "@executable_path/Test.dylib" -t /Users/shmily/test/.theos/obj/debug/微信-6.5.7\(越狱应用\)/Payload/WeChat.app/WeChat
    +

    Snip20170512_13

    +
    1
    2
    在开始打包之前,请先将 WeChat.app 里面的 Watch 目录删除,这个目录是跟 Watch 有关的,如果不删除的话,会导致后继的安装步骤出问题。
    出现 A WatchKit app within this app is not a valid bundle 的错误。
    +

    打包并重签名

    打包 ipa 与重签名可以直接使用图形化工具 ios-app-signer 来完成。

    +

    这个工具可以自动加载出本机的证书以及 Provisioning Profile 文件,使用起来十分方便,当然也可以手动选择证书文件。

    +

    Snip20170512_14

    +

    点击 start 后,指定保存路径,iOS App Signer 就会帮你搞定所有事情。

    +

    安装

    在 iOS App Signer 完成打包与重签名后,我们就可以进行安装了。

    +

    安装有两种方法,一种是使用 iTool 工具安装 ipa 文件(测试安装失败)。

    +

    另外一种是针对有 XCode 的同学,在菜单 - Window - Devices 中打开设置窗口。点击 Installed Apps 栏下面的 + 号就可以选择 ipa 文件进行安装了(这个可以用)。

    +

    效果

    重签名后的应用由于与原应用的 Bundle id 是不同的,所以可以同时安装两个应用。这也就是淘宝上所谓的微信多开的原理。

    +

    小结

    我们最终得到了一个可以安装在免越狱设备上的微信 ipa 文件,但是这些步骤对于有些来说,可能还是太过复杂了。他们需要的只是重签名过的 ipa 文件,但是很可惜,由于我是使用的个人证书打包的,所以无法直接将 ipa 文件发出来。

    +

    如果有哪位好心的小伙伴可以贡献一个企业证书的话,我就可以利用这个企业证书打个包,然后直接进行应用分发,这也许就是最方便快捷的方法了。

    +

    iOS逆向工程之Theos-青玉伏案的博客

    +

    移动App入侵与逆向破解技术-iOS篇

    +

    免越狱版 iOS 抢红包插件

    + + +
    + +
    + + + + +
    + +
    + + + + +
    + +
    + + + + +
    + + +
    + + + +
    + + + + + +
    +
    + + +
    + + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + +
    +
    + + + + +
    + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/404.html b/404.html new file mode 100644 index 0000000..9fe86aa --- /dev/null +++ b/404.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/archives/2015/05/index.html b/archives/2015/05/index.html index ac4a70d..3488f50 100644 --- a/archives/2015/05/index.html +++ b/archives/2015/05/index.html @@ -1,329 +1,944 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 归档: 2015/5 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + - + + + + + + + + + + + + + + - + + + - + + + + + + + + + + + - - -
    -
    -
    - - + + -

    - Objective-C Runtime(二) 对象模型 -

    + + + -
    -
    -
    - - -
    -
    -
    - - + + -

    - KVC 和 KVO深入 -

    + + + + -
    -
    -
    - - -
    -
    -
    - - + + + + + + + + -

    - 单例模式的ARC和MRC实现 -

    -
    -
    -
    + + + + + + + - - -
    -
    -
    - - -

    - Swift 入门 -

    + -
    -
    -
    - + - + + + + + + - - - - - - - - - - + + - - + + - + + + + + - - \ No newline at end of file + diff --git a/archives/2015/06/index.html b/archives/2015/06/index.html new file mode 100644 index 0000000..a4a19b6 --- /dev/null +++ b/archives/2015/06/index.html @@ -0,0 +1,722 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2015/index.html b/archives/2015/index.html index 667497a..6d13306 100644 --- a/archives/2015/index.html +++ b/archives/2015/index.html @@ -1,329 +1,985 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 归档: 2015 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    -
    -
    -
    - - + +
    + -

    - Objective-C Runtime(一) 概述 -

    + + + + + + + + + + + - - -
    + + + + + + + + + + + - - -
    -
    -
    - - + + -

    - Objective-C Runtime(二) 对象模型 -

    + + + -
    -
    -
    - - -
    -
    -
    - - + + -

    - KVC 和 KVO深入 -

    + + + + -
    -
    -
    - - -
    -
    -
    - - + + + + + + + + -

    - 单例模式的ARC和MRC实现 -

    -
    -
    -
    + + + + + + + - - -
    -
    -
    - - -

    - Swift 入门 -

    + -
    -
    -
    - + - + + + + + + - - - - - - - - - - + + - - + + - + + + + + - - \ No newline at end of file + diff --git a/archives/2015/page/2/index.html b/archives/2015/page/2/index.html new file mode 100644 index 0000000..4cd3e36 --- /dev/null +++ b/archives/2015/page/2/index.html @@ -0,0 +1,689 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2016/04/index.html b/archives/2016/04/index.html new file mode 100644 index 0000000..14ef7e9 --- /dev/null +++ b/archives/2016/04/index.html @@ -0,0 +1,648 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2016/11/index.html b/archives/2016/11/index.html index 8e96047..ae44d3b 100644 --- a/archives/2016/11/index.html +++ b/archives/2016/11/index.html @@ -1,196 +1,648 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 归档: 2016/11 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/archives/2016/12/index.html b/archives/2016/12/index.html new file mode 100644 index 0000000..40614cb --- /dev/null +++ b/archives/2016/12/index.html @@ -0,0 +1,648 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2016/index.html b/archives/2016/index.html index cbbead6..c30f7fb 100644 --- a/archives/2016/index.html +++ b/archives/2016/index.html @@ -1,196 +1,722 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 归档: 2016 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/archives/2017/04/index.html b/archives/2017/04/index.html new file mode 100644 index 0000000..4d1aefc --- /dev/null +++ b/archives/2017/04/index.html @@ -0,0 +1,722 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2017/index.html b/archives/2017/index.html new file mode 100644 index 0000000..775a48e --- /dev/null +++ b/archives/2017/index.html @@ -0,0 +1,722 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/index.html b/archives/index.html index 6cfe37c..3d19338 100644 --- a/archives/index.html +++ b/archives/index.html @@ -1,358 +1,995 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 归档 | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + - + - + + - - -
    -
    - - - + + + + + + + -
    -
    - 2016 -
    -
    - - - - + + + + + -
    -
    -
    - 2015 -
    -
    - - - - - - - - + + + + -
    + + - -
    - + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    -
    -
    -
    - - + +
    + -

    - Objective-C Runtime(一) 概述 -

    + + + + + + + + + + + - - -
    + + + + + + + + + + + - - -
    -
    -
    - - + + -

    - Objective-C Runtime(二) 对象模型 -

    + + + -
    -
    -
    - - -
    -
    -
    - - + + -

    - KVC 和 KVO深入 -

    + + + + -
    -
    -
    - - -
    -
    -
    - - + + + + + + + + -

    - 单例模式的ARC和MRC实现 -

    -
    -
    -
    + + + + + + + - - -
    -
    -
    - - -

    - Swift 入门 -

    + -
    -
    -
    - + - + + + + + + - - - - - - - - - - + + - - + + - + + + + + - - \ No newline at end of file + diff --git a/archives/page/2/index.html b/archives/page/2/index.html new file mode 100644 index 0000000..8fb545d --- /dev/null +++ b/archives/page/2/index.html @@ -0,0 +1,911 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/categories/Swift/index.html b/categories/Swift/index.html index 669fe07..082c588 100644 --- a/categories/Swift/index.html +++ b/categories/Swift/index.html @@ -1,225 +1,649 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Category: Swift | CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + + + + + + + + + + 分类: Swift | CoderShmily's Blog + + + + + + + + + + + + + + + + + + - - + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/categories/iOS/index.html b/categories/iOS/index.html new file mode 100644 index 0000000..50ee917 --- /dev/null +++ b/categories/iOS/index.html @@ -0,0 +1,877 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 分类: iOS | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/categories/iOS/page/2/index.html b/categories/iOS/page/2/index.html new file mode 100644 index 0000000..0a9a4f8 --- /dev/null +++ b/categories/iOS/page/2/index.html @@ -0,0 +1,765 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 分类: iOS | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/categories/index.html b/categories/index.html new file mode 100644 index 0000000..df670b9 --- /dev/null +++ b/categories/index.html @@ -0,0 +1,627 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + categories | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/css/fonts/FontAwesome.otf b/css/fonts/FontAwesome.otf deleted file mode 100644 index 8b0f54e..0000000 Binary files a/css/fonts/FontAwesome.otf and /dev/null differ diff --git a/css/fonts/fontawesome-webfont.eot b/css/fonts/fontawesome-webfont.eot deleted file mode 100644 index 7c79c6a..0000000 Binary files a/css/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/css/fonts/fontawesome-webfont.svg b/css/fonts/fontawesome-webfont.svg deleted file mode 100644 index 45fdf33..0000000 --- a/css/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,414 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/css/fonts/fontawesome-webfont.ttf b/css/fonts/fontawesome-webfont.ttf deleted file mode 100644 index e89738d..0000000 Binary files a/css/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/css/fonts/fontawesome-webfont.woff b/css/fonts/fontawesome-webfont.woff deleted file mode 100644 index 8c1748a..0000000 Binary files a/css/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/css/images/banner.jpg b/css/images/banner.jpg deleted file mode 100644 index b963e06..0000000 Binary files a/css/images/banner.jpg and /dev/null differ diff --git a/css/main.css b/css/main.css new file mode 100644 index 0000000..0d74c2a --- /dev/null +++ b/css/main.css @@ -0,0 +1,3007 @@ +/* normalize.css v3.0.2 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +::selection { + background: #262a30; + color: #fff; +} +body { + position: relative; + font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif; + font-size: 14px; + line-height: 2; + color: #555; + background: #f5f7f9; +} +@media (max-width: 767px) { + body { + padding-right: 0 !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + body { + padding-right: 0 !important; + } +} +@media (min-width: 1600px) { + body { + font-size: 16px; + } +} +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; + padding: 0; + font-weight: bold; + line-height: 1.5; + font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif; +} +h2, +h3, +h4, +h5, +h6 { + margin: 20px 0 15px; +} +h1 { + font-size: 22px; +} +@media (max-width: 767px) { + h1 { + font-size: 18px; + } +} +h2 { + font-size: 20px; +} +@media (max-width: 767px) { + h2 { + font-size: 16px; + } +} +h3 { + font-size: 18px; +} +@media (max-width: 767px) { + h3 { + font-size: 14px; + } +} +h4 { + font-size: 16px; +} +@media (max-width: 767px) { + h4 { + font-size: 12px; + } +} +h5 { + font-size: 14px; +} +@media (max-width: 767px) { + h5 { + font-size: 10px; + } +} +h6 { + font-size: 12px; +} +@media (max-width: 767px) { + h6 { + font-size: 8px; + } +} +p { + margin: 0 0 25px 0; +} +a { + color: #555; + text-decoration: none; + border-bottom: 1px solid #999; + word-wrap: break-word; +} +a:hover { + color: #222; + border-bottom-color: #222; +} +blockquote { + margin: 0; + padding: 0; +} +img { + display: block; + margin: auto; + max-width: 100%; + height: auto; +} +hr { + margin: 40px 0; + height: 3px; + border: none; + background-color: #ddd; + background-image: repeating-linear-gradient(-45deg, #fff, #fff 4px, transparent 4px, transparent 8px); +} +blockquote { + padding: 0 15px; + color: #666; + border-left: 4px solid #ddd; +} +blockquote cite::before { + content: "-"; + padding: 0 5px; +} +dt { + font-weight: 700; +} +dd { + margin: 0; + padding: 0; +} +.text-left { + text-align: left; +} +.text-center { + text-align: center; +} +.text-right { + text-align: right; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.clearfix:before, +.clearfix:after { + content: " "; + display: table; +} +.clearfix:after { + clear: both; +} +.pullquote { + width: 45%; +} +.pullquote.left { + float: left; + margin-left: 5px; + margin-right: 10px; +} +.pullquote.right { + float: right; + margin-left: 10px; + margin-right: 5px; +} +.affix.affix.affix { + position: fixed; +} +.translation { + margin-top: -20px; + font-size: 14px; + color: #999; +} +.scrollbar-measure { + width: 100px; + height: 100px; + overflow: scroll; + position: absolute; + top: -9999px; +} +.use-motion .motion-element { + opacity: 0; +} +table { + margin: 20px 0; + width: 100%; + border-collapse: collapse; + border-spacing: 0; + border: 1px solid #ddd; + font-size: 14px; + table-layout: fixed; + word-wrap: break-all; +} +table>tbody>tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +table>tbody>tr:hover { + background-color: #f5f5f5; +} +caption, +th, +td { + padding: 8px; + text-align: left; + vertical-align: middle; + font-weight: normal; +} +th, +td { + border-bottom: 3px solid #ddd; + border-right: 1px solid #eee; +} +th { + padding-bottom: 10px; + font-weight: 700; +} +td { + border-bottom-width: 1px; +} +html, +body { + height: 100%; +} +.container { + position: relative; + min-height: 100%; +} +.header-inner { + margin: 0 auto; + padding: 100px 0 70px; + width: 700px; +} +@media (min-width: 1600px) { + .container .header-inner { + width: 900px; + } +} +.main { + padding-bottom: 150px; +} +.main-inner { + margin: 0 auto; + width: 700px; +} +@media (min-width: 1600px) { + .container .main-inner { + width: 900px; + } +} +.footer { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + min-height: 50px; +} +.footer-inner { + box-sizing: border-box; + margin: 20px auto; + width: 700px; +} +@media (min-width: 1600px) { + .container .footer-inner { + width: 900px; + } +} +pre, +.highlight { + overflow: auto; + margin: 20px 0; + padding: 0; + font-size: 13px; + color: #4d4d4c; + background: #f7f7f7; + line-height: 1.6; +} +pre, +code { + font-family: consolas, Menlo, "PingFang SC", "Microsoft YaHei", monospace; +} +code { + padding: 2px 4px; + word-wrap: break-word; + color: #555; + background: #eee; + border-radius: 3px; + font-size: 13px; +} +pre code { + padding: 0; + color: #4d4d4c; + background: none; + text-shadow: none; +} +.highlight { + border-radius: 1px; +} +.highlight pre { + border: none; + margin: 0; + padding: 10px 0; +} +.highlight table { + margin: 0; + width: auto; + border: none; +} +.highlight td { + border: none; + padding: 0; +} +.highlight figcaption { + font-size: 1em; + color: #4d4d4c; + line-height: 1em; + margin-bottom: 1em; +} +.highlight figcaption:before, +.highlight figcaption:after { + content: " "; + display: table; +} +.highlight figcaption:after { + clear: both; +} +.highlight figcaption a { + float: right; + color: #4d4d4c; +} +.highlight figcaption a:hover { + border-bottom-color: #4d4d4c; +} +.highlight .gutter pre { + padding-left: 10px; + padding-right: 10px; + color: #869194; + text-align: right; + background-color: #eff2f3; +} +.highlight .code pre { + width: 100%; + padding-left: 10px; + padding-right: 10px; + background-color: #f7f7f7; +} +.highlight .line { + height: 20px; +} +.gutter { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.gist table { + width: auto; +} +.gist table td { + border: none; +} +pre .deletion { + background: #fdd; +} +pre .addition { + background: #dfd; +} +pre .meta { + color: #8959a8; +} +pre .comment { + color: #8e908c; +} +pre .variable, +pre .attribute, +pre .tag, +pre .regexp, +pre .ruby .constant, +pre .xml .tag .title, +pre .xml .pi, +pre .xml .doctype, +pre .html .doctype, +pre .css .id, +pre .css .class, +pre .css .pseudo { + color: #c82829; +} +pre .number, +pre .preprocessor, +pre .built_in, +pre .literal, +pre .params, +pre .constant, +pre .command { + color: #f5871f; +} +pre .ruby .class .title, +pre .css .rules .attribute, +pre .string, +pre .value, +pre .inheritance, +pre .header, +pre .ruby .symbol, +pre .xml .cdata, +pre .special, +pre .number, +pre .formula { + color: #718c00; +} +pre .title, +pre .css .hexcolor { + color: #3e999f; +} +pre .function, +pre .python .decorator, +pre .python .title, +pre .ruby .function .title, +pre .ruby .title .keyword, +pre .perl .sub, +pre .javascript .title, +pre .coffeescript .title { + color: #4271ae; +} +pre .keyword, +pre .javascript .function { + color: #8959a8; +} +.full-image.full-image.full-image { + border: none; + max-width: 100%; + width: auto; + margin: 20px auto; +} +@media (min-width: 992px) { + .full-image.full-image.full-image { + max-width: none; + width: 118%; + margin: 0 -9%; + } +} +.blockquote-center, +.page-home .post-type-quote blockquote, +.page-post-detail .post-type-quote blockquote { + position: relative; + margin: 40px 0; + padding: 0; + border-left: none; + text-align: center; +} +.blockquote-center::before, +.page-home .post-type-quote blockquote::before, +.page-post-detail .post-type-quote blockquote::before, +.blockquote-center::after, +.page-home .post-type-quote blockquote::after, +.page-post-detail .post-type-quote blockquote::after { + position: absolute; + content: ' '; + display: block; + width: 100%; + height: 24px; + opacity: 0.2; + background-repeat: no-repeat; + background-position: 0 -6px; + background-size: 22px 22px; +} +.blockquote-center::before, +.page-home .post-type-quote blockquote::before, +.page-post-detail .post-type-quote blockquote::before { + top: -20px; + background-image: url("../images/quote-l.svg"); + border-top: 1px solid #ccc; +} +.blockquote-center::after, +.page-home .post-type-quote blockquote::after, +.page-post-detail .post-type-quote blockquote::after { + bottom: -20px; + background-image: url("../images/quote-r.svg"); + border-bottom: 1px solid #ccc; + background-position: 100% 8px; +} +.blockquote-center p, +.page-home .post-type-quote blockquote p, +.page-post-detail .post-type-quote blockquote p, +.blockquote-center div, +.page-home .post-type-quote blockquote div, +.page-post-detail .post-type-quote blockquote div { + text-align: center; +} +.post .post-body .group-picture img { + box-sizing: border-box; + padding: 0 3px; + border: none; +} +.post .group-picture-row { + overflow: hidden; + margin-top: 6px; +} +.post .group-picture-row:first-child { + margin-top: 0; +} +.post .group-picture-column { + float: left; +} +.page-post-detail .post-body .group-picture-column { + float: none; + margin-top: 10px; + width: auto !important; +} +.page-post-detail .post-body .group-picture-column img { + margin: 0 auto; +} +.page-archive .group-picture-container { + overflow: hidden; +} +.page-archive .group-picture-row { + float: left; +} +.page-archive .group-picture-row:first-child { + margin-top: 6px; +} +.page-archive .group-picture-column { + max-width: 150px; + max-height: 150px; +} +.note { + padding: 20px; + margin: 20px 0; + border: 1px solid #eee; + border-left-width: 5px; + border-radius: 3px; +} +.note h2, +.note h3, +.note h4, +.note h5, +.note h6 { + margin-top: 0; + margin-bottom: 5px; +} +.note p:last-child { + margin-bottom: 0; +} +.note code { + border-radius: 3px; +} +.note+.note { + margin-top: -5px; +} +.default { + border-left-color: #777; +} +.default h2, +.default h3, +.default h4, +.default h5, +.default h6 { + color: #777; +} +.primary { + border-left-color: #428bca; +} +.primary h2, +.primary h3, +.primary h4, +.primary h5, +.primary h6 { + color: #428bca; +} +.success { + border-left-color: #5cb85c; +} +.success h2, +.success h3, +.success h4, +.success h5, +.success h6 { + color: #5cb85c; +} +.danger { + border-left-color: #d9534f; +} +.danger h2, +.danger h3, +.danger h4, +.danger h5, +.danger h6 { + color: #d9534f; +} +.warning { + border-left-color: #f0ad4e; +} +.warning h2, +.warning h3, +.warning h4, +.warning h5, +.warning h6 { + color: #f0ad4e; +} +.info { + border-left-color: #5bc0de; +} +.info h2, +.info h3, +.info h4, +.info h5, +.info h6 { + color: #5bc0de; +} +.btn { + display: inline-block; + padding: 0 20px; + font-size: 14px; + color: #fff; + background: #222; + border: 2px solid #555; + text-decoration: none; + border-radius: 0; + transition-property: background-color; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; +} +.btn:hover, +.post-button .btn:hover { + border-color: #222; + color: #fff; + background: #222; +} +.btn-bar { + display: block; + width: 22px; + height: 2px; + background: #555; + border-radius: 1px; +} +.btn-bar+.btn-bar { + margin-top: 4px; +} +.pagination { + margin: 120px 0 40px; + text-align: center; + border-top: 1px solid #eee; +} +.page-number-basic, +.pagination .prev, +.pagination .next, +.pagination .page-number, +.pagination .space { + display: inline-block; + position: relative; + top: -1px; + margin: 0 10px; + padding: 0 10px; + line-height: 30px; +} +@media (max-width: 767px) { + .page-number-basic, + .pagination .prev, + .pagination .next, + .pagination .page-number, + .pagination .space { + margin: 0 5px; + } +} +.pagination .prev, +.pagination .next, +.pagination .page-number { + border-bottom: 0; + border-top: 1px solid #eee; + transition-property: border-color; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; +} +.pagination .prev:hover, +.pagination .next:hover, +.pagination .page-number:hover { + border-top-color: #222; +} +.pagination .space { + padding: 0; + margin: 0; +} +.pagination .prev { + margin-left: 0; +} +.pagination .next { + margin-right: 0; +} +.pagination .page-number.current, +.algolia-pagination .current .page-number { + color: #fff; + background: #ccc; + border-top-color: #ccc; +} +@media (max-width: 767px) { + .pagination { + border-top: none; + } + .pagination .prev, + .pagination .next, + .pagination .page-number { + margin-bottom: 10px; + border-top: 0; + border-bottom: 1px solid #eee; + } + .pagination .prev:hover, + .pagination .next:hover, + .pagination .page-number:hover { + border-bottom-color: #222; + } +} +.comments { + margin: 60px 20px 0; +} +.tag-cloud { + text-align: center; +} +.tag-cloud a { + display: inline-block; + margin: 10px; +} +.back-to-top { + box-sizing: border-box; + position: fixed; + bottom: -100px; + right: 30px; + z-index: 1050; + padding: 0 6px; + width: 24px; + background: #222; + font-size: 12px; + opacity: 0.6; + color: #fff; + cursor: pointer; + text-align: center; + -webkit-transform: translateZ(0); + transition-property: bottom; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; +} +@media (max-width: 767px) { + .back-to-top { + display: none; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .back-to-top { + display: none; + } +} +.back-to-top.back-to-top-on { + bottom: 30px; +} +.header { + background: transparent; +} +.header-inner { + position: relative; +} +.headband { + height: 3px; + background: #222; +} +.site-meta { + margin: 0; + text-align: center; +} +@media (max-width: 767px) { + .site-meta { + text-align: center; + } +} +.brand { + position: relative; + display: inline-block; + padding: 0 40px; + color: #fff; + background: #222; + border-bottom: none; +} +.brand:hover { + color: #fff; +} +.logo { + display: inline-block; + margin-right: 5px; + line-height: 36px; + vertical-align: top; +} +.site-title { + display: inline-block; + vertical-align: top; + line-height: 36px; + font-size: 20px; + font-weight: normal; + font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif; +} +.site-subtitle { + margin-top: 10px; + font-size: 13px; + color: #ddd; +} +.use-motion .brand { + opacity: 0; +} +.use-motion .logo, +.use-motion .site-title, +.use-motion .site-subtitle { + opacity: 0; + position: relative; + top: -10px; +} +.site-nav-toggle { + display: none; + position: absolute; + top: 10px; + left: 10px; +} +@media (max-width: 767px) { + .site-nav-toggle { + display: block; + } +} +.site-nav-toggle button { + margin-top: 2px; + padding: 9px 10px; + background: transparent; + border: none; +} +@media (max-width: 767px) { + .site-nav { + display: none; + margin: 0 -10px; + padding: 0 10px; + clear: both; + border-top: 1px solid #ddd; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .site-nav { + display: block !important; + } +} +@media (min-width: 992px) { + .site-nav { + display: block !important; + } +} +.menu { + margin-top: 20px; + padding-left: 0; + text-align: center; +} +.menu .menu-item { + display: inline-block; + margin: 0 10px; + list-style: none; +} +@media screen and (max-width: 767px) { + .menu .menu-item { + margin-top: 10px; + } +} +.menu .menu-item a { + display: block; + font-size: 13px; + line-height: inherit; + border-bottom: 1px solid transparent; + transition-property: border-color; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; +} +.menu .menu-item a:hover, +.menu-item-active a { + border-bottom-color: #222; +} +.menu .menu-item .fa { + margin-right: 5px; +} +.use-motion .menu-item { + opacity: 0; +} +.post-body { + font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif; +} +@media (max-width: 767px) { + .post-body { + word-break: break-word; + } +} +.post-body .fancybox img { + display: block !important; + margin: 0 auto; + cursor: pointer; + cursor: zoom-in; + cursor: -webkit-zoom-in; +} +.post-body .image-caption, +.post-body .figure .caption { + margin: 10px auto 15px; + text-align: center; + font-size: 14px; + color: #999; + font-weight: bold; + line-height: 1; +} +.post-sticky-flag { + display: inline-block; + font-size: 16px; + -ms-transform: rotate(30deg); + -webkit-transform: rotate(30deg); + -moz-transform: rotate(30deg); + -ms-transform: rotate(30deg); + -o-transform: rotate(30deg); + transform: rotate(30deg); +} +.posts-expand { + padding-top: 40px; +} +@media (max-width: 767px) { + .posts-expand { + margin: 0 20px; + } + .post-body pre { + padding: 10px; + } + .post-body pre .gutter pre { + padding-right: 10px; + } + .post-body .highlight { + margin-left: 0px; + margin-right: 0px; + padding: 0; + } + .post-body .highlight .gutter pre { + padding-right: 10px; + } +} +@media (min-width: 992px) { + .posts-expand .post-body { + text-align: justify; + } +} +.posts-expand .post-body h2, +.posts-expand .post-body h3, +.posts-expand .post-body h4, +.posts-expand .post-body h5, +.posts-expand .post-body h6 { + padding-top: 10px; +} +.posts-expand .post-body h2 .header-anchor, +.posts-expand .post-body h3 .header-anchor, +.posts-expand .post-body h4 .header-anchor, +.posts-expand .post-body h5 .header-anchor, +.posts-expand .post-body h6 .header-anchor { + float: right; + margin-left: 10px; + color: #ccc; + border-bottom-style: none; + visibility: hidden; +} +.posts-expand .post-body h2 .header-anchor:hover, +.posts-expand .post-body h3 .header-anchor:hover, +.posts-expand .post-body h4 .header-anchor:hover, +.posts-expand .post-body h5 .header-anchor:hover, +.posts-expand .post-body h6 .header-anchor:hover { + color: inherit; +} +.posts-expand .post-body h2:hover .header-anchor, +.posts-expand .post-body h3:hover .header-anchor, +.posts-expand .post-body h4:hover .header-anchor, +.posts-expand .post-body h5:hover .header-anchor, +.posts-expand .post-body h6:hover .header-anchor { + visibility: visible; +} +.posts-expand .post-body ul li { + list-style: circle; +} +.posts-expand .post-body img { + box-sizing: border-box; + margin: auto; + padding: 3px; + border: 1px solid #ddd; +} +.posts-expand .fancybox img { + margin: 0 auto; +} +@media (max-width: 767px) { + .posts-collapse { + margin: 0 20px; + } + .posts-collapse .post-title, + .posts-collapse .post-meta { + display: block; + width: auto; + text-align: left; + } +} +.posts-collapse { + position: relative; + z-index: 1010; + margin-left: 55px; +} +.posts-collapse::after { + content: " "; + position: absolute; + top: 20px; + left: 0; + margin-left: -2px; + width: 4px; + height: 100%; + background: #f5f5f5; + z-index: -1; +} +@media (max-width: 767px) { + .posts-collapse { + margin: 0 20px; + } +} +.posts-collapse .collection-title { + position: relative; + margin: 60px 0; +} +.posts-collapse .collection-title h2 { + margin-left: 20px; +} +.posts-collapse .collection-title small { + color: #bbb; + margin-left: 5px; +} +.posts-collapse .collection-title::before { + content: " "; + position: absolute; + left: 0; + top: 50%; + margin-left: -4px; + margin-top: -4px; + width: 8px; + height: 8px; + background: #bbb; + border-radius: 50%; +} +.posts-collapse .post { + margin: 30px 0; +} +.posts-collapse .post-header { + position: relative; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; + transition-property: border; + border-bottom: 1px dashed #ccc; +} +.posts-collapse .post-header::before { + content: " "; + position: absolute; + left: 0; + top: 12px; + width: 6px; + height: 6px; + margin-left: -4px; + background: #bbb; + border-radius: 50%; + border: 1px solid #fff; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; + transition-property: background; +} +.posts-collapse .post-header:hover { + border-bottom-color: #666; +} +.posts-collapse .post-header:hover::before { + background: #222; +} +.posts-collapse .post-meta { + position: absolute; + font-size: 12px; + left: 20px; + top: 5px; +} +.posts-collapse .post-comments-count { + display: none; +} +.posts-collapse .post-title { + margin-left: 60px; + font-size: 16px; + font-weight: normal; + line-height: inherit; +} +.posts-collapse .post-title::after { + margin-left: 3px; + opacity: 0.6; +} +.posts-collapse .post-title a { + color: #666; + border-bottom: none; +} +.page-home .post-type-quote .post-header, +.page-post-detail .post-type-quote .post-header, +.page-home .post-type-quote .post-tags, +.page-post-detail .post-type-quote .post-tags { + display: none; +} +.posts-expand .post-title { + font-size: 26px; + text-align: center; + word-break: break-word; + font-weight: 400; +} +@media (max-width: 767px) { + .posts-expand .post-title { + font-size: 22px; + } +} +.posts-expand .post-title-link { + display: inline-block; + position: relative; + color: #555; + border-bottom: none; + line-height: 1.2; + vertical-align: top; +} +.posts-expand .post-title-link::before { + content: ""; + position: absolute; + width: 100%; + height: 2px; + bottom: 0; + left: 0; + background-color: #000; + visibility: hidden; + -webkit-transform: scaleX(0); + -moz-transform: scaleX(0); + -ms-transform: scaleX(0); + -o-transform: scaleX(0); + transform: scaleX(0); + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; +} +.posts-expand .post-title-link:hover::before { + visibility: visible; + -webkit-transform: scaleX(1); + -moz-transform: scaleX(1); + -ms-transform: scaleX(1); + -o-transform: scaleX(1); + transform: scaleX(1); +} +.posts-expand .post-title-link .fa { + font-size: 16px; +} +.posts-expand .post-meta { + margin: 3px 0 60px 0; + color: #999; + font-family: 'Lato', "PingFang SC", "Microsoft YaHei", sans-serif; + font-size: 12px; + text-align: center; +} +.posts-expand .post-meta .post-category-list { + display: inline-block; + margin: 0; + padding: 3px; +} +.posts-expand .post-meta .post-category-list-link { + color: #999; +} +.posts-expand .post-meta .post-description { + font-size: 14px; + margin-top: 2px; +} +.post-wordcount { + display: inline-block; +} +.post-meta-divider { + margin: 0 0.5em; +} +.post-meta-item-icon { + margin-right: 3px; +} +@media (min-width: 768px) and (max-width: 991px) { + .post-meta-item-icon { + display: inline-block; + } +} +@media (max-width: 767px) { + .post-meta-item-icon { + display: inline-block; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .post-meta-item-text { + display: none; + } +} +@media (max-width: 767px) { + .post-meta-item-text { + display: none; + } +} +@media (max-width: 767px) { + .posts-expand .post-comments-count { + display: none; + } +} +.social-like { + font-size: 14px; + height: 20px; + text-align: center; + border-top: 1px solid #eee; + padding-top: 9px; + margin-top: 45px; + display: flex; + justify-content: center; +} +.vk_like { + width: 85px; + height: 21px; + padding-top: 7px; + align-self: center; +} +.fb_like { + height: 30px; + align-self: center; +} +.post-button { + margin-top: 50px; +} +.post-button .btn { + color: #555; + font-size: 14px; + background: #fff; + border-radius: 2px; + line-height: 2; + margin: 0 4px 8px 4px; +} +.post-button .fa-fw { + width: 1.285714285714286em; + text-align: left; +} +.posts-expand .post-tags { + margin-top: 40px; + text-align: center; +} +.posts-expand .post-tags a { + display: inline-block; + margin-right: 10px; + font-size: 13px; +} +.post-nav { + display: table; + margin-top: 15px; + width: 100%; + border-top: 1px solid #eee; +} +.post-nav-divider { + display: table-cell; + width: 10%; +} +.post-nav-item { + display: table-cell; + padding: 10px 0 0 0; + width: 45%; + vertical-align: top; +} +.post-nav-item a { + position: relative; + display: block; + line-height: 25px; + font-size: 14px; + color: #555; + border-bottom: none; +} +.post-nav-item a:hover { + color: #222; + border-bottom: none; +} +.post-nav-item a:active { + top: 2px; +} +.post-nav-item .fa { + position: absolute; + top: 8px; + left: 0; + font-size: 12px; +} +.post-nav-next a { + padding-left: 15px; +} +.post-nav-prev { + text-align: right; +} +.post-nav-prev a { + padding-right: 15px; +} +.post-nav-prev .fa { + right: 0; + left: auto; +} +.posts-expand .post-eof { + display: block; + margin: 80px auto 60px; + width: 8%; + height: 1px; + background: #ccc; + text-align: center; +} +.post:last-child .post-eof.post-eof.post-eof { + display: none; +} +.post-gallery { + display: table; + table-layout: fixed; + width: 100%; + border-collapse: separate; +} +.post-gallery-row { + display: table-row; +} +.post-gallery .post-gallery-img { + display: table-cell; + text-align: center; + vertical-align: middle; + border: none; +} +.post-gallery .post-gallery-img img { + max-width: 100%; + max-height: 100%; + border: none; +} +.fancybox-close, +.fancybox-close:hover { + border: none; +} +.sidebar { + position: fixed; + right: 0; + top: 0; + bottom: 0; + width: 0; + z-index: 1040; + box-shadow: inset 0 2px 6px #000; + background: #222; + -webkit-transform: translateZ(0); +} +.sidebar a { + color: #999; + border-bottom-color: #555; +} +.sidebar a:hover { + color: #eee; +} +@media (min-width: 768px) and (max-width: 991px) { + .sidebar { + display: none !important; + } +} +@media (max-width: 767px) { + .sidebar { + display: none !important; + } +} +.sidebar-inner { + position: relative; + padding: 20px 10px; + color: #999; + text-align: center; +} +.sidebar-toggle { + position: fixed; + right: 30px; + bottom: 45px; + width: 14px; + height: 14px; + padding: 5px; + background: #222; + line-height: 0; + z-index: 1050; + cursor: pointer; + -webkit-transform: translateZ(0); +} +@media (min-width: 768px) and (max-width: 991px) { + .sidebar-toggle { + display: none; + } +} +@media (max-width: 767px) { + .sidebar-toggle { + display: none; + } +} +.sidebar-toggle-line { + position: relative; + display: inline-block; + vertical-align: top; + height: 2px; + width: 100%; + background: #fff; + margin-top: 3px; +} +.sidebar-toggle-line:first-child { + margin-top: 0; +} +.site-author-image { + display: block; + margin: 0 auto; + padding: 2px; + max-width: 120px; + height: auto; + border: 1px solid #eee; +} +.site-author-name { + margin: 0; + text-align: center; + color: #222; + font-weight: 600; +} +.site-description { + margin-top: 0; + text-align: center; + font-size: 13px; + color: #999; +} +.site-state { + overflow: hidden; + line-height: 1.4; + white-space: nowrap; + text-align: center; +} +.site-state-item { + display: inline-block; + padding: 0 15px; + border-left: 1px solid #eee; +} +.site-state-item:first-child { + border-left: none; +} +.site-state-item a { + border-bottom: none; +} +.site-state-item-count { + display: block; + text-align: center; + color: inherit; + font-weight: 600; + font-size: 16px; +} +.site-state-item-name { + font-size: 13px; + color: #999; +} +.feed-link { + margin-top: 20px; +} +.feed-link a { + display: inline-block; + padding: 0 15px; + color: #fc6423; + border: 1px solid #fc6423; + border-radius: 4px; +} +.feed-link a i { + color: #fc6423; + font-size: 14px; +} +.feed-link a:hover { + color: #fff; + background: #fc6423; +} +.feed-link a:hover i { + color: #fff; +} +.links-of-author { + margin-top: 20px; +} +.links-of-author a { + display: inline-block; + vertical-align: middle; + margin-right: 10px; + margin-bottom: 10px; + border-bottom-color: #555; + font-size: 13px; +} +.links-of-author a:before { + display: inline-block; + vertical-align: middle; + margin-right: 3px; + content: " "; + width: 4px; + height: 4px; + border-radius: 50%; + background: #5c7acf; +} +.links-of-blogroll { + font-size: 13px; +} +.links-of-blogroll-title { + margin-top: 20px; + font-size: 14px; + font-weight: 600; +} +.links-of-blogroll-list { + margin: 0; + padding: 0; + list-style: none; +} +.links-of-blogroll-item { + padding: 2px 10px; +} +.sidebar-nav { + margin: 0 0 20px; + padding-left: 0; +} +.sidebar-nav li { + display: inline-block; + cursor: pointer; + border-bottom: 1px solid transparent; + font-size: 14px; + color: #555; +} +.sidebar-nav li:hover { + color: #fc6423; +} +.page-post-detail .sidebar-nav-toc { + padding: 0 5px; +} +.page-post-detail .sidebar-nav-overview { + margin-left: 10px; +} +.sidebar-nav .sidebar-nav-active { + color: #fc6423; + border-bottom-color: #fc6423; +} +.sidebar-nav .sidebar-nav-active:hover { + color: #fc6423; +} +.sidebar-panel { + display: none; +} +.sidebar-panel-active { + display: block; +} +.post-toc-empty { + font-size: 14px; + color: #666; +} +.post-toc-wrap { + overflow: hidden; +} +.post-toc { + overflow: auto; +} +.post-toc ol { + margin: 0; + padding: 0 2px 5px 10px; + text-align: left; + list-style: none; + font-size: 14px; +} +.post-toc ol > ol { + padding-left: 0; +} +.post-toc ol a { + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; + transition-property: all; + color: #666; + border-bottom-color: #ccc; +} +.post-toc ol a:hover { + color: #000; + border-bottom-color: #000; +} +.post-toc .nav-item { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + line-height: 1.8; +} +.post-toc .nav .nav-child { + display: none; +} +.post-toc .nav .active > .nav-child { + display: block; +} +.post-toc .nav .active-current > .nav-child { + display: block; +} +.post-toc .nav .active-current > .nav-child > .nav-item { + display: block; +} +.post-toc .nav .active > a { + color: #fc6423; + border-bottom-color: #fc6423; +} +.post-toc .nav .active-current > a { + color: #fc6423; +} +.post-toc .nav .active-current > a:hover { + color: #fc6423; +} +.footer { + font-size: 14px; + color: #999; +} +.footer img { + border: none; +} +.footer-inner { + text-align: center; +} +.with-love { + display: inline-block; + margin: 0 5px; +} +.powered-by, +.theme-info { + display: inline-block; +} +.powered-by { + margin-right: 10px; +} +.powered-by::after { + content: "|"; + padding-left: 10px; +} +.cc-license { + margin-top: 10px; + text-align: center; +} +.cc-license .cc-opacity { + opacity: 0.7; + border-bottom: none; +} +.cc-license .cc-opacity:hover { + opacity: 0.9; +} +.cc-license img { + display: inline-block; +} +.theme-next #ds-thread #ds-reset { + color: #555; +} +.theme-next #ds-thread #ds-reset .ds-replybox { + margin-bottom: 30px; +} +.theme-next #ds-thread #ds-reset .ds-replybox .ds-avatar, +.theme-next #ds-reset .ds-avatar img { + box-shadow: none; +} +.theme-next #ds-thread #ds-reset .ds-textarea-wrapper { + border-color: #c7d4e1; + background: none; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.theme-next #ds-thread #ds-reset .ds-textarea-wrapper textarea { + height: 60px; +} +.theme-next #ds-reset .ds-rounded-top { + border-radius: 0; +} +.theme-next #ds-thread #ds-reset .ds-post-toolbar { + box-sizing: border-box; + border: 1px solid #c7d4e1; + background: #f6f8fa; +} +.theme-next #ds-thread #ds-reset .ds-post-options { + height: 40px; + border: none; + background: none; +} +.theme-next #ds-thread #ds-reset .ds-toolbar-buttons { + top: 11px; +} +.theme-next #ds-thread #ds-reset .ds-sync { + top: 5px; +} +.theme-next #ds-thread #ds-reset .ds-post-button { + top: 4px; + right: 5px; + width: 90px; + height: 30px; + border: 1px solid #c5ced7; + border-radius: 3px; + background-image: linear-gradient(#fbfbfc, #f5f7f9); + color: #60676d; +} +.theme-next #ds-thread #ds-reset .ds-post-button:hover { + background-position: 0 -30px; + color: #60676d; +} +.theme-next #ds-thread #ds-reset .ds-comments-info { + padding: 10px 0; +} +.theme-next #ds-thread #ds-reset .ds-sort { + display: none; +} +.theme-next #ds-thread #ds-reset li.ds-tab a.ds-current { + border: none; + background: #f6f8fa; + color: #60676d; +} +.theme-next #ds-thread #ds-reset li.ds-tab a.ds-current:hover { + background-color: #e9f0f7; + color: #60676d; +} +.theme-next #ds-thread #ds-reset li.ds-tab a { + border-radius: 2px; + padding: 5px; +} +.theme-next #ds-thread #ds-reset .ds-login-buttons p { + color: #999; + line-height: 36px; +} +.theme-next #ds-thread #ds-reset .ds-login-buttons .ds-service-list li { + height: 28px; +} +.theme-next #ds-thread #ds-reset .ds-service-list a { + background: none; + padding: 5px; + border: 1px solid; + border-radius: 3px; + text-align: center; +} +.theme-next #ds-thread #ds-reset .ds-service-list a:hover { + color: #fff; + background: #666; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-weibo { + color: #fc9b00; + border-color: #fc9b00; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-weibo:hover { + background: #fc9b00; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-qq { + color: #60a3ec; + border-color: #60a3ec; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-qq:hover { + background: #60a3ec; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-renren { + color: #2e7ac4; + border-color: #2e7ac4; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-renren:hover { + background: #2e7ac4; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-douban { + color: #37994c; + border-color: #37994c; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-douban:hover { + background: #37994c; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-kaixin { + color: #fef20d; + border-color: #fef20d; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-kaixin:hover { + background: #fef20d; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-netease { + color: #f00; + border-color: #f00; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-netease:hover { + background: #f00; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-sohu { + color: #ffcb05; + border-color: #ffcb05; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-sohu:hover { + background: #ffcb05; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-baidu { + color: #2831e0; + border-color: #2831e0; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-baidu:hover { + background: #2831e0; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-google { + color: #166bec; + border-color: #166bec; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-google:hover { + background: #166bec; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-weixin { + color: #00ce0d; + border-color: #00ce0d; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-weixin:hover { + background: #00ce0d; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-more-services { + border: none; +} +.theme-next #ds-thread #ds-reset .ds-service-list .ds-more-services:hover { + background: none; +} +.theme-next #ds-reset .duoshuo-ua-admin { + display: inline-block; + color: #f00; +} +.theme-next #ds-reset .duoshuo-ua-platform, +.theme-next #ds-reset .duoshuo-ua-browser { + color: #ccc; +} +.theme-next #ds-reset .duoshuo-ua-platform .fa, +.theme-next #ds-reset .duoshuo-ua-browser .fa { + display: inline-block; + margin-right: 3px; +} +.theme-next #ds-reset .duoshuo-ua-separator { + display: inline-block; + margin-left: 5px; +} +.theme-next .this_ua { + background-color: #ccc !important; + border-radius: 4px; + padding: 0 5px !important; + margin: 1px 1px !important; + border: 1px solid #bbb !important; + color: #fff; + display: inline-block !important; +} +.theme-next .this_ua.admin { + background-color: #d9534f !important; + border-color: #d9534f !important; +} +.theme-next .this_ua.platform.iOS, +.theme-next .this_ua.platform.Mac, +.theme-next .this_ua.platform.Windows { + background-color: #39b3d7 !important; + border-color: #46b8da !important; +} +.theme-next .this_ua.platform.Linux { + background-color: #3a3a3a !important; + border-color: #1f1f1f !important; +} +.theme-next .this_ua.platform.Android { + background-color: #00c47d !important; + border-color: #01b171 !important; +} +.theme-next .this_ua.browser.Mobile, +.theme-next .this_ua.browser.Chrome { + background-color: #5cb85c !important; + border-color: #4cae4c !important; +} +.theme-next .this_ua.browser.Firefox { + background-color: #f0ad4e !important; + border-color: #eea236 !important; +} +.theme-next .this_ua.browser.Maxthon, +.theme-next .this_ua.browser.IE { + background-color: #428bca !important; + border-color: #357ebd !important; +} +.theme-next .this_ua.browser.baidu, +.theme-next .this_ua.browser.UCBrowser, +.theme-next .this_ua.browser.Opera { + background-color: #d9534f !important; + border-color: #d43f3a !important; +} +.theme-next .this_ua.browser.Android, +.theme-next .this_ua.browser.QQBrowser { + background-color: #78ace9 !important; + border-color: #4cae4c !important; +} +.cloud-tie-wrapper img { + display: inline-block; +} +.cloud-tie-wrapper .total-txt { + font-size: 1em !important; +} +.cloud-tie-join-count .join-count { + color: #555 !important; + font-size: inherit !important; + margin: 0 !important; +} +.post-spread { + margin-top: 20px; + text-align: center; +} +.jiathis_style { + display: inline-block; +} +.jiathis_style a { + border: none; +} +.fa { + font-family: FontAwesome !important; +} +.post-spread { + margin-top: 20px; + text-align: center; +} +.bdshare-slide-button-box a { + border: none; +} +.bdsharebuttonbox { + display: inline-block; +} +.bdsharebuttonbox a { + border: none; +} +.local-search-pop-overlay { + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 2080; + background-color: rgba(0,0,0,0.3); +} +.local-search-popup { + display: none; + position: fixed; + top: 10%; + left: 50%; + margin-left: -350px; + width: 700px; + height: 80%; + padding: 0; + background: #fff; + color: #333; + z-index: 9999; + border-radius: 5px; +} +@media (max-width: 767px) { + .local-search-popup { + padding: 0; + top: 0; + left: 0; + margin: 0; + width: 100%; + height: 100%; + border-radius: 0; + } +} +.local-search-popup ul.search-result-list { + padding: 0; + margin: 0 5px; +} +.local-search-popup p.search-result { + border-bottom: 1px dashed #ccc; + padding: 5px 0; +} +.local-search-popup a.search-result-title { + font-weight: bold; + font-size: 16px; +} +.local-search-popup .search-keyword { + border-bottom: 1px dashed #f00; + font-weight: bold; + color: #f00; +} +.local-search-popup .local-search-header { + padding: 5px; + height: 36px; + background: #f5f5f5; + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} +.local-search-popup #local-search-result { + overflow: auto; + position: relative; + padding: 5px 25px; + height: calc(100% - 55px); +} +.local-search-popup .local-search-input-wrapper { + display: inline-block; + width: calc(100% - 90px); + height: 36px; + line-height: 36px; + padding: 0 5px; +} +.local-search-popup .local-search-input-wrapper input { + padding: 8px 0; + height: 20px; + display: block; + width: 100%; + outline: none; + border: none; + background: transparent; + vertical-align: middle; +} +.local-search-popup .search-icon, +.local-search-popup .popup-btn-close { + display: inline-block; + font-size: 18px; + color: #999; + height: 36px; + width: 18px; + padding-left: 10px; + padding-right: 10px; +} +.local-search-popup .search-icon { + float: left; +} +.local-search-popup .popup-btn-close { + border-left: 1px solid #eee; + float: right; + cursor: pointer; +} +.local-search-popup #no-result { + position: absolute; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + -webkit-transform: translate(-50%, -50%); + -moz-transform: translate(-50%, -50%); + -ms-transform: translate(-50%, -50%); + -o-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + color: #ccc; +} +@media (min-width: 768px) and (max-width: 991px) { + .busuanzi-count { + width: auto; + } +} +@media (max-width: 767px) { + .busuanzi-count { + width: auto; + } +} +.site-uv, +.site-pv, +.page-pv { + display: inline-block; +} +.site-uv .busuanzi-value, +.site-pv .busuanzi-value, +.page-pv .busuanzi-value { + margin: 0 5px; +} +.site-uv { + margin-right: 10px; +} +.site-uv::after { + content: "|"; + padding-left: 10px; +} +.algolia-pop-overlay { + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 2080; + background-color: rgba(0,0,0,0.3); +} +.algolia-popup { + overflow: hidden; + padding: 0; + display: none; + position: fixed; + top: 10%; + left: 50%; + width: 700px; + height: 80%; + margin-left: -350px; + background: #fff; + color: #333; + z-index: 9999; + border-radius: 5px; +} +@media (max-width: 767px) { + .algolia-popup { + padding: 0; + top: 0; + left: 0; + margin: 0; + width: 100%; + height: 100%; + border-radius: 0; + } +} +.algolia-popup .popup-btn-close { + position: absolute; + right: 14px; + color: #4ebd79; + font-size: 14px; + font-weight: bold; + text-transform: uppercase; + cursor: pointer; + padding-left: 15px; + border-left: 1px solid #eee; + top: 10px; +} +.algolia-popup .popup-btn-close .fa { + color: #999; + font-size: 18px; +} +.algolia-popup .popup-btn-close:hover .fa { + color: #222; +} +.algolia-search { + padding: 10px 15px 5px; + max-height: 50px; + border-bottom: 1px solid #ccc; + background: #f5f5f5; + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} +.algolia-search-input-icon { + display: inline-block; + width: 20px; +} +.algolia-search-input-icon .fa { + font-size: 18px; +} +.algolia-search-input { + display: inline-block; + width: calc(90% - 20px); +} +.algolia-search-input input { + padding: 5px 0; + width: 100%; + outline: none; + border: none; + background: transparent; +} +.algolia-powered { + float: right; +} +.algolia-powered img { + display: inline-block; + height: 18px; + vertical-align: middle; +} +.algolia-results { + position: relative; + overflow: auto; + padding: 10px 30px; + height: calc(100% - 50px); +} +.algolia-results hr { + margin: 10px 0; +} +.algolia-results .highlight { + font-style: normal; + margin: 0; + padding: 0 2px; + font-size: inherit; + color: #f00; +} +.algolia-hits { + margin-top: 20px; +} +.algolia-hit-item { + margin: 15px 0; +} +.algolia-hit-item-link { + display: block; + border-bottom: 1px dashed #ccc; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; +} +.algolia-pagination .pagination { + margin-top: 40px; + border-top: none; + padding: 0; +} +.algolia-pagination .pagination-item { + display: inline-block; +} +.algolia-pagination .page-number { + border-top: none; +} +.algolia-pagination .page-number:hover { + border-bottom: 1px solid #222; +} +.algolia-pagination .disabled-item { + visibility: hidden; +} +.use-motion .post { + opacity: 0; +} +.page-archive .archive-page-counter { + position: relative; + top: 3px; + left: 20px; +} +@media (max-width: 767px) { + .page-archive .archive-page-counter { + top: 5px; + } +} +.page-archive .posts-collapse .archive-move-on { + position: absolute; + top: 11px; + left: 0; + margin-left: -6px; + width: 10px; + height: 10px; + opacity: 0.5; + background: #555; + border: 1px solid #fff; + border-radius: 50%; +} +.category-all-page .category-all-title { + text-align: center; +} +.category-all-page .category-all { + margin-top: 20px; +} +.category-all-page .category-list { + margin: 0; + padding: 0; + list-style: none; +} +.category-all-page .category-list-item { + margin: 5px 10px; +} +.category-all-page .category-list-count { + color: #bbb; +} +.category-all-page .category-list-count:before { + display: inline; + content: " ("; +} +.category-all-page .category-list-count:after { + display: inline; + content: ") "; +} +.category-all-page .category-list-child { + padding-left: 10px; +} +#schedule ul#event-list { + padding-left: 30px; +} +#schedule ul#event-list hr { + margin: 20px 0 45px 0 !important; + background: #222; +} +#schedule ul#event-list hr:after { + display: inline-block; + content: 'NOW'; + background: #222; + color: #fff; + font-weight: bold; + text-align: right; + padding: 0 5px; +} +#schedule ul#event-list li.event { + margin: 20px 0px; + background: #f9f9f9; + padding-left: 10px; + min-height: 40px; +} +#schedule ul#event-list li.event h2.event-summary { + margin: 0; + padding-bottom: 3px; +} +#schedule ul#event-list li.event h2.event-summary:before { + display: inline-block; + font-family: FontAwesome; + font-size: 8px; + content: '\f111'; + vertical-align: middle; + margin-right: 25px; + color: #bbb; +} +#schedule ul#event-list li.event span.event-relative-time { + display: inline-block; + font-size: 12px; + font-weight: 400; + padding-left: 12px; + color: #bbb; +} +#schedule ul#event-list li.event span.event-details { + display: block; + color: #bbb; + margin-left: 56px; + padding-top: 3px; + padding-bottom: 6px; + text-indent: -24px; + line-height: 18px; +} +#schedule ul#event-list li.event span.event-details:before { + text-indent: 0; + display: inline-block; + width: 14px; + font-family: FontAwesome; + text-align: center; + margin-right: 9px; + color: #bbb; +} +#schedule ul#event-list li.event span.event-details.event-location:before { + content: '\f041'; +} +#schedule ul#event-list li.event span.event-details.event-duration:before { + content: '\f017'; +} +#schedule ul#event-list li.event-past { + background: #fcfcfc; +} +#schedule ul#event-list li.event-past > * { + opacity: 0.6; +} +#schedule ul#event-list li.event-past h2.event-summary { + color: #bbb; +} +#schedule ul#event-list li.event-past h2.event-summary:before { + color: #dfdfdf; +} +#schedule ul#event-list li.event-now { + background: #222; + color: #fff; + padding: 15px 0 15px 10px; +} +#schedule ul#event-list li.event-now h2.event-summary:before { + -webkit-transform: scale(1.2); + -moz-transform: scale(1.2); + -ms-transform: scale(1.2); + -o-transform: scale(1.2); + transform: scale(1.2); + color: #fff; + animation: dot-flash 1s alternate infinite ease-in-out; +} +#schedule ul#event-list li.event-now * { + color: #fff !important; +} +@-moz-keyframes dot-flash { + from { + opacity: 1; + -webkit-transform: scale(1.1); + -moz-transform: scale(1.1); + -ms-transform: scale(1.1); + -o-transform: scale(1.1); + transform: scale(1.1); + } + to { + opacity: 0; + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } +} +@-webkit-keyframes dot-flash { + from { + opacity: 1; + -webkit-transform: scale(1.1); + -moz-transform: scale(1.1); + -ms-transform: scale(1.1); + -o-transform: scale(1.1); + transform: scale(1.1); + } + to { + opacity: 0; + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } +} +@-o-keyframes dot-flash { + from { + opacity: 1; + -webkit-transform: scale(1.1); + -moz-transform: scale(1.1); + -ms-transform: scale(1.1); + -o-transform: scale(1.1); + transform: scale(1.1); + } + to { + opacity: 0; + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } +} +@keyframes dot-flash { + from { + opacity: 1; + -webkit-transform: scale(1.1); + -moz-transform: scale(1.1); + -ms-transform: scale(1.1); + -o-transform: scale(1.1); + transform: scale(1.1); + } + to { + opacity: 0; + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } +} +.page-post-detail .sidebar-toggle-line { + background: #fc6423; +} +.page-post-detail .comments { + overflow: hidden; +} +.header { + position: relative; + margin: 0 auto; + width: 960px; +} +@media (min-width: 768px) and (max-width: 991px) { + .header { + width: auto; + } +} +@media (max-width: 767px) { + .header { + width: auto; + } +} +.header-inner { + position: absolute; + top: 0; + overflow: hidden; + padding: 0; + width: 240px; + background: #fff; + box-shadow: initial; + border-radius: initial; +} +@media (min-width: 1600px) { + .container .header-inner { + width: 240px; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .header-inner { + position: relative; + width: auto; + border-radius: initial; + } +} +@media (max-width: 767px) { + .header-inner { + position: relative; + width: auto; + border-radius: initial; + } +} +.main:before, +.main:after { + content: " "; + display: table; +} +.main:after { + clear: both; +} +@media (min-width: 768px) and (max-width: 991px) { + .main { + padding-bottom: 100px; + } +} +@media (max-width: 767px) { + .main { + padding-bottom: 100px; + } +} +.container .main-inner { + width: 960px; +} +@media (min-width: 768px) and (max-width: 991px) { + .container .main-inner { + width: auto; + } +} +@media (max-width: 767px) { + .container .main-inner { + width: auto; + } +} +.content-wrap { + float: right; + box-sizing: border-box; + padding: 40px; + width: 700px; + background: #fff; + min-height: 700px; + box-shadow: initial; + border-radius: initial; +} +@media (min-width: 768px) and (max-width: 991px) { + .content-wrap { + width: 100%; + padding: 20px; + border-radius: initial; + } +} +@media (max-width: 767px) { + .content-wrap { + width: 100%; + padding: 20px; + min-height: auto; + border-radius: initial; + } +} +.sidebar { + position: static; + float: left; + margin-top: 300px; + width: 240px; + background: #f5f7f9; + box-shadow: none; +} +@media (min-width: 768px) and (max-width: 991px) { + .sidebar { + display: none; + } +} +@media (max-width: 767px) { + .sidebar { + display: none; + } +} +.sidebar-toggle { + display: none; +} +.footer-inner { + width: 960px; + padding-left: 260px; +} +@media (min-width: 768px) and (max-width: 991px) { + .footer-inner { + width: auto; + padding-left: 0 !important; + padding-right: 0 !important; + } +} +@media (max-width: 767px) { + .footer-inner { + width: auto; + padding-left: 0 !important; + padding-right: 0 !important; + } +} +.sidebar-position-right .header-inner { + right: 0; +} +.sidebar-position-right .content-wrap { + float: left; +} +.sidebar-position-right .sidebar { + float: right; +} +.sidebar-position-right .footer-inner { + padding-left: 0; + padding-right: 260px; +} +.site-brand-wrapper { + position: relative; +} +.site-meta { + padding: 20px 0; + color: #fff; + background: #222; +} +@media (min-width: 768px) and (max-width: 991px) { + .site-meta { + box-shadow: 0 0 16px rgba(0,0,0,0.5); + } +} +@media (max-width: 767px) { + .site-meta { + box-shadow: 0 0 16px rgba(0,0,0,0.5); + } +} +.brand { + padding: 0; + background: none; +} +.brand:hover { + color: #fff; +} +.site-subtitle { + margin: 10px 10px 0; + font-weight: initial; +} +.site-search form { + display: none; +} +.site-nav { + border-top: none; +} +@media (min-width: 768px) and (max-width: 991px) { + .site-nav { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .site-nav-on { + display: block !important; + } +} +.menu .menu-item { + display: block; + margin: 0; +} +.menu .menu-item a { + position: relative; + box-sizing: border-box; + padding: 5px 20px; + text-align: left; + line-height: inherit; + transition-property: background-color; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; +} +.menu .menu-item a:hover, +.menu-item-active a { + background: #f9f9f9; + border-bottom-color: #fff; +} +.menu .menu-item br { + display: none; +} +.menu-item-active a:after { + content: " "; + position: absolute; + top: 50%; + margin-top: -3px; + right: 15px; + width: 6px; + height: 6px; + border-radius: 50%; + background-color: #bbb; +} +.btn-bar { + background-color: #fff; +} +.site-nav-toggle { + left: 20px; + top: 50%; + -webkit-transform: translateY(-50%); + -webkit-transform: translateY(-50%); + -moz-transform: translateY(-50%); + -ms-transform: translateY(-50%); + -o-transform: translateY(-50%); + transform: translateY(-50%); +} +@media (min-width: 768px) and (max-width: 991px) { + .site-nav-toggle { + display: block; + } +} +.use-motion .sidebar .motion-element { + opacity: 1; +} +.sidebar { + display: none; + right: auto; + bottom: auto; + -webkit-transform: none; +} +.sidebar-inner { + box-sizing: border-box; + width: 240px; + color: #555; + background: #fff; + box-shadow: initial; + border-radius: initial; +} +.sidebar-inner.affix { + position: fixed; + top: 0px; +} +.site-overview { + margin: 0 2px; + text-align: left; +} +.site-author:before, +.site-author:after { + content: " "; + display: table; +} +.site-author:after { + clear: both; +} +.sidebar a { + color: #555; +} +.sidebar a:hover { + color: #222; +} +.links-of-author-item a:before { + display: none; +} +.links-of-author-item a { + border-bottom: none; + text-decoration: underline; +} +.feed-link { + border-top: 1px dotted #ccc; + border-bottom: 1px dotted #ccc; + text-align: center; +} +.feed-link a { + display: block; + color: #fc6423; + border: none; +} +.feed-link a:hover { + background: none; + color: #e34603; +} +.feed-link a:hover i { + color: #e34603; +} +.links-of-author:before, +.links-of-author:after { + content: " "; + display: table; +} +.links-of-author:after { + clear: both; +} +.links-of-author-item { + float: left; + margin: 5px 0 0; + width: 50%; +} +.links-of-author-item a { + box-sizing: border-box; + display: inline-block; + margin-right: 0; + margin-bottom: 0; + padding: 0 5px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.links-of-author-item a { + display: block; + text-decoration: none; +} +.links-of-author-item a:hover { + border-radius: 4px; + background: #eee; +} +.links-of-author-item .fa { + margin-right: 2px; + font-size: 16px; +} +.links-of-author-item .fa-globe { + font-size: 15px; +} +.links-of-blogroll { + margin-top: 20px; + padding: 3px 0 0; + border-top: 1px dotted #ccc; +} +.links-of-blogroll-title { + margin-top: 0; +} +.links-of-blogroll-item { + padding: 0; +} +.links-of-blogroll-inline:before, +.links-of-blogroll-inline:after { + content: " "; + display: table; +} +.links-of-blogroll-inline:after { + clear: both; +} +.links-of-blogroll-inline .links-of-blogroll-item { + float: left; + margin: 5px 0 0; + width: 50%; +} +.links-of-blogroll-inline .links-of-blogroll-item a { + box-sizing: border-box; + display: inline-block; + margin-right: 0; + margin-bottom: 0; + padding: 0 5px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +@media (max-width: 767px) { + .post-body { + text-align: justify; + } +} diff --git a/css/style.css b/css/style.css deleted file mode 100644 index dd01e88..0000000 --- a/css/style.css +++ /dev/null @@ -1,1374 +0,0 @@ -body { - width: 100%; -} -body:before, -body:after { - content: ""; - display: table; -} -body:after { - clear: both; -} -html, -body, -div, -span, -applet, -object, -iframe, -h1, -h2, -h3, -h4, -h5, -h6, -p, -blockquote, -pre, -a, -abbr, -acronym, -address, -big, -cite, -code, -del, -dfn, -em, -img, -ins, -kbd, -q, -s, -samp, -small, -strike, -strong, -sub, -sup, -tt, -var, -dl, -dt, -dd, -ol, -ul, -li, -fieldset, -form, -label, -legend, -table, -caption, -tbody, -tfoot, -thead, -tr, -th, -td { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-family: inherit; - font-size: 100%; - vertical-align: baseline; -} -body { - line-height: 1; - color: #000; - background: #fff; -} -ol, -ul { - list-style: none; -} -table { - border-collapse: separate; - border-spacing: 0; - vertical-align: middle; -} -caption, -th, -td { - text-align: left; - font-weight: normal; - vertical-align: middle; -} -a img { - border: none; -} -input, -button { - margin: 0; - padding: 0; -} -input::-moz-focus-inner, -button::-moz-focus-inner { - border: 0; - padding: 0; -} -@font-face { - font-family: FontAwesome; - font-style: normal; - font-weight: normal; - src: url("fonts/fontawesome-webfont.eot?v=#4.0.3"); - src: url("fonts/fontawesome-webfont.eot?#iefix&v=#4.0.3") format("embedded-opentype"), url("fonts/fontawesome-webfont.woff?v=#4.0.3") format("woff"), url("fonts/fontawesome-webfont.ttf?v=#4.0.3") format("truetype"), url("fonts/fontawesome-webfont.svg#fontawesomeregular?v=#4.0.3") format("svg"); -} -html, -body, -#container { - height: 100%; -} -body { - background: #eee; - font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif; - -webkit-text-size-adjust: 100%; -} -.outer { - max-width: 1220px; - margin: 0 auto; - padding: 0 20px; -} -.outer:before, -.outer:after { - content: ""; - display: table; -} -.outer:after { - clear: both; -} -.inner { - display: inline; - float: left; - width: 98.33333333333333%; - margin: 0 0.833333333333333%; -} -.left, -.alignleft { - float: left; -} -.right, -.alignright { - float: right; -} -.clear { - clear: both; -} -#container { - position: relative; -} -.mobile-nav-on { - overflow: hidden; -} -#wrap { - height: 100%; - width: 100%; - position: absolute; - top: 0; - left: 0; - -webkit-transition: 0.2s ease-out; - -moz-transition: 0.2s ease-out; - -ms-transition: 0.2s ease-out; - transition: 0.2s ease-out; - z-index: 1; - background: #eee; -} -.mobile-nav-on #wrap { - left: 280px; -} -@media screen and (min-width: 768px) { - #main { - display: inline; - float: left; - width: 73.33333333333333%; - margin: 0 0.833333333333333%; - } -} -.article-date, -.article-category-link, -.archive-year, -.widget-title { - text-decoration: none; - text-transform: uppercase; - letter-spacing: 2px; - color: #999; - margin-bottom: 1em; - margin-left: 5px; - line-height: 1em; - text-shadow: 0 1px #fff; - font-weight: bold; -} -.article-inner, -.archive-article-inner { - background: #fff; - -webkit-box-shadow: 1px 2px 3px #ddd; - box-shadow: 1px 2px 3px #ddd; - border: 1px solid #ddd; - border-radius: 3px; -} -.article-entry h1, -.widget h1 { - font-size: 2em; -} -.article-entry h2, -.widget h2 { - font-size: 1.5em; -} -.article-entry h3, -.widget h3 { - font-size: 1.3em; -} -.article-entry h4, -.widget h4 { - font-size: 1.2em; -} -.article-entry h5, -.widget h5 { - font-size: 1em; -} -.article-entry h6, -.widget h6 { - font-size: 1em; - color: #999; -} -.article-entry hr, -.widget hr { - border: 1px dashed #ddd; -} -.article-entry strong, -.widget strong { - font-weight: bold; -} -.article-entry em, -.widget em, -.article-entry cite, -.widget cite { - font-style: italic; -} -.article-entry sup, -.widget sup, -.article-entry sub, -.widget sub { - font-size: 0.75em; - line-height: 0; - position: relative; - vertical-align: baseline; -} -.article-entry sup, -.widget sup { - top: -0.5em; -} -.article-entry sub, -.widget sub { - bottom: -0.2em; -} -.article-entry small, -.widget small { - font-size: 0.85em; -} -.article-entry acronym, -.widget acronym, -.article-entry abbr, -.widget abbr { - border-bottom: 1px dotted; -} -.article-entry ul, -.widget ul, -.article-entry ol, -.widget ol, -.article-entry dl, -.widget dl { - margin: 0 20px; - line-height: 1.6em; -} -.article-entry ul ul, -.widget ul ul, -.article-entry ol ul, -.widget ol ul, -.article-entry ul ol, -.widget ul ol, -.article-entry ol ol, -.widget ol ol { - margin-top: 0; - margin-bottom: 0; -} -.article-entry ul, -.widget ul { - list-style: disc; -} -.article-entry ol, -.widget ol { - list-style: decimal; -} -.article-entry dt, -.widget dt { - font-weight: bold; -} -#header { - height: 300px; - position: relative; - border-bottom: 1px solid #ddd; -} -#header:before, -#header:after { - content: ""; - position: absolute; - left: 0; - right: 0; - height: 40px; -} -#header:before { - top: 0; - background: -webkit-linear-gradient(rgba(0,0,0,0.2), transparent); - background: -moz-linear-gradient(rgba(0,0,0,0.2), transparent); - background: -ms-linear-gradient(rgba(0,0,0,0.2), transparent); - background: linear-gradient(rgba(0,0,0,0.2), transparent); -} -#header:after { - bottom: 0; - background: -webkit-linear-gradient(transparent, rgba(0,0,0,0.2)); - background: -moz-linear-gradient(transparent, rgba(0,0,0,0.2)); - background: -ms-linear-gradient(transparent, rgba(0,0,0,0.2)); - background: linear-gradient(transparent, rgba(0,0,0,0.2)); -} -#header-outer { - height: 100%; - position: relative; -} -#header-inner { - position: relative; - overflow: hidden; -} -#banner { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: url("images/banner.jpg") center #000; - -webkit-background-size: cover; - -moz-background-size: cover; - background-size: cover; - z-index: -1; -} -#header-title { - text-align: center; - height: 40px; - position: absolute; - top: 50%; - left: 0; - margin-top: -20px; -} -#logo, -#subtitle { - text-decoration: none; - color: #fff; - font-weight: 300; - text-shadow: 0 1px 4px rgba(0,0,0,0.3); -} -#logo { - font-size: 40px; - line-height: 40px; - letter-spacing: 2px; -} -#subtitle { - font-size: 16px; - line-height: 16px; - letter-spacing: 1px; -} -#subtitle-wrap { - margin-top: 16px; -} -#main-nav { - float: left; - margin-left: -15px; -} -.nav-icon, -.main-nav-link { - float: left; - color: #fff; - opacity: 0.6; - text-decoration: none; - text-shadow: 0 1px rgba(0,0,0,0.2); - -webkit-transition: opacity 0.2s; - -moz-transition: opacity 0.2s; - -ms-transition: opacity 0.2s; - transition: opacity 0.2s; - display: block; - padding: 20px 15px; -} -.nav-icon:hover, -.main-nav-link:hover { - opacity: 1; -} -.nav-icon { - font-family: FontAwesome; - text-align: center; - font-size: 14px; - width: 14px; - height: 14px; - padding: 20px 15px; - position: relative; - cursor: pointer; -} -.main-nav-link { - font-weight: 300; - letter-spacing: 1px; -} -@media screen and (max-width: 479px) { - .main-nav-link { - display: none; - } -} -#main-nav-toggle { - display: none; -} -#main-nav-toggle:before { - content: "\f0c9"; -} -@media screen and (max-width: 479px) { - #main-nav-toggle { - display: block; - } -} -#sub-nav { - float: right; - margin-right: -15px; -} -#nav-rss-link:before { - content: "\f09e"; -} -#nav-search-btn:before { - content: "\f002"; -} -#search-form-wrap { - position: absolute; - top: 15px; - width: 150px; - height: 30px; - right: -150px; - opacity: 0; - -webkit-transition: 0.2s ease-out; - -moz-transition: 0.2s ease-out; - -ms-transition: 0.2s ease-out; - transition: 0.2s ease-out; -} -#search-form-wrap.on { - opacity: 1; - right: 0; -} -@media screen and (max-width: 479px) { - #search-form-wrap { - width: 100%; - right: -100%; - } -} -.search-form { - position: absolute; - top: 0; - left: 0; - right: 0; - background: #fff; - padding: 5px 15px; - border-radius: 15px; - -webkit-box-shadow: 0 0 10px rgba(0,0,0,0.3); - box-shadow: 0 0 10px rgba(0,0,0,0.3); -} -.search-form-input { - border: none; - background: none; - color: #555; - width: 100%; - font: 13px "Helvetica Neue", Helvetica, Arial, sans-serif; - outline: none; -} -.search-form-input::-webkit-search-results-decoration, -.search-form-input::-webkit-search-cancel-button { - -webkit-appearance: none; -} -.search-form-submit { - position: absolute; - top: 50%; - right: 10px; - margin-top: -7px; - font: 13px FontAwesome; - border: none; - background: none; - color: #bbb; - cursor: pointer; -} -.search-form-submit:hover, -.search-form-submit:focus { - color: #777; -} -.article { - margin: 50px 0; -} -.article-inner { - overflow: hidden; -} -.article-meta:before, -.article-meta:after { - content: ""; - display: table; -} -.article-meta:after { - clear: both; -} -.article-date { - float: left; -} -.article-category { - float: left; - line-height: 1em; - color: #ccc; - text-shadow: 0 1px #fff; - margin-left: 8px; -} -.article-category:before { - content: "\2022"; -} -.article-category-link { - margin: 0 12px 1em; -} -.article-header { - padding: 20px 20px 0; -} -.article-title { - text-decoration: none; - font-size: 2em; - font-weight: bold; - color: #555; - line-height: 1.1em; - -webkit-transition: color 0.2s; - -moz-transition: color 0.2s; - -ms-transition: color 0.2s; - transition: color 0.2s; -} -a.article-title:hover { - color: #258fb8; -} -.article-entry { - color: #555; - padding: 0 20px; -} -.article-entry:before, -.article-entry:after { - content: ""; - display: table; -} -.article-entry:after { - clear: both; -} -.article-entry p, -.article-entry table { - line-height: 1.6em; - margin: 1.6em 0; -} -.article-entry h1, -.article-entry h2, -.article-entry h3, -.article-entry h4, -.article-entry h5, -.article-entry h6 { - font-weight: bold; -} -.article-entry h1, -.article-entry h2, -.article-entry h3, -.article-entry h4, -.article-entry h5, -.article-entry h6 { - line-height: 1.1em; - margin: 1.1em 0; -} -.article-entry a { - color: #258fb8; - text-decoration: none; -} -.article-entry a:hover { - text-decoration: underline; -} -.article-entry ul, -.article-entry ol, -.article-entry dl { - margin-top: 1.6em; - margin-bottom: 1.6em; -} -.article-entry img, -.article-entry video { - max-width: 100%; - height: auto; - display: block; - margin: auto; -} -.article-entry iframe { - border: none; -} -.article-entry table { - width: 100%; - border-collapse: collapse; - border-spacing: 0; -} -.article-entry th { - font-weight: bold; - border-bottom: 3px solid #ddd; - padding-bottom: 0.5em; -} -.article-entry td { - border-bottom: 1px solid #ddd; - padding: 10px 0; -} -.article-entry blockquote { - font-family: Georgia, "Times New Roman", serif; - font-size: 1.4em; - margin: 1.6em 20px; - text-align: center; -} -.article-entry blockquote footer { - font-size: 14px; - margin: 1.6em 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -} -.article-entry blockquote footer cite:before { - content: "—"; - padding: 0 0.5em; -} -.article-entry .pullquote { - text-align: left; - width: 45%; - margin: 0; -} -.article-entry .pullquote.left { - margin-left: 0.5em; - margin-right: 1em; -} -.article-entry .pullquote.right { - margin-right: 0.5em; - margin-left: 1em; -} -.article-entry .caption { - color: #999; - display: block; - font-size: 0.9em; - margin-top: 0.5em; - position: relative; - text-align: center; -} -.article-entry .video-container { - position: relative; - padding-top: 56.25%; - height: 0; - overflow: hidden; -} -.article-entry .video-container iframe, -.article-entry .video-container object, -.article-entry .video-container embed { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - margin-top: 0; -} -.article-more-link a { - display: inline-block; - line-height: 1em; - padding: 6px 15px; - border-radius: 15px; - background: #eee; - color: #999; - text-shadow: 0 1px #fff; - text-decoration: none; -} -.article-more-link a:hover { - background: #258fb8; - color: #fff; - text-decoration: none; - text-shadow: 0 1px #1e7293; -} -.article-footer { - font-size: 0.85em; - line-height: 1.6em; - border-top: 1px solid #ddd; - padding-top: 1.6em; - margin: 0 20px 20px; -} -.article-footer:before, -.article-footer:after { - content: ""; - display: table; -} -.article-footer:after { - clear: both; -} -.article-footer a { - color: #999; - text-decoration: none; -} -.article-footer a:hover { - color: #555; -} -.article-tag-list-item { - float: left; - margin-right: 10px; -} -.article-tag-list-link:before { - content: "#"; -} -.article-comment-link { - float: right; -} -.article-comment-link:before { - content: "\f075"; - font-family: FontAwesome; - padding-right: 8px; -} -.article-share-link { - cursor: pointer; - float: right; - margin-left: 20px; -} -.article-share-link:before { - content: "\f064"; - font-family: FontAwesome; - padding-right: 6px; -} -#article-nav { - position: relative; -} -#article-nav:before, -#article-nav:after { - content: ""; - display: table; -} -#article-nav:after { - clear: both; -} -@media screen and (min-width: 768px) { - #article-nav { - margin: 50px 0; - } - #article-nav:before { - width: 8px; - height: 8px; - position: absolute; - top: 50%; - left: 50%; - margin-top: -4px; - margin-left: -4px; - content: ""; - border-radius: 50%; - background: #ddd; - -webkit-box-shadow: 0 1px 2px #fff; - box-shadow: 0 1px 2px #fff; - } -} -.article-nav-link-wrap { - text-decoration: none; - text-shadow: 0 1px #fff; - color: #999; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - margin-top: 50px; - text-align: center; - display: block; -} -.article-nav-link-wrap:hover { - color: #555; -} -@media screen and (min-width: 768px) { - .article-nav-link-wrap { - width: 50%; - margin-top: 0; - } -} -@media screen and (min-width: 768px) { - #article-nav-newer { - float: left; - text-align: right; - padding-right: 20px; - } -} -@media screen and (min-width: 768px) { - #article-nav-older { - float: right; - text-align: left; - padding-left: 20px; - } -} -.article-nav-caption { - text-transform: uppercase; - letter-spacing: 2px; - color: #ddd; - line-height: 1em; - font-weight: bold; -} -#article-nav-newer .article-nav-caption { - margin-right: -2px; -} -.article-nav-title { - font-size: 0.85em; - line-height: 1.6em; - margin-top: 0.5em; -} -.article-share-box { - position: absolute; - display: none; - background: #fff; - -webkit-box-shadow: 1px 2px 10px rgba(0,0,0,0.2); - box-shadow: 1px 2px 10px rgba(0,0,0,0.2); - border-radius: 3px; - margin-left: -145px; - overflow: hidden; - z-index: 1; -} -.article-share-box.on { - display: block; -} -.article-share-input { - width: 100%; - background: none; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif; - padding: 0 15px; - color: #555; - outline: none; - border: 1px solid #ddd; - border-radius: 3px 3px 0 0; - height: 36px; - line-height: 36px; -} -.article-share-links { - background: #eee; -} -.article-share-links:before, -.article-share-links:after { - content: ""; - display: table; -} -.article-share-links:after { - clear: both; -} -.article-share-twitter, -.article-share-facebook, -.article-share-pinterest, -.article-share-google { - width: 50px; - height: 36px; - display: block; - float: left; - position: relative; - color: #999; - text-shadow: 0 1px #fff; -} -.article-share-twitter:before, -.article-share-facebook:before, -.article-share-pinterest:before, -.article-share-google:before { - font-size: 20px; - font-family: FontAwesome; - width: 20px; - height: 20px; - position: absolute; - top: 50%; - left: 50%; - margin-top: -10px; - margin-left: -10px; - text-align: center; -} -.article-share-twitter:hover, -.article-share-facebook:hover, -.article-share-pinterest:hover, -.article-share-google:hover { - color: #fff; -} -.article-share-twitter:before { - content: "\f099"; -} -.article-share-twitter:hover { - background: #00aced; - text-shadow: 0 1px #008abe; -} -.article-share-facebook:before { - content: "\f09a"; -} -.article-share-facebook:hover { - background: #3b5998; - text-shadow: 0 1px #2f477a; -} -.article-share-pinterest:before { - content: "\f0d2"; -} -.article-share-pinterest:hover { - background: #cb2027; - text-shadow: 0 1px #a21a1f; -} -.article-share-google:before { - content: "\f0d5"; -} -.article-share-google:hover { - background: #dd4b39; - text-shadow: 0 1px #be3221; -} -.article-gallery { - background: #000; - position: relative; -} -.article-gallery-photos { - position: relative; - overflow: hidden; -} -.article-gallery-img { - display: none; - max-width: 100%; -} -.article-gallery-img:first-child { - display: block; -} -.article-gallery-img.loaded { - position: absolute; - display: block; -} -.article-gallery-img img { - display: block; - max-width: 100%; - margin: 0 auto; -} -#comments { - background: #fff; - -webkit-box-shadow: 1px 2px 3px #ddd; - box-shadow: 1px 2px 3px #ddd; - padding: 20px; - border: 1px solid #ddd; - border-radius: 3px; - margin: 50px 0; -} -#comments a { - color: #258fb8; -} -.archives-wrap { - margin: 50px 0; -} -.archives:before, -.archives:after { - content: ""; - display: table; -} -.archives:after { - clear: both; -} -.archive-year-wrap { - margin-bottom: 1em; -} -.archives { - -webkit-column-gap: 10px; - -moz-column-gap: 10px; - column-gap: 10px; -} -@media screen and (min-width: 480px) and (max-width: 767px) { - .archives { - -webkit-column-count: 2; - -moz-column-count: 2; - column-count: 2; - } -} -@media screen and (min-width: 768px) { - .archives { - -webkit-column-count: 3; - -moz-column-count: 3; - column-count: 3; - } -} -.archive-article { - -webkit-column-break-inside: avoid; - page-break-inside: avoid; - overflow: hidden; - break-inside: avoid-column; -} -.archive-article-inner { - padding: 10px; - margin-bottom: 15px; -} -.archive-article-title { - text-decoration: none; - font-weight: bold; - color: #555; - -webkit-transition: color 0.2s; - -moz-transition: color 0.2s; - -ms-transition: color 0.2s; - transition: color 0.2s; - line-height: 1.6em; -} -.archive-article-title:hover { - color: #258fb8; -} -.archive-article-footer { - margin-top: 1em; -} -.archive-article-date { - color: #999; - text-decoration: none; - font-size: 0.85em; - line-height: 1em; - margin-bottom: 0.5em; - display: block; -} -#page-nav { - margin: 50px auto; - background: #fff; - -webkit-box-shadow: 1px 2px 3px #ddd; - box-shadow: 1px 2px 3px #ddd; - border: 1px solid #ddd; - border-radius: 3px; - text-align: center; - color: #999; - overflow: hidden; -} -#page-nav:before, -#page-nav:after { - content: ""; - display: table; -} -#page-nav:after { - clear: both; -} -#page-nav a, -#page-nav span { - padding: 10px 20px; - line-height: 1; - height: 2ex; -} -#page-nav a { - color: #999; - text-decoration: none; -} -#page-nav a:hover { - background: #999; - color: #fff; -} -#page-nav .prev { - float: left; -} -#page-nav .next { - float: right; -} -#page-nav .page-number { - display: inline-block; -} -@media screen and (max-width: 479px) { - #page-nav .page-number { - display: none; - } -} -#page-nav .current { - color: #555; - font-weight: bold; -} -#page-nav .space { - color: #ddd; -} -#footer { - background: #262a30; - padding: 50px 0; - border-top: 1px solid #ddd; - color: #999; -} -#footer a { - color: #258fb8; - text-decoration: none; -} -#footer a:hover { - text-decoration: underline; -} -#footer-info { - line-height: 1.6em; - font-size: 0.85em; -} -.article-entry pre, -.article-entry .highlight { - background: #2d2d2d; - margin: 0 -20px; - padding: 15px 20px; - border-style: solid; - border-color: #ddd; - border-width: 1px 0; - overflow: auto; - color: #ccc; - line-height: 22.400000000000002px; -} -.article-entry .highlight .gutter pre, -.article-entry .gist .gist-file .gist-data .line-numbers { - color: #666; - font-size: 0.85em; -} -.article-entry pre, -.article-entry code { - font-family: "Source Code Pro", Consolas, Monaco, Menlo, Consolas, monospace; -} -.article-entry code { - background: #eee; - text-shadow: 0 1px #fff; - padding: 0 0.3em; -} -.article-entry pre code { - background: none; - text-shadow: none; - padding: 0; -} -.article-entry .highlight pre { - border: none; - margin: 0; - padding: 0; -} -.article-entry .highlight table { - margin: 0; - width: auto; -} -.article-entry .highlight td { - border: none; - padding: 0; -} -.article-entry .highlight figcaption { - font-size: 0.85em; - color: #999; - line-height: 1em; - margin-bottom: 1em; -} -.article-entry .highlight figcaption:before, -.article-entry .highlight figcaption:after { - content: ""; - display: table; -} -.article-entry .highlight figcaption:after { - clear: both; -} -.article-entry .highlight figcaption a { - float: right; -} -.article-entry .highlight .gutter pre { - text-align: right; - padding-right: 20px; -} -.article-entry .highlight .line { - height: 22.400000000000002px; -} -.article-entry .highlight .line.marked { - background: #515151; -} -.article-entry .gist { - margin: 0 -20px; - border-style: solid; - border-color: #ddd; - border-width: 1px 0; - background: #2d2d2d; - padding: 15px 20px 15px 0; -} -.article-entry .gist .gist-file { - border: none; - font-family: "Source Code Pro", Consolas, Monaco, Menlo, Consolas, monospace; - margin: 0; -} -.article-entry .gist .gist-file .gist-data { - background: none; - border: none; -} -.article-entry .gist .gist-file .gist-data .line-numbers { - background: none; - border: none; - padding: 0 20px 0 0; -} -.article-entry .gist .gist-file .gist-data .line-data { - padding: 0 !important; -} -.article-entry .gist .gist-file .highlight { - margin: 0; - padding: 0; - border: none; -} -.article-entry .gist .gist-file .gist-meta { - background: #2d2d2d; - color: #999; - font: 0.85em "Helvetica Neue", Helvetica, Arial, sans-serif; - text-shadow: 0 0; - padding: 0; - margin-top: 1em; - margin-left: 20px; -} -.article-entry .gist .gist-file .gist-meta a { - color: #258fb8; - font-weight: normal; -} -.article-entry .gist .gist-file .gist-meta a:hover { - text-decoration: underline; -} -pre .comment, -pre .title { - color: #999; -} -pre .variable, -pre .attribute, -pre .tag, -pre .regexp, -pre .ruby .constant, -pre .xml .tag .title, -pre .xml .pi, -pre .xml .doctype, -pre .html .doctype, -pre .css .id, -pre .css .class, -pre .css .pseudo { - color: #f2777a; -} -pre .number, -pre .preprocessor, -pre .built_in, -pre .literal, -pre .params, -pre .constant { - color: #f99157; -} -pre .class, -pre .ruby .class .title, -pre .css .rules .attribute { - color: #9c9; -} -pre .string, -pre .value, -pre .inheritance, -pre .header, -pre .ruby .symbol, -pre .xml .cdata { - color: #9c9; -} -pre .css .hexcolor { - color: #6cc; -} -pre .function, -pre .python .decorator, -pre .python .title, -pre .ruby .function .title, -pre .ruby .title .keyword, -pre .perl .sub, -pre .javascript .title, -pre .coffeescript .title { - color: #69c; -} -pre .keyword, -pre .javascript .function { - color: #c9c; -} -@media screen and (max-width: 479px) { - #mobile-nav { - position: absolute; - top: 0; - left: 0; - width: 280px; - height: 100%; - background: #191919; - border-right: 1px solid #fff; - } -} -@media screen and (max-width: 479px) { - .mobile-nav-link { - display: block; - color: #999; - text-decoration: none; - padding: 15px 20px; - font-weight: bold; - } - .mobile-nav-link:hover { - color: #fff; - } -} -@media screen and (min-width: 768px) { - #sidebar { - display: inline; - float: left; - width: 23.333333333333332%; - margin: 0 0.833333333333333%; - } -} -.widget-wrap { - margin: 50px 0; -} -.widget { - color: #777; - text-shadow: 0 1px #fff; - background: #ddd; - -webkit-box-shadow: 0 -1px 4px #ccc inset; - box-shadow: 0 -1px 4px #ccc inset; - border: 1px solid #ccc; - padding: 15px; - border-radius: 3px; -} -.widget a { - color: #258fb8; - text-decoration: none; -} -.widget a:hover { - text-decoration: underline; -} -.widget ul ul, -.widget ol ul, -.widget dl ul, -.widget ul ol, -.widget ol ol, -.widget dl ol, -.widget ul dl, -.widget ol dl, -.widget dl dl { - margin-left: 15px; - list-style: disc; -} -.widget { - line-height: 1.6em; - word-wrap: break-word; - font-size: 0.9em; -} -.widget ul, -.widget ol { - list-style: none; - margin: 0; -} -.widget ul ul, -.widget ol ul, -.widget ul ol, -.widget ol ol { - margin: 0 20px; -} -.widget ul ul, -.widget ol ul { - list-style: disc; -} -.widget ul ol, -.widget ol ol { - list-style: decimal; -} -.category-list-count, -.tag-list-count, -.archive-list-count { - padding-left: 5px; - color: #999; - font-size: 0.85em; -} -.category-list-count:before, -.tag-list-count:before, -.archive-list-count:before { - content: "("; -} -.category-list-count:after, -.tag-list-count:after, -.archive-list-count:after { - content: ")"; -} -.tagcloud a { - margin-right: 5px; - display: inline-block; -} diff --git a/fancybox/jquery.fancybox.pack.js b/fancybox/jquery.fancybox.pack.js deleted file mode 100644 index 2db1280..0000000 --- a/fancybox/jquery.fancybox.pack.js +++ /dev/null @@ -1,46 +0,0 @@ -/*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */ -(function(s,H,f,w){var K=f("html"),q=f(s),p=f(H),b=f.fancybox=function(){b.open.apply(this,arguments)},J=navigator.userAgent.match(/msie/i),C=null,t=H.createTouch!==w,u=function(a){return a&&a.hasOwnProperty&&a instanceof f},r=function(a){return a&&"string"===f.type(a)},F=function(a){return r(a)&&0
    ',image:'',iframe:'",error:'

    The requested content cannot be loaded.
    Please try again later.

    ',closeBtn:'',next:'',prev:''},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0, -openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1, -isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=u(a)?f(a).get():[a]),f.each(a,function(e,c){var l={},g,h,k,n,m;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),u(c)?(l={href:c.data("fancybox-href")||c.attr("href"),title:f("
    ").text(c.data("fancybox-title")||c.attr("title")).html(),isDom:!0,element:c}, -f.metadata&&f.extend(!0,l,c.metadata())):l=c);g=d.href||l.href||(r(c)?c:null);h=d.title!==w?d.title:l.title||"";n=(k=d.content||l.content)?"html":d.type||l.type;!n&&l.isDom&&(n=c.data("fancybox-type"),n||(n=(n=c.prop("class").match(/fancybox\.(\w+)/))?n[1]:null));r(g)&&(n||(b.isImage(g)?n="image":b.isSWF(g)?n="swf":"#"===g.charAt(0)?n="inline":r(c)&&(n="html",k=c)),"ajax"===n&&(m=g.split(/\s+/,2),g=m.shift(),m=m.shift()));k||("inline"===n?g?k=f(r(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):l.isDom&&(k=c): -"html"===n?k=g:n||g||!l.isDom||(n="inline",k=c));f.extend(l,{href:g,type:n,content:k,title:h,selector:m});a[e]=l}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==w&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1===b.trigger("onCancel")||(b.hideLoading(),a&&(b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(), -b.coming=null,b.current||b._afterZoomOut(a)))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(b.isOpen&&!0!==a?(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]()):(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&& -(b.player.timer=setTimeout(b.next,b.current.playSpeed))},c=function(){d();p.unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};!0===a||!b.player.isActive&&!1!==a?b.current&&(b.current.loop||b.current.index=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==w&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,l;c&&(l=b._getPosition(d),a&&"scroll"===a.type?(delete l.position,c.stop(!0,!0).animate(l,200)):(c.css(l),e.pos=f.extend({},e.dim,l)))}, -update:function(a){var d=a&&a.originalEvent&&a.originalEvent.type,e=!d||"orientationchange"===d;e&&(clearTimeout(C),C=null);b.isOpen&&!C&&(C=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),C=null)},e&&!t?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,t&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"), -b.trigger("onUpdate")),b.update())},hideLoading:function(){p.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f('
    ').click(b.cancel).appendTo("body");p.bind("keydown.loading",function(a){27===(a.which||a.keyCode)&&(a.preventDefault(),b.cancel())});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}));b.trigger("onLoading")},getViewport:function(){var a=b.current&& -b.current.locked||!1,d={x:q.scrollLeft(),y:q.scrollTop()};a&&a.length?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=t&&s.innerWidth?s.innerWidth:q.width(),d.h=t&&s.innerHeight?s.innerHeight:q.height());return d},unbindEvents:function(){b.wrap&&u(b.wrap)&&b.wrap.unbind(".fb");p.unbind(".fb");q.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(q.bind("orientationchange.fb"+(t?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&p.bind("keydown.fb",function(e){var c= -e.which||e.keyCode,l=e.target||e.srcElement;if(27===c&&b.coming)return!1;e.ctrlKey||e.altKey||e.shiftKey||e.metaKey||l&&(l.type||f(l).is("[contenteditable]"))||f.each(d,function(d,l){if(1h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();0!==c&&!k&&1g||0>l)&&b.next(0>g?"up":"right"),d.preventDefault())}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d,e){if(e&& -b.helpers[d]&&f.isFunction(b.helpers[d][a]))b.helpers[d][a](f.extend(!0,{},b.helpers[d].defaults,e),c)})}p.trigger(a)},isImage:function(a){return r(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(a){return r(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c;a=m(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&&(d.padding=[c,c, -c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1,mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive=!0;if("image"=== -c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio=!0);"iframe"===c&&t&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(t?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,x(d.padding[a]))});b.trigger("onReady"); -if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href");"image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width= -this.width/b.opts.pixelRatio;b.coming.height=this.height/b.opts.pixelRatio;b._afterLoad()};a.onerror=function(){this.onload=this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming, -d=f(a.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",t?"auto":a.iframe.scrolling).attr("src",a.href);f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);t||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload|| -b._afterLoad()},_preloadImages:function(){var a=b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload,e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,l,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove()); -b.unbindEvents();e=a.content;c=a.type;l=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin,outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f("
    ").html(e).find(a.selector):u(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('
    ').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder", -!1)}));break;case "image":e=a.tpl.image.replace(/\{href\}/g,g);break;case "swf":e='',h="",f.each(a.swf,function(a,b){e+='';h+=" "+a+'="'+b+'"'}),e+='"}u(e)&&e.parent().is(a.inner)||a.inner.append(e);b.trigger("beforeShow"); -a.inner.css("overflow","yes"===l?"scroll":"no"===l?"hidden":l);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(!b.isOpened)f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();else if(d.prevMethod)b.transitions[d.prevMethod]();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,l=b.skin,g=b.inner,h=b.current,c=h.width,k=h.height,n=h.minWidth,v=h.minHeight,p=h.maxWidth, -q=h.maxHeight,t=h.scrolling,r=h.scrollOutside?h.scrollbarWidth:0,y=h.margin,z=m(y[1]+y[3]),s=m(y[0]+y[2]),w,A,u,D,B,G,C,E,I;e.add(l).add(g).width("auto").height("auto").removeClass("fancybox-tmp");y=m(l.outerWidth(!0)-l.width());w=m(l.outerHeight(!0)-l.height());A=z+y;u=s+w;D=F(c)?(a.w-A)*m(c)/100:c;B=F(k)?(a.h-u)*m(k)/100:k;if("iframe"===h.type){if(I=h.content,h.autoHeight&&1===I.data("ready"))try{I[0].contentWindow.document.location&&(g.width(D).height(9999),G=I.contents().find("body"),r&&G.css("overflow-x", -"hidden"),B=G.outerHeight(!0))}catch(H){}}else if(h.autoWidth||h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(D),h.autoHeight||g.height(B),h.autoWidth&&(D=g.width()),h.autoHeight&&(B=g.height()),g.removeClass("fancybox-tmp");c=m(D);k=m(B);E=D/B;n=m(F(n)?m(n,"w")-A:n);p=m(F(p)?m(p,"w")-A:p);v=m(F(v)?m(v,"h")-u:v);q=m(F(q)?m(q,"h")-u:q);G=p;C=q;h.fitToView&&(p=Math.min(a.w-A,p),q=Math.min(a.h-u,q));A=a.w-z;s=a.h-s;h.aspectRatio?(c>p&&(c=p,k=m(c/E)),k>q&&(k=q,c=m(k*E)),cA||z>s)&&c>n&&k>v&&!(19p&&(c=p,k=m(c/E)),g.width(c).height(k),e.width(c+y),a=e.width(),z=e.height();else c=Math.max(n,Math.min(c,c-(a-A))),k=Math.max(v,Math.min(k,k-(z-s)));r&&"auto"===t&&kA||z>s)&&c>n&&k>v;c=h.aspectRatio?cv&&k
    ').appendTo(d&&d.lenth?d:"body");this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this;a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(q.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay", -function(a){if(f(a.target).hasClass("fancybox-overlay"))return b.isActive?b.close():d.close(),!1});this.overlay.css(a.css).show()},close:function(){q.unbind("resize.overlay");this.el.hasClass("fancybox-lock")&&(f(".fancybox-margin").removeClass("fancybox-margin"),this.el.removeClass("fancybox-lock"),q.scrollTop(this.scrollV).scrollLeft(this.scrollH));f(".fancybox-overlay").remove().hide();f.extend(this,{overlay:null,fixed:!1})},update:function(){var a="100%",b;this.overlay.width(a).height("100%"); -J?(b=Math.max(H.documentElement.offsetWidth,H.body.offsetWidth),p.width()>b&&(a=p.width())):p.width()>q.width()&&(a=p.width());this.overlay.width(a).height(p.height())},onReady:function(a,b){var e=this.overlay;f(".fancybox-overlay").stop(!0,!0);e||this.create(a);a.locked&&this.fixed&&b.fixed&&(b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){b.locked&&!this.el.hasClass("fancybox-lock")&&(!1!==this.fixPosition&&f("*").filter(function(){return"fixed"=== -f(this).css("position")&&!f(this).hasClass("fancybox-overlay")&&!f(this).hasClass("fancybox-wrap")}).addClass("fancybox-margin"),this.el.addClass("fancybox-margin"),this.scrollV=q.scrollTop(),this.scrollH=q.scrollLeft(),this.el.addClass("fancybox-lock"),q.scrollTop(this.scrollV).scrollLeft(this.scrollH));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.coming&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float", -position:"bottom"},beforeShow:function(a){var d=b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(r(e)&&""!==f.trim(e)){d=f('
    '+e+"
    ");switch(c){case "inside":c=b.skin;break;case "outside":c=b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),J&&d.width(d.width()),d.wrapInner(''),b.current.margin[2]+=Math.abs(m(d.css("margin-bottom")))}d["top"===a.position?"prependTo": -"appendTo"](c)}}};f.fn.fancybox=function(a){var d,e=f(this),c=this.selector||"",l=function(g){var h=f(this).blur(),k=d,l,m;g.ctrlKey||g.altKey||g.shiftKey||g.metaKey||h.is(".fancybox-wrap")||(l=a.groupAttr||"data-fancybox-group",m=h.attr(l),m||(l="rel",m=h.get(0)[l]),m&&""!==m&&"nofollow"!==m&&(h=c.length?f(c):e,h=h.filter("["+l+'="'+m+'"]'),k=h.index(this)),a.index=k,!1!==b.open(h,a)&&g.preventDefault())};a=a||{};d=a.index||0;c&&!1!==a.live?p.undelegate(c,"click.fb-start").delegate(c+":not('.fancybox-item, .fancybox-nav')", -"click.fb-start",l):e.unbind("click.fb-start").bind("click.fb-start",l);this.filter("[data-fancybox-start=1]").trigger("click");return this};p.ready(function(){var a,d;f.scrollbarWidth===w&&(f.scrollbarWidth=function(){var a=f('
    ').appendTo("body"),b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});f.support.fixedPosition===w&&(f.support.fixedPosition=function(){var a=f('
    ').appendTo("body"), -b=20===a[0].offsetTop||15===a[0].offsetTop;a.remove();return b}());f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")});a=f(s).width();K.addClass("fancybox-lock-test");d=f(s).width();K.removeClass("fancybox-lock-test");f("").appendTo("head")})})(window,document,jQuery); \ No newline at end of file diff --git a/images/100.gif b/images/100.gif new file mode 100644 index 0000000..d196e01 Binary files /dev/null and b/images/100.gif differ diff --git a/images/algolia_logo.svg b/images/algolia_logo.svg new file mode 100644 index 0000000..64ce5db --- /dev/null +++ b/images/algolia_logo.svg @@ -0,0 +1,21 @@ + + + + Algolia_logo_bg-white + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/avatar.gif b/images/avatar.gif new file mode 100644 index 0000000..9899025 Binary files /dev/null and b/images/avatar.gif differ diff --git a/images/cc-by-nc-nd.svg b/images/cc-by-nc-nd.svg new file mode 100644 index 0000000..79a4f2e --- /dev/null +++ b/images/cc-by-nc-nd.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/cc-by-nc-sa.svg b/images/cc-by-nc-sa.svg new file mode 100644 index 0000000..bf6bc26 --- /dev/null +++ b/images/cc-by-nc-sa.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/cc-by-nc.svg b/images/cc-by-nc.svg new file mode 100644 index 0000000..3697349 --- /dev/null +++ b/images/cc-by-nc.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/cc-by-nd.svg b/images/cc-by-nd.svg new file mode 100644 index 0000000..934c61e --- /dev/null +++ b/images/cc-by-nd.svg @@ -0,0 +1,117 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/images/cc-by-sa.svg b/images/cc-by-sa.svg new file mode 100644 index 0000000..463276a --- /dev/null +++ b/images/cc-by-sa.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/cc-by.svg b/images/cc-by.svg new file mode 100644 index 0000000..4bccd14 --- /dev/null +++ b/images/cc-by.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/cc-zero.svg b/images/cc-zero.svg new file mode 100644 index 0000000..0f86639 --- /dev/null +++ b/images/cc-zero.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/cog.png b/images/cog.png new file mode 100644 index 0000000..3d41069 Binary files /dev/null and b/images/cog.png differ diff --git a/images/heart.png b/images/heart.png new file mode 100644 index 0000000..ce0b4d1 Binary files /dev/null and b/images/heart.png differ diff --git a/images/loading.gif b/images/loading.gif new file mode 100644 index 0000000..efb6768 Binary files /dev/null and b/images/loading.gif differ diff --git a/images/m3.jpg b/images/m3.jpg new file mode 100644 index 0000000..be7a39c Binary files /dev/null and b/images/m3.jpg differ diff --git a/images/placeholder.gif b/images/placeholder.gif new file mode 100644 index 0000000..efb6768 Binary files /dev/null and b/images/placeholder.gif differ diff --git a/images/quote-l.svg b/images/quote-l.svg new file mode 100644 index 0000000..6dd94a4 --- /dev/null +++ b/images/quote-l.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/images/quote-r.svg b/images/quote-r.svg new file mode 100644 index 0000000..312b64d --- /dev/null +++ b/images/quote-r.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/images/searchicon.png b/images/searchicon.png new file mode 100644 index 0000000..14a16ca Binary files /dev/null and b/images/searchicon.png differ diff --git a/index.html b/index.html index f57a601..ee3bf07 100644 --- a/index.html +++ b/index.html @@ -1,578 +1,2114 @@ - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - CoderShmily's Blog - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + + + + + + + + + + CoderShmily's Blog + + + + + + + + + + + + + + + + + + - - + - + + - + + + + + + + + + -
    - -
    - - -
    - + + + + + + + + + + + -

    - 单例模式的ARC和MRC实现 -

    + + + -
    - -
    - -

    单例在整个工程中,就相当于一个全局变量,就是不论在哪里需要用到这个类的实例变量,都可以通过单例方法来取得,而且一旦你创建了一个单例类,不论你在多少个界面中初始化调用了这个单例方法取得对象,它们所有的对象都是指向的同一块内存存储空间(即单例类保证了该类的实力对象是唯一存在的一个).

    - -

    - Read More -

    - - -
    - -
    -
    + + + -
    - -
    - - -
    - -

    - Swift 入门 -

    + + + -
    - -
    - -

    特色

      -
    • 苹果宣称 Swift 的特点是:快速、现代、安全、互动,而且明显优于 Objective-C 语言
    • -
    • 可以使用现有的 CocoaCocoa Touch 框架
    • -
    • Swift 取消了 Objective C 的指针及其他不安全访问的使用
    • -
    • 舍弃 Objective C 早期应用 Smalltalk 的语法,全面改为句点表示法
    • -
    • 提供了类似 Java 的名字空间(namespace)、泛型(generic)、运算对象重载(operator overloading)
    • -
    • Swift 被简单的形容为 “没有 C 的 Objective-C”(Objective-C without the C)
    • -
    - -

    - Read More -

    - - -
    - -
    + + + + + + + -
    + + + + + + + - - - - -
    -
    + + + + + -
    - -
    -
    -
    - - + - + + + + + - - - + + + + + + + + + - - \ No newline at end of file + diff --git a/js/script.js b/js/script.js deleted file mode 100644 index 1e58767..0000000 --- a/js/script.js +++ /dev/null @@ -1,137 +0,0 @@ -(function($){ - // Search - var $searchWrap = $('#search-form-wrap'), - isSearchAnim = false, - searchAnimDuration = 200; - - var startSearchAnim = function(){ - isSearchAnim = true; - }; - - var stopSearchAnim = function(callback){ - setTimeout(function(){ - isSearchAnim = false; - callback && callback(); - }, searchAnimDuration); - }; - - $('#nav-search-btn').on('click', function(){ - if (isSearchAnim) return; - - startSearchAnim(); - $searchWrap.addClass('on'); - stopSearchAnim(function(){ - $('.search-form-input').focus(); - }); - }); - - $('.search-form-input').on('blur', function(){ - startSearchAnim(); - $searchWrap.removeClass('on'); - stopSearchAnim(); - }); - - // Share - $('body').on('click', function(){ - $('.article-share-box.on').removeClass('on'); - }).on('click', '.article-share-link', function(e){ - e.stopPropagation(); - - var $this = $(this), - url = $this.attr('data-url'), - encodedUrl = encodeURIComponent(url), - id = 'article-share-box-' + $this.attr('data-id'), - offset = $this.offset(); - - if ($('#' + id).length){ - var box = $('#' + id); - - if (box.hasClass('on')){ - box.removeClass('on'); - return; - } - } else { - var html = [ - '
    ', - '', - '
    ', - '', - '', - '', - '', - '
    ', - '
    ' - ].join(''); - - var box = $(html); - - $('body').append(box); - } - - $('.article-share-box.on').hide(); - - box.css({ - top: offset.top + 25, - left: offset.left - }).addClass('on'); - }).on('click', '.article-share-box', function(e){ - e.stopPropagation(); - }).on('click', '.article-share-box-input', function(){ - $(this).select(); - }).on('click', '.article-share-box-link', function(e){ - e.preventDefault(); - e.stopPropagation(); - - window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450'); - }); - - // Caption - $('.article-entry').each(function(i){ - $(this).find('img').each(function(){ - if ($(this).parent().hasClass('fancybox')) return; - - var alt = this.alt; - - if (alt) $(this).after('' + alt + ''); - - $(this).wrap(''); - }); - - $(this).find('.fancybox').each(function(){ - $(this).attr('rel', 'article' + i); - }); - }); - - if ($.fancybox){ - $('.fancybox').fancybox(); - } - - // Mobile nav - var $container = $('#container'), - isMobileNavAnim = false, - mobileNavAnimDuration = 200; - - var startMobileNavAnim = function(){ - isMobileNavAnim = true; - }; - - var stopMobileNavAnim = function(){ - setTimeout(function(){ - isMobileNavAnim = false; - }, mobileNavAnimDuration); - } - - $('#main-nav-toggle').on('click', function(){ - if (isMobileNavAnim) return; - - startMobileNavAnim(); - $container.toggleClass('mobile-nav-on'); - stopMobileNavAnim(); - }); - - $('#wrap').on('click', function(){ - if (isMobileNavAnim || !$container.hasClass('mobile-nav-on')) return; - - $container.removeClass('mobile-nav-on'); - }); -})(jQuery); \ No newline at end of file diff --git a/js/src/affix.js b/js/src/affix.js new file mode 100644 index 0000000..11a3d39 --- /dev/null +++ b/js/src/affix.js @@ -0,0 +1,162 @@ +/* ======================================================================== + * Bootstrap: affix.js v3.3.5 + * http://getbootstrap.com/javascript/#affix + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // AFFIX CLASS DEFINITION + // ====================== + + var Affix = function (element, options) { + this.options = $.extend({}, Affix.DEFAULTS, options) + + this.$target = $(this.options.target) + .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) + .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) + + this.$element = $(element) + this.affixed = null + this.unpin = null + this.pinnedOffset = null + + this.checkPosition() + } + + Affix.VERSION = '3.3.5' + + Affix.RESET = 'affix affix-top affix-bottom' + + Affix.DEFAULTS = { + offset: 0, + target: window + } + + Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + var targetHeight = this.$target.height() + + if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false + + if (this.affixed == 'bottom') { + if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' + return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' + } + + var initializing = this.affixed == null + var colliderTop = initializing ? scrollTop : position.top + var colliderHeight = initializing ? targetHeight : height + + if (offsetTop != null && scrollTop <= offsetTop) return 'top' + if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' + + return false + } + + Affix.prototype.getPinnedOffset = function () { + if (this.pinnedOffset) return this.pinnedOffset + this.$element.removeClass(Affix.RESET).addClass('affix') + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + return (this.pinnedOffset = position.top - scrollTop) + } + + Affix.prototype.checkPositionWithEventLoop = function () { + setTimeout($.proxy(this.checkPosition, this), 1) + } + + Affix.prototype.checkPosition = function () { + if (!this.$element.is(':visible')) return + + var height = this.$element.height() + var offset = this.options.offset + var offsetTop = offset.top + var offsetBottom = offset.bottom + var scrollHeight = Math.max($(document).height(), $(document.body).height()) + + if (typeof offset != 'object') offsetBottom = offsetTop = offset + if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) + if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) + + var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) + + if (this.affixed != affix) { + if (this.unpin != null) this.$element.css('top', '') + + var affixType = 'affix' + (affix ? '-' + affix : '') + var e = $.Event(affixType + '.bs.affix') + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + this.affixed = affix + this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null + + this.$element + .removeClass(Affix.RESET) + .addClass(affixType) + .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') + } + + if (affix == 'bottom') { + this.$element.offset({ + top: scrollHeight - height - offsetBottom + }) + } + } + + + // AFFIX PLUGIN DEFINITION + // ======================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.affix') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.affix', (data = new Affix(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.affix + + $.fn.affix = Plugin + $.fn.affix.Constructor = Affix + + + // AFFIX NO CONFLICT + // ================= + + $.fn.affix.noConflict = function () { + $.fn.affix = old + return this + } + + + // AFFIX DATA-API + // ============== + + $(window).on('load', function () { + $('[data-spy="affix"]').each(function () { + var $spy = $(this) + var data = $spy.data() + + data.offset = data.offset || {} + + if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom + if (data.offsetTop != null) data.offset.top = data.offsetTop + + Plugin.call($spy, data) + }) + }) + +}(jQuery); diff --git a/js/src/algolia-search.js b/js/src/algolia-search.js new file mode 100644 index 0000000..9787e2a --- /dev/null +++ b/js/src/algolia-search.js @@ -0,0 +1,115 @@ +/* global instantsearch: true */ +/*jshint camelcase: false */ + +$(document).ready(function () { + var algoliaSettings = CONFIG.algolia; + var isAlgoliaSettingsValid = algoliaSettings.applicationID && + algoliaSettings.apiKey && + algoliaSettings.indexName; + + if (!isAlgoliaSettingsValid) { + window.console.error('Algolia Settings are invalid.'); + return; + } + + var search = instantsearch({ + appId: algoliaSettings.applicationID, + apiKey: algoliaSettings.apiKey, + indexName: algoliaSettings.indexName, + searchFunction: function (helper) { + var searchInput = $('#algolia-search-input').find('input'); + + if (searchInput.val()) { + helper.search(); + } + } + }); + + // Registering Widgets + [ + instantsearch.widgets.searchBox({ + container: '#algolia-search-input', + placeholder: algoliaSettings.labels.input_placeholder + }), + + instantsearch.widgets.hits({ + container: '#algolia-hits', + hitsPerPage: algoliaSettings.hits.per_page || 10, + templates: { + item: function (data) { + var link = data.permalink ? data.permalink : (CONFIG.root + data.path); + return ( + '' + + data._highlightResult.title.value + + '' + ); + }, + empty: function (data) { + return ( + '
    ' + + algoliaSettings.labels.hits_empty.replace(/\$\{query}/, data.query) + + '
    ' + ); + } + }, + cssClasses: { + item: 'algolia-hit-item' + } + }), + + instantsearch.widgets.stats({ + container: '#algolia-stats', + templates: { + body: function (data) { + var stats = algoliaSettings.labels.hits_stats + .replace(/\$\{hits}/, data.nbHits) + .replace(/\$\{time}/, data.processingTimeMS); + return ( + stats + + '' + + ' Algolia' + + '' + + '
    ' + ); + } + } + }), + + instantsearch.widgets.pagination({ + container: '#algolia-pagination', + scrollTo: false, + showFirstLast: false, + labels: { + first: '', + last: '', + previous: '', + next: '' + }, + cssClasses: { + root: 'pagination', + item: 'pagination-item', + link: 'page-number', + active: 'current', + disabled: 'disabled-item' + } + }) + ].forEach(search.addWidget, search); + + search.start(); + + $('.popup-trigger').on('click', function(e) { + e.stopPropagation(); + $('body') + .append('
    ') + .css('overflow', 'hidden'); + $('.popup').toggle(); + $('#algolia-search-input').find('input').focus(); + }); + + $('.popup-btn-close').click(function(){ + $('.popup').hide(); + $('.algolia-pop-overlay').remove(); + $('body').css('overflow', ''); + }); + +}); diff --git a/js/src/bootstrap.js b/js/src/bootstrap.js new file mode 100644 index 0000000..a8f34c2 --- /dev/null +++ b/js/src/bootstrap.js @@ -0,0 +1,46 @@ +/* global NexT: true */ + +$(document).ready(function () { + + $(document).trigger('bootstrap:before'); + + NexT.utils.isMobile() && window.FastClick.attach(document.body); + + NexT.utils.lazyLoadPostsImages(); + + NexT.utils.registerESCKeyEvent(); + + NexT.utils.registerBackToTop(); + + $('.site-nav-toggle button').on('click', function () { + var $siteNav = $('.site-nav'); + var ON_CLASS_NAME = 'site-nav-on'; + var isSiteNavOn = $siteNav.hasClass(ON_CLASS_NAME); + var animateAction = isSiteNavOn ? 'slideUp' : 'slideDown'; + var animateCallback = isSiteNavOn ? 'removeClass' : 'addClass'; + + $siteNav.stop()[animateAction]('fast', function () { + $siteNav[animateCallback](ON_CLASS_NAME); + }); + }); + + + CONFIG.fancybox && NexT.utils.wrapImageWithFancyBox(); + NexT.utils.embeddedVideoTransformer(); + NexT.utils.addActiveClassToMenuItem(); + + + // Define Motion Sequence. + NexT.motion.integrator + .add(NexT.motion.middleWares.logo) + .add(NexT.motion.middleWares.menu) + .add(NexT.motion.middleWares.postList) + .add(NexT.motion.middleWares.sidebar); + + $(document).trigger('motion:before'); + + // Bootstrap Motion. + CONFIG.motion && NexT.motion.integrator.bootstrap(); + + $(document).trigger('bootstrap:after'); +}); diff --git a/js/src/exturl.js b/js/src/exturl.js new file mode 100644 index 0000000..b85062a --- /dev/null +++ b/js/src/exturl.js @@ -0,0 +1,15 @@ +/* global NexT: true */ + +$(document).ready(function () { + + // Create Base64 Object + var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9+/=]/g,"");while(f>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/rn/g,"n");var t="";for(var n=0;n127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}; + + $('.exturl').on('click', function () { + var $exturl = $(this).attr('data-url'); + var $decurl = Base64.decode($exturl); + window.open($decurl, '_blank'); + return false; + }); + +}); diff --git a/js/src/hook-duoshuo.js b/js/src/hook-duoshuo.js new file mode 100644 index 0000000..ca64dbd --- /dev/null +++ b/js/src/hook-duoshuo.js @@ -0,0 +1,115 @@ +/* global DUOSHUO: true */ +/* jshint camelcase: false */ + +typeof DUOSHUO !== 'undefined' ? + hookTemplate() : + ($('#duoshuo-script')[0].onload = hookTemplate); + + +function hookTemplate() { + var post = DUOSHUO.templates.post; + + DUOSHUO.templates.post = function (e, t) { + var rs = post(e, t); + var agent = e.post.agent; + var userId = e.post.author.user_id; + var admin = ''; + + if (userId && (userId == CONFIG.duoshuo.userId)) { + admin = '' + CONFIG.duoshuo.author + ''; + } + + if (agent && /^Mozilla/.test(agent)) { + rs = rs.replace(/<\/div>

    /, admin + getAgentInfo(agent) + '

    '); + } + + return rs; + }; +} + +function getAgentInfo(string) { + $.ua.set(string); + + var UNKNOWN = 'Unknown'; + var sua = $.ua; + var separator = isMobile() ? '

    ' : ''; + var osName = sua.os.name || UNKNOWN; + var osVersion = sua.os.version || UNKNOWN; + var browserName = sua.browser.name || UNKNOWN; + var browserVersion = sua.browser.version || UNKNOWN; + var iconMapping = { + os: { + android : 'android', + linux : 'linux', + windows : 'windows', + ios : 'apple', + 'mac os': 'apple', + unknown : 'desktop' + }, + browser: { + chrome : 'chrome', + chromium : 'chrome', + firefox : 'firefox', + opera : 'opera', + safari : 'safari', + ie : 'internet-explorer', + wechat : 'wechat', + qq : 'qq', + unknown : 'globe' + } + }; + var osIcon = iconMapping.os[osName.toLowerCase()]; + var browserIcon = iconMapping.browser[getBrowserKey()]; + + return separator + + '' + + '' + + osName + ' ' + osVersion + + '' + separator + + '' + + '' + + browserName + ' ' + browserVersion + + ''; + + function getBrowserKey () { + var key = browserName.toLowerCase(); + + if (key.match(/WeChat/i)) { + return 'wechat'; + } + + if (key.match(/QQBrowser/i)) { + return 'qq'; + } + + return key; + } + + function isMobile() { + var userAgent = window.navigator.userAgent; + + var isiPad = userAgent.match(/iPad/i) !== null; + var mobileUA = [ + 'iphone', 'android', 'phone', 'mobile', + 'wap', 'netfront', 'x11', 'java', 'opera mobi', + 'opera mini', 'ucweb', 'windows ce', 'symbian', + 'symbianos', 'series', 'webos', 'sony', + 'blackberry', 'dopod', 'nokia', 'samsung', + 'palmsource', 'xda', 'pieplus', 'meizu', + 'midp' ,'cldc' , 'motorola', 'foma', + 'docomo', 'up.browser', 'up.link', 'blazer', + 'helio', 'hosin', 'huawei', 'novarra', + 'coolpad', 'webos', 'techfaith', 'palmsource', + 'alcatel', 'amoi', 'ktouch', 'nexian', + 'ericsson', 'philips', 'sagem', 'wellcom', + 'bunjalloo', 'maui', 'smartphone', 'iemobile', + 'spice', 'bird', 'zte-', 'longcos', + 'pantech', 'gionee', 'portalmmm', 'jig browser', + 'hiptop', 'benq', 'haier', '^lct', + '320x320', '240x320', '176x220' + ]; + var pattern = new RegExp(mobileUA.join('|'), 'i'); + + return !isiPad && userAgent.match(pattern); + } +} diff --git a/js/src/js.cookie.js b/js/src/js.cookie.js new file mode 100644 index 0000000..c6c3975 --- /dev/null +++ b/js/src/js.cookie.js @@ -0,0 +1,165 @@ +/*! + * JavaScript Cookie v2.1.4 + * https://github.com/js-cookie/js-cookie + * + * Copyright 2006, 2015 Klaus Hartl & Fagner Brack + * Released under the MIT license + */ +;(function (factory) { + var registeredInModuleLoader = false; + if (typeof define === 'function' && define.amd) { + define(factory); + registeredInModuleLoader = true; + } + if (typeof exports === 'object') { + module.exports = factory(); + registeredInModuleLoader = true; + } + if (!registeredInModuleLoader) { + var OldCookies = window.Cookies; + var api = window.Cookies = factory(); + api.noConflict = function () { + window.Cookies = OldCookies; + return api; + }; + } +}(function () { + function extend () { + var i = 0; + var result = {}; + for (; i < arguments.length; i++) { + var attributes = arguments[ i ]; + for (var key in attributes) { + result[key] = attributes[key]; + } + } + return result; + } + + function init (converter) { + function api (key, value, attributes) { + var result; + if (typeof document === 'undefined') { + return; + } + + // Write + + if (arguments.length > 1) { + attributes = extend({ + path: '/' + }, api.defaults, attributes); + + if (typeof attributes.expires === 'number') { + var expires = new Date(); + expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); + attributes.expires = expires; + } + + // We're using "expires" because "max-age" is not supported by IE + attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; + + try { + result = JSON.stringify(value); + if (/^[\{\[]/.test(result)) { + value = result; + } + } catch (e) {} + + if (!converter.write) { + value = encodeURIComponent(String(value)) + .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); + } else { + value = converter.write(value, key); + } + + key = encodeURIComponent(String(key)); + key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); + key = key.replace(/[\(\)]/g, escape); + + var stringifiedAttributes = ''; + + for (var attributeName in attributes) { + if (!attributes[attributeName]) { + continue; + } + stringifiedAttributes += '; ' + attributeName; + if (attributes[attributeName] === true) { + continue; + } + stringifiedAttributes += '=' + attributes[attributeName]; + } + return (document.cookie = key + '=' + value + stringifiedAttributes); + } + + // Read + + if (!key) { + result = {}; + } + + // To prevent the for loop in the first place assign an empty array + // in case there are no cookies at all. Also prevents odd result when + // calling "get()" + var cookies = document.cookie ? document.cookie.split('; ') : []; + var rdecode = /(%[0-9A-Z]{2})+/g; + var i = 0; + + for (; i < cookies.length; i++) { + var parts = cookies[i].split('='); + var cookie = parts.slice(1).join('='); + + if (cookie.charAt(0) === '"') { + cookie = cookie.slice(1, -1); + } + + try { + var name = parts[0].replace(rdecode, decodeURIComponent); + cookie = converter.read ? + converter.read(cookie, name) : converter(cookie, name) || + cookie.replace(rdecode, decodeURIComponent); + + if (this.json) { + try { + cookie = JSON.parse(cookie); + } catch (e) {} + } + + if (key === name) { + result = cookie; + break; + } + + if (!key) { + result[name] = cookie; + } + } catch (e) {} + } + + return result; + } + + api.set = api; + api.get = function (key) { + return api.call(api, key); + }; + api.getJSON = function () { + return api.apply({ + json: true + }, [].slice.call(arguments)); + }; + api.defaults = {}; + + api.remove = function (key, attributes) { + api(key, '', extend(attributes, { + expires: -1 + })); + }; + + api.withConverter = init; + + return api; + } + + return init(function () {}); +})); diff --git a/js/src/motion.js b/js/src/motion.js new file mode 100644 index 0000000..cbfb824 --- /dev/null +++ b/js/src/motion.js @@ -0,0 +1,291 @@ +/* global NexT: true */ + +$(document).ready(function () { + NexT.motion = {}; + + var sidebarToggleLines = { + lines: [], + push: function (line) { + this.lines.push(line); + }, + init: function () { + this.lines.forEach(function (line) { + line.init(); + }); + }, + arrow: function () { + this.lines.forEach(function (line) { + line.arrow(); + }); + }, + close: function () { + this.lines.forEach(function (line) { + line.close(); + }); + } + }; + + function SidebarToggleLine(settings) { + this.el = $(settings.el); + this.status = $.extend({}, { + init: { + width: '100%', + opacity: 1, + left: 0, + rotateZ: 0, + top: 0 + } + }, settings.status); + } + + SidebarToggleLine.prototype.init = function () { + this.transform('init'); + }; + SidebarToggleLine.prototype.arrow = function () { + this.transform('arrow'); + }; + SidebarToggleLine.prototype.close = function () { + this.transform('close'); + }; + SidebarToggleLine.prototype.transform = function (status) { + this.el.velocity('stop').velocity(this.status[status]); + }; + + var sidebarToggleLine1st = new SidebarToggleLine({ + el: '.sidebar-toggle-line-first', + status: { + arrow: {width: '50%', rotateZ: '-45deg', top: '2px'}, + close: {width: '100%', rotateZ: '-45deg', top: '5px'} + } + }); + var sidebarToggleLine2nd = new SidebarToggleLine({ + el: '.sidebar-toggle-line-middle', + status: { + arrow: {width: '90%'}, + close: {opacity: 0} + } + }); + var sidebarToggleLine3rd = new SidebarToggleLine({ + el: '.sidebar-toggle-line-last', + status: { + arrow: {width: '50%', rotateZ: '45deg', top: '-2px'}, + close: {width: '100%', rotateZ: '45deg', top: '-5px'} + } + }); + + sidebarToggleLines.push(sidebarToggleLine1st); + sidebarToggleLines.push(sidebarToggleLine2nd); + sidebarToggleLines.push(sidebarToggleLine3rd); + + var SIDEBAR_WIDTH = '320px'; + var SIDEBAR_DISPLAY_DURATION = 200; + + var sidebarToggleMotion = { + toggleEl: $('.sidebar-toggle'), + sidebarEl: $('.sidebar'), + isSidebarVisible: false, + init: function () { + this.toggleEl.on('click', this.clickHandler.bind(this)); + this.toggleEl.on('mouseenter', this.mouseEnterHandler.bind(this)); + this.toggleEl.on('mouseleave', this.mouseLeaveHandler.bind(this)); + + $(document) + .on('sidebar.isShowing', function () { + NexT.utils.isDesktop() && $('body').velocity('stop').velocity( + {paddingRight: SIDEBAR_WIDTH}, + SIDEBAR_DISPLAY_DURATION + ); + }) + .on('sidebar.isHiding', function () { + }); + }, + clickHandler: function () { + this.isSidebarVisible ? this.hideSidebar() : this.showSidebar(); + this.isSidebarVisible = !this.isSidebarVisible; + }, + mouseEnterHandler: function () { + if (this.isSidebarVisible) { + return; + } + sidebarToggleLines.arrow(); + }, + mouseLeaveHandler: function () { + if (this.isSidebarVisible) { + return; + } + sidebarToggleLines.init(); + }, + showSidebar: function () { + var self = this; + + sidebarToggleLines.close(); + + this.sidebarEl.velocity('stop').velocity({ + width: SIDEBAR_WIDTH + }, { + display: 'block', + duration: SIDEBAR_DISPLAY_DURATION, + begin: function () { + $('.sidebar .motion-element').velocity( + 'transition.slideRightIn', + { + stagger: 50, + drag: true, + complete: function () { + self.sidebarEl.trigger('sidebar.motion.complete'); + } + } + ); + }, + complete: function () { + self.sidebarEl.addClass('sidebar-active'); + self.sidebarEl.trigger('sidebar.didShow'); + } + } + ); + + this.sidebarEl.trigger('sidebar.isShowing'); + }, + hideSidebar: function () { + NexT.utils.isDesktop() && $('body').velocity('stop').velocity({paddingRight: 0}); + this.sidebarEl.find('.motion-element').velocity('stop').css('display', 'none'); + this.sidebarEl.velocity('stop').velocity({width: 0}, {display: 'none'}); + + sidebarToggleLines.init(); + + this.sidebarEl.removeClass('sidebar-active'); + this.sidebarEl.trigger('sidebar.isHiding'); + + //在 post 页面下按下隐藏 sidebar 时如果当前选中的是“站点概览”,将 toc 去除 motion 效果 + //防止再次打开时会出现在“站点概览”下的 bug + if (!!$('.post-toc-wrap')) { + if ($('.site-overview').css('display') === 'block') { + $('.post-toc-wrap').removeClass('motion-element'); + } + } + } + }; + sidebarToggleMotion.init(); + + NexT.motion.integrator = { + queue: [], + cursor: -1, + add: function (fn) { + this.queue.push(fn); + return this; + }, + next: function () { + this.cursor++; + var fn = this.queue[this.cursor]; + $.isFunction(fn) && fn(NexT.motion.integrator); + }, + bootstrap: function () { + this.next(); + } + }; + + NexT.motion.middleWares = { + logo: function (integrator) { + var sequence = []; + var $brand = $('.brand'); + var $title = $('.site-title'); + var $subtitle = $('.site-subtitle'); + var $logoLineTop = $('.logo-line-before i'); + var $logoLineBottom = $('.logo-line-after i'); + + $brand.size() > 0 && sequence.push({ + e: $brand, + p: {opacity: 1}, + o: {duration: 200} + }); + + NexT.utils.isMist() && hasElement([$logoLineTop, $logoLineBottom]) && + sequence.push( + getMistLineSettings($logoLineTop, '100%'), + getMistLineSettings($logoLineBottom, '-100%') + ); + + hasElement($title) && sequence.push({ + e: $title, + p: {opacity: 1, top: 0}, + o: { duration: 200 } + }); + + hasElement($subtitle) && sequence.push({ + e: $subtitle, + p: {opacity: 1, top: 0}, + o: {duration: 200} + }); + + if (sequence.length > 0) { + sequence[sequence.length - 1].o.complete = function () { + integrator.next(); + }; + $.Velocity.RunSequence(sequence); + } else { + integrator.next(); + } + + + function getMistLineSettings (element, translateX) { + return { + e: $(element), + p: {translateX: translateX}, + o: { + duration: 500, + sequenceQueue: false + } + }; + } + + /** + * Check if $elements exist. + * @param {jQuery|Array} $elements + * @returns {boolean} + */ + function hasElement ($elements) { + $elements = Array.isArray($elements) ? $elements : [$elements]; + return $elements.every(function ($element) { + return $.isFunction($element.size) && $element.size() > 0; + }); + } + }, + + menu: function (integrator) { + $('.menu-item').velocity('transition.slideDownIn', { + display: null, + duration: 200, + complete: function () { + integrator.next(); + } + }); + }, + + postList: function (integrator) { + var $post = $('.post'); + var hasPost = $post.size() > 0; + + hasPost ? postMotion() : integrator.next(); + + function postMotion () { + var postMotionOptions = window.postMotionOptions || { + stagger: 100, + drag: true + }; + postMotionOptions.complete = function () { + integrator.next(); + }; + + $post.velocity('transition.slideDownIn', postMotionOptions); + } + }, + + sidebar: function (integrator) { + if (CONFIG.sidebar.display === 'always') { + NexT.utils.displaySidebar(); + } + integrator.next(); + } + }; + +}); diff --git a/js/src/post-details.js b/js/src/post-details.js new file mode 100644 index 0000000..dbdc41c --- /dev/null +++ b/js/src/post-details.js @@ -0,0 +1,147 @@ +/* global NexT: true */ + +$(document).ready(function () { + + initScrollSpy(); + NexT.utils.needAffix() && initAffix(); + initTOCDimension(); + + function initScrollSpy () { + var tocSelector = '.post-toc'; + var $tocElement = $(tocSelector); + var activeCurrentSelector = '.active-current'; + + $tocElement + .on('activate.bs.scrollspy', function () { + var $currentActiveElement = $(tocSelector + ' .active').last(); + + removeCurrentActiveClass(); + $currentActiveElement.addClass('active-current'); + }) + .on('clear.bs.scrollspy', removeCurrentActiveClass); + + $('body').scrollspy({ target: tocSelector }); + + function removeCurrentActiveClass () { + $(tocSelector + ' ' + activeCurrentSelector) + .removeClass(activeCurrentSelector.substring(1)); + } + } + + // Sidebar float + function initAffix () { + var headerHeight = $('.header-inner').height(); + var footerOffset = parseInt($('.main').css('padding-bottom'), 10); + + /*jshint camelcase: false */ + var sidebarTop = (CONFIG.sidebar.offset_float === 0) ? + headerHeight + CONFIG.sidebar.offset : + headerHeight; + /*jshint camelcase: true */ + + $('.sidebar-inner').affix({ + offset: { + top: sidebarTop, + bottom: footerOffset + } + }); + + $(document) + .on('affixed.bs.affix', function () { + updateTOCHeight(document.body.clientHeight - 100); + }); + } + + function initTOCDimension () { + var updateTOCHeightTimer; + + $(window).on('resize', function () { + updateTOCHeightTimer && clearTimeout(updateTOCHeightTimer); + + updateTOCHeightTimer = setTimeout(function () { + var tocWrapperHeight = document.body.clientHeight - 100; + + updateTOCHeight(tocWrapperHeight); + }, 0); + }); + + // Initialize TOC Height. + updateTOCHeight(document.body.clientHeight - 100); + + // Initialize TOC Width. + var scrollbarWidth = NexT.utils.getScrollbarWidth(); + $('.post-toc').css('width', 'calc(100% + ' + scrollbarWidth + 'px)'); + } + + function updateTOCHeight (height) { + height = height || 'auto'; + $('.post-toc').css('max-height', height); + } + +}); + +$(document).ready(function () { + var html = $('html'); + var TAB_ANIMATE_DURATION = 200; + var hasVelocity = $.isFunction(html.velocity); + + $('.sidebar-nav li').on('click', function () { + var item = $(this); + var activeTabClassName = 'sidebar-nav-active'; + var activePanelClassName = 'sidebar-panel-active'; + if (item.hasClass(activeTabClassName)) { + return; + } + + var currentTarget = $('.' + activePanelClassName); + var target = $('.' + item.data('target')); + + hasVelocity ? + currentTarget.velocity('transition.slideUpOut', TAB_ANIMATE_DURATION, function () { + target + .velocity('stop') + .velocity('transition.slideDownIn', TAB_ANIMATE_DURATION) + .addClass(activePanelClassName); + }) : + currentTarget.animate({ opacity: 0 }, TAB_ANIMATE_DURATION, function () { + currentTarget.hide(); + target + .stop() + .css({'opacity': 0, 'display': 'block'}) + .animate({ opacity: 1 }, TAB_ANIMATE_DURATION, function () { + currentTarget.removeClass(activePanelClassName); + target.addClass(activePanelClassName); + }); + }); + + item.siblings().removeClass(activeTabClassName); + item.addClass(activeTabClassName); + }); + + $('.post-toc a').on('click', function (e) { + e.preventDefault(); + var targetSelector = NexT.utils.escapeSelector(this.getAttribute('href')); + var offset = $(targetSelector).offset().top; + + hasVelocity ? + html.velocity('stop').velocity('scroll', { + offset: offset + 'px', + mobileHA: false + }) : + $('html, body').stop().animate({ + scrollTop: offset + }, 500); + }); + + // Expand sidebar on post detail page by default, when post has a toc. + var $tocContent = $('.post-toc-content'); + var isSidebarCouldDisplay = CONFIG.sidebar.display === 'post' || + CONFIG.sidebar.display === 'always'; + var hasTOC = $tocContent.length > 0 && $tocContent.html().trim().length > 0; + if (isSidebarCouldDisplay && hasTOC) { + CONFIG.motion ? + (NexT.motion.middleWares.sidebar = function () { + NexT.utils.displaySidebar(); + }) : NexT.utils.displaySidebar(); + } +}); diff --git a/js/src/schemes/pisces.js b/js/src/schemes/pisces.js new file mode 100644 index 0000000..d4125b6 --- /dev/null +++ b/js/src/schemes/pisces.js @@ -0,0 +1,17 @@ +$(document).ready(function () { + var $headerInner = $('.header-inner'); + var $sidebar = $('#sidebar'); + var getSidebarTop = function(){ + return $headerInner.height() + CONFIG.sidebar.offset; + }; + var setSidebarMarginTop = function(sidebarTop){ + return $sidebar.css({ 'margin-top': sidebarTop }); + }; + var mql = window.matchMedia('(min-width: 991px)'); + setSidebarMarginTop(getSidebarTop()).show(); + mql.addListener(function(e){ + if(e.matches){ + setSidebarMarginTop(getSidebarTop()); + } + }); +}); diff --git a/js/src/scroll-cookie.js b/js/src/scroll-cookie.js new file mode 100644 index 0000000..34ff200 --- /dev/null +++ b/js/src/scroll-cookie.js @@ -0,0 +1,23 @@ +$(document).ready(function() { + + // Set relative link path (without domain) + var rpath = window.location.href.replace(window.location.origin, ""); + + // Write position in cookie + var timeout; + $(window).on("scroll", function() { + clearTimeout(timeout); + timeout = setTimeout(function () { + Cookies.set("scroll-cookie", ($(window).scrollTop() + "|" + rpath), { expires: 365, path: '' }); + }, 250); + }); + + // Read position from cookie + if (Cookies.get("scroll-cookie") !== undefined) { + var cvalues = Cookies.get("scroll-cookie").split('|'); + if (cvalues[1] == rpath) { + $(window).scrollTop(cvalues[0]); + } + } + +}); diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js new file mode 100644 index 0000000..f5c5c6c --- /dev/null +++ b/js/src/scrollspy.js @@ -0,0 +1,182 @@ +/* ======================================================================== +* Bootstrap: scrollspy.js v3.3.2 +* http://getbootstrap.com/javascript/#scrollspy +* ======================================================================== +* Copyright 2011-2015 Twitter, Inc. +* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) +* ======================================================================== */ + +/** + * Custom by iissnan + * + * - Add a `clear.bs.scrollspy` event. + * - Esacpe targets selector. + */ + + ++function ($) { + 'use strict'; + + // SCROLLSPY CLASS DEFINITION + // ========================== + + function ScrollSpy(element, options) { + this.$body = $(document.body) + this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) + this.options = $.extend({}, ScrollSpy.DEFAULTS, options) + this.selector = (this.options.target || '') + ' .nav li > a' + this.offsets = [] + this.targets = [] + this.activeTarget = null + this.scrollHeight = 0 + + this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) + this.refresh() + this.process() + } + + ScrollSpy.VERSION = '3.3.2' + + ScrollSpy.DEFAULTS = { + offset: 10 + } + + ScrollSpy.prototype.getScrollHeight = function () { + return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) + } + + ScrollSpy.prototype.refresh = function () { + var that = this + var offsetMethod = 'offset' + var offsetBase = 0 + + this.offsets = [] + this.targets = [] + this.scrollHeight = this.getScrollHeight() + + if (!$.isWindow(this.$scrollElement[0])) { + offsetMethod = 'position' + offsetBase = this.$scrollElement.scrollTop() + } + + this.$body + .find(this.selector) + .map(function () { + var $el = $(this) + var href = $el.data('target') || $el.attr('href') + var $href = /^#./.test(href) && $(NexT.utils.escapeSelector(href)) // Need to escape selector. + + return ($href + && $href.length + && $href.is(':visible') + && [[$href[offsetMethod]().top + offsetBase, href]]) || null + }) + .sort(function (a, b) { return a[0] - b[0] }) + .each(function () { + that.offsets.push(this[0]) + that.targets.push(this[1]) + }) + + + } + + ScrollSpy.prototype.process = function () { + var scrollTop = this.$scrollElement.scrollTop() + this.options.offset + var scrollHeight = this.getScrollHeight() + var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() + var offsets = this.offsets + var targets = this.targets + var activeTarget = this.activeTarget + var i + + if (this.scrollHeight != scrollHeight) { + this.refresh() + } + + if (scrollTop >= maxScroll) { + return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) + } + + if (activeTarget && scrollTop < offsets[0]) { + $(this.selector).trigger('clear.bs.scrollspy') // Add a custom event. + this.activeTarget = null + return this.clear() + } + + for (i = offsets.length; i--;) { + activeTarget != targets[i] + && scrollTop >= offsets[i] + && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) + && this.activate(targets[i]) + } + } + + ScrollSpy.prototype.activate = function (target) { + this.activeTarget = target + + this.clear() + + var selector = this.selector + + '[data-target="' + target + '"],' + + this.selector + '[href="' + target + '"]' + + var active = $(selector) + .parents('li') + .addClass('active') + + if (active.parent('.dropdown-menu').length) { + active = active + .closest('li.dropdown') + .addClass('active') + } + + active.trigger('activate.bs.scrollspy') + } + + ScrollSpy.prototype.clear = function () { + $(this.selector) + .parentsUntil(this.options.target, '.active') + .removeClass('active') + } + + + // SCROLLSPY PLUGIN DEFINITION + // =========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.scrollspy') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.scrollspy + + $.fn.scrollspy = Plugin + $.fn.scrollspy.Constructor = ScrollSpy + + + // SCROLLSPY NO CONFLICT + // ===================== + + $.fn.scrollspy.noConflict = function () { + $.fn.scrollspy = old + return this + } + + + // SCROLLSPY DATA-API + // ================== + + $(window).on('load.bs.scrollspy.data-api', function () { + $('[data-spy="scroll"]').each(function () { + var $spy = $(this) + Plugin.call($spy, $spy.data()) + }) + }) + +}(jQuery); diff --git a/js/src/utils.js b/js/src/utils.js new file mode 100644 index 0000000..80bfde3 --- /dev/null +++ b/js/src/utils.js @@ -0,0 +1,232 @@ +/* global NexT: true */ + +NexT.utils = NexT.$u = { + /** + * Wrap images with fancybox support. + */ + wrapImageWithFancyBox: function () { + $('.content img') + .not('[hidden]') + .not('.group-picture img, .post-gallery img') + .each(function () { + var $image = $(this); + var imageTitle = $image.attr('title'); + var $imageWrapLink = $image.parent('a'); + + if ($imageWrapLink.size() < 1) { + $imageWrapLink = $image.wrap('').parent('a'); + } + + $imageWrapLink.addClass('fancybox fancybox.image'); + $imageWrapLink.attr('rel', 'group'); + + if (imageTitle) { + $imageWrapLink.append('

    ' + imageTitle + '

    '); + + //make sure img title tag will show correctly in fancybox + $imageWrapLink.attr('title', imageTitle); + } + }); + + $('.fancybox').fancybox({ + helpers: { + overlay: { + locked: false + } + } + }); + }, + + lazyLoadPostsImages: function () { + $('#posts').find('img').lazyload({ + placeholder: '/images/loading.gif', + effect: 'fadeIn' + }); + }, + + registerESCKeyEvent: function () { + $(document).on('keyup', function (event) { + var shouldDismissSearchPopup = event.which === 27 && + $('.search-popup').is(':visible'); + if (shouldDismissSearchPopup) { + $('.search-popup').hide(); + $('.search-popup-overlay').remove(); + $('body').css('overflow', ''); + } + }); + }, + + registerBackToTop: function () { + var THRESHOLD = 50; + var $top = $('.back-to-top'); + + $(window).on('scroll', function () { + $top.toggleClass('back-to-top-on', window.pageYOffset > THRESHOLD); + + var scrollTop = $(window).scrollTop(); + var docHeight = $('#content').height(); + var winHeight = $(window).height(); + var contentMath = (docHeight > winHeight) ? (docHeight - winHeight) : ($(document).height() - winHeight); + var scrollPercent = (scrollTop) / (contentMath); + var scrollPercentRounded = Math.round(scrollPercent*100); + var scrollPercentMaxed = (scrollPercentRounded > 100) ? 100 : scrollPercentRounded; + $('#scrollpercent>span').html(scrollPercentMaxed); + }); + + $top.on('click', function () { + $('body').velocity('scroll'); + }); + }, + + /** + * Transform embedded video to support responsive layout. + * @see http://toddmotto.com/fluid-and-responsive-youtube-and-vimeo-videos-with-fluidvids-js/ + */ + embeddedVideoTransformer: function () { + var $iframes = $('iframe'); + + // Supported Players. Extend this if you need more players. + var SUPPORTED_PLAYERS = [ + 'www.youtube.com', + 'player.vimeo.com', + 'player.youku.com', + 'music.163.com', + 'www.tudou.com' + ]; + var pattern = new RegExp( SUPPORTED_PLAYERS.join('|') ); + + $iframes.each(function () { + var iframe = this; + var $iframe = $(this); + var oldDimension = getDimension($iframe); + var newDimension; + + if (this.src.search(pattern) > 0) { + + // Calculate the video ratio based on the iframe's w/h dimensions + var videoRatio = getAspectRadio(oldDimension.width, oldDimension.height); + + // Replace the iframe's dimensions and position the iframe absolute + // This is the trick to emulate the video ratio + $iframe.width('100%').height('100%') + .css({ + position: 'absolute', + top: '0', + left: '0' + }); + + + // Wrap the iframe in a new
    which uses a dynamically fetched padding-top property + // based on the video's w/h dimensions + var wrap = document.createElement('div'); + wrap.className = 'fluid-vids'; + wrap.style.position = 'relative'; + wrap.style.marginBottom = '20px'; + wrap.style.width = '100%'; + wrap.style.paddingTop = videoRatio + '%'; + + // Add the iframe inside our newly created
    + var iframeParent = iframe.parentNode; + iframeParent.insertBefore(wrap, iframe); + wrap.appendChild(iframe); + + // Additional adjustments for 163 Music + if (this.src.search('music.163.com') > 0) { + newDimension = getDimension($iframe); + var shouldRecalculateAspect = newDimension.width > oldDimension.width || + newDimension.height < oldDimension.height; + + // 163 Music Player has a fixed height, so we need to reset the aspect radio + if (shouldRecalculateAspect) { + wrap.style.paddingTop = getAspectRadio(newDimension.width, oldDimension.height) + '%'; + } + } + } + }); + + function getDimension($element) { + return { + width: $element.width(), + height: $element.height() + }; + } + + function getAspectRadio(width, height) { + return height / width * 100; + } + }, + + /** + * Add `menu-item-active` class name to menu item + * via comparing location.path with menu item's href. + */ + addActiveClassToMenuItem: function () { + var path = window.location.pathname; + path = path === '/' ? path : path.substring(0, path.length - 1); + $('.menu-item a[href="' + path + '"]').parent().addClass('menu-item-active'); + }, + + hasMobileUA: function () { + var nav = window.navigator; + var ua = nav.userAgent; + var pa = /iPad|iPhone|Android|Opera Mini|BlackBerry|webOS|UCWEB|Blazer|PSP|IEMobile|Symbian/g; + + return pa.test(ua); + }, + + isTablet: function () { + return window.screen.width < 992 && window.screen.width > 767 && this.hasMobileUA(); + }, + + isMobile: function () { + return window.screen.width < 767 && this.hasMobileUA(); + }, + + isDesktop: function () { + return !this.isTablet() && !this.isMobile(); + }, + + /** + * Escape meta symbols in jQuery selectors. + * + * @param selector + * @returns {string|void|XML|*} + */ + escapeSelector: function (selector) { + return selector.replace(/[!"$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, '\\$&'); + }, + + displaySidebar: function () { + if (!this.isDesktop() || this.isPisces()) { + return; + } + $('.sidebar-toggle').trigger('click'); + }, + + isMist: function () { + return CONFIG.scheme === 'Mist'; + }, + + isPisces: function () { + return CONFIG.scheme === 'Pisces'; + }, + + getScrollbarWidth: function () { + var $div = $('
    ').addClass('scrollbar-measure').prependTo('body'); + var div = $div[0]; + var scrollbarWidth = div.offsetWidth - div.clientWidth; + + $div.remove(); + + return scrollbarWidth; + }, + + /** + * Affix behaviour for Sidebar. + * + * @returns {Boolean} + */ + needAffix: function () { + return this.isPisces(); + } +}; diff --git a/lib/Han/dist/font/han-space.otf b/lib/Han/dist/font/han-space.otf new file mode 100644 index 0000000..845b1bc Binary files /dev/null and b/lib/Han/dist/font/han-space.otf differ diff --git a/lib/Han/dist/font/han-space.woff b/lib/Han/dist/font/han-space.woff new file mode 100644 index 0000000..6ccc84f Binary files /dev/null and b/lib/Han/dist/font/han-space.woff differ diff --git a/lib/Han/dist/font/han.otf b/lib/Han/dist/font/han.otf new file mode 100644 index 0000000..2ce2f46 Binary files /dev/null and b/lib/Han/dist/font/han.otf differ diff --git a/lib/Han/dist/font/han.woff b/lib/Han/dist/font/han.woff new file mode 100644 index 0000000..011e06c Binary files /dev/null and b/lib/Han/dist/font/han.woff differ diff --git a/lib/Han/dist/han.css b/lib/Han/dist/han.css new file mode 100644 index 0000000..1b82c58 --- /dev/null +++ b/lib/Han/dist/han.css @@ -0,0 +1,2038 @@ +@charset "UTF-8"; + +/*! 漢字標準格式 v3.3.0 | MIT License | css.hanzi.co */ +/*! Han.css: the CSS typography framework optimised for Hanzi */ + +/* normalize.css v4.0.0 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +main, +menu, +nav, +section, +summary { + /* 1 */ + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; +} +audio:not([controls]) { + display: none; + height: 0; +} +progress { + vertical-align: baseline; +} +template, +[hidden] { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline-width: 0; +} +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} +b, +strong { + font-weight: inherit; +} +b, +strong { + font-weight: bolder; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: .67em 0; +} +mark { + background-color: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sub { + bottom: -.25em; +} +sup { + top: -.5em; +} +img { + border-style: none; +} +svg:not(:root) { + overflow: hidden; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} +figure { + margin: 1em 40px; +} +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} +button, +input, +select, +textarea { + font: inherit; +} +optgroup { + font-weight: bold; +} +button, +input, +select { + /* 2 */ + overflow: visible; +} +button, +input, +select, +textarea { + /* 1 */ + margin: 0; +} +button, +select { + /* 1 */ + text-transform: none; +} +button, +[type="button"], +[type="reset"], +[type="submit"] { + cursor: pointer; +} +[disabled] { + cursor: default; +} +button, +html [type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; /* 2 */ +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +button:-moz-focusring, +input:-moz-focusring { + outline: 1px dotted ButtonText; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: .35em .625em .75em; +} +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} +textarea { + overflow: auto; +} +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} +[type="search"] { + -webkit-appearance: textfield; +} +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +html { + line-height: 1.3; + -webkit-font-smoothing: subpixel-antialiased; +} +ol, +ul { + padding-left: 2em; +} +figure, +blockquote { + margin-left: 2em; + margin-right: 2em; +} +address { + font-style: inherit; +} +pre { + overflow: auto; + white-space: pre; + word-wrap: normal; +} +a { + text-decoration: inherit; +} +em:lang(zh), +em:lang(ja) { + -moz-text-emphasis: filled circle; + -webkit-text-emphasis: filled circle; + text-emphasis: filled circle; + -moz-text-emphasis-position: under; + -webkit-text-emphasis-position: under; + text-emphasis-position: under; + font-style: inherit; + border-bottom: 2px dotted; + padding-bottom: .05em; + border-bottom-width: -webkit-calc(0px); + padding-bottom: -webkit-calc(0px); +} +em:lang(ja) { + -moz-text-emphasis: filled sesame; + -webkit-text-emphasis: filled sesame; + text-emphasis: filled sesame; + -moz-text-emphasis-position: over; + -webkit-text-emphasis-position: over; + text-emphasis-position: over; +} +dfn:lang(zh), +dfn:lang(ja) { + font-weight: inherit; + font-style: inherit; +} +dfn:lang(zh), +dfn:lang(ja) { + font-weight: bolder; +} +cite:lang(zh), +cite:lang(ja) { + font-style: inherit; +} +q { + quotes: "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019"; +} +q:lang(zh) { + quotes: "\300c" "\300d" "\300e" "\300f" "\300c" "\300d" "\300e" "\300f" "\300c" "\300d" "\300e" "\300f"; +} +q:lang(zh-CN), +q:lang(en) { + quotes: "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019"; +} +q:lang(en-GB) { + quotes: "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d"; +} +q:before { + content: open-quote; +} +q:after { + content: close-quote; +} +q:lang(ja):before, +q:lang(ja):after { + content: none; +} +code, +kbd, +samp, +pre { + font-family: monospace, monospace, sans-serif; +} +i:lang(zh), +var:lang(zh), +i:lang(ja), +var:lang(ja) { + font-family: cursive, serif; + font-style: inherit; +} +u + u, +ins + u, +u + ins, +ins + ins, +s + s, +del + s, +s + del, +del + del, +.han-js-rendered u.adjacent, +.han-js-rendered ins.adjacent, +.han-js-rendered s + s.adjacent, +.han-js-rendered del + s.adjacent, +.han-js-rendered s + del.adjacent, +.han-js-rendered del + del.adjacent { + margin-left: .125em; +} +u, +ins { + padding-bottom: .05em; + border-bottom: 1px solid; + text-decoration: none; +} +ruby rtc rt { + display: inline; + font-size: inherit; +} +ruby.zhuyin, +ruby.mps { + display: ruby; + -webkit-ruby-position: inter-character; + ruby-position: inter-character; +} +ruby.zhuyin > rt, +ruby.mps > rt { + -moz-transform: scale(.8); + -ms-transform: scale(.8); + -webkit-transform: scale(.8); + transform: scale(.8); + -moz-transform-origin: left center; + -ms-transform-origin: left center; + -webkit-transform-origin: left center; + transform-origin: left center; + font-size: .5em; +} +ruby.zhuyin > rt:empty, +ruby.mps > rt:empty { + display: none; +} +.han-js-rendered u + u, +.han-js-rendered ins + u, +.han-js-rendered u + ins, +.han-js-rendered ins + ins, +.han-js-rendered s + s, +.han-js-rendered del + s, +.han-js-rendered s + del, +.han-js-rendered del + del { + margin-left: auto; +} +.textemphasis $han-text-emphasis-pf h-jinze, +.textemphasis em:lang(zh) h-jinze, +.textemphasis em:lang(ja) h-jinze { + display: inline; +} +.han-js-rendered em:lang(zh), +.han-js-rendered em:lang(ja) { + padding-bottom: auto; + border-bottom-width: 0; +} +.no-textemphasis em:lang(zh), +.no-textemphasis em:lang(ja) { + line-height: 2; +} +.no-textemphasis em:lang(zh) h-char, +.no-textemphasis em:lang(ja) h-char { + position: relative; + font-style: inherit; +} +.no-textemphasis em:lang(zh) h-char:after, +.no-textemphasis em:lang(ja) h-char:after { + -moz-text-emphasis: none; + -webkit-text-emphasis: none; + text-emphasis: none; + font-style: normal; + font-weight: normal; + line-height: normal; + text-decoration: none; + text-indent: 0; + -moz-transform: scale(.5); + -ms-transform: scale(.5); + -webkit-transform: scale(.5); + transform: scale(.5); + position: absolute; + left: 50%; + top: 0; + margin-left: -250%; + overflow: hidden; + display: inline-block; + height: 1em; + width: 500%; + line-height: 1; + text-align: center; + text-indent: 0; + font-family: Georgia, "Times New Roman", Arial, !important; +} +em:lang(zh) h-char.punct, +em:lang(ja) h-char.punct, +em:lang(zh) h-char.biaodian, +em:lang(ja) h-char.biaodian { + -moz-text-emphasis: none; + -webkit-text-emphasis: none; + text-emphasis: none; +} +.no-textemphasis em:lang(zh) h-char.punct:after, +.no-textemphasis em:lang(ja) h-char.punct:after, +.no-textemphasis em:lang(zh) h-char.biaodian:after, +.no-textemphasis em:lang(ja) h-char.biaodian:after { + content: none !important; +} +.no-textemphasis em:lang(zh) h-char:after { + margin-top: 1em; + content: "\25cf"; +} +.no-textemphasis em:lang(ja) h-char:after { + margin-top: -.7em; + content: "\fe45"; +} +ruby.zhuyin h-zhuyin, +ruby.mps h-zhuyin, +h-ruby.zhuyin h-zhuyin { + position: relative; + letter-spacing: 0; +} +ruby.zhuyin h-diao, +ruby.mps h-diao, +h-ruby.zhuyin h-diao { + position: absolute; + right: -.9em; + bottom: .5em; + display: block; + font-size: 1.5em; +} +ruby.zhuyin h-diao h-char, +ruby.mps h-diao h-char, +h-ruby.zhuyin h-diao h-char { + -webkit-writing-mode: horizontal-tb; + writing-mode: horizontal-tb; +} +ruby.zhuyin [diao="˙"] h-diao, +ruby.mps [diao="˙"] h-diao, +h-ruby.zhuyin [diao="˙"] h-diao { + top: -.3em; + right: auto; + bottom: auto; + left: 0; + font-size: 1em; +} +ruby.zhuyin [diao^="ㆴ"] h-diao, +ruby.mps [diao^="ㆴ"] h-diao, +h-ruby.zhuyin [diao^="ㆴ"] h-diao, +ruby.zhuyin [diao^="ㆵ"] h-diao, +ruby.mps [diao^="ㆵ"] h-diao, +h-ruby.zhuyin [diao^="ㆵ"] h-diao, +ruby.zhuyin [diao^="ㆶ"] h-diao, +ruby.mps [diao^="ㆶ"] h-diao, +h-ruby.zhuyin [diao^="ㆶ"] h-diao, +ruby.zhuyin [diao^="ㆷ"] h-diao, +ruby.mps [diao^="ㆷ"] h-diao, +h-ruby.zhuyin [diao^="ㆷ"] h-diao, +ruby.zhuyin [diao="󳆴"] h-diao, +ruby.mps [diao="󳆴"] h-diao, +h-ruby.zhuyin [diao="󳆴"] h-diao, +ruby.zhuyin [diao="󳆵"] h-diao, +ruby.mps [diao="󳆵"] h-diao, +h-ruby.zhuyin [diao="󳆵"] h-diao, +ruby.zhuyin [diao="󳆶"] h-diao, +ruby.mps [diao="󳆶"] h-diao, +h-ruby.zhuyin [diao="󳆶"] h-diao, +ruby.zhuyin [diao="󳆷"] h-diao, +ruby.mps [diao="󳆷"] h-diao, +h-ruby.zhuyin [diao="󳆷"] h-diao { + right: -1em; + bottom: -.125em; + font-size: 1em; +} +h-ru[annotation] { + position: relative; + display: inline-table; + border-collapse: collapse; + border-spacing: 0; + line-height: 1.1; + text-align: center; + vertical-align: 1em; +} +h-ru[annotation] > h-ru[annotation] { + vertical-align: -.1em; +} +h-ru[annotation] > h-ru, +h-ru[annotation] > rb, +h-ru[annotation] > rt { + line-height: 1; + text-align: center; +} +h-ru[annotation] > rt { + display: table-header-group; + height: 1em; + font-size: .5em; + white-space: nowrap; + word-break: normal; +} +h-ru[annotation] > rt:before, +h-ru[annotation] > rt:after { + content: "\2006"; +} +h-ru[order="0"] > rt, +h-ruby[rightangle][doubleline] h-ru[order="0"] > rt { + display: table-header-group; +} +h-ru[order="1"] > rt, +h-ruby[rightangle] h-ru[order="0"] > rt, +h-ruby[rightangle][doubleline] h-ru[order="1"] > rt { + display: table-footer-group; +} +h-ru[order="0"] > h-ru[order="1"] { + vertical-align: .15em; +} +h-ruby[rightangle][doubleline] h-ru[order="0"] rt { + line-height: 1.5; +} +h-ruby[rightangle][doubleline] h-ru[annotation] { + vertical-align: .5em; +} +[zhuyin] h-zhuyin { + -moz-text-emphasis: none; + -webkit-text-emphasis: none; + text-emphasis: none; + font-style: normal; + font-weight: normal; + line-height: normal; + text-decoration: none; + text-indent: 0; + position: relative; + display: inline-block; + height: 1em; + width: .4em; + vertical-align: text-top; +} +[zhuyin] h-zhuyin > * { + -moz-transform: scale(.4); + -ms-transform: scale(.4); + -webkit-transform: scale(.4); + transform: scale(.4); + -moz-transform-origin: left top; + -ms-transform-origin: left top; + -webkit-transform-origin: left top; + transform-origin: left top; + display: inline-block; +} +[zhuyin] h-yin { + position: absolute; + left: 0; + height: 1em; + vertical-align: top; + line-height: 1; +} +[zhuyin] h-diao { + position: absolute; + bottom: 0; + right: -.9em; + line-height: 1; +} +[zhuyin] h-yin:empty, +[zhuyin] h-diao:empty { + display: none; +} +[zhuyin] [length="0"] { + margin-right: 0; +} +[zhuyin] [length="0"] h-zhuyin { + display: none; +} +[zhuyin] [length="1"] h-yin { + top: .3em; +} +[zhuyin] [length="1"] h-diao { + bottom: 0; +} +[zhuyin] [length="2"] h-yin { + top: .05em; +} +[zhuyin] [length="2"] h-diao { + bottom: -.3em; +} +[zhuyin] [length="3"] h-yin { + top: -.05em; + line-height: .85; +} +[zhuyin] [length="3"] h-diao { + bottom: -.35em; +} +[zhuyin] [diao="˙"] h-diao { + top: 0; + right: auto; + bottom: auto; + left: .06em; +} +[zhuyin] [diao="˙"] [length="1"] h-diao { + top: .15em; +} +[zhuyin] [diao="˙"] [length="2"] h-diao { + top: -.05em; +} +[zhuyin] [diao="˙"] [length="3"] h-diao { + top: -.2em; +} +[zhuyin] [diao="˪"] h-diao, +[zhuyin] [diao="˫"] h-diao { + -moz-transform: scale(.6); + -ms-transform: scale(.6); + -webkit-transform: scale(.6); + transform: scale(.6); + -moz-transform-origin: left top; + -ms-transform-origin: left top; + -webkit-transform-origin: left top; + transform-origin: left top; +} +[zhuyin] [diao^="ㆴ"] h-diao, +[zhuyin] [diao^="ㆵ"] h-diao, +[zhuyin] [diao^="ㆶ"] h-diao, +[zhuyin] [diao^="ㆷ"] h-diao, +[zhuyin] [diao="󳆴"] h-diao, +[zhuyin] [diao="󳆵"] h-diao, +[zhuyin] [diao="󳆶"] h-diao, +[zhuyin] [diao="󳆷"] h-diao { + bottom: -.6em; + margin-right: .3em; +} +[zhuyin] { + margin-right: .2em; + display: inline-block; + line-height: 1.8; +} +[rightangle] h-ru[annotation] { + vertical-align: 0; + line-height: 1; +} +[rightangle] rt:after { + content: ""; + display: inline-block; + width: 1.2em; +} +h-ru h-ru[zhuyin] { + margin-top: -.4em; + margin-bottom: -.2em; + line-height: 1.8; +} +h-jinze, +h-word { + display: inline-block; + text-indent: 0; +} +@font-face { + font-family: "Han Heiti"; + src: local("Hiragino Sans GB"), local("Lantinghei TC Extralight"), local("Lantinghei SC Extralight"), local(FZLTXHB--B51-0), local(FZLTZHK--GBK1-0), local(".PingFang SC Light"), local(".PingFang TC Light"), local(".PingFang-SC-Light"), local(".PingFang-TC-Light"), local(".PingFang SC"), local(".PingFang TC"), local("Heiti SC Light"), local(STHeitiSC-Light), local("Heiti SC"), local("Heiti TC Light"), local(STHeitiTC-Light), local("Heiti TC"), local("Microsoft Yahei"), local("Microsoft Jhenghei"), local("Noto Sans CJK KR"), local("Noto Sans CJK JP"), local("Noto Sans CJK SC"), local("Noto Sans CJK TC"), local("Source Han Sans K"), local("Source Han Sans KR"), local("Source Han Sans JP"), local("Source Han Sans CN"), local("Source Han Sans HK"), local("Source Han Sans TW"), local("Source Han Sans TWHK"), local("Droid Sans Fallback"); +} +@font-face { + unicode-range: U+4E00-9FFF, U+3400-4DB5, U+20000-2A6D6, U+2A700-2B734, U+2B740-2B81D, U+FA0E-FA0F, U+FA11, U+FA13-FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27-FA29, U+3040-309F, U+30A0-30FF, U+3099-309E, U+FF66-FF9F, U+3007, U+31C0-31E3, U+2F00-2FD5, U+2E80-2EF3; + font-family: "Han Heiti"; + src: local(YuGothic), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"); +} +@font-face { + font-family: "Han Heiti CNS"; + src: local(".PingFang TC Light"), local(".PingFang-TC-Light"), local(".PingFang TC"), local("Heiti TC Light"), local(STHeitiTC-Light), local("Heiti TC"), local("Lantinghei TC Extralight"), local(FZLTXHB--B51-0), local("Lantinghei TC"), local("Microsoft Jhenghei"), local("Microsoft Yahei"), local("Noto Sans CJK TC"), local("Source Han Sans TC"), local("Source Han Sans TW"), local("Source Han Sans TWHK"), local("Source Han Sans HK"), local("Droid Sans Fallback"); +} +@font-face { + font-family: "Han Heiti GB"; + src: local("Hiragino Sans GB"), local(".PingFang SC Light"), local(".PingFang-SC-Light"), local(".PingFang SC"), local("Lantinghei SC Extralight"), local(FZLTXHK--GBK1-0), local("Lantinghei SC"), local("Heiti SC Light"), local(STHeitiSC-Light), local("Heiti SC"), local("Microsoft Yahei"), local("Noto Sans CJK SC"), local("Source Han Sans SC"), local("Source Han Sans CN"), local("Droid Sans Fallback"); +} +@font-face { + font-family: "Han Heiti"; + font-weight: 600; + src: local("Hiragino Sans GB W6"), local(HiraginoSansGB-W6), local("Lantinghei TC Demibold"), local("Lantinghei SC Demibold"), local(FZLTZHB--B51-0), local(FZLTZHK--GBK1-0), local(".PingFang-SC-Semibold"), local(".PingFang-TC-Semibold"), local("Heiti SC Medium"), local("STHeitiSC-Medium"), local("Heiti SC"), local("Heiti TC Medium"), local("STHeitiTC-Medium"), local("Heiti TC"), local("Microsoft YaHei Bold"), local("Microsoft Jhenghei Bold"), local(MicrosoftYaHei-Bold), local(MicrosoftJhengHeiBold), local("Microsoft YaHei"), local("Microsoft Jhenghei"), local("Noto Sans CJK KR Bold"), local("Noto Sans CJK JP Bold"), local("Noto Sans CJK SC Bold"), local("Noto Sans CJK TC Bold"), local(NotoSansCJKkr-Bold), local(NotoSansCJKjp-Bold), local(NotoSansCJKsc-Bold), local(NotoSansCJKtc-Bold), local("Source Han Sans K Bold"), local(SourceHanSansK-Bold), local("Source Han Sans K"), local("Source Han Sans KR Bold"), local("Source Han Sans JP Bold"), local("Source Han Sans CN Bold"), local("Source Han Sans HK Bold"), local("Source Han Sans TW Bold"), local("Source Han Sans TWHK Bold"), local("SourceHanSansKR-Bold"), local("SourceHanSansJP-Bold"), local("SourceHanSansCN-Bold"), local("SourceHanSansHK-Bold"), local("SourceHanSansTW-Bold"), local("SourceHanSansTWHK-Bold"), local("Source Han Sans KR"), local("Source Han Sans CN"), local("Source Han Sans HK"), local("Source Han Sans TW"), local("Source Han Sans TWHK"); +} +@font-face { + unicode-range: U+4E00-9FFF, U+3400-4DB5, U+20000-2A6D6, U+2A700-2B734, U+2B740-2B81D, U+FA0E-FA0F, U+FA11, U+FA13-FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27-FA29, U+3040-309F, U+30A0-30FF, U+3099-309E, U+FF66-FF9F, U+3007, U+31C0-31E3, U+2F00-2FD5, U+2E80-2EF3; + font-family: "Han Heiti"; + font-weight: 600; + src: local("YuGothic Bold"), local("Hiragino Kaku Gothic ProN W6"), local("Hiragino Kaku Gothic Pro W6"), local(YuGo-Bold), local(HiraKakuProN-W6), local(HiraKakuPro-W6); +} +@font-face { + font-family: "Han Heiti CNS"; + font-weight: 600; + src: local(".PingFang TC Semibold"), local(".PingFang-TC-Semibold"), local("Heiti TC Medium"), local("STHeitiTC-Medium"), local("Heiti TC"), local("Lantinghei TC Demibold"), local(FZLTXHB--B51-0), local("Microsoft Jhenghei Bold"), local(MicrosoftJhengHeiBold), local("Microsoft Jhenghei"), local("Microsoft YaHei Bold"), local(MicrosoftYaHei-Bold), local("Noto Sans CJK TC Bold"), local(NotoSansCJKtc-Bold), local("Noto Sans CJK TC"), local("Source Han Sans TC Bold"), local("SourceHanSansTC-Bold"), local("Source Han Sans TC"), local("Source Han Sans TW Bold"), local("SourceHanSans-TW"), local("Source Han Sans TW"), local("Source Han Sans TWHK Bold"), local("SourceHanSans-TWHK"), local("Source Han Sans TWHK"), local("Source Han Sans HK"), local("SourceHanSans-HK"), local("Source Han Sans HK"); +} +@font-face { + font-family: "Han Heiti GB"; + font-weight: 600; + src: local("Hiragino Sans GB W6"), local(HiraginoSansGB-W6), local(".PingFang SC Semibold"), local(".PingFang-SC-Semibold"), local("Lantinghei SC Demibold"), local(FZLTZHK--GBK1-0), local("Heiti SC Medium"), local("STHeitiSC-Medium"), local("Heiti SC"), local("Microsoft YaHei Bold"), local(MicrosoftYaHei-Bold), local("Microsoft YaHei"), local("Noto Sans CJK SC Bold"), local(NotoSansCJKsc-Bold), local("Noto Sans CJK SC"), local("Source Han Sans SC Bold"), local("SourceHanSansSC-Bold"), local("Source Han Sans CN Bold"), local("SourceHanSansCN-Bold"), local("Source Han Sans SC"), local("Source Han Sans CN"); +} +@font-face { + font-family: "Han Heiti"; + src: local("Hiragino Sans GB"), local("Lantinghei TC Extralight"), local("Lantinghei SC Extralight"), local(FZLTXHB--B51-0), local(FZLTZHK--GBK1-0), local(".PingFang SC Light"), local(".PingFang TC Light"), local(".PingFang-SC-Light"), local(".PingFang-TC-Light"), local(".PingFang SC"), local(".PingFang TC"), local("Heiti SC Light"), local("STHeitiSC-Light"), local("Heiti SC"), local("Heiti TC Light"), local("STHeitiTC-Light"), local("Heiti TC"), local("Microsoft Yahei"), local("Microsoft Jhenghei"), local("Noto Sans CJK KR"), local("Noto Sans CJK JP"), local("Noto Sans CJK SC"), local("Noto Sans CJK TC"), local("Source Han Sans K"), local("Source Han Sans KR"), local("Source Han Sans JP"), local("Source Han Sans CN"), local("Source Han Sans HK"), local("Source Han Sans TW"), local("Source Han Sans TWHK"), local("Droid Sans Fallback"); + unicode-range: U+270C; +} +@font-face { + font-family: "Han Heiti"; + font-weight: 600; + src: local("Hiragino Sans GB W6"), local(HiraginoSansGB-W6), local("Lantinghei TC Demibold"), local("Lantinghei SC Demibold"), local(FZLTZHB--B51-0), local(FZLTZHK--GBK1-0), local(".PingFang-SC-Semibold"), local(".PingFang-TC-Semibold"), local("Heiti SC Medium"), local("STHeitiSC-Medium"), local("Heiti SC"), local("Heiti TC Medium"), local("STHeitiTC-Medium"), local("Heiti TC"), local("Microsoft YaHei Bold"), local("Microsoft Jhenghei Bold"), local(MicrosoftYaHei-Bold), local(MicrosoftJhengHeiBold), local("Microsoft YaHei"), local("Microsoft Jhenghei"), local("Noto Sans CJK KR Bold"), local("Noto Sans CJK JP Bold"), local("Noto Sans CJK SC Bold"), local("Noto Sans CJK TC Bold"), local(NotoSansCJKkr-Bold), local(NotoSansCJKjp-Bold), local(NotoSansCJKsc-Bold), local(NotoSansCJKtc-Bold), local("Source Han Sans K Bold"), local(SourceHanSansK-Bold), local("Source Han Sans K"), local("Source Han Sans KR Bold"), local("Source Han Sans JP Bold"), local("Source Han Sans CN Bold"), local("Source Han Sans HK Bold"), local("Source Han Sans TW Bold"), local("Source Han Sans TWHK Bold"), local("SourceHanSansKR-Bold"), local("SourceHanSansJP-Bold"), local("SourceHanSansCN-Bold"), local("SourceHanSansHK-Bold"), local("SourceHanSansTW-Bold"), local("SourceHanSansTWHK-Bold"), local("Source Han Sans KR"), local("Source Han Sans CN"), local("Source Han Sans HK"), local("Source Han Sans TW"), local("Source Han Sans TWHK"); + unicode-range: U+270C; +} +@font-face { + font-family: "Han Songti"; + src: local("Songti SC Regular"), local(STSongti-SC-Regular), local("Songti SC"), local("Songti TC Regular"), local(STSongti-TC-Regular), local("Songti TC"), local(STSong), local("Lisong Pro"), local(SimSun), local(PMingLiU); +} +@font-face { + unicode-range: U+4E00-9FFF, U+3400-4DB5, U+20000-2A6D6, U+2A700-2B734, U+2B740-2B81D, U+FA0E-FA0F, U+FA11, U+FA13-FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27-FA29, U+3040-309F, U+30A0-30FF, U+3099-309E, U+FF66-FF9F, U+3007, U+31C0-31E3, U+2F00-2FD5, U+2E80-2EF3; + font-family: "Han Songti"; + src: local(YuMincho), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("MS Mincho"); +} +@font-face { + font-family: "Han Songti CNS"; + src: local("Songti TC Regular"), local(STSongti-TC-Regular), local("Songti TC"), local("Lisong Pro"), local("Songti SC Regular"), local(STSongti-SC-Regular), local("Songti SC"), local(STSong), local(PMingLiU), local(SimSun); +} +@font-face { + font-family: "Han Songti GB"; + src: local("Songti SC Regular"), local(STSongti-SC-Regular), local("Songti SC"), local(STSong), local(SimSun), local(PMingLiU); +} +@font-face { + font-family: "Han Songti"; + font-weight: 600; + src: local("STSongti SC Bold"), local("STSongti TC Bold"), local(STSongti-SC-Bold), local(STSongti-TC-Bold), local("STSongti SC"), local("STSongti TC"); +} +@font-face { + unicode-range: U+4E00-9FFF, U+3400-4DB5, U+20000-2A6D6, U+2A700-2B734, U+2B740-2B81D, U+FA0E-FA0F, U+FA11, U+FA13-FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27-FA29, U+3040-309F, U+30A0-30FF, U+3099-309E, U+FF66-FF9F, U+3007, U+31C0-31E3, U+2F00-2FD5, U+2E80-2EF3; + font-family: "Han Songti"; + font-weight: 600; + src: local("YuMincho Demibold"), local("Hiragino Mincho ProN W6"), local("Hiragino Mincho Pro W6"), local(YuMin-Demibold), local(HiraMinProN-W6), local(HiraMinPro-W6), local(YuMincho), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"); +} +@font-face { + font-family: "Han Songti CNS"; + font-weight: 600; + src: local("STSongti TC Bold"), local("STSongti SC Bold"), local(STSongti-TC-Bold), local(STSongti-SC-Bold), local("STSongti TC"), local("STSongti SC"); +} +@font-face { + font-family: "Han Songti GB"; + font-weight: 600; + src: local("STSongti SC Bold"), local(STSongti-SC-Bold), local("STSongti SC"); +} +@font-face { + font-family: "Han Songti"; + src: local("Songti SC Regular"), local(STSongti-SC-Regular), local("Songti SC"), local("Songti TC Regular"), local(STSongti-TC-Regular), local("Songti TC"), local(STSongti), local("Lisong Pro"), local("MS Mincho"), local(SimSun), local(PMingLiU); + unicode-range: U+270C; +} +@font-face { + font-family: "Han Songti"; + font-weight: 600; + src: local("Songti TC Bold"), local("Songti SC Bold"), local(STSongti-TC-Bold), local(STSongti-SC-Bold), local("Songti TC"), local("Songti SC"); + unicode-range: U+270C; +} +@font-face { + font-family: "Han Songti CNS"; + src: local("Songti TC Regular"), local("Lisong Pro"), local("Songti TC"), local("Songti SC Regular"), local(STSong), local("Songti SC"), local("MS Mincho"), local(PMingLiU), local(SimSun); + unicode-range: U+270C; +} +@font-face { + font-family: "Han Songti CNS"; + font-weight: 600; + src: local("Songti TC Bold"), local("Songti SC Bold"), local(STSongti-TC-Bold), local(STSongti-SC-Bold), local("Songti TC"), local("Songti SC"); + unicode-range: U+270C; +} +@font-face { + font-family: "Han Songti GB"; + src: local("Songti SC"), local(STSong), local(SimSun); + unicode-range: U+270C; +} +@font-face { + font-family: "Han Songti GB"; + font-weight: 600; + src: local("Songti SC Bold"), local(STSongti-SC-Bold), local("Songti SC"); + unicode-range: U+270C; +} +@font-face { + font-family: cursive; + src: local("Kaiti TC Regular"), local(STKaiTi-TC-Regular), local("Kaiti TC"), local("Kaiti SC"), local(STKaiti), local(BiauKai), local("標楷體"), local(DFKaiShu-SB-Estd-BF), local(Kaiti), local(DFKai-SB); +} +@font-face { + unicode-range: U+4E00-9FFF, U+3400-4DB5, U+20000-2A6D6, U+2A700-2B734, U+2B740-2B81D, U+FA0E-FA0F, U+FA11, U+FA13-FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27-FA29, U+3040-309F, U+30A0-30FF, U+3099-309E, U+FF66-FF9F, U+3007, U+31C0-31E3, U+2F00-2FD5, U+2E80-2EF3; + font-family: "Han Kaiti"; + src: local("Kaiti TC Regular"), local(STKaiTi-TC-Regular), local("Kaiti TC"), local("Kaiti SC"), local(STKaiti), local(BiauKai), local("標楷體"), local(DFKaiShu-SB-Estd-BF), local(Kaiti), local(DFKai-SB); +} +@font-face { + unicode-range: U+4E00-9FFF, U+3400-4DB5, U+20000-2A6D6, U+2A700-2B734, U+2B740-2B81D, U+FA0E-FA0F, U+FA11, U+FA13-FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27-FA29, U+3040-309F, U+30A0-30FF, U+3099-309E, U+FF66-FF9F, U+3007, U+31C0-31E3, U+2F00-2FD5, U+2E80-2EF3; + font-family: "Han Kaiti CNS"; + src: local(BiauKai), local("標楷體"), local(DFKaiShu-SB-Estd-BF), local("Kaiti TC Regular"), local(STKaiTi-TC-Regular), local("Kaiti TC"); +} +@font-face { + unicode-range: U+4E00-9FFF, U+3400-4DB5, U+20000-2A6D6, U+2A700-2B734, U+2B740-2B81D, U+FA0E-FA0F, U+FA11, U+FA13-FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27-FA29, U+3040-309F, U+30A0-30FF, U+3099-309E, U+FF66-FF9F, U+3007, U+31C0-31E3, U+2F00-2FD5, U+2E80-2EF3; + font-family: "Han Kaiti GB"; + src: local("Kaiti SC Regular"), local(STKaiTi-SC-Regular), local("Kaiti SC"), local(STKaiti), local(Kai), local(Kaiti), local(DFKai-SB); +} +@font-face { + font-family: cursive; + font-weight: 600; + src: local("Kaiti TC Bold"), local(STKaiTi-TC-Bold), local("Kaiti SC Bold"), local(STKaiti-SC-Bold), local("Kaiti TC"), local("Kaiti SC"); +} +@font-face { + font-family: "Han Kaiti"; + font-weight: 600; + src: local("Kaiti TC Bold"), local(STKaiTi-TC-Bold), local("Kaiti SC Bold"), local(STKaiti-SC-Bold), local("Kaiti TC"), local("Kaiti SC"); +} +@font-face { + font-family: "Han Kaiti CNS"; + font-weight: 600; + src: local("Kaiti TC Bold"), local(STKaiTi-TC-Bold), local("Kaiti TC"); +} +@font-face { + font-family: "Han Kaiti GB"; + font-weight: 600; + src: local("Kaiti SC Bold"), local(STKaiti-SC-Bold); +} +@font-face { + unicode-range: U+4E00-9FFF, U+3400-4DB5, U+20000-2A6D6, U+2A700-2B734, U+2B740-2B81D, U+FA0E-FA0F, U+FA11, U+FA13-FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27-FA29, U+3040-309F, U+30A0-30FF, U+3099-309E, U+FF66-FF9F, U+3007, U+31C0-31E3, U+2F00-2FD5, U+2E80-2EF3; + font-family: "Han Fangsong"; + src: local(STFangsong), local(FangSong); +} +@font-face { + unicode-range: U+4E00-9FFF, U+3400-4DB5, U+20000-2A6D6, U+2A700-2B734, U+2B740-2B81D, U+FA0E-FA0F, U+FA11, U+FA13-FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27-FA29, U+3040-309F, U+30A0-30FF, U+3099-309E, U+FF66-FF9F, U+3007, U+31C0-31E3, U+2F00-2FD5, U+2E80-2EF3; + font-family: "Han Fangsong CNS"; + src: local(STFangsong), local(FangSong); +} +@font-face { + unicode-range: U+4E00-9FFF, U+3400-4DB5, U+20000-2A6D6, U+2A700-2B734, U+2B740-2B81D, U+FA0E-FA0F, U+FA11, U+FA13-FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27-FA29, U+3040-309F, U+30A0-30FF, U+3099-309E, U+FF66-FF9F, U+3007, U+31C0-31E3, U+2F00-2FD5, U+2E80-2EF3; + font-family: "Han Fangsong GB"; + src: local(STFangsong), local(FangSong); +} +@font-face { + font-family: "Biaodian Sans"; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local("MS Gothic"), local(SimSun); + unicode-range: U+FF0E; +} +@font-face { + font-family: "Biaodian Serif"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(STSong), local(SimSun); + unicode-range: U+FF0E; +} +@font-face { + font-family: "Biaodian Pro Sans"; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local("MS Gothic"), local(SimSun); + unicode-range: U+FF0E; +} +@font-face { + font-family: "Biaodian Pro Serif"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(STSong), local(SimSun); + unicode-range: U+FF0E; +} +@font-face { + font-family: "Biaodian Pro Sans CNS"; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local("MS Gothic"), local(SimSun); + unicode-range: U+FF0E; +} +@font-face { + font-family: "Biaodian Pro Serif CNS"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(STSong), local(SimSun); + unicode-range: U+FF0E; +} +@font-face { + font-family: "Biaodian Pro Sans GB"; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local("MS Gothic"), local(SimSun); + unicode-range: U+FF0E; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(STSong), local(SimSun); + unicode-range: U+FF0E; +} +@font-face { + font-family: "Biaodian Sans"; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local(SimSun); + unicode-range: U+00B7; +} +@font-face { + font-family: "Biaodian Serif"; + src: local("Songti SC"), local(STSong), local("Heiti SC"), local(SimSun); + unicode-range: U+00B7; +} +@font-face { + font-family: "Biaodian Pro Sans"; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local(SimSun); + unicode-range: U+00B7; +} +@font-face { + font-family: "Biaodian Pro Serif"; + src: local("Songti SC"), local(STSong), local("Heiti SC"), local(SimSun); + unicode-range: U+00B7; +} +@font-face { + font-family: "Biaodian Pro Sans CNS"; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local(SimSun); + unicode-range: U+00B7; +} +@font-face { + font-family: "Biaodian Pro Serif CNS"; + src: local("Songti SC"), local(STSong), local("Heiti SC"), local(SimSun); + unicode-range: U+00B7; +} +@font-face { + font-family: "Biaodian Pro Sans GB"; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local(SimSun); + unicode-range: U+00B7; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + src: local("Songti SC"), local(STSong), local("Heiti SC"), local(SimSun); + unicode-range: U+00B7; +} +@font-face { + font-family: "Biaodian Sans"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Sans GB"), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local("Microsoft Yahei"), local(SimSun); + unicode-range: U+2014; +} +@font-face { + font-family: "Biaodian Serif"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(STSong), local("Microsoft Yahei"), local(SimSun); + unicode-range: U+2014; +} +@font-face { + font-family: "Yakumono Sans"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local("Arial Unicode MS"), local("MS Gothic"); + unicode-range: U+2014; +} +@font-face { + font-family: "Yakumono Serif"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("MS Mincho"), local("Microsoft Yahei"); + unicode-range: U+2014; +} +@font-face { + font-family: "Biaodian Pro Sans"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Sans GB"), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local("Microsoft Yahei"), local(SimSun); + unicode-range: U+2014; +} +@font-face { + font-family: "Biaodian Pro Serif"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(STSong), local("Microsoft Yahei"), local(SimSun); + unicode-range: U+2014; +} +@font-face { + font-family: "Biaodian Pro Sans CNS"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Sans GB"), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local("Microsoft Yahei"), local(SimSun); + unicode-range: U+2014; +} +@font-face { + font-family: "Biaodian Pro Serif CNS"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(STSong), local("Microsoft Yahei"), local(SimSun); + unicode-range: U+2014; +} +@font-face { + font-family: "Biaodian Pro Sans GB"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Sans GB"), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local("Microsoft Yahei"), local(SimSun); + unicode-range: U+2014; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(STSong), local("Microsoft Yahei"), local(SimSun); + unicode-range: U+2014; +} +@font-face { + font-family: "Biaodian Sans"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Sans GB"), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local(Meiryo), local("MS Gothic"), local(SimSun), local(PMingLiU); + unicode-range: U+2026; +} +@font-face { + font-family: "Biaodian Serif"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local("MS Mincho"), local(SimSun), local(PMingLiU); + unicode-range: U+2026; +} +@font-face { + font-family: "Yakumono Sans"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local(Meiryo), local("MS Gothic"); + unicode-range: U+2026; +} +@font-face { + font-family: "Yakumono Serif"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("MS Mincho"); + unicode-range: U+2026; +} +@font-face { + font-family: "Biaodian Pro Sans"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Sans GB"), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local(SimSun), local(PMingLiU); + unicode-range: U+2026; +} +@font-face { + font-family: "Biaodian Pro Serif"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(SimSun), local(PMingLiU); + unicode-range: U+2026; +} +@font-face { + font-family: "Biaodian Pro Sans CNS"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Sans GB"), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local(SimSun), local(PMingLiU); + unicode-range: U+2026; +} +@font-face { + font-family: "Biaodian Pro Serif CNS"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(STSongti), local(SimSun), local(PMingLiU); + unicode-range: U+2026; +} +@font-face { + font-family: "Biaodian Pro Sans GB"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Sans GB"), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local(SimSun), local(PMingLiU); + unicode-range: U+2026; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Songti SC"), local(STSongti), local(SimSun), local(PMingLiU); + unicode-range: U+2026; +} +@font-face { + font-family: "Biaodian Pro Sans GB"; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local(SimSun), local(PMingLiU); + unicode-range: U+201C-201D, U+2018-2019; +} +@font-face { + font-family: "Biaodian Pro Sans GB"; + font-weight: bold; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local(SimSun), local(PMingLiU); + unicode-range: U+201C-201D, U+2018-2019; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + src: local("Lisong Pro"), local("Heiti SC"), local(STHeiti), local(SimSun), local(PMingLiU); + unicode-range: U+201C-201D, U+2018-2019; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + font-weight: bold; + src: local("Lisong Pro"), local("Heiti SC"), local(STHeiti), local(SimSun), local(PMingLiU); + unicode-range: U+201C-201D, U+2018-2019; +} +@font-face { + font-family: "Biaodian Sans"; + src: local(Georgia), local("Times New Roman"), local(Arial), local("Droid Sans Fallback"); + unicode-range: U+25CF; +} +@font-face { + font-family: "Biaodian Serif"; + src: local(Georgia), local("Times New Roman"), local(Arial), local("Droid Sans Fallback"); + unicode-range: U+25CF; +} +@font-face { + font-family: "Biaodian Pro Sans"; + src: local(Georgia), local("Times New Roman"), local(Arial), local("Droid Sans Fallback"); + unicode-range: U+25CF; +} +@font-face { + font-family: "Biaodian Pro Serif"; + src: local(Georgia), local("Times New Roman"), local(Arial), local("Droid Sans Fallback"); + unicode-range: U+25CF; +} +@font-face { + font-family: "Biaodian Pro Sans CNS"; + src: local(Georgia), local("Times New Roman"), local(Arial), local("Droid Sans Fallback"); + unicode-range: U+25CF; +} +@font-face { + font-family: "Biaodian Pro Serif CNS"; + src: local(Georgia), local("Times New Roman"), local(Arial), local("Droid Sans Fallback"); + unicode-range: U+25CF; +} +@font-face { + font-family: "Biaodian Pro Sans GB"; + src: local(Georgia), local("Times New Roman"), local(Arial), local("Droid Sans Fallback"); + unicode-range: U+25CF; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + src: local(Georgia), local("Times New Roman"), local(Arial), local("Droid Sans Fallback"); + unicode-range: U+25CF; +} +@font-face { + font-family: "Biaodian Pro Sans"; + src: local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local("MS Gothic"); + unicode-range: U+3002, U+FF0C, U+3001, U+FF1B, U+FF1A, U+FF1F, U+FF01, U+FF0D, U+FF0F, U+FF3C; +} +@font-face { + font-family: "Biaodian Pro Serif"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("MS Mincho"); + unicode-range: U+3002, U+FF0C, U+3001, U+FF1B, U+FF1A, U+FF1F, U+FF01, U+FF0D, U+FF0F, U+FF3C; +} +@font-face { + font-family: "Biaodian Pro Sans CNS"; + src: local("Heiti TC"), local("Lihei Pro"), local("Microsoft Jhenghei"), local(PMingLiU); + unicode-range: U+3002, U+FF0C, U+3001; +} +@font-face { + font-family: "Biaodian Pro Sans CNS"; + src: local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local("Heiti TC"), local("Lihei Pro"), local("Microsoft Jhenghei"), local(PMingLiU), local("MS Gothic"); + unicode-range: U+FF1B, U+FF1A, U+FF1F, U+FF01; +} +@font-face { + font-family: "Biaodian Pro Sans CNS"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("MS Mincho"); + unicode-range: U+FF0D, U+FF0F, U+FF3C; +} +@font-face { + font-family: "Biaodian Pro Serif CNS"; + src: local(STSongti-TC-Regular), local("Lisong Pro"), local("Heiti TC"), local(PMingLiU); + unicode-range: U+3002, U+FF0C, U+3001; +} +@font-face { + font-family: "Biaodian Pro Serif CNS"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local(PMingLiU), local("MS Mincho"); + unicode-range: U+FF1B, U+FF1A, U+FF1F, U+FF01, U+FF0D, U+FF0F, U+FF3C; +} +@font-face { + font-family: "Biaodian Pro Sans GB"; + src: local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local(SimSun), local("MS Gothic"); + unicode-range: U+3002, U+FF0C, U+3001, U+FF1B, U+FF1A, U+FF1F, U+FF01, U+FF0D, U+FF0F, U+FF3C; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + src: local("Songti SC"), local(STSongti), local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Hiragino Sans GB"), local("Heiti SC"), local(STHeiti), local(SimSun), local("MS Mincho"); + unicode-range: U+3002, U+FF0C, U+3001, U+FF1B, U+FF1A, U+FF1F, U+FF01; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local(PMingLiU), local("MS Mincho"); + unicode-range: U+FF0D, U+FF0F, U+FF3C; +} +@font-face { + font-family: "Biaodian Pro Sans"; + src: local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local("Yu Gothic"), local(YuGothic), local(SimSun), local(PMingLiU); + unicode-range: U+300C-300F, U+300A-300B, U+3008-3009, U+FF08-FF09, U+3014-3015; +} +@font-face { + font-family: "Biaodian Pro Serif"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Yu Mincho"), local(YuMincho), local(SimSun), local(PMingLiU); + unicode-range: U+300C-300F, U+300A-300B, U+3008-3009, U+FF08-FF09, U+3014-3015; +} +@font-face { + font-family: "Biaodian Pro Sans CNS"; + src: local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local("Yu Gothic"), local(YuGothic), local(SimSun), local(PMingLiU); + unicode-range: U+300C-300F, U+300A-300B, U+3008-3009, U+FF08-FF09, U+3014-3015; +} +@font-face { + font-family: "Biaodian Pro Serif CNS"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Yu Mincho"), local(YuMincho), local(SimSun), local(PMingLiU); + unicode-range: U+300C-300F, U+300A-300B, U+3008-3009, U+FF08-FF09, U+3014-3015; +} +@font-face { + font-family: "Biaodian Pro Sans GB"; + src: local("Hiragino Kaku Gothic ProN"), local("Hiragino Kaku Gothic Pro"), local("Yu Gothic"), local(YuGothic), local(SimSun), local(PMingLiU); + unicode-range: U+300C-300F, U+300A-300B, U+3008-3009, U+FF08-FF09, U+3014-3015; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + src: local("Hiragino Mincho ProN"), local("Hiragino Mincho Pro"), local("Yu Mincho"), local(YuMincho), local(SimSun), local(PMingLiU); + unicode-range: U+300C-300F, U+300A-300B, U+3008-3009, U+FF08-FF09, U+3014-3015; +} +@font-face { + font-family: "Biaodian Basic"; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+2014, U+2026, U+00B7; +} +@font-face { + font-family: "Biaodian Basic"; + font-weight: bold; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+2014, U+2026, U+00B7; +} +@font-face { + font-family: "Biaodian Sans"; + font-weight: bold; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+2014, U+2026, U+00B7; +} +@font-face { + font-family: "Biaodian Pro Sans"; + font-weight: bold; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+2014, U+2026, U+00B7; +} +@font-face { + font-family: "Biaodian Pro Sans"; + font-weight: bold; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+2014, U+2026, U+00B7; +} +@font-face { + font-family: "Biaodian Pro Sans CNS"; + font-weight: bold; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+2014, U+2026, U+00B7; +} +@font-face { + font-family: "Biaodian Pro Sans GB"; + font-weight: bold; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+2014, U+2026, U+00B7; +} +@font-face { + font-family: "Biaodian Pro Serif"; + font-weight: bold; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+2014, U+2026, U+00B7; +} +@font-face { + font-family: "Biaodian Pro Serif CNS"; + font-weight: bold; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+2014, U+2026, U+00B7; +} +@font-face { + font-family: "Biaodian Pro Serif GB"; + font-weight: bold; + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+2014, U+2026, U+00B7; +} +@font-face { + font-family: "Latin Italic Serif"; + src: local("Georgia Italic"), local("Times New Roman Italic"), local(Georgia-Italic), local(TimesNewRomanPS-ItalicMT), local(Times-Italic); +} +@font-face { + font-family: "Latin Italic Serif"; + font-weight: 700; + src: local("Georgia Bold Italic"), local("Times New Roman Bold Italic"), local(Georgia-BoldItalic), local(TimesNewRomanPS-BoldItalicMT), local(Times-Italic); +} +@font-face { + font-family: "Latin Italic Sans"; + src: local("Helvetica Neue Italic"), local("Helvetica Oblique"), local("Arial Italic"), local(HelveticaNeue-Italic), local(Helvetica-LightOblique), local(Arial-ItalicMT); +} +@font-face { + font-family: "Latin Italic Sans"; + font-weight: 700; + src: local("Helvetica Neue Bold Italic"), local("Helvetica Bold Oblique"), local("Arial Bold Italic"), local(HelveticaNeue-BoldItalic), local(Helvetica-BoldOblique), local(Arial-BoldItalicMT); +} +@font-face { + unicode-range: U+0030-0039; + font-family: "Numeral TF Sans"; + src: local(Skia), local("Neutraface 2 Text"), local(Candara), local(Corbel); +} +@font-face { + unicode-range: U+0030-0039; + font-family: "Numeral TF Serif"; + src: local(Georgia), local("Hoefler Text"), local("Big Caslon"); +} +@font-face { + unicode-range: U+0030-0039; + font-family: "Numeral TF Italic Serif"; + src: local("Georgia Italic"), local("Hoefler Text Italic"), local(Georgia-Italic), local(HoeflerText-Italic); +} +@font-face { + unicode-range: U+0030-0039; + font-family: "Numeral LF Sans"; + src: local("Helvetica Neue"), local(Helvetica), local(Arial); +} +@font-face { + unicode-range: U+0030-0039; + font-family: "Numeral LF Italic Sans"; + src: local("Helvetica Neue Italic"), local("Helvetica Oblique"), local("Arial Italic"), local(HelveticaNeue-Italic), local(Helvetica-LightOblique), local(Arial-ItalicMT); +} +@font-face { + unicode-range: U+0030-0039; + font-family: "Numeral LF Italic Sans"; + font-weight: bold; + src: local("Helvetica Neue Bold Italic"), local("Helvetica Bold Oblique"), local("Arial Bold Italic"), local(HelveticaNeue-BoldItalic), local(Helvetica-BoldOblique), local(Arial-BoldItalicMT); +} +@font-face { + unicode-range: U+0030-0039; + font-family: "Numeral LF Serif"; + src: local(Palatino), local("Palatino Linotype"), local("Times New Roman"); +} +@font-face { + unicode-range: U+0030-0039; + font-family: "Numeral LF Italic Serif"; + src: local("Palatino Italic"), local("Palatino Italic Linotype"), local("Times New Roman Italic"), local(Palatino-Italic), local(Palatino-Italic-Linotype), local(TimesNewRomanPS-ItalicMT); +} +@font-face { + unicode-range: U+0030-0039; + font-family: "Numeral LF Italic Serif"; + font-weight: bold; + src: local("Palatino Bold Italic"), local("Palatino Bold Italic Linotype"), local("Times New Roman Bold Italic"), local(Palatino-BoldItalic), local(Palatino-BoldItalic-Linotype), local(TimesNewRomanPS-BoldItalicMT); +} +@font-face { + font-family: "Numeral TF Sans"; + src: local(lying-to-firefox); + unicode-range: U+270C; +} +@font-face { + font-family: "Numeral TF Serif"; + src: local(lying-to-firefox); + unicode-range: U+270C; +} +@font-face { + font-family: "Numeral TF Italic Serif"; + src: local(lying-to-firefox); + unicode-range: U+270C; +} +@font-face { + font-family: "Numeral LF Sans"; + src: local(lying-to-firefox); + unicode-range: U+270C; +} +@font-face { + font-family: "Numeral LF Italic Sans"; + src: local(lying-to-firefox); + unicode-range: U+270C; +} +@font-face { + font-family: "Numeral LF Italic Sans"; + font-weight: bold; + src: local(lying-to-firefox); + unicode-range: U+270C; +} +@font-face { + font-family: "Numeral LF Serif"; + src: local(lying-to-firefox); + unicode-range: U+270C; +} +@font-face { + font-family: "Numeral LF Italic Serif"; + src: local(lying-to-firefox); + unicode-range: U+270C; +} +@font-face { + font-family: "Numeral LF Italic Serif"; + font-weight: bold; + src: local(lying-to-firefox); + unicode-range: U+270C; +} +@font-face { + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+3105-312D, U+31A0-31BA, U+02D9, U+02CA, U+02C5, U+02C7, U+02CB, U+02EA-02EB, U+030D, U+0358, U+F31B4-F31B7, U+F0061, U+F0065, U+F0069, U+F006F, U+F0075; + font-family: "Zhuyin Kaiti"; +} +@font-face { + unicode-range: U+3105-312D, U+31A0-31BA, U+02D9, U+02CA, U+02C5, U+02C7, U+02CB, U+02EA-02EB, U+030D, U+0358, U+F31B4-F31B7, U+F0061, U+F0065, U+F0069, U+F006F, U+F0075; + font-family: "Zhuyin Heiti"; + src: local("Hiragino Sans GB"), local("Heiti TC"), local("Microsoft Jhenghei"), url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); +} +@font-face { + font-family: "Zhuyin Heiti"; + src: local("Heiti TC"), local("Microsoft Jhenghei"), url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + unicode-range: U+3127; +} +@font-face { + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + font-family: "Zhuyin Heiti"; + unicode-range: U+02D9, U+02CA, U+02C5, U+02C7, U+02CB, U+02EA-02EB, U+31B4, U+31B5, U+31B6, U+31B7, U+030D, U+0358, U+F31B4-F31B7, U+F0061, U+F0065, U+F0069, U+F006F, U+F0075; +} +@font-face { + src: url("./font/han.woff?v3.3.0") format("woff"), url("./font/han.otf?v3.3.0") format("opentype"); + font-family: "Romanization Sans"; + unicode-range: U+030D, U+0358, U+F31B4-F31B7, U+F0061, U+F0065, U+F0069, U+F006F, U+F0075; +} +html:lang(zh-Latn), +html:lang(ja-Latn), +html:not(:lang(zh)):not(:lang(ja)), +html *:lang(zh-Latn), +html *:lang(ja-Latn), +html *:not(:lang(zh)):not(:lang(ja)), +article strong:lang(zh-Latn), +article strong:lang(ja-Latn), +article strong:not(:lang(zh)):not(:lang(ja)), +article strong *:lang(zh-Latn), +article strong *:lang(ja-Latn), +article strong *:not(:lang(zh)):not(:lang(ja)) { + font-family: "Helvetica Neue", Helvetica, Arial, "Han Heiti", sans-serif; +} +html:lang(zh), +html:lang(zh-Hant), +[lang^="zh"], +[lang*="Hant"], +[lang="zh-TW"], +[lang="zh-HK"], +article strong:lang(zh), +article strong:lang(zh-Hant) { + font-family: "Biaodian Pro Sans CNS", "Helvetica Neue", Helvetica, Arial, "Zhuyin Heiti", "Han Heiti", sans-serif; +} +html:lang(zh).no-unicoderange, +html:lang(zh-Hant).no-unicoderange, +.no-unicoderange [lang^="zh"], +.no-unicoderange [lang*="Hant"], +.no-unicoderange [lang="zh-TW"], +.no-unicoderange [lang="zh-HK"], +.no-unicoderange article strong:lang(zh), +.no-unicoderange article strong:lang(zh-Hant) { + font-family: "Helvetica Neue", Helvetica, Arial, "Han Heiti", sans-serif; +} +html:lang(zh-Hans), +html:lang(zh-CN), +[lang*="Hans"], +[lang="zh-CN"], +article strong:lang(zh-Hans), +article strong:lang(zh-CN) { + font-family: "Biaodian Pro Sans GB", "Helvetica Neue", Helvetica, Arial, "Han Heiti GB", sans-serif; +} +html:lang(zh-Hans).no-unicoderange, +html:lang(zh-CN).no-unicoderange, +.no-unicoderange [lang*="Hans"], +.no-unicoderange [lang="zh-CN"], +.no-unicoderange article strong:lang(zh-Hans), +.no-unicoderange article strong:lang(zh-CN) { + font-family: "Helvetica Neue", Helvetica, Arial, "Han Heiti GB", sans-serif; +} +html:lang(ja), +[lang^="ja"], +article strong:lang(ja) { + font-family: "Yakumono Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +} +html:lang(ja).no-unicoderange, +.no-unicoderange [lang^="ja"], +.no-unicoderange article strong:lang(ja) { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} +article blockquote i:lang(zh-Latn), +article blockquote var:lang(zh-Latn), +article blockquote i:lang(ja-Latn), +article blockquote var:lang(ja-Latn), +article blockquote i:not(:lang(zh)):not(:lang(ja)), +article blockquote var:not(:lang(zh)):not(:lang(ja)), +article blockquote i *:lang(zh-Latn), +article blockquote var *:lang(zh-Latn), +article blockquote i *:lang(ja-Latn), +article blockquote var *:lang(ja-Latn), +article blockquote i *:not(:lang(zh)):not(:lang(ja)), +article blockquote var *:not(:lang(zh)):not(:lang(ja)) { + font-family: "Latin Italic Sans", "Helvetica Neue", Helvetica, Arial, "Han Heiti", sans-serif; +} +article blockquote i:lang(zh), +article blockquote var:lang(zh), +article blockquote i:lang(zh-Hant), +article blockquote var:lang(zh-Hant) { + font-family: "Biaodian Pro Sans CNS", "Latin Italic Sans", "Helvetica Neue", Helvetica, Arial, "Zhuyin Heiti", "Han Heiti", sans-serif; +} +.no-unicoderange article blockquote i:lang(zh), +.no-unicoderange article blockquote var:lang(zh), +.no-unicoderange article blockquote i:lang(zh-Hant), +.no-unicoderange article blockquote var:lang(zh-Hant) { + font-family: "Latin Italic Sans", "Helvetica Neue", Helvetica, Arial, "Han Heiti", sans-serif; +} +.no-unicoderange article blockquote i:lang(zh), +.no-unicoderange article blockquote var:lang(zh), +.no-unicoderange article blockquote i:lang(zh-Hant), +.no-unicoderange article blockquote var:lang(zh-Hant) { + font-family: "Latin Italic Sans", "Helvetica Neue", Helvetica, Arial, "Han Heiti", sans-serif; +} +article blockquote i:lang(zh-Hans), +article blockquote var:lang(zh-Hans), +article blockquote i:lang(zh-CN), +article blockquote var:lang(zh-CN) { + font-family: "Biaodian Pro Sans GB", "Latin Italic Sans", "Helvetica Neue", Helvetica, Arial, "Han Heiti GB", sans-serif; +} +.no-unicoderange article blockquote i:lang(zh-Hans), +.no-unicoderange article blockquote var:lang(zh-Hans), +.no-unicoderange article blockquote i:lang(zh-CN), +.no-unicoderange article blockquote var:lang(zh-CN) { + font-family: "Latin Italic Sans", "Helvetica Neue", Helvetica, Arial, "Han Heiti GB", sans-serif; +} +article blockquote i:lang(ja), +article blockquote var:lang(ja) { + font-family: "Yakumono Sans", "Latin Italic Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +} +.no-unicoderange article blockquote i:lang(ja), +.no-unicoderange article blockquote var:lang(ja) { + font-family: "Latin Italic Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +} +article figure blockquote:lang(zh-Latn), +article figure blockquote:lang(ja-Latn), +article figure blockquote:not(:lang(zh)):not(:lang(ja)), +article figure blockquote *:lang(zh-Latn), +article figure blockquote *:lang(ja-Latn), +article figure blockquote *:not(:lang(zh)):not(:lang(ja)) { + font-family: Georgia, "Times New Roman", "Han Songti", cursive, serif; +} +article figure blockquote:lang(zh), +article figure blockquote:lang(zh-Hant) { + font-family: "Biaodian Pro Serif CNS", "Numeral LF Serif", Georgia, "Times New Roman", "Zhuyin Kaiti", "Han Songti", serif; +} +.no-unicoderange article figure blockquote:lang(zh), +.no-unicoderange article figure blockquote:lang(zh-Hant) { + font-family: "Numeral LF Serif", Georgia, "Times New Roman", "Han Songti", serif; +} +article figure blockquote:lang(zh-Hans), +article figure blockquote:lang(zh-CN) { + font-family: "Biaodian Pro Serif GB", "Numeral LF Serif", Georgia, "Times New Roman", "Han Songti GB", serif; +} +.no-unicoderange article figure blockquote:lang(zh-Hans), +.no-unicoderange article figure blockquote:lang(zh-CN) { + font-family: "Numeral LF Serif", Georgia, "Times New Roman", "Han Songti GB", serif; +} +article figure blockquote:lang(ja) { + font-family: "Yakumono Serif", "Numeral LF Serif", Georgia, "Times New Roman", serif; +} +.no-unicoderange article figure blockquote:lang(ja) { + font-family: "Numeral LF Serif", Georgia, "Times New Roman", serif; +} +article blockquote:lang(zh-Latn), +article blockquote:lang(ja-Latn), +article blockquote:not(:lang(zh)):not(:lang(ja)), +article blockquote *:lang(zh-Latn), +article blockquote *:lang(ja-Latn), +article blockquote *:not(:lang(zh)):not(:lang(ja)) { + font-family: Georgia, "Times New Roman", "Han Kaiti", cursive, serif; +} +article blockquote:lang(zh), +article blockquote:lang(zh-Hant) { + font-family: "Biaodian Pro Serif CNS", "Numeral LF Serif", Georgia, "Times New Roman", "Zhuyin Kaiti", "Han Kaiti", cursive, serif; +} +.no-unicoderange article blockquote:lang(zh), +.no-unicoderange article blockquote:lang(zh-Hant) { + font-family: "Numeral LF Serif", Georgia, "Times New Roman", "Han Kaiti", cursive, serif; +} +article blockquote:lang(zh-Hans), +article blockquote:lang(zh-CN) { + font-family: "Biaodian Pro Serif GB", "Numeral LF Serif", Georgia, "Times New Roman", "Han Kaiti GB", cursive, serif; +} +.no-unicoderange article blockquote:lang(zh-Hans), +.no-unicoderange article blockquote:lang(zh-CN) { + font-family: "Numeral LF Serif", Georgia, "Times New Roman", "Han Kaiti GB", cursive, serif; +} +article blockquote:lang(ja) { + font-family: "Yakumono Serif", "Numeral LF Serif", Georgia, "Times New Roman", cursive, serif; +} +.no-unicoderange article blockquote:lang(ja) { + font-family: "Numeral LF Serif", Georgia, "Times New Roman", cursive, serif; +} +i:lang(zh-Latn), +var:lang(zh-Latn), +i:lang(ja-Latn), +var:lang(ja-Latn), +i:not(:lang(zh)):not(:lang(ja)), +var:not(:lang(zh)):not(:lang(ja)), +i *:lang(zh-Latn), +var *:lang(zh-Latn), +i *:lang(ja-Latn), +var *:lang(ja-Latn), +i *:not(:lang(zh)):not(:lang(ja)), +var *:not(:lang(zh)):not(:lang(ja)) { + font-family: "Latin Italic Serif", Georgia, "Times New Roman", "Han Kaiti", cursive, serif; +} +i:lang(zh), +var:lang(zh), +i:lang(zh-Hant), +var:lang(zh-Hant) { + font-family: "Biaodian Pro Serif CNS", "Numeral LF Italic Serif", "Latin Italic Serif", Georgia, "Times New Roman", "Zhuyin Kaiti", "Han Kaiti", cursive, serif; +} +.no-unicoderange i:lang(zh), +.no-unicoderange var:lang(zh), +.no-unicoderange i:lang(zh-Hant), +.no-unicoderange var:lang(zh-Hant) { + font-family: "Numeral LF Italic Serif", "Latin Italic Serif", Georgia, "Times New Roman", "Han Kaiti", cursive, serif; +} +i:lang(zh-Hans), +var:lang(zh-Hans), +i:lang(zh-CN), +var:lang(zh-CN) { + font-family: "Biaodian Pro Serif GB", "Numeral LF Italic Serif", "Latin Italic Serif", Georgia, "Times New Roman", "Han Kaiti GB", cursive, serif; +} +.no-unicoderange i:lang(zh-Hans), +.no-unicoderange var:lang(zh-Hans), +.no-unicoderange i:lang(zh-CN), +.no-unicoderange var:lang(zh-CN) { + font-family: "Numeral LF Italic Serif", "Latin Italic Serif", Georgia, "Times New Roman", "Han Kaiti GB", cursive, serif; +} +i:lang(ja), +var:lang(ja) { + font-family: "Yakumono Serif", "Numeral LF Italic Serif", "Latin Italic Serif", Georgia, "Times New Roman", cursive, serif; +} +.no-unicoderange i:lang(ja), +.no-unicoderange var:lang(ja) { + font-family: "Numeral LF Italic Serif", "Latin Italic Serif", Georgia, "Times New Roman", cursive, serif; +} +code:lang(zh-Latn), +kbd:lang(zh-Latn), +samp:lang(zh-Latn), +pre:lang(zh-Latn), +code:lang(ja-Latn), +kbd:lang(ja-Latn), +samp:lang(ja-Latn), +pre:lang(ja-Latn), +code:not(:lang(zh)):not(:lang(ja)), +kbd:not(:lang(zh)):not(:lang(ja)), +samp:not(:lang(zh)):not(:lang(ja)), +pre:not(:lang(zh)):not(:lang(ja)), +code *:lang(zh-Latn), +kbd *:lang(zh-Latn), +samp *:lang(zh-Latn), +pre *:lang(zh-Latn), +code *:lang(ja-Latn), +kbd *:lang(ja-Latn), +samp *:lang(ja-Latn), +pre *:lang(ja-Latn), +code *:not(:lang(zh)):not(:lang(ja)), +kbd *:not(:lang(zh)):not(:lang(ja)), +samp *:not(:lang(zh)):not(:lang(ja)), +pre *:not(:lang(zh)):not(:lang(ja)) { + font-family: Menlo, Consolas, Courier, "Han Heiti", monospace, monospace, sans-serif; +} +code:lang(zh), +kbd:lang(zh), +samp:lang(zh), +pre:lang(zh), +code:lang(zh-Hant), +kbd:lang(zh-Hant), +samp:lang(zh-Hant), +pre:lang(zh-Hant) { + font-family: "Biaodian Pro Sans CNS", Menlo, Consolas, Courier, "Zhuyin Heiti", "Han Heiti", monospace, monospace, sans-serif; +} +.no-unicoderange code:lang(zh), +.no-unicoderange kbd:lang(zh), +.no-unicoderange samp:lang(zh), +.no-unicoderange pre:lang(zh), +.no-unicoderange code:lang(zh-Hant), +.no-unicoderange kbd:lang(zh-Hant), +.no-unicoderange samp:lang(zh-Hant), +.no-unicoderange pre:lang(zh-Hant) { + font-family: Menlo, Consolas, Courier, "Han Heiti", monospace, monospace, sans-serif; +} +code:lang(zh-Hans), +kbd:lang(zh-Hans), +samp:lang(zh-Hans), +pre:lang(zh-Hans), +code:lang(zh-CN), +kbd:lang(zh-CN), +samp:lang(zh-CN), +pre:lang(zh-CN) { + font-family: "Biaodian Pro Sans GB", Menlo, Consolas, Courier, "Han Heiti GB", monospace, monospace, sans-serif; +} +.no-unicoderange code:lang(zh-Hans), +.no-unicoderange kbd:lang(zh-Hans), +.no-unicoderange samp:lang(zh-Hans), +.no-unicoderange pre:lang(zh-Hans), +.no-unicoderange code:lang(zh-CN), +.no-unicoderange kbd:lang(zh-CN), +.no-unicoderange samp:lang(zh-CN), +.no-unicoderange pre:lang(zh-CN) { + font-family: Menlo, Consolas, Courier, "Han Heiti GB", monospace, monospace, sans-serif; +} +code:lang(ja), +kbd:lang(ja), +samp:lang(ja), +pre:lang(ja) { + font-family: "Yakumono Sans", Menlo, Consolas, Courier, monospace, monospace, sans-serif; +} +.no-unicoderange code:lang(ja), +.no-unicoderange kbd:lang(ja), +.no-unicoderange samp:lang(ja), +.no-unicoderange pre:lang(ja) { + font-family: Menlo, Consolas, Courier, monospace, monospace, sans-serif; +} +html, +.no-unicoderange h-char.bd-liga, +.no-unicoderange h-char[unicode="b7"], +ruby h-zhuyin, +h-ruby h-zhuyin, +ruby h-zhuyin h-diao, +h-ruby h-zhuyin h-diao, +ruby.romanization rt, +h-ruby.romanization rt, +ruby [annotation] rt, +h-ruby [annotation] rt { + -moz-font-feature-settings: "liga"; + -ms-font-feature-settings: "liga"; + -webkit-font-feature-settings: "liga"; + font-feature-settings: "liga"; +} +html, +[lang^="zh"], +[lang*="Hant"], +[lang="zh-TW"], +[lang="zh-HK"], +[lang*="Hans"], +[lang="zh-CN"], +article strong, +code, +kbd, +samp, +pre, +article blockquote i, +article blockquote var { + -moz-font-feature-settings: "liga=1, locl=0"; + -ms-font-feature-settings: "liga", "locl" 0; + -webkit-font-feature-settings: "liga", "locl" 0; + font-feature-settings: "liga", "locl" 0; +} +.no-unicoderange h-char.bd-cop:lang(zh-Hant), +.no-unicoderange h-char.bd-cop:lang(zh-TW), +.no-unicoderange h-char.bd-cop:lang(zh-HK) { + font-family: -apple-system, "Han Heiti CNS"; +} +.no-unicoderange h-char.bd-liga, +.no-unicoderange h-char[unicode="b7"] { + font-family: "Biaodian Basic", "Han Heiti"; +} +.no-unicoderange h-char[unicode="2018"]:lang(zh-Hans), +.no-unicoderange h-char[unicode="2019"]:lang(zh-Hans), +.no-unicoderange h-char[unicode="201c"]:lang(zh-Hans), +.no-unicoderange h-char[unicode="201d"]:lang(zh-Hans), +.no-unicoderange h-char[unicode="2018"]:lang(zh-CN), +.no-unicoderange h-char[unicode="2019"]:lang(zh-CN), +.no-unicoderange h-char[unicode="201c"]:lang(zh-CN), +.no-unicoderange h-char[unicode="201d"]:lang(zh-CN) { + font-family: "Han Heiti GB"; +} +i, +var { + font-style: inherit; +} +.no-unicoderange ruby h-zhuyin, +.no-unicoderange h-ruby h-zhuyin, +.no-unicoderange ruby h-zhuyin h-diao, +.no-unicoderange h-ruby h-zhuyin h-diao { + font-family: "Zhuyin Kaiti", cursive, serif; +} +ruby h-diao, +h-ruby h-diao { + font-family: "Zhuyin Kaiti", cursive, serif; +} +ruby.romanization rt, +h-ruby.romanization rt, +ruby [annotation] rt, +h-ruby [annotation] rt { + font-family: "Romanization Sans", "Helvetica Neue", Helvetica, Arial, "Han Heiti", sans-serif; +} +.no-kaiti i, +.no-kaiti var { + padding-bottom: .05em; + border-bottom: 3px double #d3d3d3; +} +article h1 + blockquote, +article h2 + blockquote, +article h3 + blockquote, +article h4 + blockquote, +article h5 + blockquote, +article h6 + blockquote, +article h1 + p, +article h2 + p, +article h3 + p, +article h4 + p, +article h5 + p, +article h6 + p, +article h1 + ol, +article h2 + ol, +article h3 + ol, +article h4 + ol, +article h5 + ol, +article h6 + ol, +article h1 + ul, +article h2 + ul, +article h3 + ul, +article h4 + ul, +article h5 + ul, +article h6 + ul, +article h1 + h6, +article h2 + h6, +article h3 + h6, +article h4 + h6, +article h5 + h6, +article h6 + h6, +article h1 + section > h6:first-child, +article h2 + section > h6:first-child, +article h3 + section > h6:first-child, +article h4 + section > h6:first-child, +article h5 + section > h6:first-child, +article h6 + section > h6:first-child, +article h1 + section > p:first-child, +article h2 + section > p:first-child, +article h3 + section > p:first-child, +article h4 + section > p:first-child, +article h5 + section > p:first-child, +article h6 + section > p:first-child, +article h1 + section > ol:first-child, +article h2 + section > ol:first-child, +article h3 + section > ol:first-child, +article h4 + section > ol:first-child, +article h5 + section > ol:first-child, +article h6 + section > ol:first-child, +article h1 + section > ul:first-child, +article h2 + section > ul:first-child, +article h3 + section > ul:first-child, +article h4 + section > ul:first-child, +article h5 + section > ul:first-child, +article h6 + section > ul:first-child, +article h1 + section > blockquote:first-child, +article h2 + section > blockquote:first-child, +article h3 + section > blockquote:first-child, +article h4 + section > blockquote:first-child, +article h5 + section > blockquote:first-child, +article h6 + section > blockquote:first-child, +article h1 + h5, +article h2 + h5, +article h3 + h5, +article h4 + h5, +article h5 + h5, +article h1 + section > h5:first-child, +article h2 + section > h5:first-child, +article h3 + section > h5:first-child, +article h4 + section > h5:first-child, +article h5 + section > h5:first-child, +article h1 + h4, +article h2 + h4, +article h3 + h4, +article h4 + h4, +article h1 + section > h4:first-child, +article h2 + section > h4:first-child, +article h3 + section > h4:first-child, +article h4 + section > h4:first-child, +article h1 + h3, +article h2 + h3, +article h3 + h3, +article h1 + section > h3:first-child, +article h2 + section > h3:first-child, +article h3 + section > h3:first-child, +article h1 + h2, +article h2 + h2, +article h1 + section > h2:first-child, +article h2 + section > h2:first-child { + margin-top: -1em; +} +article { + line-height: 1.7; +} +article { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} +article p, +article li { + text-align: justify; + text-justify: inter-ideograph; +} +p.poem-like, +.poem-like p { + margin-left: 2em; +} +@media only screen and (max-width: 480px) { + p.poem-like, + .poem-like p { + margin-left: 1em; + } +} +article blockquote { + margin-right: 0; +} +@media only screen and (max-width: 480px) { + article blockquote { + margin-left: 1em; + } +} +figure blockquote { + margin: 0; +} +blockquote blockquote { + margin-left: 1em; + margin-right: 1em; +} +article blockquote blockquote { + margin-right: 0; +} +@media only screen and (max-width: 480px) { + blockquote, + figure { + margin-left: 1em; + margin-right: 1em; + } +} +h-hws, +h-hws[hidden] { + display: inline; + visibility: hidden; + font: .89em Arial; +} +code h-hws, +code h-hws[hidden], +kbd h-hws, +kbd h-hws[hidden], +samp h-hws, +samp h-hws[hidden], +pre h-hws, +pre h-hws[hidden], +h-hws.quote-inner, +h-hws[hidden].quote-inner, +h-hws.quote-outer:lang(zh-Hans), +h-hws[hidden].quote-outer:lang(zh-Hans), +h-hws.quote-outer:lang(zh-CN), +h-hws[hidden].quote-outer:lang(zh-CN) { + display: none; +} +@font-face { + src: url("./font/han-space.woff?v3.3.0") format("woff"), url("./font/han-space.otf?v3.3.0") format("opentype"); + font-family: "Han Space"; + unicode-range: U+20; +} +h-char.bd-hangable:lang(zh) h-cs, +h-char.bd-hangable:lang(zh-Hant) h-cs, +h-char.bd-hangable:lang(zh-TW) h-cs, +h-char.bd-hangable:lang(zh-HK) h-cs, +h-cs, +h-char.bd-hangable:lang(zh) h-cs[hidden], +h-char.bd-hangable:lang(zh-Hant) h-cs[hidden], +h-char.bd-hangable:lang(zh-TW) h-cs[hidden], +h-char.bd-hangable:lang(zh-HK) h-cs[hidden], +h-cs[hidden] { + display: inline; + visibility: inherit; + font-family: inherit; + font-size: inherit; +} +h-cs.hangable-outer, +h-cs.hangable-outer[hidden] { + display: inline; + font: 1em "Han Space"; +} +h-cs.hangable-outer:lang(zh-Hant), +h-cs.hangable-outer[hidden]:lang(zh-Hant), +h-cs.hangable-outer:lang(zh-TW), +h-cs.hangable-outer[hidden]:lang(zh-TW), +h-cs.hangable-outer:lang(zh-HK), +h-cs.hangable-outer[hidden]:lang(zh-HK) { + display: none; +} +h-char.bd-hangable:lang(zh-Hans), +h-char.bd-hangable:lang(zh-CN), +h-char.bd-hangable:lang(ja) { + position: relative; +} +h-char.bd-hangable:lang(zh-Hans):after, +h-char.bd-hangable:lang(zh-CN):after, +h-char.bd-hangable:lang(ja):after { + display: none !important; +} +h-char.bd-hangable:lang(zh-Hans):before, +h-char.bd-hangable:lang(zh-CN):before, +h-char.bd-hangable:lang(ja):before { + display: inline !important; + content: " "; + font: 1em "Han Space", Menlo, Consolas, Courier; +} +h-char.bd-hangable:lang(zh-Hans) > h-inner, +h-char.bd-hangable:lang(zh-CN) > h-inner, +h-char.bd-hangable:lang(ja) > h-inner { + -moz-text-emphasis: none; + -webkit-text-emphasis: none; + text-emphasis: none; + font-style: normal; + font-weight: normal; + line-height: normal; + text-decoration: none; + text-indent: 0; + position: absolute; + left: 0; + top: 0; + display: inline-block; + line-height: 1.1; +} +ruby h-char.bd-hangable:lang(zh-Hans) > h-inner, +ruby h-char.bd-hangable:lang(zh-CN) > h-inner, +ruby h-char.bd-hangable:lang(ja) > h-inner, +h-ru h-char.bd-hangable:lang(zh-Hans) > h-inner, +h-ru h-char.bd-hangable:lang(zh-CN) > h-inner, +h-ru h-char.bd-hangable:lang(ja) > h-inner { + position: relative; +} +h-char.bd-jiya.bd-open:before, +h-char.bd-jiya.bd-end:after, +h-cs, +h-cs[hidden] { + display: none; + visibility: hidden; + content: " "; + font: .825em Courier; + letter-spacing: 0; + white-space: normal; +} +h-cs.jinze-outer, +h-cs.jinze-outer[hidden] { + display: inline; +} +h-char.bd-jiya.bd-open > h-inner { + margin-left: -.5em; +} +h-char.bd-jiya.bd-close > h-inner, +h-char.bd-jiya.bd-cop > h-inner, +h-char.bd-jiya[unicode="ff0e"] > h-inner { + letter-spacing: -.5em; +} +h-char.bd-jiya.bd-open:before, +h-char.bd-jiya.bd-close:after, +h-char.bd-jiya.bd-cop:after, +h-char.bd-jiya[unicode="ff0e"]:after { + display: inline; +} +h-char.bd-jiya.bd-cop:lang(zh-Hant):after, +h-char.bd-jiya.bd-cop:lang(zh-TW):after, +h-char.bd-jiya.bd-cop:lang(zh-HK):after { + display: none; +} +h-char.bd-jiya.bd-cop:lang(zh-Hant) > h-inner, +h-char.bd-jiya.bd-cop:lang(zh-TW) > h-inner, +h-char.bd-jiya.bd-cop:lang(zh-HK) > h-inner { + letter-spacing: inherit; +} +h-char.bd-consecutive.bd-end:not(.end-portion):after, +h-char.bd-consecutive.bd-open[prev="bd-open"]:before, +h-cs.jiya-outer.bd-end:not(.end-portion) { + display: none; +} +h-cs.jiya-outer.bd-end[next="bd-open"] { + display: inline; +} +h-char.bd-consecutive.bd-open[prev*="bd-cop"]:lang(zh-Hant):before, +h-char.bd-consecutive.bd-open[prev*="bd-cop"]:lang(zh-TW):before, +h-char.bd-consecutive.bd-open[prev*="bd-cop"]:lang(zh-HK):before { + display: none; +} +h-cs.jiya-outer[prev*="bd-cop"]:lang(zh-Hant), +h-cs.jiya-outer.bd-end:lang(zh-Hant), +h-cs.jiya-outer[prev*="bd-cop"]:lang(zh-TW), +h-cs.jiya-outer.bd-end:lang(zh-TW), +h-cs.jiya-outer[prev*="bd-cop"]:lang(zh-HK), +h-cs.jiya-outer.bd-end:lang(zh-HK) { + display: none; +} +h-char.bd-consecutive[unicode="b7"]:not(.end-portion), +h-char.bd-consecutive[unicode="30fb"]:not(.end-portion) { + letter-spacing: -.5em; +} +h-char.bd-consecutive.bd-liga:not(.end-portion) { + margin-right: -.25em; +} +h-char[display-as] { + position: relative; + display: inline-block; +} +h-char[display-as] h-inner { + color: transparent; +} +h-char[display-as]:after { + position: absolute; + left: 0; + display: inline-block; + content: attr(display-as); +} +h-char[display-as].comb-liga:after { + font-family: "Romanization Sans", "Zhuyin Kaiti"; +} diff --git a/lib/Han/dist/han.js b/lib/Han/dist/han.js new file mode 100644 index 0000000..75976c6 --- /dev/null +++ b/lib/Han/dist/han.js @@ -0,0 +1,3005 @@ +/*! + * 漢字標準格式 v3.3.0 | MIT License | css.hanzi.co + * Han.css: the CSS typography framework optimised for Hanzi + */ + +void function( global, factory ) { + + // CommonJS + if ( typeof module === 'object' && typeof module.exports === 'object' ) { + module.exports = factory( global, true ) + // AMD + } else if ( typeof define === 'function' && define.amd ) { + define(function() { return factory( global, true ) }) + // Global namespace + } else { + factory( global ) + } + +}( typeof window !== 'undefined' ? window : this, function( window, noGlobalNS ) { + +'use strict' + +var document = window.document + +var root = document.documentElement + +var body = document.body + +var VERSION = '3.3.0' + +var ROUTINE = [ + // Initialise the condition with feature-detecting + // classes (Modernizr-alike), binding onto the root + // element, possibly ``. + 'initCond', + + // Address element normalisation + 'renderElem', + + // Handle Biaodian + /* 'jinzify', */ + 'renderJiya', + 'renderHanging', + + // Address Biaodian correction + 'correctBiaodian', + + // Address Hanzi and Western script mixed spacing + 'renderHWS', + + // Address presentational correction to combining ligatures + 'substCombLigaWithPUA' + + // Address semantic correction to inaccurate characters + // **Note:** inactivated by default + /* 'substInaccurateChar', */ +] + +// Define Han +var Han = function( context, condition ) { + return new Han.fn.init( context, condition ) +} + +var init = function() { + if ( arguments[ 0 ] ) { + this.context = arguments[ 0 ] + } + if ( arguments[ 1 ] ) { + this.condition = arguments[ 1 ] + } + return this +} + +Han.version = VERSION + +Han.fn = Han.prototype = { + version: VERSION, + + constructor: Han, + + // Body as the default target context + context: body, + + // Root element as the default condition + condition: root, + + // Default rendering routine + routine: ROUTINE, + + init: init, + + setRoutine: function( routine ) { + if ( Array.isArray( routine )) { + this.routine = routine + } + return this + }, + + // Note that the routine set up here will execute + // only once. The method won't alter the routine in + // the instance or in the prototype chain. + render: function( routine ) { + var it = this + var routine = Array.isArray( routine ) + ? routine + : this.routine + + routine + .forEach(function( method ) { + if ( + typeof method === 'string' && + typeof it[ method ] === 'function' + ) { + it[ method ]() + } else if ( + Array.isArray( method ) && + typeof it[ method[0] ] === 'function' + ) { + it[ method.shift() ].apply( it, method ) + } + }) + return this + } +} + +Han.fn.init.prototype = Han.fn + +/** + * Shortcut for `render()` under the default + * situation. + * + * Once initialised, replace `Han.init` with the + * instance for future usage. + */ +Han.init = function() { + return Han.init = Han().render() +} + +var UNICODE = { + /** + * Western punctuation (西文標點符號) + */ + punct: { + base: '[\u2026,.;:!?\u203D_]', + sing: '[\u2010-\u2014\u2026]', + middle: '[\\\/~\\-&\u2010-\u2014_]', + open: '[\'"‘“\\(\\[\u00A1\u00BF\u2E18\u00AB\u2039\u201A\u201C\u201E]', + close: '[\'"”’\\)\\]\u00BB\u203A\u201B\u201D\u201F]', + end: '[\'"”’\\)\\]\u00BB\u203A\u201B\u201D\u201F\u203C\u203D\u2047-\u2049,.;:!?]', + }, + + /** + * CJK biaodian (CJK標點符號) + */ + biaodian: { + base: '[︰.、,。:;?!ー]', + liga: '[—…⋯]', + middle: '[·\/-゠\uFF06\u30FB\uFF3F]', + open: '[「『《〈(〔[{【〖]', + close: '[」』》〉)〕]}】〗]', + end: '[」』》〉)〕]}】〗︰.、,。:;?!ー]' + }, + + /** + * CJK-related blocks (CJK相關字符區段) + * + * 1. 中日韓統一意音文字:[\u4E00-\u9FFF] + Basic CJK unified ideographs + * 2. 擴展-A區:[\u3400-\u4DB5] + Extended-A + * 3. 擴展-B區:[\u20000-\u2A6D6]([\uD840-\uD869][\uDC00-\uDED6]) + Extended-B + * 4. 擴展-C區:[\u2A700-\u2B734](\uD86D[\uDC00-\uDF3F]|[\uD86A-\uD86C][\uDC00-\uDFFF]|\uD869[\uDF00-\uDFFF]) + Extended-C + * 5. 擴展-D區:[\u2B740-\u2B81D](急用漢字,\uD86D[\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1F]) + Extended-D + * 6. 擴展-E區:[\u2B820-\u2F7FF](暫未支援) + Extended-E (not supported yet) + * 7. 擴展-F區(暫未支援) + Extended-F (not supported yet) + * 8. 筆畫區:[\u31C0-\u31E3] + Strokes + * 9. 意音數字「〇」:[\u3007] + Ideographic number zero + * 10. 相容意音文字及補充:[\uF900-\uFAFF][\u2F800-\u2FA1D](不使用) + Compatibility ideograph and supplement (not supported) + + 12 exceptions: + [\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29] + + https://zh.wikipedia.org/wiki/中日韓統一表意文字#cite_note-1 + + * 11. 康熙字典及簡化字部首:[\u2F00-\u2FD5\u2E80-\u2EF3] + Kangxi and supplement radicals + * 12. 意音文字描述字元:[\u2FF0-\u2FFA] + Ideographic description characters + */ + hanzi: { + base: '[\u4E00-\u9FFF\u3400-\u4DB5\u31C0-\u31E3\u3007\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD800-\uDBFF][\uDC00-\uDFFF]', + desc: '[\u2FF0-\u2FFA]', + radical: '[\u2F00-\u2FD5\u2E80-\u2EF3]' + }, + + /** + * Latin script blocks (拉丁字母區段) + * + * 1. 基本拉丁字母:A-Za-z + Basic Latin + * 2. 阿拉伯數字:0-9 + Digits + * 3. 補充-1:[\u00C0-\u00FF] + Latin-1 supplement + * 4. 擴展-A區:[\u0100-\u017F] + Extended-A + * 5. 擴展-B區:[\u0180-\u024F] + Extended-B + * 5. 擴展-C區:[\u2C60-\u2C7F] + Extended-C + * 5. 擴展-D區:[\uA720-\uA7FF] + Extended-D + * 6. 附加區:[\u1E00-\u1EFF] + Extended additional + * 7. 變音組字符:[\u0300-\u0341\u1DC0-\u1DFF] + Combining diacritical marks + */ + latin: { + base: '[A-Za-z0-9\u00C0-\u00FF\u0100-\u017F\u0180-\u024F\u2C60-\u2C7F\uA720-\uA7FF\u1E00-\u1EFF]', + combine: '[\u0300-\u0341\u1DC0-\u1DFF]' + }, + + /** + * Elli̱niká (Greek) script blocks (希臘字母區段) + * + * 1. 希臘字母及擴展:[\u0370–\u03FF\u1F00-\u1FFF] + Basic Greek & Greek Extended + * 2. 阿拉伯數字:0-9 + Digits + * 3. 希臘字母變音組字符:[\u0300-\u0345\u1DC0-\u1DFF] + Combining diacritical marks + */ + ellinika: { + base: '[0-9\u0370-\u03FF\u1F00-\u1FFF]', + combine: '[\u0300-\u0345\u1DC0-\u1DFF]' + }, + + /** + * Kirillica (Cyrillic) script blocks (西里爾字母區段) + * + * 1. 西里爾字母及補充:[\u0400-\u0482\u048A-\u04FF\u0500-\u052F] + Basic Cyrillic and supplement + * 2. 擴展B區:[\uA640-\uA66E\uA67E-\uA697] + Extended-B + * 3. 阿拉伯數字:0-9 + Digits + * 4. 西里爾字母組字符:[\u0483-\u0489\u2DE0-\u2DFF\uA66F-\uA67D\uA69F](位擴展A、B區) + Cyrillic combining diacritical marks (in extended-A, B) + */ + kirillica: { + base: '[0-9\u0400-\u0482\u048A-\u04FF\u0500-\u052F\uA640-\uA66E\uA67E-\uA697]', + combine: '[\u0483-\u0489\u2DE0-\u2DFF\uA66F-\uA67D\uA69F]' + }, + + /** + * Kana (假名) + * + * 1. 日文假名:[\u30A2\u30A4\u30A6\u30A8\u30AA-\u30FA\u3042\u3044\u3046\u3048\u304A-\u3094\u309F\u30FF] + Japanese Kana + * 2. 假名補充[\u1B000\u1B001](\uD82C[\uDC00-\uDC01]) + Kana supplement + * 3. 日文假名小寫:[\u3041\u3043\u3045\u3047\u3049\u30A1\u30A3\u30A5\u30A7\u30A9\u3063\u3083\u3085\u3087\u308E\u3095\u3096\u30C3\u30E3\u30E5\u30E7\u30EE\u30F5\u30F6\u31F0-\u31FF] + Japanese small Kana + * 4. 假名組字符:[\u3099-\u309C] + Kana combining characters + * 5. 半形假名:[\uFF66-\uFF9F] + Halfwidth Kana + * 6. 符號:[\u309D\u309E\u30FB-\u30FE] + Marks + */ + kana: { + base: '[\u30A2\u30A4\u30A6\u30A8\u30AA-\u30FA\u3042\u3044\u3046\u3048\u304A-\u3094\u309F\u30FF]|\uD82C[\uDC00-\uDC01]', + small: '[\u3041\u3043\u3045\u3047\u3049\u30A1\u30A3\u30A5\u30A7\u30A9\u3063\u3083\u3085\u3087\u308E\u3095\u3096\u30C3\u30E3\u30E5\u30E7\u30EE\u30F5\u30F6\u31F0-\u31FF]', + combine: '[\u3099-\u309C]', + half: '[\uFF66-\uFF9F]', + mark: '[\u30A0\u309D\u309E\u30FB-\u30FE]' + }, + + /** + * Eonmun (Hangul, 諺文) + * + * 1. 諺文音節:[\uAC00-\uD7A3] + Eonmun (Hangul) syllables + * 2. 諺文字母:[\u1100-\u11FF\u314F-\u3163\u3131-\u318E\uA960-\uA97C\uD7B0-\uD7FB] + Eonmun (Hangul) letters + * 3. 半形諺文字母:[\uFFA1-\uFFDC] + Halfwidth Eonmun (Hangul) letters + */ + eonmun: { + base: '[\uAC00-\uD7A3]', + letter: '[\u1100-\u11FF\u314F-\u3163\u3131-\u318E\uA960-\uA97C\uD7B0-\uD7FB]', + half: '[\uFFA1-\uFFDC]' + }, + + /** + * Zhuyin (注音符號, Mandarin & Dialect Phonetic Symbols) + * + * 1. 國語注音、方言音符號:[\u3105-\u312D][\u31A0-\u31BA] + Bopomofo phonetic symbols + * 2. 平上去聲調號:[\u02D9\u02CA\u02C5\u02C7\u02EA\u02EB\u02CB] (**註:**國語三聲包含乙個不合規範的符號) + Level, rising, departing tones + * 3. 入聲調號:[\u31B4-\u31B7][\u0358\u030d]? + Checked (entering) tones + */ + zhuyin: { + base: '[\u3105-\u312D\u31A0-\u31BA]', + initial: '[\u3105-\u3119\u312A-\u312C\u31A0-\u31A3]', + medial: '[\u3127-\u3129]', + final: '[\u311A-\u3129\u312D\u31A4-\u31B3\u31B8-\u31BA]', + tone: '[\u02D9\u02CA\u02C5\u02C7\u02CB\u02EA\u02EB]', + checked: '[\u31B4-\u31B7][\u0358\u030d]?' + } +} + +var TYPESET = (function() { + var rWhite = '[\\x20\\t\\r\\n\\f]' + // Whitespace characters + // http://www.w3.org/TR/css3-selectors/#whitespace + + var rPtOpen = UNICODE.punct.open + var rPtClose = UNICODE.punct.close + var rPtEnd = UNICODE.punct.end + var rPtMid = UNICODE.punct.middle + var rPtSing = UNICODE.punct.sing + var rPt = rPtOpen + '|' + rPtEnd + '|' + rPtMid + + var rBDOpen = UNICODE.biaodian.open + var rBDClose = UNICODE.biaodian.close + var rBDEnd = UNICODE.biaodian.end + var rBDMid = UNICODE.biaodian.middle + var rBDLiga = UNICODE.biaodian.liga + '{2}' + var rBD = rBDOpen + '|' + rBDEnd + '|' + rBDMid + + var rKana = UNICODE.kana.base + UNICODE.kana.combine + '?' + var rKanaS = UNICODE.kana.small + UNICODE.kana.combine + '?' + var rKanaH = UNICODE.kana.half + var rEon = UNICODE.eonmun.base + '|' + UNICODE.eonmun.letter + var rEonH = UNICODE.eonmun.half + + var rHan = UNICODE.hanzi.base + '|' + UNICODE.hanzi.desc + '|' + UNICODE.hanzi.radical + '|' + rKana + + var rCbn = UNICODE.ellinika.combine + var rLatn = UNICODE.latin.base + rCbn + '*' + var rGk = UNICODE.ellinika.base + rCbn + '*' + + var rCyCbn = UNICODE.kirillica.combine + var rCy = UNICODE.kirillica.base + rCyCbn + '*' + + var rAlph = rLatn + '|' + rGk + '|' + rCy + + // For words like `it's`, `Jones’s` or `'99` + var rApo = '[\u0027\u2019]' + var rChar = rHan + '|(?:' + rAlph + '|' + rApo + ')+' + + var rZyS = UNICODE.zhuyin.initial + var rZyJ = UNICODE.zhuyin.medial + var rZyY = UNICODE.zhuyin.final + var rZyD = UNICODE.zhuyin.tone + '|' + UNICODE.zhuyin.checked + + return { + /* Character-level selector (字級選擇器) + */ + char: { + punct: { + all: new RegExp( '(' + rPt + ')', 'g' ), + open: new RegExp( '(' + rPtOpen + ')', 'g' ), + end: new RegExp( '(' + rPtEnd + ')', 'g' ), + sing: new RegExp( '(' + rPtSing + ')', 'g' ) + }, + + biaodian: { + all: new RegExp( '(' + rBD + ')', 'g' ), + open: new RegExp( '(' + rBDOpen + ')', 'g' ), + close: new RegExp( '(' + rBDClose + ')', 'g' ), + end: new RegExp( '(' + rBDEnd + ')', 'g' ), + liga: new RegExp( '(' + rBDLiga + ')', 'g' ) + }, + + hanzi: new RegExp( '(' + rHan + ')', 'g' ), + + latin: new RegExp( '(' + rLatn + ')', 'ig' ), + ellinika: new RegExp( '(' + rGk + ')', 'ig' ), + kirillica: new RegExp( '(' + rCy + ')', 'ig' ), + + kana: new RegExp( '(' + rKana + '|' + rKanaS + '|' + rKanaH + ')', 'g' ), + eonmun: new RegExp( '(' + rEon + '|' + rEonH + ')', 'g' ) + }, + + /* Word-level selectors (詞級選擇器) + */ + group: { + biaodian: [ + new RegExp( '((' + rBD + '){2,})', 'g' ), + new RegExp( '(' + rBDLiga + rBDOpen + ')', 'g' ) + ], + punct: null, + hanzi: new RegExp( '(' + rHan + ')+', 'g' ), + western: new RegExp( '(' + rLatn + '|' + rGk + '|' + rCy + '|' + rPt + ')+', 'ig' ), + kana: new RegExp( '(' + rKana + '|' + rKanaS + '|' + rKanaH + ')+', 'g' ), + eonmun: new RegExp( '(' + rEon + '|' + rEonH + '|' + rPt + ')+', 'g' ) + }, + + /* Punctuation Rules (禁則) + */ + jinze: { + hanging: new RegExp( rWhite + '*([、,。.])(?!' + rBDEnd + ')', 'ig' ), + touwei: new RegExp( '(' + rBDOpen + '+)(' + rChar + ')(' + rBDEnd + '+)', 'ig' ), + tou: new RegExp( '(' + rBDOpen + '+)(' + rChar + ')', 'ig' ), + wei: new RegExp( '(' + rChar + ')(' + rBDEnd + '+)', 'ig' ), + middle: new RegExp( '(' + rChar + ')(' + rBDMid + ')(' + rChar + ')', 'ig' ) + }, + + zhuyin: { + form: new RegExp( '^\u02D9?(' + rZyS + ')?(' + rZyJ + ')?(' + rZyY + ')?(' + rZyD + ')?$' ), + diao: new RegExp( '(' + rZyD + ')', 'g' ) + }, + + /* Hanzi and Western mixed spacing (漢字西文混排間隙) + * - Basic mode + * - Strict mode + */ + hws: { + base: [ + new RegExp( '('+ rHan + ')(' + rAlph + '|' + rPtOpen + ')', 'ig' ), + new RegExp( '('+ rAlph + '|' + rPtEnd + ')(' + rHan + ')', 'ig' ) + ], + + strict: [ + new RegExp( '('+ rHan + ')' + rWhite + '?(' + rAlph + '|' + rPtOpen + ')', 'ig' ), + new RegExp( '('+ rAlph + '|' + rPtEnd + ')' + rWhite + '?(' + rHan + ')', 'ig' ) + ] + }, + + // The feature displays the following characters + // in its variant form for font consistency and + // presentational reason. Meanwhile, this won't + // alter the original character in the DOM. + 'display-as': { + 'ja-font-for-hant': [ + // '夠 够', + '查 査', + '啟 啓', + '鄉 鄕', + '值 値', + '污 汚' + ], + + 'comb-liga-pua': [ + [ '\u0061[\u030d\u0358]', '\uDB80\uDC61' ], + [ '\u0065[\u030d\u0358]', '\uDB80\uDC65' ], + [ '\u0069[\u030d\u0358]', '\uDB80\uDC69' ], + [ '\u006F[\u030d\u0358]', '\uDB80\uDC6F' ], + [ '\u0075[\u030d\u0358]', '\uDB80\uDC75' ], + + [ '\u31B4[\u030d\u0358]', '\uDB8C\uDDB4' ], + [ '\u31B5[\u030d\u0358]', '\uDB8C\uDDB5' ], + [ '\u31B6[\u030d\u0358]', '\uDB8C\uDDB6' ], + [ '\u31B7[\u030d\u0358]', '\uDB8C\uDDB7' ] + ], + + 'comb-liga-vowel': [ + [ '\u0061[\u030d\u0358]', '\uDB80\uDC61' ], + [ '\u0065[\u030d\u0358]', '\uDB80\uDC65' ], + [ '\u0069[\u030d\u0358]', '\uDB80\uDC69' ], + [ '\u006F[\u030d\u0358]', '\uDB80\uDC6F' ], + [ '\u0075[\u030d\u0358]', '\uDB80\uDC75' ] + ], + + 'comb-liga-zhuyin': [ + [ '\u31B4[\u030d\u0358]', '\uDB8C\uDDB4' ], + [ '\u31B5[\u030d\u0358]', '\uDB8C\uDDB5' ], + [ '\u31B6[\u030d\u0358]', '\uDB8C\uDDB6' ], + [ '\u31B7[\u030d\u0358]', '\uDB8C\uDDB7' ] + ] + }, + + // The feature actually *converts* the character + // in the DOM for semantic reason. + // + // Note that this could be aggressive. + 'inaccurate-char': [ + [ '[\u2022\u2027]', '\u00B7' ], + [ '\u22EF\u22EF', '\u2026\u2026' ], + [ '\u2500\u2500', '\u2014\u2014' ], + [ '\u2035', '\u2018' ], + [ '\u2032', '\u2019' ], + [ '\u2036', '\u201C' ], + [ '\u2033', '\u201D' ] + ] + } +})() + +Han.UNICODE = UNICODE +Han.TYPESET = TYPESET + +// Aliases +Han.UNICODE.cjk = Han.UNICODE.hanzi +Han.UNICODE.greek = Han.UNICODE.ellinika +Han.UNICODE.cyrillic = Han.UNICODE.kirillica +Han.UNICODE.hangul = Han.UNICODE.eonmun +Han.UNICODE.zhuyin.ruyun = Han.UNICODE.zhuyin.checked + +Han.TYPESET.char.cjk = Han.TYPESET.char.hanzi +Han.TYPESET.char.greek = Han.TYPESET.char.ellinika +Han.TYPESET.char.cyrillic = Han.TYPESET.char.kirillica +Han.TYPESET.char.hangul = Han.TYPESET.char.eonmun + +Han.TYPESET.group.hangul = Han.TYPESET.group.eonmun +Han.TYPESET.group.cjk = Han.TYPESET.group.hanzi + +var $ = { + /** + * Query selectors which return arrays of the resulted + * node lists. + */ + id: function( selector, $context ) { + return ( $context || document ).getElementById( selector ) + }, + + tag: function( selector, $context ) { + return this.makeArray( + ( $context || document ).getElementsByTagName( selector ) + ) + }, + + qs: function( selector, $context ) { + return ( $context || document ).querySelector( selector ) + }, + + qsa: function( selector, $context ) { + return this.makeArray( + ( $context || document ).querySelectorAll( selector ) + ) + }, + + parent: function( $node, selector ) { + return selector + ? (function() { + if ( typeof $.matches !== 'function' ) return + + while (!$.matches( $node, selector )) { + if ( + !$node || + $node === document.documentElement + ) { + $node = undefined + break + } + $node = $node.parentNode + } + return $node + })() + : $node + ? $node.parentNode : undefined + }, + + /** + * Create a document fragment, a text node with text + * or an element with/without classes. + */ + create: function( name, clazz ) { + var $elmt = '!' === name + ? document.createDocumentFragment() + : '' === name + ? document.createTextNode( clazz || '' ) + : document.createElement( name ) + + try { + if ( clazz ) { + $elmt.className = clazz + } + } catch (e) {} + + return $elmt + }, + + /** + * Clone a DOM node (text, element or fragment) deeply + * or childlessly. + */ + clone: function( $node, deep ) { + return $node.cloneNode( + typeof deep === 'boolean' + ? deep + : true + ) + }, + + /** + * Remove a node (text, element or fragment). + */ + remove: function( $node ) { + return $node.parentNode.removeChild( $node ) + }, + + /** + * Set attributes all in once with an object. + */ + setAttr: function( target, attr ) { + if ( typeof attr !== 'object' ) return + var len = attr.length + + // Native `NamedNodeMap``: + if ( + typeof attr[0] === 'object' && + 'name' in attr[0] + ) { + for ( var i = 0; i < len; i++ ) { + if ( attr[ i ].value !== undefined ) { + target.setAttribute( attr[ i ].name, attr[ i ].value ) + } + } + + // Plain object: + } else { + for ( var name in attr ) { + if ( + attr.hasOwnProperty( name ) && + attr[ name ] !== undefined + ) { + target.setAttribute( name, attr[ name ] ) + } + } + } + return target + }, + + /** + * Indicate whether or not the given node is an + * element. + */ + isElmt: function( $node ) { + return $node && $node.nodeType === Node.ELEMENT_NODE + }, + + /** + * Indicate whether or not the given node should + * be ignored (`` or comments). + */ + isIgnorable: function( $node ) { + if ( !$node ) return false + + return ( + $node.nodeName === 'WBR' || + $node.nodeType === Node.COMMENT_NODE + ) + }, + + /** + * Convert array-like objects into real arrays. + */ + makeArray: function( object ) { + return Array.prototype.slice.call( object ) + }, + + /** + * Extend target with an object. + */ + extend: function( target, object ) { + if (( + typeof target === 'object' || + typeof target === 'function' ) && + typeof object === 'object' + ) { + for ( var name in object ) { + if (object.hasOwnProperty( name )) { + target[ name ] = object[ name ] + } + } + } + return target + } +} + +var Fibre = +/*! + * Fibre.js v0.2.1 | MIT License | github.com/ethantw/fibre.js + * Based on findAndReplaceDOMText + */ + +function( Finder ) { + +'use strict' + +var VERSION = '0.2.1' +var NON_INLINE_PROSE = Finder.NON_INLINE_PROSE +var AVOID_NON_PROSE = Finder.PRESETS.prose.filterElements + +var global = window || {} +var document = global.document || undefined + +function matches( node, selector, bypassNodeType39 ) { + var Efn = Element.prototype + var matches = Efn.matches || Efn.mozMatchesSelector || Efn.msMatchesSelector || Efn.webkitMatchesSelector + + if ( node instanceof Element ) { + return matches.call( node, selector ) + } else if ( bypassNodeType39 ) { + if ( /^[39]$/.test( node.nodeType )) return true + } + return false +} + +if ( typeof document === 'undefined' ) throw new Error( 'Fibre requires a DOM-supported environment.' ) + +var Fibre = function( context, preset ) { + return new Fibre.fn.init( context, preset ) +} + +Fibre.version = VERSION +Fibre.matches = matches + +Fibre.fn = Fibre.prototype = { + constructor: Fibre, + + version: VERSION, + + finder: [], + + context: undefined, + + portionMode: 'retain', + + selector: {}, + + preset: 'prose', + + init: function( context, noPreset ) { + if ( !!noPreset ) this.preset = null + + this.selector = { + context: null, + filter: [], + avoid: [], + boundary: [] + } + + if ( !context ) { + throw new Error( 'A context is required for Fibre to initialise.' ) + } else if ( context instanceof Node ) { + if ( context instanceof Document ) this.context = context.body || context + else this.context = context + } else if ( typeof context === 'string' ) { + this.context = document.querySelector( context ) + this.selector.context = context + } + return this + }, + + filterFn: function( node ) { + var filter = this.selector.filter.join( ', ' ) || '*' + var avoid = this.selector.avoid.join( ', ' ) || null + var result = matches( node, filter, true ) && !matches( node, avoid ) + return ( this.preset === 'prose' ) ? AVOID_NON_PROSE( node ) && result : result + }, + + boundaryFn: function( node ) { + var boundary = this.selector.boundary.join( ', ' ) || null + var result = matches( node, boundary ) + return ( this.preset === 'prose' ) ? NON_INLINE_PROSE( node ) || result : result + }, + + filter: function( selector ) { + if ( typeof selector === 'string' ) { + this.selector.filter.push( selector ) + } + return this + }, + + endFilter: function( all ) { + if ( all ) { + this.selector.filter = [] + } else { + this.selector.filter.pop() + } + return this + }, + + avoid: function( selector ) { + if ( typeof selector === 'string' ) { + this.selector.avoid.push( selector ) + } + return this + }, + + endAvoid: function( all ) { + if ( all ) { + this.selector.avoid = [] + } else { + this.selector.avoid.pop() + } + return this + }, + + addBoundary: function( selector ) { + if ( typeof selector === 'string' ) { + this.selector.boundary.push( selector ) + } + return this + }, + + removeBoundary: function() { + this.selector.boundary = [] + return this + }, + + setMode: function( portionMode ) { + this.portionMode = portionMode === 'first' ? 'first' : 'retain' + return this + }, + + replace: function( regexp, newSubStr ) { + var it = this + it.finder.push(Finder( it.context, { + find: regexp, + replace: newSubStr, + filterElements: function( currentNode ) { + return it.filterFn( currentNode ) + }, + forceContext: function( currentNode ) { + return it.boundaryFn( currentNode ) + }, + portionMode: it.portionMode + })) + return it + }, + + wrap: function( regexp, strElemName ) { + var it = this + it.finder.push(Finder( it.context, { + find: regexp, + wrap: strElemName, + filterElements: function( currentNode ) { + return it.filterFn( currentNode ) + }, + forceContext: function( currentNode ) { + return it.boundaryFn( currentNode ) + }, + portionMode: it.portionMode + })) + return it + }, + + revert: function( level ) { + var max = this.finder.length + var level = Number( level ) || ( level === 0 ? Number(0) : + ( level === 'all' ? max : 1 )) + + if ( typeof max === 'undefined' || max === 0 ) return this + else if ( level > max ) level = max + + for ( var i = level; i > 0; i-- ) { + this.finder.pop().revert() + } + return this + } +} + +// Deprecated API(s) +Fibre.fn.filterOut = Fibre.fn.avoid + +// Make sure init() inherit from Fibre() +Fibre.fn.init.prototype = Fibre.fn + +return Fibre + +}( + +/** + * findAndReplaceDOMText v 0.4.3 + * @author James Padolsey http://james.padolsey.com + * @license http://unlicense.org/UNLICENSE + * + * Matches the text of a DOM node against a regular expression + * and replaces each match (or node-separated portions of the match) + * in the specified element. + */ + (function() { + + var PORTION_MODE_RETAIN = 'retain' + var PORTION_MODE_FIRST = 'first' + var doc = document + var toString = {}.toString + var hasOwn = {}.hasOwnProperty + function isArray(a) { + return toString.call(a) == '[object Array]' + } + + function escapeRegExp(s) { + return String(s).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1') + } + + function exposed() { + // Try deprecated arg signature first: + return deprecated.apply(null, arguments) || findAndReplaceDOMText.apply(null, arguments) + } + + function deprecated(regex, node, replacement, captureGroup, elFilter) { + if ((node && !node.nodeType) && arguments.length <= 2) { + return false + } + var isReplacementFunction = typeof replacement == 'function' + if (isReplacementFunction) { + replacement = (function(original) { + return function(portion, match) { + return original(portion.text, match.startIndex) + } + }(replacement)) + } + + // Awkward support for deprecated argument signature (<0.4.0) + var instance = findAndReplaceDOMText(node, { + + find: regex, + + wrap: isReplacementFunction ? null : replacement, + replace: isReplacementFunction ? replacement : '$' + (captureGroup || '&'), + + prepMatch: function(m, mi) { + + // Support captureGroup (a deprecated feature) + + if (!m[0]) throw 'findAndReplaceDOMText cannot handle zero-length matches' + if (captureGroup > 0) { + var cg = m[captureGroup] + m.index += m[0].indexOf(cg) + m[0] = cg + } + + m.endIndex = m.index + m[0].length + m.startIndex = m.index + m.index = mi + return m + }, + filterElements: elFilter + }) + exposed.revert = function() { + return instance.revert() + } + return true + } + + /** + * findAndReplaceDOMText + * + * Locates matches and replaces with replacementNode + * + * @param {Node} node Element or Text node to search within + * @param {RegExp} options.find The regular expression to match + * @param {String|Element} [options.wrap] A NodeName, or a Node to clone + * @param {String|Function} [options.replace='$&'] What to replace each match with + * @param {Function} [options.filterElements] A Function to be called to check whether to + * process an element. (returning true = process element, + * returning false = avoid element) + */ + function findAndReplaceDOMText(node, options) { + return new Finder(node, options) + } + + exposed.NON_PROSE_ELEMENTS = { + br:1, hr:1, + // Media / Source elements: + script:1, style:1, img:1, video:1, audio:1, canvas:1, svg:1, map:1, object:1, + // Input elements + input:1, textarea:1, select:1, option:1, optgroup: 1, button:1 + } + exposed.NON_CONTIGUOUS_PROSE_ELEMENTS = { + + // Elements that will not contain prose or block elements where we don't + // want prose to be matches across element borders: + + // Block Elements + address:1, article:1, aside:1, blockquote:1, dd:1, div:1, + dl:1, fieldset:1, figcaption:1, figure:1, footer:1, form:1, h1:1, h2:1, h3:1, + h4:1, h5:1, h6:1, header:1, hgroup:1, hr:1, main:1, nav:1, noscript:1, ol:1, + output:1, p:1, pre:1, section:1, ul:1, + // Other misc. elements that are not part of continuous inline prose: + br:1, li: 1, summary: 1, dt:1, details:1, rp:1, rt:1, rtc:1, + // Media / Source elements: + script:1, style:1, img:1, video:1, audio:1, canvas:1, svg:1, map:1, object:1, + // Input elements + input:1, textarea:1, select:1, option:1, optgroup: 1, button:1, + // Table related elements: + table:1, tbody:1, thead:1, th:1, tr:1, td:1, caption:1, col:1, tfoot:1, colgroup:1 + + } + exposed.NON_INLINE_PROSE = function(el) { + return hasOwn.call(exposed.NON_CONTIGUOUS_PROSE_ELEMENTS, el.nodeName.toLowerCase()) + } + // Presets accessed via `options.preset` when calling findAndReplaceDOMText(): + exposed.PRESETS = { + prose: { + forceContext: exposed.NON_INLINE_PROSE, + filterElements: function(el) { + return !hasOwn.call(exposed.NON_PROSE_ELEMENTS, el.nodeName.toLowerCase()) + } + } + } + exposed.Finder = Finder + /** + * Finder -- encapsulates logic to find and replace. + */ + function Finder(node, options) { + + var preset = options.preset && exposed.PRESETS[options.preset] + options.portionMode = options.portionMode || PORTION_MODE_RETAIN + if (preset) { + for (var i in preset) { + if (hasOwn.call(preset, i) && !hasOwn.call(options, i)) { + options[i] = preset[i] + } + } + } + + this.node = node + this.options = options + // ENable match-preparation method to be passed as option: + this.prepMatch = options.prepMatch || this.prepMatch + this.reverts = [] + this.matches = this.search() + if (this.matches.length) { + this.processMatches() + } + + } + + Finder.prototype = { + + /** + * Searches for all matches that comply with the instance's 'match' option + */ + search: function() { + + var match + var matchIndex = 0 + var offset = 0 + var regex = this.options.find + var textAggregation = this.getAggregateText() + var matches = [] + var self = this + regex = typeof regex === 'string' ? RegExp(escapeRegExp(regex), 'g') : regex + matchAggregation(textAggregation) + function matchAggregation(textAggregation) { + for (var i = 0, l = textAggregation.length; i < l; ++i) { + + var text = textAggregation[i] + if (typeof text !== 'string') { + // Deal with nested contexts: (recursive) + matchAggregation(text) + continue + } + + if (regex.global) { + while (match = regex.exec(text)) { + matches.push(self.prepMatch(match, matchIndex++, offset)) + } + } else { + if (match = text.match(regex)) { + matches.push(self.prepMatch(match, 0, offset)) + } + } + + offset += text.length + } + } + + return matches + }, + + /** + * Prepares a single match with useful meta info: + */ + prepMatch: function(match, matchIndex, characterOffset) { + + if (!match[0]) { + throw new Error('findAndReplaceDOMText cannot handle zero-length matches') + } + + match.endIndex = characterOffset + match.index + match[0].length + match.startIndex = characterOffset + match.index + match.index = matchIndex + return match + }, + + /** + * Gets aggregate text within subject node + */ + getAggregateText: function() { + + var elementFilter = this.options.filterElements + var forceContext = this.options.forceContext + return getText(this.node) + /** + * Gets aggregate text of a node without resorting + * to broken innerText/textContent + */ + function getText(node, txt) { + + if (node.nodeType === 3) { + return [node.data] + } + + if (elementFilter && !elementFilter(node)) { + return [] + } + + var txt = [''] + var i = 0 + if (node = node.firstChild) do { + + if (node.nodeType === 3) { + txt[i] += node.data + continue + } + + var innerText = getText(node) + if ( + forceContext && + node.nodeType === 1 && + (forceContext === true || forceContext(node)) + ) { + txt[++i] = innerText + txt[++i] = '' + } else { + if (typeof innerText[0] === 'string') { + // Bridge nested text-node data so that they're + // not considered their own contexts: + // I.e. ['some', ['thing']] -> ['something'] + txt[i] += innerText.shift() + } + if (innerText.length) { + txt[++i] = innerText + txt[++i] = '' + } + } + } while (node = node.nextSibling) + return txt + } + + }, + + /** + * Steps through the target node, looking for matches, and + * calling replaceFn when a match is found. + */ + processMatches: function() { + + var matches = this.matches + var node = this.node + var elementFilter = this.options.filterElements + var startPortion, + endPortion, + innerPortions = [], + curNode = node, + match = matches.shift(), + atIndex = 0, // i.e. nodeAtIndex + matchIndex = 0, + portionIndex = 0, + doAvoidNode, + nodeStack = [node] + out: while (true) { + + if (curNode.nodeType === 3) { + + if (!endPortion && curNode.length + atIndex >= match.endIndex) { + + // We've found the ending + endPortion = { + node: curNode, + index: portionIndex++, + text: curNode.data.substring(match.startIndex - atIndex, match.endIndex - atIndex), + indexInMatch: atIndex - match.startIndex, + indexInNode: match.startIndex - atIndex, // always zero for end-portions + endIndexInNode: match.endIndex - atIndex, + isEnd: true + } + } else if (startPortion) { + // Intersecting node + innerPortions.push({ + node: curNode, + index: portionIndex++, + text: curNode.data, + indexInMatch: atIndex - match.startIndex, + indexInNode: 0 // always zero for inner-portions + }) + } + + if (!startPortion && curNode.length + atIndex > match.startIndex) { + // We've found the match start + startPortion = { + node: curNode, + index: portionIndex++, + indexInMatch: 0, + indexInNode: match.startIndex - atIndex, + endIndexInNode: match.endIndex - atIndex, + text: curNode.data.substring(match.startIndex - atIndex, match.endIndex - atIndex) + } + } + + atIndex += curNode.data.length + } + + doAvoidNode = curNode.nodeType === 1 && elementFilter && !elementFilter(curNode) + if (startPortion && endPortion) { + + curNode = this.replaceMatch(match, startPortion, innerPortions, endPortion) + // processMatches has to return the node that replaced the endNode + // and then we step back so we can continue from the end of the + // match: + + atIndex -= (endPortion.node.data.length - endPortion.endIndexInNode) + startPortion = null + endPortion = null + innerPortions = [] + match = matches.shift() + portionIndex = 0 + matchIndex++ + if (!match) { + break; // no more matches + } + + } else if ( + !doAvoidNode && + (curNode.firstChild || curNode.nextSibling) + ) { + // Move down or forward: + if (curNode.firstChild) { + nodeStack.push(curNode) + curNode = curNode.firstChild + } else { + curNode = curNode.nextSibling + } + continue + } + + // Move forward or up: + while (true) { + if (curNode.nextSibling) { + curNode = curNode.nextSibling + break + } + curNode = nodeStack.pop() + if (curNode === node) { + break out + } + } + + } + + }, + + /** + * Reverts ... TODO + */ + revert: function() { + // Reversion occurs backwards so as to avoid nodes subsequently + // replaced during the matching phase (a forward process): + for (var l = this.reverts.length; l--;) { + this.reverts[l]() + } + this.reverts = [] + }, + + prepareReplacementString: function(string, portion, match, matchIndex) { + var portionMode = this.options.portionMode + if ( + portionMode === PORTION_MODE_FIRST && + portion.indexInMatch > 0 + ) { + return '' + } + string = string.replace(/\$(\d+|&|`|')/g, function($0, t) { + var replacement + switch(t) { + case '&': + replacement = match[0] + break + case '`': + replacement = match.input.substring(0, match.startIndex) + break + case '\'': + replacement = match.input.substring(match.endIndex) + break + default: + replacement = match[+t] + } + return replacement + }) + if (portionMode === PORTION_MODE_FIRST) { + return string + } + + if (portion.isEnd) { + return string.substring(portion.indexInMatch) + } + + return string.substring(portion.indexInMatch, portion.indexInMatch + portion.text.length) + }, + + getPortionReplacementNode: function(portion, match, matchIndex) { + + var replacement = this.options.replace || '$&' + var wrapper = this.options.wrap + if (wrapper && wrapper.nodeType) { + // Wrapper has been provided as a stencil-node for us to clone: + var clone = doc.createElement('div') + clone.innerHTML = wrapper.outerHTML || new XMLSerializer().serializeToString(wrapper) + wrapper = clone.firstChild + } + + if (typeof replacement == 'function') { + replacement = replacement(portion, match, matchIndex) + if (replacement && replacement.nodeType) { + return replacement + } + return doc.createTextNode(String(replacement)) + } + + var el = typeof wrapper == 'string' ? doc.createElement(wrapper) : wrapper + replacement = doc.createTextNode( + this.prepareReplacementString( + replacement, portion, match, matchIndex + ) + ) + if (!replacement.data) { + return replacement + } + + if (!el) { + return replacement + } + + el.appendChild(replacement) + return el + }, + + replaceMatch: function(match, startPortion, innerPortions, endPortion) { + + var matchStartNode = startPortion.node + var matchEndNode = endPortion.node + var preceedingTextNode + var followingTextNode + if (matchStartNode === matchEndNode) { + + var node = matchStartNode + if (startPortion.indexInNode > 0) { + // Add `before` text node (before the match) + preceedingTextNode = doc.createTextNode(node.data.substring(0, startPortion.indexInNode)) + node.parentNode.insertBefore(preceedingTextNode, node) + } + + // Create the replacement node: + var newNode = this.getPortionReplacementNode( + endPortion, + match + ) + node.parentNode.insertBefore(newNode, node) + if (endPortion.endIndexInNode < node.length) { // ????? + // Add `after` text node (after the match) + followingTextNode = doc.createTextNode(node.data.substring(endPortion.endIndexInNode)) + node.parentNode.insertBefore(followingTextNode, node) + } + + node.parentNode.removeChild(node) + this.reverts.push(function() { + if (preceedingTextNode === newNode.previousSibling) { + preceedingTextNode.parentNode.removeChild(preceedingTextNode) + } + if (followingTextNode === newNode.nextSibling) { + followingTextNode.parentNode.removeChild(followingTextNode) + } + newNode.parentNode.replaceChild(node, newNode) + }) + return newNode + } else { + // Replace matchStartNode -> [innerMatchNodes...] -> matchEndNode (in that order) + + preceedingTextNode = doc.createTextNode( + matchStartNode.data.substring(0, startPortion.indexInNode) + ) + followingTextNode = doc.createTextNode( + matchEndNode.data.substring(endPortion.endIndexInNode) + ) + var firstNode = this.getPortionReplacementNode( + startPortion, + match + ) + var innerNodes = [] + for (var i = 0, l = innerPortions.length; i < l; ++i) { + var portion = innerPortions[i] + var innerNode = this.getPortionReplacementNode( + portion, + match + ) + portion.node.parentNode.replaceChild(innerNode, portion.node) + this.reverts.push((function(portion, innerNode) { + return function() { + innerNode.parentNode.replaceChild(portion.node, innerNode) + } + }(portion, innerNode))) + innerNodes.push(innerNode) + } + + var lastNode = this.getPortionReplacementNode( + endPortion, + match + ) + matchStartNode.parentNode.insertBefore(preceedingTextNode, matchStartNode) + matchStartNode.parentNode.insertBefore(firstNode, matchStartNode) + matchStartNode.parentNode.removeChild(matchStartNode) + matchEndNode.parentNode.insertBefore(lastNode, matchEndNode) + matchEndNode.parentNode.insertBefore(followingTextNode, matchEndNode) + matchEndNode.parentNode.removeChild(matchEndNode) + this.reverts.push(function() { + preceedingTextNode.parentNode.removeChild(preceedingTextNode) + firstNode.parentNode.replaceChild(matchStartNode, firstNode) + followingTextNode.parentNode.removeChild(followingTextNode) + lastNode.parentNode.replaceChild(matchEndNode, lastNode) + }) + return lastNode + } + } + + } + return exposed +}()) + +); + +var isNodeNormalizeNormal = (function() { + //// Disabled `Node.normalize()` for temp due to + //// issue below in IE11. + //// See: http://stackoverflow.com/questions/22337498/why-does-ie11-handle-node-normalize-incorrectly-for-the-minus-symbol + var div = $.create( 'div' ) + + div.appendChild($.create( '', '0-' )) + div.appendChild($.create( '', '2' )) + div.normalize() + + return div.firstChild.length !== 2 +})() + +function getFuncOrElmt( obj ) { + return ( + typeof obj === 'function' || + obj instanceof Element + ) + ? obj + : undefined +} + +function createBDGroup( portion ) { + var clazz = portion.index === 0 && portion.isEnd + ? 'biaodian cjk' + : 'biaodian cjk portion ' + ( + portion.index === 0 + ? 'is-first' + : portion.isEnd + ? 'is-end' + : 'is-inner' + ) + + var $elmt = $.create( 'h-char-group', clazz ) + $elmt.innerHTML = portion.text + return $elmt +} + +function createBDChar( char ) { + var div = $.create( 'div' ) + var unicode = char.charCodeAt( 0 ).toString( 16 ) + + div.innerHTML = ( + '' + char + '' + ) + return div.firstChild +} + +function getBDType( char ) { + return char.match( TYPESET.char.biaodian.open ) + ? 'bd-open' + : char.match( TYPESET.char.biaodian.close ) + ? 'bd-close bd-end' + : char.match( TYPESET.char.biaodian.end ) + ? ( + /(?:\u3001|\u3002|\uff0c)/i.test( char ) + ? 'bd-end bd-cop' + : 'bd-end' + ) + : char.match(new RegExp( UNICODE.biaodian.liga )) + ? 'bd-liga' + : char.match(new RegExp( UNICODE.biaodian.middle )) + ? 'bd-middle' + : '' +} + +$.extend( Fibre.fn, { + normalize: function() { + if ( isNodeNormalizeNormal ) { + this.context.normalize() + } + return this + }, + + // Force punctuation & biaodian typesetting rules to be applied. + jinzify: function( selector ) { + return ( + this + .filter( selector || null ) + .avoid( 'h-jinze' ) + .replace( + TYPESET.jinze.touwei, + function( portion, match ) { + var elem = $.create( 'h-jinze', 'touwei' ) + elem.innerHTML = match[0] + return (( portion.index === 0 && portion.isEnd ) || portion.index === 1 ) ? elem : '' + } + ) + .replace( + TYPESET.jinze.wei, + function( portion, match ) { + var elem = $.create( 'h-jinze', 'wei' ) + elem.innerHTML = match[0] + return portion.index === 0 ? elem : '' + } + ) + .replace( + TYPESET.jinze.tou, + function( portion, match ) { + var elem = $.create( 'h-jinze', 'tou' ) + elem.innerHTML = match[0] + return (( portion.index === 0 && portion.isEnd ) || portion.index === 1 ) + ? elem : '' + } + ) + .replace( + TYPESET.jinze.middle, + function( portion, match ) { + var elem = $.create( 'h-jinze', 'middle' ) + elem.innerHTML = match[0] + return (( portion.index === 0 && portion.isEnd ) || portion.index === 1 ) + ? elem : '' + } + ) + .endAvoid() + .endFilter() + ) + }, + + groupify: function( option ) { + var option = $.extend({ + biaodian: false, + //punct: false, + hanzi: false, // Includes Kana + kana: false, + eonmun: false, + western: false // Includes Latin, Greek and Cyrillic + }, option || {}) + + this.avoid( 'h-word, h-char-group' ) + + if ( option.biaodian ) { + this.replace( + TYPESET.group.biaodian[0], createBDGroup + ).replace( + TYPESET.group.biaodian[1], createBDGroup + ) + } + + if ( option.hanzi || option.cjk ) { + this.wrap( + TYPESET.group.hanzi, $.clone($.create( 'h-char-group', 'hanzi cjk' )) + ) + } + if ( option.western ) { + this.wrap( + TYPESET.group.western, $.clone($.create( 'h-word', 'western' )) + ) + } + if ( option.kana ) { + this.wrap( + TYPESET.group.kana, $.clone($.create( 'h-char-group', 'kana' )) + ) + } + if ( option.eonmun || option.hangul ) { + this.wrap( + TYPESET.group.eonmun, $.clone($.create( 'h-word', 'eonmun hangul' )) + ) + } + + this.endAvoid() + return this + }, + + charify: function( option ) { + var option = $.extend({ + avoid: true, + biaodian: false, + punct: false, + hanzi: false, // Includes Kana + latin: false, + ellinika: false, + kirillica: false, + kana: false, + eonmun: false + }, option || {}) + + if ( option.avoid ) { + this.avoid( 'h-char' ) + } + + if ( option.biaodian ) { + this.replace( + TYPESET.char.biaodian.all, + getFuncOrElmt( option.biaodian ) + || + function( portion ) { return createBDChar( portion.text ) } + ).replace( + TYPESET.char.biaodian.liga, + getFuncOrElmt( option.biaodian ) + || + function( portion ) { return createBDChar( portion.text ) } + ) + } + if ( option.hanzi || option.cjk ) { + this.wrap( + TYPESET.char.hanzi, + getFuncOrElmt( option.hanzi || option.cjk ) + || + $.clone($.create( 'h-char', 'hanzi cjk' )) + ) + } + if ( option.punct ) { + this.wrap( + TYPESET.char.punct.all, + getFuncOrElmt( option.punct ) + || + $.clone($.create( 'h-char', 'punct' )) + ) + } + if ( option.latin ) { + this.wrap( + TYPESET.char.latin, + getFuncOrElmt( option.latin ) + || + $.clone($.create( 'h-char', 'alphabet latin' )) + ) + } + if ( option.ellinika || option.greek ) { + this.wrap( + TYPESET.char.ellinika, + getFuncOrElmt( option.ellinika || option.greek ) + || + $.clone($.create( 'h-char', 'alphabet ellinika greek' )) + ) + } + if ( option.kirillica || option.cyrillic ) { + this.wrap( + TYPESET.char.kirillica, + getFuncOrElmt( option.kirillica || option.cyrillic ) + || + $.clone($.create( 'h-char', 'alphabet kirillica cyrillic' )) + ) + } + if ( option.kana ) { + this.wrap( + TYPESET.char.kana, + getFuncOrElmt( option.kana ) + || + $.clone($.create( 'h-char', 'kana' )) + ) + } + if ( option.eonmun || option.hangul ) { + this.wrap( + TYPESET.char.eonmun, + getFuncOrElmt( option.eonmun || option.hangul ) + || + $.clone($.create( 'h-char', 'eonmun hangul' )) + ) + } + + this.endAvoid() + return this + } +}) + +$.extend( Han, { + isNodeNormalizeNormal: isNodeNormalizeNormal, + find: Fibre, + createBDGroup: createBDGroup, + createBDChar: createBDChar +}) + +$.matches = Han.find.matches + +void [ + 'setMode', + 'wrap', 'replace', 'revert', + 'addBoundary', 'removeBoundary', + 'avoid', 'endAvoid', + 'filter', 'endFilter', + 'jinzify', 'groupify', 'charify' +].forEach(function( method ) { + Han.fn[ method ] = function() { + if ( !this.finder ) { + // Share the same selector + this.finder = Han.find( this.context ) + } + + this.finder[ method ]( arguments[ 0 ], arguments[ 1 ] ) + return this + } +}) + +var Locale = {} + +function writeOnCanvas( text, font ) { + var canvas = $.create( 'canvas' ) + var context + + canvas.width = '50' + canvas.height = '20' + canvas.style.display = 'none' + + body.appendChild( canvas ) + + context = canvas.getContext( '2d' ) + context.textBaseline = 'top' + context.font = '15px ' + font + ', sans-serif' + context.fillStyle = 'black' + context.strokeStyle = 'black' + context.fillText( text, 0, 0 ) + + return { + node: canvas, + context: context, + remove: function() { + $.remove( canvas, body ) + } + } +} + +function compareCanvases( treat, control ) { + var ret + var a = treat.context + var b = control.context + + try { + for ( var j = 1; j <= 20; j++ ) { + for ( var i = 1; i <= 50; i++ ) { + if ( + typeof ret === 'undefined' && + a.getImageData(i, j, 1, 1).data[3] !== b.getImageData(i, j, 1, 1).data[3] + ) { + ret = false + break + } else if ( typeof ret === 'boolean' ) { + break + } + + if ( i === 50 && j === 20 && typeof ret === 'undefined' ) { + ret = true + } + } + } + + // Remove and clean from memory + treat.remove() + control.remove() + treat = null + control = null + + return ret + } catch (e) {} + return false +} + +function detectFont( treat, control, text ) { + var treat = treat + var control = control || 'sans-serif' + var text = text || '辭Q' + var ret + + control = writeOnCanvas( text, control ) + treat = writeOnCanvas( text, treat ) + + return !compareCanvases( treat, control ) +} + +Locale.writeOnCanvas = writeOnCanvas +Locale.compareCanvases = compareCanvases +Locale.detectFont = detectFont + +Locale.support = (function() { + + var PREFIX = 'Webkit Moz ms'.split(' ') + + // Create an element for feature detecting + // (in `testCSSProp`) + var elem = $.create( 'h-test' ) + + function testCSSProp( prop ) { + var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1) + var allProp = ( prop + ' ' + PREFIX.join( ucProp + ' ' ) + ucProp ).split(' ') + var ret + + allProp.forEach(function( prop ) { + if ( typeof elem.style[ prop ] === 'string' ) { + ret = true + } + }) + return ret || false + } + + function injectElementWithStyle( rule, callback ) { + var fakeBody = body || $.create( 'body' ) + var div = $.create( 'div' ) + var container = body ? div : fakeBody + var callback = typeof callback === 'function' ? callback : function() {} + var style, ret, docOverflow + + style = [ '' ].join('') + + container.innerHTML += style + fakeBody.appendChild( div ) + + if ( !body ) { + fakeBody.style.background = '' + fakeBody.style.overflow = 'hidden' + docOverflow = root.style.overflow + + root.style.overflow = 'hidden' + root.appendChild( fakeBody ) + } + + // Callback + ret = callback( container, rule ) + + // Remove the injected scope + $.remove( container ) + if ( !body ) { + root.style.overflow = docOverflow + } + return !!ret + } + + function getStyle( elem, prop ) { + var ret + + if ( window.getComputedStyle ) { + ret = document.defaultView.getComputedStyle( elem, null ).getPropertyValue( prop ) + } else if ( elem.currentStyle ) { + // for IE + ret = elem.currentStyle[ prop ] + } + return ret + } + + return { + columnwidth: testCSSProp( 'columnWidth' ), + + fontface: (function() { + var ret + + injectElementWithStyle( + '@font-face { font-family: font; src: url("//"); }', + function( node, rule ) { + var style = $.qsa( 'style', node )[0] + var sheet = style.sheet || style.styleSheet + var cssText = sheet ? + ( sheet.cssRules && sheet.cssRules[0] ? + sheet.cssRules[0].cssText : sheet.cssText || '' + ) : '' + + ret = /src/i.test( cssText ) && + cssText.indexOf( rule.split(' ')[0] ) === 0 + } + ) + + return ret + })(), + + ruby: (function() { + var ruby = $.create( 'ruby' ) + var rt = $.create( 'rt' ) + var rp = $.create( 'rp' ) + var ret + + ruby.appendChild( rp ) + ruby.appendChild( rt ) + root.appendChild( ruby ) + + // Browsers that support ruby hide the `` via `display: none` + ret = ( + getStyle( rp, 'display' ) === 'none' || + // but in IE, `` has `display: inline`, so the test needs other conditions: + getStyle( ruby, 'display' ) === 'ruby' && + getStyle( rt, 'display' ) === 'ruby-text' + ) ? true : false + + // Remove and clean from memory + root.removeChild( ruby ) + ruby = null + rt = null + rp = null + + return ret + })(), + + 'ruby-display': (function() { + var div = $.create( 'div' ) + + div.innerHTML = '' + return div.querySelector( 'h-test-a' ).style.display === 'ruby' && div.querySelector( 'h-test-b' ).style.display === 'ruby-text-container' + })(), + + 'ruby-interchar': (function() { + var IC = 'inter-character' + var div = $.create( 'div' ) + var css + + div.innerHTML = '' + css = div.querySelector( 'h-test' ).style + return css.rubyPosition === IC || css.WebkitRubyPosition === IC || css.MozRubyPosition === IC || css.msRubyPosition === IC + })(), + + textemphasis: testCSSProp( 'textEmphasis' ), + + // Address feature support test for `unicode-range` via + // detecting whether it's Arial (supported) or + // Times New Roman (not supported). + unicoderange: (function() { + var ret + + injectElementWithStyle( + '@font-face{font-family:test-for-unicode-range;src:local(Arial),local("Droid Sans")}@font-face{font-family:test-for-unicode-range;src:local("Times New Roman"),local(Times),local("Droid Serif");unicode-range:U+270C}', + function() { + ret = !Locale.detectFont( + 'test-for-unicode-range', // treatment group + 'Arial, "Droid Sans"', // control group + 'Q' // ASCII characters only + ) + } + ) + return ret + })(), + + writingmode: testCSSProp( 'writingMode' ) + } +})() + +Locale.initCond = function( target ) { + var target = target || root + var ret = '' + var clazz + + for ( var feature in Locale.support ) { + clazz = ( Locale.support[ feature ] ? '' : 'no-' ) + feature + + target.classList.add( clazz ) + ret += clazz + ' ' + } + return ret +} + +var SUPPORT_IC = Locale.support[ 'ruby-interchar' ] + +// 1. Simple ruby polyfill; +// 2. Inter-character polyfill for Zhuyin +function renderSimpleRuby( $ruby ) { + var frag = $.create( '!' ) + var clazz = $ruby.classList + var $rb, $ru + + frag.appendChild( $.clone( $ruby )) + + $ + .tag( 'rt', frag.firstChild ) + .forEach(function( $rt ) { + var $rb = $.create( '!' ) + var airb = [] + var irb + + // Consider the previous nodes the implied + // ruby base + do { + irb = ( irb || $rt ).previousSibling + if ( !irb || irb.nodeName.match( /((?:h\-)?r[ubt])/i )) break + + $rb.insertBefore( $.clone( irb ), $rb.firstChild ) + airb.push( irb ) + } while ( !irb.nodeName.match( /((?:h\-)?r[ubt])/i )) + + // Create a real `` to append. + $ru = clazz.contains( 'zhuyin' ) ? createZhuyinRu( $rb, $rt ) : createNormalRu( $rb, $rt ) + + // Replace the ruby text with the new ``, + // and remove the original implied ruby base(s) + try { + $rt.parentNode.replaceChild( $ru, $rt ) + airb.map( $.remove ) + } catch ( e ) {} + }) + return createCustomRuby( frag ) +} + +function renderInterCharRuby( $ruby ) { + var frag = $.create( '!' ) + frag.appendChild( $.clone( $ruby )) + + $ + .tag( 'rt', frag.firstChild ) + .forEach(function( $rt ) { + var $rb = $.create( '!' ) + var airb = [] + var irb, $zhuyin + + // Consider the previous nodes the implied + // ruby base + do { + irb = ( irb || $rt ).previousSibling + if ( !irb || irb.nodeName.match( /((?:h\-)?r[ubt])/i )) break + + $rb.insertBefore( $.clone( irb ), $rb.firstChild ) + airb.push( irb ) + } while ( !irb.nodeName.match( /((?:h\-)?r[ubt])/i )) + + $zhuyin = $.create( 'rt' ) + $zhuyin.innerHTML = getZhuyinHTML( $rt ) + $rt.parentNode.replaceChild( $zhuyin, $rt ) + }) + return frag.firstChild +} + +// 3. Complex ruby polyfill +// - Double-lined annotation; +// - Right-angled annotation. +function renderComplexRuby( $ruby ) { + var frag = $.create( '!' ) + var clazz = $ruby.classList + var $cloned, $rb, $ru, maxspan + + frag.appendChild( $.clone( $ruby )) + $cloned = frag.firstChild + + $rb = $ru = $.tag( 'rb', $cloned ) + maxspan = $rb.length + + // First of all, deal with Zhuyin containers + // individually + // + // Note that we only support one single Zhuyin + // container in each complex ruby + void function( $rtc ) { + if ( !$rtc ) return + + $ru = $ + .tag( 'rt', $rtc ) + .map(function( $rt, i ) { + if ( !$rb[ i ] ) return + var ret = createZhuyinRu( $rb[ i ], $rt ) + + try { + $rb[ i ].parentNode.replaceChild( ret, $rb[ i ] ) + } catch ( e ) {} + return ret + }) + + // Remove the container once it's useless + $.remove( $rtc ) + $cloned.setAttribute( 'rightangle', 'true' ) + }( $cloned.querySelector( 'rtc.zhuyin' )) + + // Then, normal annotations other than Zhuyin + $ + .qsa( 'rtc:not(.zhuyin)', $cloned ) + .forEach(function( $rtc, order ) { + var ret + ret = $ + .tag( 'rt', $rtc ) + .map(function( $rt, i ) { + var rbspan = Number( $rt.getAttribute( 'rbspan' ) || 1 ) + var span = 0 + var aRb = [] + var $rb, ret + + if ( rbspan > maxspan ) rbspan = maxspan + + do { + try { + $rb = $ru.shift() + aRb.push( $rb ) + } catch (e) {} + + if ( typeof $rb === 'undefined' ) break + span += Number( $rb.getAttribute( 'span' ) || 1 ) + } while ( rbspan > span ) + + if ( rbspan < span ) { + if ( aRb.length > 1 ) { + console.error( 'An impossible `rbspan` value detected.', ruby ) + return + } + aRb = $.tag( 'rb', aRb[0] ) + $ru = aRb.slice( rbspan ).concat( $ru ) + aRb = aRb.slice( 0, rbspan ) + span = rbspan + } + + ret = createNormalRu( aRb, $rt, { + 'class': clazz, + span: span, + order: order + }) + + try { + aRb[0].parentNode.replaceChild( ret, aRb.shift() ) + aRb.map( $.remove ) + } catch (e) {} + return ret + }) + $ru = ret + if ( order === 1 ) $cloned.setAttribute( 'doubleline', 'true' ) + + // Remove the container once it's useless + $.remove( $rtc ) + }) + return createCustomRuby( frag ) +} + +// Create a new fake `` element so the +// style sheets will render it as a polyfill, +// which also helps to avoid the UA style. +function createCustomRuby( frag ) { + var $ruby = frag.firstChild + var hruby = $.create( 'h-ruby' ) + + hruby.innerHTML = $ruby.innerHTML + $.setAttr( hruby, $ruby.attributes ) + hruby.normalize() + return hruby +} + +function simplifyRubyClass( elem ) { + if ( !elem instanceof Element ) return elem + var clazz = elem.classList + + if ( clazz.contains( 'pinyin' )) clazz.add( 'romanization' ) + else if ( clazz.contains( 'romanization' )) clazz.add( 'annotation' ) + else if ( clazz.contains( 'mps' )) clazz.add( 'zhuyin' ) + else if ( clazz.contains( 'rightangle' )) clazz.add( 'complex' ) + return elem +} + +/** + * Create and return a new `` element + * according to the given contents + */ +function createNormalRu( $rb, $rt, attr ) { + var $ru = $.create( 'h-ru' ) + var $rt = $.clone( $rt ) + var attr = attr || {} + attr.annotation = 'true' + + if ( Array.isArray( $rb )) { + $ru.innerHTML = $rb.map(function( rb ) { + if ( typeof rb === 'undefined' ) return '' + return rb.outerHTML + }).join('') + $rt.outerHTML + } else { + $ru.appendChild( $.clone( $rb )) + $ru.appendChild( $rt ) + } + + $.setAttr( $ru, attr ) + return $ru +} + +/** + * Create and return a new `` element + * in Zhuyin form + */ +function createZhuyinRu( $rb, $rt ) { + var $rb = $.clone( $rb ) + + // Create an element to return + var $ru = $.create( 'h-ru' ) + $ru.setAttribute( 'zhuyin', true ) + + // - + // - + // - + // - + // - + // - + // - + $ru.appendChild( $rb ) + $ru.innerHTML += getZhuyinHTML( $rt ) + return $ru +} + +/** + * Create a Zhuyin-form HTML string + */ +function getZhuyinHTML( rt ) { + // #### Explanation #### + // * `zhuyin`: the entire phonetic annotation + // * `yin`: the plain pronunciation (w/out tone) + // * `diao`: the tone + // * `len`: the length of the plain pronunciation (`yin`) + var zhuyin = typeof rt === 'string' ? rt : rt.textContent + var yin, diao, len + + yin = zhuyin.replace( TYPESET.zhuyin.diao, '' ) + len = yin ? yin.length : 0 + diao = zhuyin + .replace( yin, '' ) + .replace( /[\u02C5]/g, '\u02C7' ) + .replace( /[\u030D]/g, '\u0358' ) + return len === 0 ? '' : '' + yin + '' + diao + '' +} + +/** + * Normalize `ruby` elements + */ +$.extend( Locale, { + + // Address normalisation for both simple and complex + // rubies (interlinear annotations) + renderRuby: function( context, target ) { + var target = target || 'ruby' + var $target = $.qsa( target, context ) + + $.qsa( 'rtc', context ) + .concat( $target ).map( simplifyRubyClass ) + + $target + .forEach(function( $ruby ) { + var clazz = $ruby.classList + var $new + + if ( clazz.contains( 'complex' )) $new = renderComplexRuby( $ruby ) + else if ( clazz.contains( 'zhuyin' )) $new = SUPPORT_IC ? renderInterCharRuby( $ruby ) : renderSimpleRuby( $ruby ) + + // Finally, replace it + if ( $new ) $ruby.parentNode.replaceChild( $new, $ruby ) + }) + }, + + simplifyRubyClass: simplifyRubyClass, + getZhuyinHTML: getZhuyinHTML, + renderComplexRuby: renderComplexRuby, + renderSimpleRuby: renderSimpleRuby, + renderInterCharRuby: renderInterCharRuby + + // ### TODO list ### + // + // * Debug mode + // * Better error-tolerance +}) + +/** + * Normalisation rendering mechanism + */ +$.extend( Locale, { + + // Render and normalise the given context by routine: + // + // ruby -> u, ins -> s, del -> em + // + renderElem: function( context ) { + this.renderRuby( context ) + this.renderDecoLine( context ) + this.renderDecoLine( context, 's, del' ) + this.renderEm( context ) + }, + + // Traverse all target elements and address + // presentational corrections if any two of + // them are adjacent to each other. + renderDecoLine: function( context, target ) { + var $$target = $.qsa( target || 'u, ins', context ) + var i = $$target.length + + traverse: while ( i-- ) { + var $this = $$target[ i ] + var $prev = null + + // Ignore all `` and comments in between, + // and add class `.adjacent` once two targets + // are next to each other. + ignore: do { + $prev = ( $prev || $this ).previousSibling + + if ( !$prev ) { + continue traverse + } else if ( $$target[ i-1 ] === $prev ) { + $this.classList.add( 'adjacent' ) + } + } while ( $.isIgnorable( $prev )) + } + }, + + // Traverse all target elements to render + // emphasis marks. + renderEm: function( context, target ) { + var method = target ? 'qsa' : 'tag' + var target = target || 'em' + var $target = $[ method ]( target, context ) + + $target + .forEach(function( elem ) { + var $elem = Han( elem ) + + if ( Locale.support.textemphasis ) { + $elem + .avoid( 'rt, h-char' ) + .charify({ biaodian: true, punct: true }) + } else { + $elem + .avoid( 'rt, h-char, h-char-group' ) + .jinzify() + .groupify({ western: true }) + .charify({ + hanzi: true, + biaodian: true, + punct: true, + latin: true, + ellinika: true, + kirillica: true + }) + } + }) + } +}) + +Han.normalize = Locale +Han.localize = Locale +Han.support = Locale.support +Han.detectFont = Locale.detectFont + +Han.fn.initCond = function() { + this.condition.classList.add( 'han-js-rendered' ) + Han.normalize.initCond( this.condition ) + return this +} + +void [ + 'Elem', + 'DecoLine', + 'Em', + 'Ruby' +].forEach(function( elem ) { + var method = 'render' + elem + + Han.fn[ method ] = function( target ) { + Han.normalize[ method ]( this.context, target ) + return this + } +}) + +$.extend( Han.support, { + // Assume that all devices support Heiti for we + // use `sans-serif` to do the comparison. + heiti: true, + // 'heiti-gb': true, + + songti: Han.detectFont( '"Han Songti"' ), + 'songti-gb': Han.detectFont( '"Han Songti GB"' ), + + kaiti: Han.detectFont( '"Han Kaiti"' ), + // 'kaiti-gb': Han.detectFont( '"Han Kaiti GB"' ), + + fangsong: Han.detectFont( '"Han Fangsong"' ) + // 'fangsong-gb': Han.detectFont( '"Han Fangsong GB"' ) +}) + +Han.correctBiaodian = function( context ) { + var context = context || document + var finder = Han.find( context ) + + finder + .avoid( 'h-char' ) + .replace( /([‘“])/g, function( portion ) { + var $char = Han.createBDChar( portion.text ) + $char.classList.add( 'bd-open', 'punct' ) + return $char + }) + .replace( /([’”])/g, function( portion ) { + var $char = Han.createBDChar( portion.text ) + $char.classList.add( 'bd-close', 'bd-end', 'punct' ) + return $char + }) + + return Han.support.unicoderange + ? finder + : finder.charify({ biaodian: true }) +} + +Han.correctBasicBD = Han.correctBiaodian +Han.correctBD = Han.correctBiaodian + +$.extend( Han.fn, { + biaodian: null, + + correctBiaodian: function() { + this.biaodian = Han.correctBiaodian( this.context ) + return this + }, + + revertCorrectedBiaodian: function() { + try { + this.biaodian.revert( 'all' ) + } catch (e) {} + return this + } +}) + +// Legacy support (deprecated): +Han.fn.correctBasicBD = Han.fn.correctBiaodian +Han.fn.revertBasicBD = Han.fn.revertCorrectedBiaodian + +var hws = '<>' + +var $hws = $.create( 'h-hws' ) +$hws.setAttribute( 'hidden', '' ) +$hws.innerHTML = ' ' + +function sharingSameParent( $a, $b ) { + return $a && $b && $a.parentNode === $b.parentNode +} + +function properlyPlaceHWSBehind( $node, text ) { + var $elmt = $node + var text = text || '' + + if ( + $.isElmt( $node.nextSibling ) || + sharingSameParent( $node, $node.nextSibling ) + ) { + return text + hws + } else { + // One of the parental elements of the current text + // node would definitely have a next sibling, since + // it is of the first portion and not `isEnd`. + while ( !$elmt.nextSibling ) { + $elmt = $elmt.parentNode + } + if ( $node !== $elmt ) { + $elmt.insertAdjacentHTML( 'afterEnd', '' ) + } + } + return text +} + +function firstStepLabel( portion, mat ) { + return portion.isEnd && portion.index === 0 + ? mat[1] + hws + mat[2] + : portion.index === 0 + ? properlyPlaceHWSBehind( portion.node, portion.text ) + : portion.text +} + +function real$hwsElmt( portion ) { + return portion.index === 0 + ? $.clone( $hws ) + : '' +} + +var last$hwsIdx + +function apostrophe( portion ) { + var $elmt = portion.node.parentNode + + if ( portion.index === 0 ) { + last$hwsIdx = portion.endIndexInNode-2 + } + + if ( + $elmt.nodeName.toLowerCase() === 'h-hws' && ( + portion.index === 1 || portion.indexInMatch === last$hwsIdx + )) { + $elmt.classList.add( 'quote-inner' ) + } + return portion.text +} + +function curveQuote( portion ) { + var $elmt = portion.node.parentNode + + if ( $elmt.nodeName.toLowerCase() === 'h-hws' ) { + $elmt.classList.add( 'quote-outer' ) + } + return portion.text +} + +$.extend( Han, { + renderHWS: function( context, strict ) { + // Elements to be filtered according to the + // HWS rendering mode. + var AVOID = strict + ? 'textarea, code, kbd, samp, pre' + : 'textarea' + + var mode = strict ? 'strict' : 'base' + var context = context || document + var finder = Han.find( context ) + + finder + .avoid( AVOID ) + + // Basic situations: + // - 字a => 字a + // - A字 => A字 + .replace( Han.TYPESET.hws[ mode ][0], firstStepLabel ) + .replace( Han.TYPESET.hws[ mode ][1], firstStepLabel ) + + // Convert text nodes `` into real element nodes: + .replace( new RegExp( '(' + hws + ')+', 'g' ), real$hwsElmt ) + + // Deal with: + // - '' => '字' + // - "" => "字" + .replace( /([\'"])\s(.+?)\s\1/g, apostrophe ) + + // Deal with: + // - “字” + // - ‘字’ + .replace( /\s[‘“]/g, curveQuote ) + .replace( /[’”]\s/g, curveQuote ) + .normalize() + + // Return the finder instance for future usage + return finder + } +}) + +$.extend( Han.fn, { + renderHWS: function( strict ) { + Han.renderHWS( this.context, strict ) + return this + }, + + revertHWS: function() { + $.tag( 'h-hws', this.context ) + .forEach(function( hws ) { + $.remove( hws ) + }) + this.HWS = [] + return this + } +}) + +var HANGABLE_CLASS = 'bd-hangable' +var HANGABLE_AVOID = 'h-char.bd-hangable' +var HANGABLE_CS_HTML = '' + +var matches = Han.find.matches + +function detectSpaceFont() { + var div = $.create( 'div' ) + var ret + + div.innerHTML = 'a ba b' + body.appendChild( div ) + ret = div.firstChild.offsetWidth !== div.lastChild.offsetWidth + $.remove( div ) + return ret +} + +function insertHangableCS( $jinze ) { + var $cs = $jinze.nextSibling + + if ( $cs && matches( $cs, 'h-cs.jinze-outer' )) { + $cs.classList.add( 'hangable-outer' ) + } else { + $jinze.insertAdjacentHTML( + 'afterend', + HANGABLE_CS_HTML + ) + } +} + +Han.support['han-space'] = detectSpaceFont() + +$.extend( Han, { + detectSpaceFont: detectSpaceFont, + isSpaceFontLoaded: detectSpaceFont(), + + renderHanging: function( context ) { + var context = context || document + var finder = Han.find( context ) + + finder + .avoid( 'textarea, code, kbd, samp, pre' ) + .avoid( HANGABLE_AVOID ) + .replace( + TYPESET.jinze.hanging, + function( portion ) { + if ( /^[\x20\t\r\n\f]+$/.test( portion.text )) { + return '' + } + + var $elmt = portion.node.parentNode + var $jinze, $new, $bd, biaodian + + if ( $jinze = $.parent( $elmt, 'h-jinze' )) { + insertHangableCS( $jinze ) + } + + biaodian = portion.text.trim() + + $new = Han.createBDChar( biaodian ) + $new.innerHTML = '' + biaodian + '' + $new.classList.add( HANGABLE_CLASS ) + + $bd = $.parent( $elmt, 'h-char.biaodian' ) + + return !$bd + ? $new + : (function() { + $bd.classList.add( HANGABLE_CLASS ) + + return matches( $elmt, 'h-inner, h-inner *' ) + ? biaodian + : $new.firstChild + })() + } + ) + return finder + } +}) + +$.extend( Han.fn, { + renderHanging: function() { + var classList = this.condition.classList + Han.isSpaceFontLoaded = detectSpaceFont() + + if ( + Han.isSpaceFontLoaded && + classList.contains( 'no-han-space' ) + ) { + classList.remove( 'no-han-space' ) + classList.add( 'han-space' ) + } + + Han.renderHanging( this.context ) + return this + }, + + revertHanging: function() { + $.qsa( + 'h-char.bd-hangable, h-cs.hangable-outer', + this.context + ).forEach(function( $elmt ) { + var classList = $elmt.classList + classList.remove( 'bd-hangable' ) + classList.remove( 'hangable-outer' ) + }) + return this + } +}) + +var JIYA_CLASS = 'bd-jiya' +var JIYA_AVOID = 'h-char.bd-jiya' +var CONSECUTIVE_CLASS = 'bd-consecutive' +var JIYA_CS_HTML = '' + +var matches = Han.find.matches + +function trimBDClass( clazz ) { + return clazz.replace( + /(biaodian|cjk|bd-jiya|bd-consecutive|bd-hangable)/gi, '' + ).trim() +} + +function charifyBiaodian( portion ) { + var biaodian = portion.text + var $elmt = portion.node.parentNode + var $bd = $.parent( $elmt, 'h-char.biaodian' ) + var $new = Han.createBDChar( biaodian ) + var $jinze + + $new.innerHTML = '' + biaodian + '' + $new.classList.add( JIYA_CLASS ) + + if ( $jinze = $.parent( $elmt, 'h-jinze' )) { + insertJiyaCS( $jinze ) + } + + return !$bd + ? $new + : (function() { + $bd.classList.add( JIYA_CLASS ) + + return matches( $elmt, 'h-inner, h-inner *' ) + ? biaodian + : $new.firstChild + })() +} + +var prevBDType, $$prevCS + +function locateConsecutiveBD( portion ) { + var prev = prevBDType + var $elmt = portion.node.parentNode + var $bd = $.parent( $elmt, 'h-char.biaodian' ) + var $jinze = $.parent( $bd, 'h-jinze' ) + var classList + + classList = $bd.classList + + if ( prev ) { + $bd.setAttribute( 'prev', prev ) + } + + if ( $$prevCS && classList.contains( 'bd-open' )) { + $$prevCS.pop().setAttribute( 'next', 'bd-open' ) + } + + $$prevCS = undefined + + if ( portion.isEnd ) { + prevBDType = undefined + classList.add( CONSECUTIVE_CLASS, 'end-portion' ) + } else { + prevBDType = trimBDClass($bd.getAttribute( 'class' )) + classList.add( CONSECUTIVE_CLASS ) + } + + if ( $jinze ) { + $$prevCS = locateCS( $jinze, { + prev: prev, + 'class': trimBDClass($bd.getAttribute( 'class' )) + }) + } + return portion.text +} + +function insertJiyaCS( $jinze ) { + if ( + matches( $jinze, '.tou, .touwei' ) && + !matches( $jinze.previousSibling, 'h-cs.jiya-outer' ) + ) { + $jinze.insertAdjacentHTML( 'beforebegin', JIYA_CS_HTML ) + } + if ( + matches( $jinze, '.wei, .touwei' ) && + !matches( $jinze.nextSibling, 'h-cs.jiya-outer' ) + ) { + $jinze.insertAdjacentHTML( 'afterend', JIYA_CS_HTML ) + } +} + +function locateCS( $jinze, attr ) { + var $prev, $next + + if (matches( $jinze, '.tou, .touwei' )) { + $prev = $jinze.previousSibling + + if (matches( $prev, 'h-cs' )) { + $prev.className = 'jinze-outer jiya-outer' + $prev.setAttribute( 'prev', attr.prev ) + } + } + if (matches( $jinze, '.wei, .touwei' )) { + $next = $jinze.nextSibling + + if (matches( $next, 'h-cs' )) { + $next.className = 'jinze-outer jiya-outer ' + attr[ 'class' ] + $next.removeAttribute( 'prev' ) + } + } + return [ $prev, $next ] +} + +Han.renderJiya = function( context ) { + var context = context || document + var finder = Han.find( context ) + + finder + .avoid( 'textarea, code, kbd, samp, pre, h-cs' ) + + .avoid( JIYA_AVOID ) + .charify({ + avoid: false, + biaodian: charifyBiaodian + }) + // End avoiding `JIYA_AVOID`: + .endAvoid() + + .avoid( 'textarea, code, kbd, samp, pre, h-cs' ) + .replace( TYPESET.group.biaodian[0], locateConsecutiveBD ) + .replace( TYPESET.group.biaodian[1], locateConsecutiveBD ) + + return finder +} + +$.extend( Han.fn, { + renderJiya: function() { + Han.renderJiya( this.context ) + return this + }, + + revertJiya: function() { + $.qsa( + 'h-char.bd-jiya, h-cs.jiya-outer', + this.context + ).forEach(function( $elmt ) { + var classList = $elmt.classList + classList.remove( 'bd-jiya' ) + classList.remove( 'jiya-outer' ) + }) + return this + } +}) + +var QUERY_RU_W_ANNO = 'h-ru[annotation]' +var SELECTOR_TO_IGNORE = 'textarea, code, kbd, samp, pre' + +function createCompareFactory( font, treat, control ) { + return function() { + var a = Han.localize.writeOnCanvas( treat, font ) + var b = Han.localize.writeOnCanvas( control, font ) + return Han.localize.compareCanvases( a, b ) + } +} + +function isVowelCombLigaNormal() { + return createCompareFactory( '"Romanization Sans"', '\u0061\u030D', '\uDB80\uDC61' ) +} + +function isVowelICombLigaNormal() { + return createCompareFactory( '"Romanization Sans"', '\u0069\u030D', '\uDB80\uDC69' ) +} + +function isZhuyinCombLigaNormal() { + return createCompareFactory( '"Zhuyin Kaiti"', '\u31B4\u0358', '\uDB8C\uDDB4' ) +} + +function createSubstFactory( regexToSubst ) { + return function( context ) { + var context = context || document + var finder = Han.find( context ).avoid( SELECTOR_TO_IGNORE ) + + regexToSubst + .forEach(function( pattern ) { + finder + .replace( + new RegExp( pattern[ 0 ], 'ig' ), + function( portion, match ) { + var ret = $.clone( charCombLiga ) + + // Put the original content in an inner container + // for better presentational effect of hidden text + ret.innerHTML = '' + match[0] + '' + ret.setAttribute( 'display-as', pattern[ 1 ] ) + return portion.index === 0 ? ret : '' + } + ) + }) + return finder + } +} + +var charCombLiga = $.create( 'h-char', 'comb-liga' ) + +$.extend( Han, { + isVowelCombLigaNormal: isVowelCombLigaNormal(), + isVowelICombLigaNormal: isVowelICombLigaNormal(), + isZhuyinCombLigaNormal: isZhuyinCombLigaNormal(), + + isCombLigaNormal: isVowelICombLigaNormal()(), // ### Deprecated + + substVowelCombLiga: createSubstFactory( Han.TYPESET[ 'display-as' ][ 'comb-liga-vowel' ] ), + substZhuyinCombLiga: createSubstFactory( Han.TYPESET[ 'display-as' ][ 'comb-liga-zhuyin' ] ), + substCombLigaWithPUA: createSubstFactory( Han.TYPESET[ 'display-as' ][ 'comb-liga-pua' ] ), + + substInaccurateChar: function( context ) { + var context = context || document + var finder = Han.find( context ) + + finder.avoid( SELECTOR_TO_IGNORE ) + + Han.TYPESET[ 'inaccurate-char' ] + .forEach(function( pattern ) { + finder + .replace( + new RegExp( pattern[ 0 ], 'ig' ), + pattern[ 1 ] + ) + }) + } +}) + +$.extend( Han.fn, { + 'comb-liga-vowel': null, + 'comb-liga-vowel-i': null, + 'comb-liga-zhuyin': null, + 'inaccurate-char': null, + + substVowelCombLiga: function() { + this['comb-liga-vowel'] = Han.substVowelCombLiga( this.context ) + return this + }, + + substVowelICombLiga: function() { + this['comb-liga-vowel-i'] = Han.substVowelICombLiga( this.context ) + return this + }, + + substZhuyinCombLiga: function() { + this['comb-liga-zhuyin'] = Han.substZhuyinCombLiga( this.context ) + return this + }, + + substCombLigaWithPUA: function() { + if ( !Han.isVowelCombLigaNormal()) { + this['comb-liga-vowel'] = Han.substVowelCombLiga( this.context ) + } else if ( !Han.isVowelICombLigaNormal()) { + this['comb-liga-vowel-i'] = Han.substVowelICombLiga( this.context ) + } + + if ( !Han.isZhuyinCombLigaNormal()) { + this['comb-liga-zhuyin'] = Han.substZhuyinCombLiga( this.context ) + } + return this + }, + + revertVowelCombLiga: function() { + try { + this['comb-liga-vowel'].revert( 'all' ) + } catch (e) {} + return this + }, + + revertVowelICombLiga: function() { + try { + this['comb-liga-vowel-i'].revert( 'all' ) + } catch (e) {} + return this + }, + + revertZhuyinCombLiga: function() { + try { + this['comb-liga-zhuyin'].revert( 'all' ) + } catch (e) {} + return this + }, + + revertCombLigaWithPUA: function() { + try { + this['comb-liga-vowel'].revert( 'all' ) + this['comb-liga-vowel-i'].revert( 'all' ) + this['comb-liga-zhuyin'].revert( 'all' ) + } catch (e) {} + return this + }, + + substInaccurateChar: function() { + this['inaccurate-char'] = Han.substInaccurateChar( this.context ) + return this + }, + + revertInaccurateChar: function() { + try { + this['inaccurate-char'].revert( 'all' ) + } catch (e) {} + return this + } +}) + +window.addEventListener( 'DOMContentLoaded', function() { + var initContext + + // Use the shortcut under the default situation + if ( root.classList.contains( 'han-init' )) { + Han.init() + + // Consider ‘a configured context’ the special + // case of the default situation. Will have to + // replace the `Han.init` with the instance as + // well (for future usage). + } else if ( initContext = document.querySelector( '.han-init-context' )) { + Han.init = Han( initContext ).render() + } +}) + +// Expose to global namespace +if ( typeof noGlobalNS === 'undefined' || noGlobalNS === false ) { + window.Han = Han +} + +return Han +}); + diff --git a/lib/Han/dist/han.min.css b/lib/Han/dist/han.min.css new file mode 100644 index 0000000..39ce287 --- /dev/null +++ b/lib/Han/dist/han.min.css @@ -0,0 +1,6 @@ +@charset "UTF-8"; + +/*! 漢字標準格式 v3.3.0 | MIT License | css.hanzi.co */ +/*! Han.css: the CSS typography framework optimised for Hanzi */ + +progress,sub,sup{vertical-align:baseline}button,hr,input,select{overflow:visible}[type=checkbox],[type=radio],legend{box-sizing:border-box;padding:0}pre,textarea{overflow:auto}[zhuyin] [length="0"],article blockquote,article blockquote blockquote{margin-right:0}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent;text-decoration:inherit}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}button,input,select,textarea{font:inherit;margin:0}optgroup{font-weight:700}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{cursor:pointer}[disabled]{cursor:default}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button:-moz-focusring,input:-moz-focusring{outline:ButtonText dotted 1px}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{color:inherit;display:table;max-width:100%;white-space:normal}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}html{line-height:1.3;-webkit-font-smoothing:subpixel-antialiased}ol,ul{padding-left:2em}blockquote,figure{margin-left:2em;margin-right:2em}address,cite:lang(ja),cite:lang(zh),i:lang(ja),i:lang(zh),var:lang(ja),var:lang(zh){font-style:inherit}pre{white-space:pre;word-wrap:normal}em:lang(ja),em:lang(zh){-moz-text-emphasis:filled circle;-webkit-text-emphasis:filled circle;text-emphasis:filled circle;-moz-text-emphasis-position:under;-webkit-text-emphasis-position:under;text-emphasis-position:under;font-style:inherit;border-bottom:2px dotted;padding-bottom:.05em;border-bottom-width:-webkit-calc(0px);padding-bottom:-webkit-calc(0px)}em:lang(ja){-moz-text-emphasis:filled sesame;-webkit-text-emphasis:filled sesame;text-emphasis:filled sesame;-moz-text-emphasis-position:over;-webkit-text-emphasis-position:over;text-emphasis-position:over}dfn:lang(ja),dfn:lang(zh){font-style:inherit;font-weight:bolder}q,q:lang(en),q:lang(zh-CN){quotes:"\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019"}q:lang(zh){quotes:"\300c" "\300d" "\300e" "\300f" "\300c" "\300d" "\300e" "\300f" "\300c" "\300d" "\300e" "\300f"}q:lang(en-GB){quotes:"\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d"}q:before{content:open-quote}q:after{content:close-quote}q:lang(ja):after,q:lang(ja):before{content:none}code,kbd,pre,samp{font-family:monospace,monospace,sans-serif}.han-js-rendered del+del.adjacent,.han-js-rendered del+s.adjacent,.han-js-rendered ins.adjacent,.han-js-rendered s+del.adjacent,.han-js-rendered s+s.adjacent,.han-js-rendered u.adjacent,del+del,del+s,ins+ins,ins+u,s+del,s+s,u+ins,u+u{margin-left:.125em}ins,u{padding-bottom:.05em;border-bottom:1px solid;text-decoration:none}ruby rtc rt{display:inline;font-size:inherit}ruby.mps,ruby.zhuyin{display:ruby;-webkit-ruby-position:inter-character;ruby-position:inter-character}ruby.mps>rt,ruby.zhuyin>rt{-moz-transform:scale(.8);-ms-transform:scale(.8);-webkit-transform:scale(.8);transform:scale(.8);-moz-transform-origin:left center;-ms-transform-origin:left center;-webkit-transform-origin:left center;transform-origin:left center;font-size:.5em}ruby.mps>rt:empty,ruby.zhuyin>rt:empty{display:none}.han-js-rendered del+del,.han-js-rendered del+s,.han-js-rendered ins+ins,.han-js-rendered ins+u,.han-js-rendered s+del,.han-js-rendered s+s,.han-js-rendered u+ins,.han-js-rendered u+u{margin-left:auto}.textemphasis $han-text-emphasis-pf h-jinze,.textemphasis em:lang(ja) h-jinze,.textemphasis em:lang(zh) h-jinze{display:inline}.han-js-rendered em:lang(ja),.han-js-rendered em:lang(zh){padding-bottom:auto;border-bottom-width:0}.no-textemphasis em:lang(ja),.no-textemphasis em:lang(zh){line-height:2}.no-textemphasis em:lang(ja) h-char,.no-textemphasis em:lang(zh) h-char{position:relative;font-style:inherit}.no-textemphasis em:lang(ja) h-char:after,.no-textemphasis em:lang(zh) h-char:after,[zhuyin] h-zhuyin{font-style:normal;font-weight:400;-moz-text-emphasis:none;-webkit-text-emphasis:none;text-emphasis:none;text-decoration:none;text-indent:0}.no-textemphasis em:lang(ja) h-char:after,.no-textemphasis em:lang(zh) h-char:after{-moz-transform:scale(.5);-ms-transform:scale(.5);-webkit-transform:scale(.5);transform:scale(.5);position:absolute;left:50%;top:0;margin-left:-250%;overflow:hidden;display:inline-block;height:1em;width:500%;line-height:1;text-align:center;font-family:Georgia,"Times New Roman",Arial ,!important}em:lang(ja) h-char.biaodian,em:lang(ja) h-char.punct,em:lang(zh) h-char.biaodian,em:lang(zh) h-char.punct{-moz-text-emphasis:none;-webkit-text-emphasis:none;text-emphasis:none}.no-textemphasis em:lang(ja) h-char.biaodian:after,.no-textemphasis em:lang(ja) h-char.punct:after,.no-textemphasis em:lang(zh) h-char.biaodian:after,.no-textemphasis em:lang(zh) h-char.punct:after{content:none!important}.no-textemphasis em:lang(zh) h-char:after{margin-top:1em;content:"\25cf"}.no-textemphasis em:lang(ja) h-char:after{margin-top:-.7em;content:"\fe45"}h-ruby.zhuyin h-zhuyin,ruby.mps h-zhuyin,ruby.zhuyin h-zhuyin{position:relative;letter-spacing:0}h-ruby.zhuyin h-diao,ruby.mps h-diao,ruby.zhuyin h-diao{position:absolute;right:-.9em;bottom:.5em;display:block;font-size:1.5em}h-ruby.zhuyin h-diao h-char,ruby.mps h-diao h-char,ruby.zhuyin h-diao h-char{-webkit-writing-mode:horizontal-tb;writing-mode:horizontal-tb}h-ruby.zhuyin [diao="˙"] h-diao,ruby.mps [diao="˙"] h-diao,ruby.zhuyin [diao="˙"] h-diao{top:-.3em;right:auto;bottom:auto;left:0;font-size:1em}h-ruby.zhuyin [diao="󳆴"] h-diao,h-ruby.zhuyin [diao="󳆵"] h-diao,h-ruby.zhuyin [diao="󳆶"] h-diao,h-ruby.zhuyin [diao="󳆷"] h-diao,h-ruby.zhuyin [diao^="ㆴ"] h-diao,h-ruby.zhuyin [diao^="ㆵ"] h-diao,h-ruby.zhuyin [diao^="ㆶ"] h-diao,h-ruby.zhuyin [diao^="ㆷ"] h-diao,ruby.mps [diao="󳆴"] h-diao,ruby.mps [diao="󳆵"] h-diao,ruby.mps [diao="󳆶"] h-diao,ruby.mps [diao="󳆷"] h-diao,ruby.mps [diao^="ㆴ"] h-diao,ruby.mps [diao^="ㆵ"] h-diao,ruby.mps [diao^="ㆶ"] h-diao,ruby.mps [diao^="ㆷ"] h-diao,ruby.zhuyin [diao="󳆴"] h-diao,ruby.zhuyin [diao="󳆵"] h-diao,ruby.zhuyin [diao="󳆶"] h-diao,ruby.zhuyin [diao="󳆷"] h-diao,ruby.zhuyin [diao^="ㆴ"] h-diao,ruby.zhuyin [diao^="ㆵ"] h-diao,ruby.zhuyin [diao^="ㆶ"] h-diao,ruby.zhuyin [diao^="ㆷ"] h-diao{right:-1em;bottom:-.125em;font-size:1em}h-ru[annotation]{position:relative;display:inline-table;border-collapse:collapse;border-spacing:0;line-height:1.1;text-align:center;vertical-align:1em}h-ru[annotation]>rt,h-ru[order="0"]>rt,h-ruby[rightangle][doubleline] h-ru[order="0"]>rt{display:table-header-group}h-ru[annotation]>h-ru[annotation]{vertical-align:-.1em}h-ru[annotation]>h-ru,h-ru[annotation]>rb,h-ru[annotation]>rt{line-height:1;text-align:center}h-ru[annotation]>rt{height:1em;font-size:.5em;white-space:nowrap;word-break:normal}h-ru[annotation]>rt:after,h-ru[annotation]>rt:before{content:"\2006"}h-ru[order="1"]>rt,h-ruby[rightangle] h-ru[order="0"]>rt,h-ruby[rightangle][doubleline] h-ru[order="1"]>rt{display:table-footer-group}[zhuyin],[zhuyin] h-zhuyin,[zhuyin] h-zhuyin>*,h-jinze,h-word{display:inline-block}h-ru[order="0"]>h-ru[order="1"]{vertical-align:.15em}h-ruby[rightangle][doubleline] h-ru[order="0"] rt{line-height:1.5}h-ruby[rightangle][doubleline] h-ru[annotation]{vertical-align:.5em}[zhuyin] h-zhuyin{line-height:normal;position:relative;height:1em;width:.4em;vertical-align:text-top}[zhuyin] h-zhuyin>*{-moz-transform:scale(.4);-ms-transform:scale(.4);-webkit-transform:scale(.4);transform:scale(.4);-moz-transform-origin:left top;-ms-transform-origin:left top;-webkit-transform-origin:left top;transform-origin:left top}[zhuyin] h-yin{position:absolute;left:0;height:1em;vertical-align:top;line-height:1}[zhuyin] h-diao{position:absolute;bottom:0;right:-.9em;line-height:1}[zhuyin] [length="0"] h-zhuyin,[zhuyin] h-diao:empty,[zhuyin] h-yin:empty{display:none}[zhuyin] [length="1"] h-yin{top:.3em}[zhuyin] [length="1"] h-diao{bottom:0}[zhuyin] [length="2"] h-yin{top:.05em}[zhuyin] [length="2"] h-diao{bottom:-.3em}[zhuyin] [length="3"] h-yin{top:-.05em;line-height:.85}[zhuyin] [length="3"] h-diao{bottom:-.35em}[zhuyin] [diao="˙"] h-diao{top:0;right:auto;bottom:auto;left:.06em}[zhuyin] [diao="˙"] [length="1"] h-diao{top:.15em}[zhuyin] [diao="˙"] [length="2"] h-diao{top:-.05em}[zhuyin] [diao="˙"] [length="3"] h-diao{top:-.2em}[zhuyin] [diao="˪"] h-diao,[zhuyin] [diao="˫"] h-diao{-moz-transform:scale(.6);-ms-transform:scale(.6);-webkit-transform:scale(.6);transform:scale(.6);-moz-transform-origin:left top;-ms-transform-origin:left top;-webkit-transform-origin:left top;transform-origin:left top}[zhuyin] [diao="󳆴"] h-diao,[zhuyin] [diao="󳆵"] h-diao,[zhuyin] [diao="󳆶"] h-diao,[zhuyin] [diao="󳆷"] h-diao,[zhuyin] [diao^="ㆴ"] h-diao,[zhuyin] [diao^="ㆵ"] h-diao,[zhuyin] [diao^="ㆶ"] h-diao,[zhuyin] [diao^="ㆷ"] h-diao{bottom:-.6em;margin-right:.3em}[zhuyin]{margin-right:.2em;line-height:1.8}[rightangle] h-ru[annotation]{vertical-align:0;line-height:1}[rightangle] rt:after{content:"";display:inline-block;width:1.2em}h-ru h-ru[zhuyin]{margin-top:-.4em;margin-bottom:-.2em;line-height:1.8}h-jinze,h-word{text-indent:0}@font-face{font-family:"Han Heiti";src:local("Hiragino Sans GB"),local("Lantinghei TC Extralight"),local("Lantinghei SC Extralight"),local(FZLTXHB--B51-0),local(FZLTZHK--GBK1-0),local(".PingFang SC Light"),local(".PingFang TC Light"),local(".PingFang-SC-Light"),local(".PingFang-TC-Light"),local(".PingFang SC"),local(".PingFang TC"),local("Heiti SC Light"),local(STHeitiSC-Light),local("Heiti SC"),local("Heiti TC Light"),local(STHeitiTC-Light),local("Heiti TC"),local("Microsoft Yahei"),local("Microsoft Jhenghei"),local("Noto Sans CJK KR"),local("Noto Sans CJK JP"),local("Noto Sans CJK SC"),local("Noto Sans CJK TC"),local("Source Han Sans K"),local("Source Han Sans KR"),local("Source Han Sans JP"),local("Source Han Sans CN"),local("Source Han Sans HK"),local("Source Han Sans TW"),local("Source Han Sans TWHK"),local("Droid Sans Fallback")}@font-face{unicode-range:U+4E00-9FFF,U+3400-4DB5,U+20000-2A6D6,U+2A700-2B734,U+2B740-2B81D,U+FA0E-FA0F,U+FA11,U+FA13-FA14,U+FA1F,U+FA21,U+FA23,U+FA24,U+FA27-FA29,U+3040-309F,U+30A0-30FF,U+3099-309E,U+FF66-FF9F,U+3007,U+31C0-31E3,U+2F00-2FD5,U+2E80-2EF3;font-family:"Han Heiti";src:local(YuGothic),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro")}@font-face{font-family:"Han Heiti CNS";src:local(".PingFang TC Light"),local(".PingFang-TC-Light"),local(".PingFang TC"),local("Heiti TC Light"),local(STHeitiTC-Light),local("Heiti TC"),local("Lantinghei TC Extralight"),local(FZLTXHB--B51-0),local("Lantinghei TC"),local("Microsoft Jhenghei"),local("Microsoft Yahei"),local("Noto Sans CJK TC"),local("Source Han Sans TC"),local("Source Han Sans TW"),local("Source Han Sans TWHK"),local("Source Han Sans HK"),local("Droid Sans Fallback")}@font-face{font-family:"Han Heiti GB";src:local("Hiragino Sans GB"),local(".PingFang SC Light"),local(".PingFang-SC-Light"),local(".PingFang SC"),local("Lantinghei SC Extralight"),local(FZLTXHK--GBK1-0),local("Lantinghei SC"),local("Heiti SC Light"),local(STHeitiSC-Light),local("Heiti SC"),local("Microsoft Yahei"),local("Noto Sans CJK SC"),local("Source Han Sans SC"),local("Source Han Sans CN"),local("Droid Sans Fallback")}@font-face{font-family:"Han Heiti";font-weight:600;src:local("Hiragino Sans GB W6"),local(HiraginoSansGB-W6),local("Lantinghei TC Demibold"),local("Lantinghei SC Demibold"),local(FZLTZHB--B51-0),local(FZLTZHK--GBK1-0),local(".PingFang-SC-Semibold"),local(".PingFang-TC-Semibold"),local("Heiti SC Medium"),local("STHeitiSC-Medium"),local("Heiti SC"),local("Heiti TC Medium"),local("STHeitiTC-Medium"),local("Heiti TC"),local("Microsoft YaHei Bold"),local("Microsoft Jhenghei Bold"),local(MicrosoftYaHei-Bold),local(MicrosoftJhengHeiBold),local("Microsoft YaHei"),local("Microsoft Jhenghei"),local("Noto Sans CJK KR Bold"),local("Noto Sans CJK JP Bold"),local("Noto Sans CJK SC Bold"),local("Noto Sans CJK TC Bold"),local(NotoSansCJKkr-Bold),local(NotoSansCJKjp-Bold),local(NotoSansCJKsc-Bold),local(NotoSansCJKtc-Bold),local("Source Han Sans K Bold"),local(SourceHanSansK-Bold),local("Source Han Sans K"),local("Source Han Sans KR Bold"),local("Source Han Sans JP Bold"),local("Source Han Sans CN Bold"),local("Source Han Sans HK Bold"),local("Source Han Sans TW Bold"),local("Source Han Sans TWHK Bold"),local("SourceHanSansKR-Bold"),local("SourceHanSansJP-Bold"),local("SourceHanSansCN-Bold"),local("SourceHanSansHK-Bold"),local("SourceHanSansTW-Bold"),local("SourceHanSansTWHK-Bold"),local("Source Han Sans KR"),local("Source Han Sans CN"),local("Source Han Sans HK"),local("Source Han Sans TW"),local("Source Han Sans TWHK")}@font-face{unicode-range:U+4E00-9FFF,U+3400-4DB5,U+20000-2A6D6,U+2A700-2B734,U+2B740-2B81D,U+FA0E-FA0F,U+FA11,U+FA13-FA14,U+FA1F,U+FA21,U+FA23,U+FA24,U+FA27-FA29,U+3040-309F,U+30A0-30FF,U+3099-309E,U+FF66-FF9F,U+3007,U+31C0-31E3,U+2F00-2FD5,U+2E80-2EF3;font-family:"Han Heiti";font-weight:600;src:local("YuGothic Bold"),local("Hiragino Kaku Gothic ProN W6"),local("Hiragino Kaku Gothic Pro W6"),local(YuGo-Bold),local(HiraKakuProN-W6),local(HiraKakuPro-W6)}@font-face{font-family:"Han Heiti CNS";font-weight:600;src:local(".PingFang TC Semibold"),local(".PingFang-TC-Semibold"),local("Heiti TC Medium"),local("STHeitiTC-Medium"),local("Heiti TC"),local("Lantinghei TC Demibold"),local(FZLTXHB--B51-0),local("Microsoft Jhenghei Bold"),local(MicrosoftJhengHeiBold),local("Microsoft Jhenghei"),local("Microsoft YaHei Bold"),local(MicrosoftYaHei-Bold),local("Noto Sans CJK TC Bold"),local(NotoSansCJKtc-Bold),local("Noto Sans CJK TC"),local("Source Han Sans TC Bold"),local("SourceHanSansTC-Bold"),local("Source Han Sans TC"),local("Source Han Sans TW Bold"),local("SourceHanSans-TW"),local("Source Han Sans TW"),local("Source Han Sans TWHK Bold"),local("SourceHanSans-TWHK"),local("Source Han Sans TWHK"),local("Source Han Sans HK"),local("SourceHanSans-HK"),local("Source Han Sans HK")}@font-face{font-family:"Han Heiti GB";font-weight:600;src:local("Hiragino Sans GB W6"),local(HiraginoSansGB-W6),local(".PingFang SC Semibold"),local(".PingFang-SC-Semibold"),local("Lantinghei SC Demibold"),local(FZLTZHK--GBK1-0),local("Heiti SC Medium"),local("STHeitiSC-Medium"),local("Heiti SC"),local("Microsoft YaHei Bold"),local(MicrosoftYaHei-Bold),local("Microsoft YaHei"),local("Noto Sans CJK SC Bold"),local(NotoSansCJKsc-Bold),local("Noto Sans CJK SC"),local("Source Han Sans SC Bold"),local("SourceHanSansSC-Bold"),local("Source Han Sans CN Bold"),local("SourceHanSansCN-Bold"),local("Source Han Sans SC"),local("Source Han Sans CN")}@font-face{font-family:"Han Heiti";src:local("Hiragino Sans GB"),local("Lantinghei TC Extralight"),local("Lantinghei SC Extralight"),local(FZLTXHB--B51-0),local(FZLTZHK--GBK1-0),local(".PingFang SC Light"),local(".PingFang TC Light"),local(".PingFang-SC-Light"),local(".PingFang-TC-Light"),local(".PingFang SC"),local(".PingFang TC"),local("Heiti SC Light"),local("STHeitiSC-Light"),local("Heiti SC"),local("Heiti TC Light"),local("STHeitiTC-Light"),local("Heiti TC"),local("Microsoft Yahei"),local("Microsoft Jhenghei"),local("Noto Sans CJK KR"),local("Noto Sans CJK JP"),local("Noto Sans CJK SC"),local("Noto Sans CJK TC"),local("Source Han Sans K"),local("Source Han Sans KR"),local("Source Han Sans JP"),local("Source Han Sans CN"),local("Source Han Sans HK"),local("Source Han Sans TW"),local("Source Han Sans TWHK"),local("Droid Sans Fallback");unicode-range:U+270C}@font-face{font-family:"Han Heiti";font-weight:600;src:local("Hiragino Sans GB W6"),local(HiraginoSansGB-W6),local("Lantinghei TC Demibold"),local("Lantinghei SC Demibold"),local(FZLTZHB--B51-0),local(FZLTZHK--GBK1-0),local(".PingFang-SC-Semibold"),local(".PingFang-TC-Semibold"),local("Heiti SC Medium"),local("STHeitiSC-Medium"),local("Heiti SC"),local("Heiti TC Medium"),local("STHeitiTC-Medium"),local("Heiti TC"),local("Microsoft YaHei Bold"),local("Microsoft Jhenghei Bold"),local(MicrosoftYaHei-Bold),local(MicrosoftJhengHeiBold),local("Microsoft YaHei"),local("Microsoft Jhenghei"),local("Noto Sans CJK KR Bold"),local("Noto Sans CJK JP Bold"),local("Noto Sans CJK SC Bold"),local("Noto Sans CJK TC Bold"),local(NotoSansCJKkr-Bold),local(NotoSansCJKjp-Bold),local(NotoSansCJKsc-Bold),local(NotoSansCJKtc-Bold),local("Source Han Sans K Bold"),local(SourceHanSansK-Bold),local("Source Han Sans K"),local("Source Han Sans KR Bold"),local("Source Han Sans JP Bold"),local("Source Han Sans CN Bold"),local("Source Han Sans HK Bold"),local("Source Han Sans TW Bold"),local("Source Han Sans TWHK Bold"),local("SourceHanSansKR-Bold"),local("SourceHanSansJP-Bold"),local("SourceHanSansCN-Bold"),local("SourceHanSansHK-Bold"),local("SourceHanSansTW-Bold"),local("SourceHanSansTWHK-Bold"),local("Source Han Sans KR"),local("Source Han Sans CN"),local("Source Han Sans HK"),local("Source Han Sans TW"),local("Source Han Sans TWHK");unicode-range:U+270C}@font-face{font-family:"Han Songti";src:local("Songti SC Regular"),local(STSongti-SC-Regular),local("Songti SC"),local("Songti TC Regular"),local(STSongti-TC-Regular),local("Songti TC"),local(STSong),local("Lisong Pro"),local(SimSun),local(PMingLiU)}@font-face{unicode-range:U+4E00-9FFF,U+3400-4DB5,U+20000-2A6D6,U+2A700-2B734,U+2B740-2B81D,U+FA0E-FA0F,U+FA11,U+FA13-FA14,U+FA1F,U+FA21,U+FA23,U+FA24,U+FA27-FA29,U+3040-309F,U+30A0-30FF,U+3099-309E,U+FF66-FF9F,U+3007,U+31C0-31E3,U+2F00-2FD5,U+2E80-2EF3;font-family:"Han Songti";src:local(YuMincho),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("MS Mincho")}@font-face{font-family:"Han Songti CNS";src:local("Songti TC Regular"),local(STSongti-TC-Regular),local("Songti TC"),local("Lisong Pro"),local("Songti SC Regular"),local(STSongti-SC-Regular),local("Songti SC"),local(STSong),local(PMingLiU),local(SimSun)}@font-face{font-family:"Han Songti GB";src:local("Songti SC Regular"),local(STSongti-SC-Regular),local("Songti SC"),local(STSong),local(SimSun),local(PMingLiU)}@font-face{font-family:"Han Songti";font-weight:600;src:local("STSongti SC Bold"),local("STSongti TC Bold"),local(STSongti-SC-Bold),local(STSongti-TC-Bold),local("STSongti SC"),local("STSongti TC")}@font-face{unicode-range:U+4E00-9FFF,U+3400-4DB5,U+20000-2A6D6,U+2A700-2B734,U+2B740-2B81D,U+FA0E-FA0F,U+FA11,U+FA13-FA14,U+FA1F,U+FA21,U+FA23,U+FA24,U+FA27-FA29,U+3040-309F,U+30A0-30FF,U+3099-309E,U+FF66-FF9F,U+3007,U+31C0-31E3,U+2F00-2FD5,U+2E80-2EF3;font-family:"Han Songti";font-weight:600;src:local("YuMincho Demibold"),local("Hiragino Mincho ProN W6"),local("Hiragino Mincho Pro W6"),local(YuMin-Demibold),local(HiraMinProN-W6),local(HiraMinPro-W6),local(YuMincho),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro")}@font-face{font-family:"Han Songti CNS";font-weight:600;src:local("STSongti TC Bold"),local("STSongti SC Bold"),local(STSongti-TC-Bold),local(STSongti-SC-Bold),local("STSongti TC"),local("STSongti SC")}@font-face{font-family:"Han Songti GB";font-weight:600;src:local("STSongti SC Bold"),local(STSongti-SC-Bold),local("STSongti SC")}@font-face{font-family:"Han Songti";src:local("Songti SC Regular"),local(STSongti-SC-Regular),local("Songti SC"),local("Songti TC Regular"),local(STSongti-TC-Regular),local("Songti TC"),local(STSongti),local("Lisong Pro"),local("MS Mincho"),local(SimSun),local(PMingLiU);unicode-range:U+270C}@font-face{font-family:"Han Songti";font-weight:600;src:local("Songti TC Bold"),local("Songti SC Bold"),local(STSongti-TC-Bold),local(STSongti-SC-Bold),local("Songti TC"),local("Songti SC");unicode-range:U+270C}@font-face{font-family:"Han Songti CNS";src:local("Songti TC Regular"),local("Lisong Pro"),local("Songti TC"),local("Songti SC Regular"),local(STSong),local("Songti SC"),local("MS Mincho"),local(PMingLiU),local(SimSun);unicode-range:U+270C}@font-face{font-family:"Han Songti CNS";font-weight:600;src:local("Songti TC Bold"),local("Songti SC Bold"),local(STSongti-TC-Bold),local(STSongti-SC-Bold),local("Songti TC"),local("Songti SC");unicode-range:U+270C}@font-face{font-family:"Han Songti GB";src:local("Songti SC"),local(STSong),local(SimSun);unicode-range:U+270C}@font-face{font-family:"Han Songti GB";font-weight:600;src:local("Songti SC Bold"),local(STSongti-SC-Bold),local("Songti SC");unicode-range:U+270C}@font-face{font-family:cursive;src:local("Kaiti TC Regular"),local(STKaiTi-TC-Regular),local("Kaiti TC"),local("Kaiti SC"),local(STKaiti),local(BiauKai),local("標楷體"),local(DFKaiShu-SB-Estd-BF),local(Kaiti),local(DFKai-SB)}@font-face{unicode-range:U+4E00-9FFF,U+3400-4DB5,U+20000-2A6D6,U+2A700-2B734,U+2B740-2B81D,U+FA0E-FA0F,U+FA11,U+FA13-FA14,U+FA1F,U+FA21,U+FA23,U+FA24,U+FA27-FA29,U+3040-309F,U+30A0-30FF,U+3099-309E,U+FF66-FF9F,U+3007,U+31C0-31E3,U+2F00-2FD5,U+2E80-2EF3;font-family:"Han Kaiti";src:local("Kaiti TC Regular"),local(STKaiTi-TC-Regular),local("Kaiti TC"),local("Kaiti SC"),local(STKaiti),local(BiauKai),local("標楷體"),local(DFKaiShu-SB-Estd-BF),local(Kaiti),local(DFKai-SB)}@font-face{unicode-range:U+4E00-9FFF,U+3400-4DB5,U+20000-2A6D6,U+2A700-2B734,U+2B740-2B81D,U+FA0E-FA0F,U+FA11,U+FA13-FA14,U+FA1F,U+FA21,U+FA23,U+FA24,U+FA27-FA29,U+3040-309F,U+30A0-30FF,U+3099-309E,U+FF66-FF9F,U+3007,U+31C0-31E3,U+2F00-2FD5,U+2E80-2EF3;font-family:"Han Kaiti CNS";src:local(BiauKai),local("標楷體"),local(DFKaiShu-SB-Estd-BF),local("Kaiti TC Regular"),local(STKaiTi-TC-Regular),local("Kaiti TC")}@font-face{unicode-range:U+4E00-9FFF,U+3400-4DB5,U+20000-2A6D6,U+2A700-2B734,U+2B740-2B81D,U+FA0E-FA0F,U+FA11,U+FA13-FA14,U+FA1F,U+FA21,U+FA23,U+FA24,U+FA27-FA29,U+3040-309F,U+30A0-30FF,U+3099-309E,U+FF66-FF9F,U+3007,U+31C0-31E3,U+2F00-2FD5,U+2E80-2EF3;font-family:"Han Kaiti GB";src:local("Kaiti SC Regular"),local(STKaiTi-SC-Regular),local("Kaiti SC"),local(STKaiti),local(Kai),local(Kaiti),local(DFKai-SB)}@font-face{font-family:cursive;font-weight:600;src:local("Kaiti TC Bold"),local(STKaiTi-TC-Bold),local("Kaiti SC Bold"),local(STKaiti-SC-Bold),local("Kaiti TC"),local("Kaiti SC")}@font-face{font-family:"Han Kaiti";font-weight:600;src:local("Kaiti TC Bold"),local(STKaiTi-TC-Bold),local("Kaiti SC Bold"),local(STKaiti-SC-Bold),local("Kaiti TC"),local("Kaiti SC")}@font-face{font-family:"Han Kaiti CNS";font-weight:600;src:local("Kaiti TC Bold"),local(STKaiTi-TC-Bold),local("Kaiti TC")}@font-face{font-family:"Han Kaiti GB";font-weight:600;src:local("Kaiti SC Bold"),local(STKaiti-SC-Bold)}@font-face{unicode-range:U+4E00-9FFF,U+3400-4DB5,U+20000-2A6D6,U+2A700-2B734,U+2B740-2B81D,U+FA0E-FA0F,U+FA11,U+FA13-FA14,U+FA1F,U+FA21,U+FA23,U+FA24,U+FA27-FA29,U+3040-309F,U+30A0-30FF,U+3099-309E,U+FF66-FF9F,U+3007,U+31C0-31E3,U+2F00-2FD5,U+2E80-2EF3;font-family:"Han Fangsong";src:local(STFangsong),local(FangSong)}@font-face{unicode-range:U+4E00-9FFF,U+3400-4DB5,U+20000-2A6D6,U+2A700-2B734,U+2B740-2B81D,U+FA0E-FA0F,U+FA11,U+FA13-FA14,U+FA1F,U+FA21,U+FA23,U+FA24,U+FA27-FA29,U+3040-309F,U+30A0-30FF,U+3099-309E,U+FF66-FF9F,U+3007,U+31C0-31E3,U+2F00-2FD5,U+2E80-2EF3;font-family:"Han Fangsong CNS";src:local(STFangsong),local(FangSong)}@font-face{unicode-range:U+4E00-9FFF,U+3400-4DB5,U+20000-2A6D6,U+2A700-2B734,U+2B740-2B81D,U+FA0E-FA0F,U+FA11,U+FA13-FA14,U+FA1F,U+FA21,U+FA23,U+FA24,U+FA27-FA29,U+3040-309F,U+30A0-30FF,U+3099-309E,U+FF66-FF9F,U+3007,U+31C0-31E3,U+2F00-2FD5,U+2E80-2EF3;font-family:"Han Fangsong GB";src:local(STFangsong),local(FangSong)}@font-face{font-family:"Biaodian Sans";src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local("MS Gothic"),local(SimSun);unicode-range:U+FF0E}@font-face{font-family:"Biaodian Serif";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(STSong),local(SimSun);unicode-range:U+FF0E}@font-face{font-family:"Biaodian Pro Sans";src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local("MS Gothic"),local(SimSun);unicode-range:U+FF0E}@font-face{font-family:"Biaodian Pro Serif";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(STSong),local(SimSun);unicode-range:U+FF0E}@font-face{font-family:"Biaodian Pro Sans CNS";src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local("MS Gothic"),local(SimSun);unicode-range:U+FF0E}@font-face{font-family:"Biaodian Pro Serif CNS";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(STSong),local(SimSun);unicode-range:U+FF0E}@font-face{font-family:"Biaodian Pro Sans GB";src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local("MS Gothic"),local(SimSun);unicode-range:U+FF0E}@font-face{font-family:"Biaodian Pro Serif GB";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(STSong),local(SimSun);unicode-range:U+FF0E}@font-face{font-family:"Biaodian Sans";src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local(SimSun);unicode-range:U+00B7}@font-face{font-family:"Biaodian Serif";src:local("Songti SC"),local(STSong),local("Heiti SC"),local(SimSun);unicode-range:U+00B7}@font-face{font-family:"Biaodian Pro Sans";src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local(SimSun);unicode-range:U+00B7}@font-face{font-family:"Biaodian Pro Serif";src:local("Songti SC"),local(STSong),local("Heiti SC"),local(SimSun);unicode-range:U+00B7}@font-face{font-family:"Biaodian Pro Sans CNS";src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local(SimSun);unicode-range:U+00B7}@font-face{font-family:"Biaodian Pro Serif CNS";src:local("Songti SC"),local(STSong),local("Heiti SC"),local(SimSun);unicode-range:U+00B7}@font-face{font-family:"Biaodian Pro Sans GB";src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local(SimSun);unicode-range:U+00B7}@font-face{font-family:"Biaodian Pro Serif GB";src:local("Songti SC"),local(STSong),local("Heiti SC"),local(SimSun);unicode-range:U+00B7}@font-face{font-family:"Biaodian Sans";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Sans GB"),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local("Microsoft Yahei"),local(SimSun);unicode-range:U+2014}@font-face{font-family:"Biaodian Serif";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(STSong),local("Microsoft Yahei"),local(SimSun);unicode-range:U+2014}@font-face{font-family:"Yakumono Sans";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local("Arial Unicode MS"),local("MS Gothic");unicode-range:U+2014}@font-face{font-family:"Yakumono Serif";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("MS Mincho"),local("Microsoft Yahei");unicode-range:U+2014}@font-face{font-family:"Biaodian Pro Sans";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Sans GB"),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local("Microsoft Yahei"),local(SimSun);unicode-range:U+2014}@font-face{font-family:"Biaodian Pro Serif";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(STSong),local("Microsoft Yahei"),local(SimSun);unicode-range:U+2014}@font-face{font-family:"Biaodian Pro Sans CNS";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Sans GB"),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local("Microsoft Yahei"),local(SimSun);unicode-range:U+2014}@font-face{font-family:"Biaodian Pro Serif CNS";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(STSong),local("Microsoft Yahei"),local(SimSun);unicode-range:U+2014}@font-face{font-family:"Biaodian Pro Sans GB";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Sans GB"),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local("Microsoft Yahei"),local(SimSun);unicode-range:U+2014}@font-face{font-family:"Biaodian Pro Serif GB";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(STSong),local("Microsoft Yahei"),local(SimSun);unicode-range:U+2014}@font-face{font-family:"Biaodian Sans";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Sans GB"),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local(Meiryo),local("MS Gothic"),local(SimSun),local(PMingLiU);unicode-range:U+2026}@font-face{font-family:"Biaodian Serif";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local("MS Mincho"),local(SimSun),local(PMingLiU);unicode-range:U+2026}@font-face{font-family:"Yakumono Sans";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local(Meiryo),local("MS Gothic");unicode-range:U+2026}@font-face{font-family:"Yakumono Serif";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("MS Mincho");unicode-range:U+2026}@font-face{font-family:"Biaodian Pro Sans";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Sans GB"),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local(SimSun),local(PMingLiU);unicode-range:U+2026}@font-face{font-family:"Biaodian Pro Serif";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(SimSun),local(PMingLiU);unicode-range:U+2026}@font-face{font-family:"Biaodian Pro Sans CNS";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Sans GB"),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local(SimSun),local(PMingLiU);unicode-range:U+2026}@font-face{font-family:"Biaodian Pro Serif CNS";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(STSongti),local(SimSun),local(PMingLiU);unicode-range:U+2026}@font-face{font-family:"Biaodian Pro Sans GB";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Sans GB"),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local(SimSun),local(PMingLiU);unicode-range:U+2026}@font-face{font-family:"Biaodian Pro Serif GB";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype"),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Songti SC"),local(STSongti),local(SimSun),local(PMingLiU);unicode-range:U+2026}@font-face{font-family:"Biaodian Pro Sans GB";src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local(SimSun),local(PMingLiU);unicode-range:U+201C-201D,U+2018-2019}@font-face{font-family:"Biaodian Pro Sans GB";font-weight:700;src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local(SimSun),local(PMingLiU);unicode-range:U+201C-201D,U+2018-2019}@font-face{font-family:"Biaodian Pro Serif GB";src:local("Lisong Pro"),local("Heiti SC"),local(STHeiti),local(SimSun),local(PMingLiU);unicode-range:U+201C-201D,U+2018-2019}@font-face{font-family:"Biaodian Pro Serif GB";font-weight:700;src:local("Lisong Pro"),local("Heiti SC"),local(STHeiti),local(SimSun),local(PMingLiU);unicode-range:U+201C-201D,U+2018-2019}@font-face{font-family:"Biaodian Sans";src:local(Georgia),local("Times New Roman"),local(Arial),local("Droid Sans Fallback");unicode-range:U+25CF}@font-face{font-family:"Biaodian Serif";src:local(Georgia),local("Times New Roman"),local(Arial),local("Droid Sans Fallback");unicode-range:U+25CF}@font-face{font-family:"Biaodian Pro Sans";src:local(Georgia),local("Times New Roman"),local(Arial),local("Droid Sans Fallback");unicode-range:U+25CF}@font-face{font-family:"Biaodian Pro Serif";src:local(Georgia),local("Times New Roman"),local(Arial),local("Droid Sans Fallback");unicode-range:U+25CF}@font-face{font-family:"Biaodian Pro Sans CNS";src:local(Georgia),local("Times New Roman"),local(Arial),local("Droid Sans Fallback");unicode-range:U+25CF}@font-face{font-family:"Biaodian Pro Serif CNS";src:local(Georgia),local("Times New Roman"),local(Arial),local("Droid Sans Fallback");unicode-range:U+25CF}@font-face{font-family:"Biaodian Pro Sans GB";src:local(Georgia),local("Times New Roman"),local(Arial),local("Droid Sans Fallback");unicode-range:U+25CF}@font-face{font-family:"Biaodian Pro Serif GB";src:local(Georgia),local("Times New Roman"),local(Arial),local("Droid Sans Fallback");unicode-range:U+25CF}@font-face{font-family:"Biaodian Pro Sans";src:local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local("MS Gothic");unicode-range:U+3002,U+FF0C,U+3001,U+FF1B,U+FF1A,U+FF1F,U+FF01,U+FF0D,U+FF0F,U+FF3C}@font-face{font-family:"Biaodian Pro Serif";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("MS Mincho");unicode-range:U+3002,U+FF0C,U+3001,U+FF1B,U+FF1A,U+FF1F,U+FF01,U+FF0D,U+FF0F,U+FF3C}@font-face{font-family:"Biaodian Pro Sans CNS";src:local("Heiti TC"),local("Lihei Pro"),local("Microsoft Jhenghei"),local(PMingLiU);unicode-range:U+3002,U+FF0C,U+3001}@font-face{font-family:"Biaodian Pro Sans CNS";src:local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local("Heiti TC"),local("Lihei Pro"),local("Microsoft Jhenghei"),local(PMingLiU),local("MS Gothic");unicode-range:U+FF1B,U+FF1A,U+FF1F,U+FF01}@font-face{font-family:"Biaodian Pro Sans CNS";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("MS Mincho");unicode-range:U+FF0D,U+FF0F,U+FF3C}@font-face{font-family:"Biaodian Pro Serif CNS";src:local(STSongti-TC-Regular),local("Lisong Pro"),local("Heiti TC"),local(PMingLiU);unicode-range:U+3002,U+FF0C,U+3001}@font-face{font-family:"Biaodian Pro Serif CNS";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local(PMingLiU),local("MS Mincho");unicode-range:U+FF1B,U+FF1A,U+FF1F,U+FF01,U+FF0D,U+FF0F,U+FF3C}@font-face{font-family:"Biaodian Pro Sans GB";src:local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local(SimSun),local("MS Gothic");unicode-range:U+3002,U+FF0C,U+3001,U+FF1B,U+FF1A,U+FF1F,U+FF01,U+FF0D,U+FF0F,U+FF3C}@font-face{font-family:"Biaodian Pro Serif GB";src:local("Songti SC"),local(STSongti),local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Hiragino Sans GB"),local("Heiti SC"),local(STHeiti),local(SimSun),local("MS Mincho");unicode-range:U+3002,U+FF0C,U+3001,U+FF1B,U+FF1A,U+FF1F,U+FF01}@font-face{font-family:"Biaodian Pro Serif GB";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local(PMingLiU),local("MS Mincho");unicode-range:U+FF0D,U+FF0F,U+FF3C}@font-face{font-family:"Biaodian Pro Sans";src:local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local("Yu Gothic"),local(YuGothic),local(SimSun),local(PMingLiU);unicode-range:U+300C-300F,U+300A-300B,U+3008-3009,U+FF08-FF09,U+3014-3015}@font-face{font-family:"Biaodian Pro Serif";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Yu Mincho"),local(YuMincho),local(SimSun),local(PMingLiU);unicode-range:U+300C-300F,U+300A-300B,U+3008-3009,U+FF08-FF09,U+3014-3015}@font-face{font-family:"Biaodian Pro Sans CNS";src:local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local("Yu Gothic"),local(YuGothic),local(SimSun),local(PMingLiU);unicode-range:U+300C-300F,U+300A-300B,U+3008-3009,U+FF08-FF09,U+3014-3015}@font-face{font-family:"Biaodian Pro Serif CNS";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Yu Mincho"),local(YuMincho),local(SimSun),local(PMingLiU);unicode-range:U+300C-300F,U+300A-300B,U+3008-3009,U+FF08-FF09,U+3014-3015}@font-face{font-family:"Biaodian Pro Sans GB";src:local("Hiragino Kaku Gothic ProN"),local("Hiragino Kaku Gothic Pro"),local("Yu Gothic"),local(YuGothic),local(SimSun),local(PMingLiU);unicode-range:U+300C-300F,U+300A-300B,U+3008-3009,U+FF08-FF09,U+3014-3015}@font-face{font-family:"Biaodian Pro Serif GB";src:local("Hiragino Mincho ProN"),local("Hiragino Mincho Pro"),local("Yu Mincho"),local(YuMincho),local(SimSun),local(PMingLiU);unicode-range:U+300C-300F,U+300A-300B,U+3008-3009,U+FF08-FF09,U+3014-3015}@font-face{font-family:"Biaodian Basic";src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+2014,U+2026,U+00B7}@font-face{font-family:"Biaodian Basic";font-weight:700;src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+2014,U+2026,U+00B7}@font-face{font-family:"Biaodian Sans";font-weight:700;src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+2014,U+2026,U+00B7}@font-face{font-family:"Biaodian Pro Sans";font-weight:700;src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+2014,U+2026,U+00B7}@font-face{font-family:"Biaodian Pro Sans";font-weight:700;src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+2014,U+2026,U+00B7}@font-face{font-family:"Biaodian Pro Sans CNS";font-weight:700;src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+2014,U+2026,U+00B7}@font-face{font-family:"Biaodian Pro Sans GB";font-weight:700;src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+2014,U+2026,U+00B7}@font-face{font-family:"Biaodian Pro Serif";font-weight:700;src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+2014,U+2026,U+00B7}@font-face{font-family:"Biaodian Pro Serif CNS";font-weight:700;src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+2014,U+2026,U+00B7}@font-face{font-family:"Biaodian Pro Serif GB";font-weight:700;src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+2014,U+2026,U+00B7}@font-face{font-family:"Latin Italic Serif";src:local("Georgia Italic"),local("Times New Roman Italic"),local(Georgia-Italic),local(TimesNewRomanPS-ItalicMT),local(Times-Italic)}@font-face{font-family:"Latin Italic Serif";font-weight:700;src:local("Georgia Bold Italic"),local("Times New Roman Bold Italic"),local(Georgia-BoldItalic),local(TimesNewRomanPS-BoldItalicMT),local(Times-Italic)}@font-face{font-family:"Latin Italic Sans";src:local("Helvetica Neue Italic"),local("Helvetica Oblique"),local("Arial Italic"),local(HelveticaNeue-Italic),local(Helvetica-LightOblique),local(Arial-ItalicMT)}@font-face{font-family:"Latin Italic Sans";font-weight:700;src:local("Helvetica Neue Bold Italic"),local("Helvetica Bold Oblique"),local("Arial Bold Italic"),local(HelveticaNeue-BoldItalic),local(Helvetica-BoldOblique),local(Arial-BoldItalicMT)}@font-face{unicode-range:U+0030-0039;font-family:"Numeral TF Sans";src:local(Skia),local("Neutraface 2 Text"),local(Candara),local(Corbel)}@font-face{unicode-range:U+0030-0039;font-family:"Numeral TF Serif";src:local(Georgia),local("Hoefler Text"),local("Big Caslon")}@font-face{unicode-range:U+0030-0039;font-family:"Numeral TF Italic Serif";src:local("Georgia Italic"),local("Hoefler Text Italic"),local(Georgia-Italic),local(HoeflerText-Italic)}@font-face{unicode-range:U+0030-0039;font-family:"Numeral LF Sans";src:local("Helvetica Neue"),local(Helvetica),local(Arial)}@font-face{unicode-range:U+0030-0039;font-family:"Numeral LF Italic Sans";src:local("Helvetica Neue Italic"),local("Helvetica Oblique"),local("Arial Italic"),local(HelveticaNeue-Italic),local(Helvetica-LightOblique),local(Arial-ItalicMT)}@font-face{unicode-range:U+0030-0039;font-family:"Numeral LF Italic Sans";font-weight:700;src:local("Helvetica Neue Bold Italic"),local("Helvetica Bold Oblique"),local("Arial Bold Italic"),local(HelveticaNeue-BoldItalic),local(Helvetica-BoldOblique),local(Arial-BoldItalicMT)}@font-face{unicode-range:U+0030-0039;font-family:"Numeral LF Serif";src:local(Palatino),local("Palatino Linotype"),local("Times New Roman")}@font-face{unicode-range:U+0030-0039;font-family:"Numeral LF Italic Serif";src:local("Palatino Italic"),local("Palatino Italic Linotype"),local("Times New Roman Italic"),local(Palatino-Italic),local(Palatino-Italic-Linotype),local(TimesNewRomanPS-ItalicMT)}@font-face{unicode-range:U+0030-0039;font-family:"Numeral LF Italic Serif";font-weight:700;src:local("Palatino Bold Italic"),local("Palatino Bold Italic Linotype"),local("Times New Roman Bold Italic"),local(Palatino-BoldItalic),local(Palatino-BoldItalic-Linotype),local(TimesNewRomanPS-BoldItalicMT)}@font-face{font-family:"Numeral TF Sans";src:local(lying-to-firefox);unicode-range:U+270C}@font-face{font-family:"Numeral TF Serif";src:local(lying-to-firefox);unicode-range:U+270C}@font-face{font-family:"Numeral TF Italic Serif";src:local(lying-to-firefox);unicode-range:U+270C}@font-face{font-family:"Numeral LF Sans";src:local(lying-to-firefox);unicode-range:U+270C}@font-face{font-family:"Numeral LF Italic Sans";src:local(lying-to-firefox);unicode-range:U+270C}@font-face{font-family:"Numeral LF Italic Sans";font-weight:700;src:local(lying-to-firefox);unicode-range:U+270C}@font-face{font-family:"Numeral LF Serif";src:local(lying-to-firefox);unicode-range:U+270C}@font-face{font-family:"Numeral LF Italic Serif";src:local(lying-to-firefox);unicode-range:U+270C}@font-face{font-family:"Numeral LF Italic Serif";font-weight:700;src:local(lying-to-firefox);unicode-range:U+270C}@font-face{src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+3105-312D,U+31A0-31BA,U+02D9,U+02CA,U+02C5,U+02C7,U+02CB,U+02EA-02EB,U+030D,U+0358,U+F31B4-F31B7,U+F0061,U+F0065,U+F0069,U+F006F,U+F0075;font-family:"Zhuyin Kaiti"}@font-face{unicode-range:U+3105-312D,U+31A0-31BA,U+02D9,U+02CA,U+02C5,U+02C7,U+02CB,U+02EA-02EB,U+030D,U+0358,U+F31B4-F31B7,U+F0061,U+F0065,U+F0069,U+F006F,U+F0075;font-family:"Zhuyin Heiti";src:local("Hiragino Sans GB"),local("Heiti TC"),local("Microsoft Jhenghei"),url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype")}@font-face{font-family:"Zhuyin Heiti";src:local("Heiti TC"),local("Microsoft Jhenghei"),url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");unicode-range:U+3127}@font-face{src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");font-family:"Zhuyin Heiti";unicode-range:U+02D9,U+02CA,U+02C5,U+02C7,U+02CB,U+02EA-02EB,U+31B4,U+31B5,U+31B6,U+31B7,U+030D,U+0358,U+F31B4-F31B7,U+F0061,U+F0065,U+F0069,U+F006F,U+F0075}@font-face{src:url(./font/han.woff?v3.3.0) format("woff"),url(./font/han.otf?v3.3.0) format("opentype");font-family:"Romanization Sans";unicode-range:U+030D,U+0358,U+F31B4-F31B7,U+F0061,U+F0065,U+F0069,U+F006F,U+F0075}article strong :lang(ja-Latn),article strong :lang(zh-Latn),article strong :not(:lang(zh)):not(:lang(ja)),article strong:lang(ja-Latn),article strong:lang(zh-Latn),article strong:not(:lang(zh)):not(:lang(ja)),html :lang(ja-Latn),html :lang(zh-Latn),html :not(:lang(zh)):not(:lang(ja)),html:lang(ja-Latn),html:lang(zh-Latn),html:not(:lang(zh)):not(:lang(ja)){font-family:"Helvetica Neue",Helvetica,Arial,"Han Heiti",sans-serif}[lang*=Hant],[lang=zh-TW],[lang=zh-HK],[lang^=zh],article strong:lang(zh),article strong:lang(zh-Hant),html:lang(zh),html:lang(zh-Hant){font-family:"Biaodian Pro Sans CNS","Helvetica Neue",Helvetica,Arial,"Zhuyin Heiti","Han Heiti",sans-serif}.no-unicoderange [lang*=Hant],.no-unicoderange [lang=zh-TW],.no-unicoderange [lang=zh-HK],.no-unicoderange [lang^=zh],.no-unicoderange article strong:lang(zh),.no-unicoderange article strong:lang(zh-Hant),html:lang(zh).no-unicoderange,html:lang(zh-Hant).no-unicoderange{font-family:"Helvetica Neue",Helvetica,Arial,"Han Heiti",sans-serif}[lang*=Hans],[lang=zh-CN],article strong:lang(zh-CN),article strong:lang(zh-Hans),html:lang(zh-CN),html:lang(zh-Hans){font-family:"Biaodian Pro Sans GB","Helvetica Neue",Helvetica,Arial,"Han Heiti GB",sans-serif}.no-unicoderange [lang*=Hans],.no-unicoderange [lang=zh-CN],.no-unicoderange article strong:lang(zh-CN),.no-unicoderange article strong:lang(zh-Hans),html:lang(zh-CN).no-unicoderange,html:lang(zh-Hans).no-unicoderange{font-family:"Helvetica Neue",Helvetica,Arial,"Han Heiti GB",sans-serif}[lang^=ja],article strong:lang(ja),html:lang(ja){font-family:"Yakumono Sans","Helvetica Neue",Helvetica,Arial,sans-serif}.no-unicoderange [lang^=ja],.no-unicoderange article strong:lang(ja),html:lang(ja).no-unicoderange{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}article blockquote i :lang(ja-Latn),article blockquote i :lang(zh-Latn),article blockquote i :not(:lang(zh)):not(:lang(ja)),article blockquote i:lang(ja-Latn),article blockquote i:lang(zh-Latn),article blockquote i:not(:lang(zh)):not(:lang(ja)),article blockquote var :lang(ja-Latn),article blockquote var :lang(zh-Latn),article blockquote var :not(:lang(zh)):not(:lang(ja)),article blockquote var:lang(ja-Latn),article blockquote var:lang(zh-Latn),article blockquote var:not(:lang(zh)):not(:lang(ja)){font-family:"Latin Italic Sans","Helvetica Neue",Helvetica,Arial,"Han Heiti",sans-serif}article blockquote i:lang(zh),article blockquote i:lang(zh-Hant),article blockquote var:lang(zh),article blockquote var:lang(zh-Hant){font-family:"Biaodian Pro Sans CNS","Latin Italic Sans","Helvetica Neue",Helvetica,Arial,"Zhuyin Heiti","Han Heiti",sans-serif}.no-unicoderange article blockquote i:lang(zh),.no-unicoderange article blockquote i:lang(zh-Hant),.no-unicoderange article blockquote var:lang(zh),.no-unicoderange article blockquote var:lang(zh-Hant){font-family:"Latin Italic Sans","Helvetica Neue",Helvetica,Arial,"Han Heiti",sans-serif}article blockquote i:lang(zh-CN),article blockquote i:lang(zh-Hans),article blockquote var:lang(zh-CN),article blockquote var:lang(zh-Hans){font-family:"Biaodian Pro Sans GB","Latin Italic Sans","Helvetica Neue",Helvetica,Arial,"Han Heiti GB",sans-serif}.no-unicoderange article blockquote i:lang(zh-CN),.no-unicoderange article blockquote i:lang(zh-Hans),.no-unicoderange article blockquote var:lang(zh-CN),.no-unicoderange article blockquote var:lang(zh-Hans){font-family:"Latin Italic Sans","Helvetica Neue",Helvetica,Arial,"Han Heiti GB",sans-serif}article blockquote i:lang(ja),article blockquote var:lang(ja){font-family:"Yakumono Sans","Latin Italic Sans","Helvetica Neue",Helvetica,Arial,sans-serif}.no-unicoderange article blockquote i:lang(ja),.no-unicoderange article blockquote var:lang(ja){font-family:"Latin Italic Sans","Helvetica Neue",Helvetica,Arial,sans-serif}article figure blockquote :lang(ja-Latn),article figure blockquote :lang(zh-Latn),article figure blockquote :not(:lang(zh)):not(:lang(ja)),article figure blockquote:lang(ja-Latn),article figure blockquote:lang(zh-Latn),article figure blockquote:not(:lang(zh)):not(:lang(ja)){font-family:Georgia,"Times New Roman","Han Songti",cursive,serif}article figure blockquote:lang(zh),article figure blockquote:lang(zh-Hant){font-family:"Biaodian Pro Serif CNS","Numeral LF Serif",Georgia,"Times New Roman","Zhuyin Kaiti","Han Songti",serif}.no-unicoderange article figure blockquote:lang(zh),.no-unicoderange article figure blockquote:lang(zh-Hant){font-family:"Numeral LF Serif",Georgia,"Times New Roman","Han Songti",serif}article figure blockquote:lang(zh-CN),article figure blockquote:lang(zh-Hans){font-family:"Biaodian Pro Serif GB","Numeral LF Serif",Georgia,"Times New Roman","Han Songti GB",serif}.no-unicoderange article figure blockquote:lang(zh-CN),.no-unicoderange article figure blockquote:lang(zh-Hans){font-family:"Numeral LF Serif",Georgia,"Times New Roman","Han Songti GB",serif}article figure blockquote:lang(ja){font-family:"Yakumono Serif","Numeral LF Serif",Georgia,"Times New Roman",serif}.no-unicoderange article figure blockquote:lang(ja){font-family:"Numeral LF Serif",Georgia,"Times New Roman",serif}article blockquote :lang(ja-Latn),article blockquote :lang(zh-Latn),article blockquote :not(:lang(zh)):not(:lang(ja)),article blockquote:lang(ja-Latn),article blockquote:lang(zh-Latn),article blockquote:not(:lang(zh)):not(:lang(ja)){font-family:Georgia,"Times New Roman","Han Kaiti",cursive,serif}article blockquote:lang(zh),article blockquote:lang(zh-Hant){font-family:"Biaodian Pro Serif CNS","Numeral LF Serif",Georgia,"Times New Roman","Zhuyin Kaiti","Han Kaiti",cursive,serif}.no-unicoderange article blockquote:lang(zh),.no-unicoderange article blockquote:lang(zh-Hant){font-family:"Numeral LF Serif",Georgia,"Times New Roman","Han Kaiti",cursive,serif}article blockquote:lang(zh-CN),article blockquote:lang(zh-Hans){font-family:"Biaodian Pro Serif GB","Numeral LF Serif",Georgia,"Times New Roman","Han Kaiti GB",cursive,serif}.no-unicoderange article blockquote:lang(zh-CN),.no-unicoderange article blockquote:lang(zh-Hans){font-family:"Numeral LF Serif",Georgia,"Times New Roman","Han Kaiti GB",cursive,serif}article blockquote:lang(ja){font-family:"Yakumono Serif","Numeral LF Serif",Georgia,"Times New Roman",cursive,serif}.no-unicoderange article blockquote:lang(ja){font-family:"Numeral LF Serif",Georgia,"Times New Roman",cursive,serif}i :lang(ja-Latn),i :lang(zh-Latn),i :not(:lang(zh)):not(:lang(ja)),i:lang(ja-Latn),i:lang(zh-Latn),i:not(:lang(zh)):not(:lang(ja)),var :lang(ja-Latn),var :lang(zh-Latn),var :not(:lang(zh)):not(:lang(ja)),var:lang(ja-Latn),var:lang(zh-Latn),var:not(:lang(zh)):not(:lang(ja)){font-family:"Latin Italic Serif",Georgia,"Times New Roman","Han Kaiti",cursive,serif}i:lang(zh),i:lang(zh-Hant),var:lang(zh),var:lang(zh-Hant){font-family:"Biaodian Pro Serif CNS","Numeral LF Italic Serif","Latin Italic Serif",Georgia,"Times New Roman","Zhuyin Kaiti","Han Kaiti",cursive,serif}.no-unicoderange i:lang(zh),.no-unicoderange i:lang(zh-Hant),.no-unicoderange var:lang(zh),.no-unicoderange var:lang(zh-Hant){font-family:"Numeral LF Italic Serif","Latin Italic Serif",Georgia,"Times New Roman","Han Kaiti",cursive,serif}i:lang(zh-CN),i:lang(zh-Hans),var:lang(zh-CN),var:lang(zh-Hans){font-family:"Biaodian Pro Serif GB","Numeral LF Italic Serif","Latin Italic Serif",Georgia,"Times New Roman","Han Kaiti GB",cursive,serif}.no-unicoderange i:lang(zh-CN),.no-unicoderange i:lang(zh-Hans),.no-unicoderange var:lang(zh-CN),.no-unicoderange var:lang(zh-Hans){font-family:"Numeral LF Italic Serif","Latin Italic Serif",Georgia,"Times New Roman","Han Kaiti GB",cursive,serif}i:lang(ja),var:lang(ja){font-family:"Yakumono Serif","Numeral LF Italic Serif","Latin Italic Serif",Georgia,"Times New Roman",cursive,serif}.no-unicoderange i:lang(ja),.no-unicoderange var:lang(ja){font-family:"Numeral LF Italic Serif","Latin Italic Serif",Georgia,"Times New Roman",cursive,serif}code :lang(ja-Latn),code :lang(zh-Latn),code :not(:lang(zh)):not(:lang(ja)),code:lang(ja-Latn),code:lang(zh-Latn),code:not(:lang(zh)):not(:lang(ja)),kbd :lang(ja-Latn),kbd :lang(zh-Latn),kbd :not(:lang(zh)):not(:lang(ja)),kbd:lang(ja-Latn),kbd:lang(zh-Latn),kbd:not(:lang(zh)):not(:lang(ja)),pre :lang(ja-Latn),pre :lang(zh-Latn),pre :not(:lang(zh)):not(:lang(ja)),pre:lang(ja-Latn),pre:lang(zh-Latn),pre:not(:lang(zh)):not(:lang(ja)),samp :lang(ja-Latn),samp :lang(zh-Latn),samp :not(:lang(zh)):not(:lang(ja)),samp:lang(ja-Latn),samp:lang(zh-Latn),samp:not(:lang(zh)):not(:lang(ja)){font-family:Menlo,Consolas,Courier,"Han Heiti",monospace,monospace,sans-serif}code:lang(zh),code:lang(zh-Hant),kbd:lang(zh),kbd:lang(zh-Hant),pre:lang(zh),pre:lang(zh-Hant),samp:lang(zh),samp:lang(zh-Hant){font-family:"Biaodian Pro Sans CNS",Menlo,Consolas,Courier,"Zhuyin Heiti","Han Heiti",monospace,monospace,sans-serif}.no-unicoderange code:lang(zh),.no-unicoderange code:lang(zh-Hant),.no-unicoderange kbd:lang(zh),.no-unicoderange kbd:lang(zh-Hant),.no-unicoderange pre:lang(zh),.no-unicoderange pre:lang(zh-Hant),.no-unicoderange samp:lang(zh),.no-unicoderange samp:lang(zh-Hant){font-family:Menlo,Consolas,Courier,"Han Heiti",monospace,monospace,sans-serif}code:lang(zh-CN),code:lang(zh-Hans),kbd:lang(zh-CN),kbd:lang(zh-Hans),pre:lang(zh-CN),pre:lang(zh-Hans),samp:lang(zh-CN),samp:lang(zh-Hans){font-family:"Biaodian Pro Sans GB",Menlo,Consolas,Courier,"Han Heiti GB",monospace,monospace,sans-serif}.no-unicoderange code:lang(zh-CN),.no-unicoderange code:lang(zh-Hans),.no-unicoderange kbd:lang(zh-CN),.no-unicoderange kbd:lang(zh-Hans),.no-unicoderange pre:lang(zh-CN),.no-unicoderange pre:lang(zh-Hans),.no-unicoderange samp:lang(zh-CN),.no-unicoderange samp:lang(zh-Hans){font-family:Menlo,Consolas,Courier,"Han Heiti GB",monospace,monospace,sans-serif}code:lang(ja),kbd:lang(ja),pre:lang(ja),samp:lang(ja){font-family:"Yakumono Sans",Menlo,Consolas,Courier,monospace,monospace,sans-serif}.no-unicoderange code:lang(ja),.no-unicoderange kbd:lang(ja),.no-unicoderange pre:lang(ja),.no-unicoderange samp:lang(ja){font-family:Menlo,Consolas,Courier,monospace,monospace,sans-serif}.no-unicoderange h-char.bd-liga,.no-unicoderange h-char[unicode=b7],h-ruby [annotation] rt,h-ruby h-zhuyin,h-ruby h-zhuyin h-diao,h-ruby.romanization rt,html,ruby [annotation] rt,ruby h-zhuyin,ruby h-zhuyin h-diao,ruby.romanization rt{-moz-font-feature-settings:"liga";-ms-font-feature-settings:"liga";-webkit-font-feature-settings:"liga";font-feature-settings:"liga"}[lang*=Hant],[lang*=Hans],[lang=zh-TW],[lang=zh-HK],[lang=zh-CN],[lang^=zh],article blockquote i,article blockquote var,article strong,code,html,kbd,pre,samp{-moz-font-feature-settings:"liga=1, locl=0";-ms-font-feature-settings:"liga","locl" 0;-webkit-font-feature-settings:"liga","locl" 0;font-feature-settings:"liga","locl" 0}.no-unicoderange h-char.bd-cop:lang(zh-HK),.no-unicoderange h-char.bd-cop:lang(zh-Hant),.no-unicoderange h-char.bd-cop:lang(zh-TW){font-family:-apple-system,"Han Heiti CNS"}.no-unicoderange h-char.bd-liga,.no-unicoderange h-char[unicode=b7]{font-family:"Biaodian Basic","Han Heiti"}.no-unicoderange h-char[unicode="2018"]:lang(zh-CN),.no-unicoderange h-char[unicode="2018"]:lang(zh-Hans),.no-unicoderange h-char[unicode="2019"]:lang(zh-CN),.no-unicoderange h-char[unicode="2019"]:lang(zh-Hans),.no-unicoderange h-char[unicode="201c"]:lang(zh-CN),.no-unicoderange h-char[unicode="201c"]:lang(zh-Hans),.no-unicoderange h-char[unicode="201d"]:lang(zh-CN),.no-unicoderange h-char[unicode="201d"]:lang(zh-Hans){font-family:"Han Heiti GB"}i,var{font-style:inherit}.no-unicoderange h-ruby h-zhuyin,.no-unicoderange h-ruby h-zhuyin h-diao,.no-unicoderange ruby h-zhuyin,.no-unicoderange ruby h-zhuyin h-diao,h-ruby h-diao,ruby h-diao{font-family:"Zhuyin Kaiti",cursive,serif}h-ruby [annotation] rt,h-ruby.romanization rt,ruby [annotation] rt,ruby.romanization rt{font-family:"Romanization Sans","Helvetica Neue",Helvetica,Arial,"Han Heiti",sans-serif}.no-kaiti i,.no-kaiti var{padding-bottom:.05em;border-bottom:3px double #d3d3d3}article h1+blockquote,article h1+h2,article h1+h3,article h1+h4,article h1+h5,article h1+h6,article h1+ol,article h1+p,article h1+section>blockquote:first-child,article h1+section>h2:first-child,article h1+section>h3:first-child,article h1+section>h4:first-child,article h1+section>h5:first-child,article h1+section>h6:first-child,article h1+section>ol:first-child,article h1+section>p:first-child,article h1+section>ul:first-child,article h1+ul,article h2+blockquote,article h2+h2,article h2+h3,article h2+h4,article h2+h5,article h2+h6,article h2+ol,article h2+p,article h2+section>blockquote:first-child,article h2+section>h2:first-child,article h2+section>h3:first-child,article h2+section>h4:first-child,article h2+section>h5:first-child,article h2+section>h6:first-child,article h2+section>ol:first-child,article h2+section>p:first-child,article h2+section>ul:first-child,article h2+ul,article h3+blockquote,article h3+h3,article h3+h4,article h3+h5,article h3+h6,article h3+ol,article h3+p,article h3+section>blockquote:first-child,article h3+section>h3:first-child,article h3+section>h4:first-child,article h3+section>h5:first-child,article h3+section>h6:first-child,article h3+section>ol:first-child,article h3+section>p:first-child,article h3+section>ul:first-child,article h3+ul,article h4+blockquote,article h4+h4,article h4+h5,article h4+h6,article h4+ol,article h4+p,article h4+section>blockquote:first-child,article h4+section>h4:first-child,article h4+section>h5:first-child,article h4+section>h6:first-child,article h4+section>ol:first-child,article h4+section>p:first-child,article h4+section>ul:first-child,article h4+ul,article h5+blockquote,article h5+h5,article h5+h6,article h5+ol,article h5+p,article h5+section>blockquote:first-child,article h5+section>h5:first-child,article h5+section>h6:first-child,article h5+section>ol:first-child,article h5+section>p:first-child,article h5+section>ul:first-child,article h5+ul,article h6+blockquote,article h6+h6,article h6+ol,article h6+p,article h6+section>blockquote:first-child,article h6+section>h6:first-child,article h6+section>ol:first-child,article h6+section>p:first-child,article h6+section>ul:first-child,article h6+ul{margin-top:-1em}article{line-height:1.7;-moz-hyphens:auto;-ms-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}article li,article p{text-align:justify;text-justify:inter-ideograph}.poem-like p,p.poem-like{margin-left:2em}@media only screen and (max-width:480px){.poem-like p,article blockquote,p.poem-like{margin-left:1em}blockquote,figure{margin-left:1em;margin-right:1em}}figure blockquote{margin:0}blockquote blockquote{margin-left:1em;margin-right:1em}h-hws,h-hws[hidden]{display:inline;visibility:hidden;font:.89em Arial}code h-hws,code h-hws[hidden],h-hws.quote-inner,h-hws.quote-outer:lang(zh-CN),h-hws.quote-outer:lang(zh-Hans),h-hws[hidden].quote-inner,h-hws[hidden].quote-outer:lang(zh-CN),h-hws[hidden].quote-outer:lang(zh-Hans),kbd h-hws,kbd h-hws[hidden],pre h-hws,pre h-hws[hidden],samp h-hws,samp h-hws[hidden]{display:none}@font-face{src:url(./font/han-space.woff?v3.3.0) format("woff"),url(./font/han-space.otf?v3.3.0) format("opentype");font-family:"Han Space";unicode-range:U+20}h-char.bd-hangable:lang(zh) h-cs,h-char.bd-hangable:lang(zh) h-cs[hidden],h-char.bd-hangable:lang(zh-HK) h-cs,h-char.bd-hangable:lang(zh-HK) h-cs[hidden],h-char.bd-hangable:lang(zh-Hant) h-cs,h-char.bd-hangable:lang(zh-Hant) h-cs[hidden],h-char.bd-hangable:lang(zh-TW) h-cs,h-char.bd-hangable:lang(zh-TW) h-cs[hidden],h-cs,h-cs[hidden]{display:inline;visibility:inherit;font-family:inherit;font-size:inherit}h-cs.hangable-outer,h-cs.hangable-outer[hidden]{display:inline;font:1em "Han Space"}h-cs.hangable-outer:lang(zh-HK),h-cs.hangable-outer:lang(zh-Hant),h-cs.hangable-outer:lang(zh-TW),h-cs.hangable-outer[hidden]:lang(zh-HK),h-cs.hangable-outer[hidden]:lang(zh-Hant),h-cs.hangable-outer[hidden]:lang(zh-TW){display:none}h-char.bd-hangable:lang(ja),h-char.bd-hangable:lang(zh-CN),h-char.bd-hangable:lang(zh-Hans){position:relative}h-char.bd-hangable:lang(ja):after,h-char.bd-hangable:lang(zh-CN):after,h-char.bd-hangable:lang(zh-Hans):after{display:none!important}h-char.bd-hangable:lang(ja):before,h-char.bd-hangable:lang(zh-CN):before,h-char.bd-hangable:lang(zh-Hans):before{display:inline!important;content:" ";font:1em "Han Space",Menlo,Consolas,Courier}h-char.bd-hangable:lang(ja)>h-inner,h-char.bd-hangable:lang(zh-CN)>h-inner,h-char.bd-hangable:lang(zh-Hans)>h-inner{-moz-text-emphasis:none;-webkit-text-emphasis:none;text-emphasis:none;font-style:normal;font-weight:400;text-decoration:none;text-indent:0;position:absolute;left:0;top:0;display:inline-block;line-height:1.1}h-ru h-char.bd-hangable:lang(ja)>h-inner,h-ru h-char.bd-hangable:lang(zh-CN)>h-inner,h-ru h-char.bd-hangable:lang(zh-Hans)>h-inner,ruby h-char.bd-hangable:lang(ja)>h-inner,ruby h-char.bd-hangable:lang(zh-CN)>h-inner,ruby h-char.bd-hangable:lang(zh-Hans)>h-inner{position:relative}h-char.bd-jiya.bd-end:after,h-char.bd-jiya.bd-open:before,h-cs,h-cs[hidden]{display:none;visibility:hidden;content:" ";font:.825em Courier;letter-spacing:0;white-space:normal}h-char.bd-jiya.bd-close:after,h-char.bd-jiya.bd-cop:after,h-char.bd-jiya.bd-open:before,h-char.bd-jiya[unicode=ff0e]:after,h-cs.jinze-outer,h-cs.jinze-outer[hidden]{display:inline}h-char.bd-jiya.bd-open>h-inner{margin-left:-.5em}h-char.bd-jiya.bd-close>h-inner,h-char.bd-jiya.bd-cop>h-inner,h-char.bd-jiya[unicode=ff0e]>h-inner{letter-spacing:-.5em}h-char.bd-consecutive.bd-end:not(.end-portion):after,h-char.bd-consecutive.bd-open[prev=bd-open]:before,h-char.bd-jiya.bd-cop:lang(zh-HK):after,h-char.bd-jiya.bd-cop:lang(zh-Hant):after,h-char.bd-jiya.bd-cop:lang(zh-TW):after,h-cs.jiya-outer.bd-end:not(.end-portion){display:none}h-char.bd-jiya.bd-cop:lang(zh-HK)>h-inner,h-char.bd-jiya.bd-cop:lang(zh-Hant)>h-inner,h-char.bd-jiya.bd-cop:lang(zh-TW)>h-inner{letter-spacing:inherit}h-cs.jiya-outer.bd-end[next=bd-open]{display:inline}h-char.bd-consecutive.bd-open[prev*=bd-cop]:lang(zh-HK):before,h-char.bd-consecutive.bd-open[prev*=bd-cop]:lang(zh-Hant):before,h-char.bd-consecutive.bd-open[prev*=bd-cop]:lang(zh-TW):before,h-cs.jiya-outer.bd-end:lang(zh-HK),h-cs.jiya-outer.bd-end:lang(zh-Hant),h-cs.jiya-outer.bd-end:lang(zh-TW),h-cs.jiya-outer[prev*=bd-cop]:lang(zh-HK),h-cs.jiya-outer[prev*=bd-cop]:lang(zh-Hant),h-cs.jiya-outer[prev*=bd-cop]:lang(zh-TW){display:none}h-char.bd-consecutive[unicode=b7]:not(.end-portion),h-char.bd-consecutive[unicode="30fb"]:not(.end-portion){letter-spacing:-.5em}h-char.bd-consecutive.bd-liga:not(.end-portion){margin-right:-.25em}h-char[display-as]{position:relative;display:inline-block}h-char[display-as] h-inner{color:transparent}h-char[display-as]:after{position:absolute;left:0;display:inline-block;content:attr(display-as)}h-char[display-as].comb-liga:after{font-family:"Romanization Sans","Zhuyin Kaiti"} \ No newline at end of file diff --git a/lib/Han/dist/han.min.js b/lib/Han/dist/han.min.js new file mode 100644 index 0000000..a557ad3 --- /dev/null +++ b/lib/Han/dist/han.min.js @@ -0,0 +1,5 @@ +/*! 漢字標準格式 v3.3.0 | MIT License | css.hanzi.co */ +/*! Han.css: the CSS typography framework optimised for Hanzi */ + +void function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=b(a,!0):"function"==typeof define&&define.amd?define(function(){return b(a,!0)}):b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";function c(a){return"function"==typeof a||a instanceof Element?a:void 0}function d(a){var b=0===a.index&&a.isEnd?"biaodian cjk":"biaodian cjk portion "+(0===a.index?"is-first":a.isEnd?"is-end":"is-inner"),c=S.create("h-char-group",b);return c.innerHTML=a.text,c}function e(a){var b=S.create("div"),c=a.charCodeAt(0).toString(16);return b.innerHTML=''+a+"",b.firstChild}function f(a){return a.match(R["char"].biaodian.open)?"bd-open":a.match(R["char"].biaodian.close)?"bd-close bd-end":a.match(R["char"].biaodian.end)?/(?:\u3001|\u3002|\uff0c)/i.test(a)?"bd-end bd-cop":"bd-end":a.match(new RegExp(Q.biaodian.liga))?"bd-liga":a.match(new RegExp(Q.biaodian.middle))?"bd-middle":""}function g(a,b){var c,d=S.create("canvas");return d.width="50",d.height="20",d.style.display="none",L.appendChild(d),c=d.getContext("2d"),c.textBaseline="top",c.font="15px "+b+", sans-serif",c.fillStyle="black",c.strokeStyle="black",c.fillText(a,0,0),{node:d,context:c,remove:function(){S.remove(d,L)}}}function h(a,b){var c,d=a.context,e=b.context;try{for(var f=1;20>=f;f++)for(var g=1;50>=g;g++){if("undefined"==typeof c&&d.getImageData(g,f,1,1).data[3]!==e.getImageData(g,f,1,1).data[3]){c=!1;break}if("boolean"==typeof c)break;50===g&&20===f&&"undefined"==typeof c&&(c=!0)}return a.remove(),b.remove(),a=null,b=null,c}catch(h){}return!1}function i(a,b,c){var a=a,b=b||"sans-serif",c=c||"\u8fadQ";return b=g(c,b),a=g(c,a),!h(a,b)}function j(a){var b,c=S.create("!"),d=a.classList;return c.appendChild(S.clone(a)),S.tag("rt",c.firstChild).forEach(function(a){var c,e=S.create("!"),f=[];do{if(c=(c||a).previousSibling,!c||c.nodeName.match(/((?:h\-)?r[ubt])/i))break;e.insertBefore(S.clone(c),e.firstChild),f.push(c)}while(!c.nodeName.match(/((?:h\-)?r[ubt])/i));b=d.contains("zhuyin")?p(e,a):o(e,a);try{a.parentNode.replaceChild(b,a),f.map(S.remove)}catch(g){}}),m(c)}function k(a){var b=S.create("!");return b.appendChild(S.clone(a)),S.tag("rt",b.firstChild).forEach(function(a){var b,c,d=S.create("!"),e=[];do{if(b=(b||a).previousSibling,!b||b.nodeName.match(/((?:h\-)?r[ubt])/i))break;d.insertBefore(S.clone(b),d.firstChild),e.push(b)}while(!b.nodeName.match(/((?:h\-)?r[ubt])/i));c=S.create("rt"),c.innerHTML=q(a),a.parentNode.replaceChild(c,a)}),b.firstChild}function l(a){var b,c,d,e,f=S.create("!"),g=a.classList;return f.appendChild(S.clone(a)),b=f.firstChild,c=d=S.tag("rb",b),e=c.length,void function(a){a&&(d=S.tag("rt",a).map(function(a,b){if(c[b]){var d=p(c[b],a);try{c[b].parentNode.replaceChild(d,c[b])}catch(e){}return d}}),S.remove(a),b.setAttribute("rightangle","true"))}(b.querySelector("rtc.zhuyin")),S.qsa("rtc:not(.zhuyin)",b).forEach(function(a,c){var f;f=S.tag("rt",a).map(function(a,b){var f,h,i=Number(a.getAttribute("rbspan")||1),j=0,k=[];i>e&&(i=e);do{try{f=d.shift(),k.push(f)}catch(l){}if("undefined"==typeof f)break;j+=Number(f.getAttribute("span")||1)}while(i>j);if(j>i){if(k.length>1)return void console.error("An impossible `rbspan` value detected.",ruby);k=S.tag("rb",k[0]),d=k.slice(i).concat(d),k=k.slice(0,i),j=i}h=o(k,a,{"class":g,span:j,order:c});try{k[0].parentNode.replaceChild(h,k.shift()),k.map(S.remove)}catch(l){}return h}),d=f,1===c&&b.setAttribute("doubleline","true"),S.remove(a)}),m(f)}function m(a){var b=a.firstChild,c=S.create("h-ruby");return c.innerHTML=b.innerHTML,S.setAttr(c,b.attributes),c.normalize(),c}function n(a){if(!a instanceof Element)return a;var b=a.classList;return b.contains("pinyin")?b.add("romanization"):b.contains("romanization")?b.add("annotation"):b.contains("mps")?b.add("zhuyin"):b.contains("rightangle")&&b.add("complex"),a}function o(a,b,c){var d=S.create("h-ru"),b=S.clone(b),c=c||{};return c.annotation="true",Array.isArray(a)?d.innerHTML=a.map(function(a){return"undefined"==typeof a?"":a.outerHTML}).join("")+b.outerHTML:(d.appendChild(S.clone(a)),d.appendChild(b)),S.setAttr(d,c),d}function p(a,b){var a=S.clone(a),c=S.create("h-ru");return c.setAttribute("zhuyin",!0),c.appendChild(a),c.innerHTML+=q(b),c}function q(a){var b,c,d,e="string"==typeof a?a:a.textContent;return b=e.replace(R.zhuyin.diao,""),d=b?b.length:0,c=e.replace(b,"").replace(/[\u02C5]/g,"\u02c7").replace(/[\u030D]/g,"\u0358"),0===d?"":''+b+""+c+""}function r(a,b){return a&&b&&a.parentNode===b.parentNode}function s(a,b){var c=a,b=b||"";if(S.isElmt(a.nextSibling)||r(a,a.nextSibling))return b+X;for(;!c.nextSibling;)c=c.parentNode;return a!==c&&c.insertAdjacentHTML("afterEnd",""),b}function t(a,b){return a.isEnd&&0===a.index?b[1]+X+b[2]:0===a.index?s(a.node,a.text):a.text}function u(a){return 0===a.index?S.clone(Y):""}function v(a){var b=a.node.parentNode;return 0===a.index&&(Z=a.endIndexInNode-2),"h-hws"!==b.nodeName.toLowerCase()||1!==a.index&&a.indexInMatch!==Z||b.classList.add("quote-inner"),a.text}function w(a){var b=a.node.parentNode;return"h-hws"===b.nodeName.toLowerCase()&&b.classList.add("quote-outer"),a.text}function x(){var a,b=S.create("div");return b.innerHTML="a ba b",L.appendChild(b),a=b.firstChild.offsetWidth!==b.lastChild.offsetWidth,S.remove(b),a}function y(a){var b=a.nextSibling;b&&ba(b,"h-cs.jinze-outer")?b.classList.add("hangable-outer"):a.insertAdjacentHTML("afterend",aa)}function z(a){return a.replace(/(biaodian|cjk|bd-jiya|bd-consecutive|bd-hangable)/gi,"").trim()}function A(a){var b,c=a.text,d=a.node.parentNode,e=S.parent(d,"h-char.biaodian"),f=O.createBDChar(c);return f.innerHTML=""+c+"",f.classList.add(ea),(b=S.parent(d,"h-jinze"))&&C(b),e?function(){return e.classList.add(ea),ba(d,"h-inner, h-inner *")?c:f.firstChild}():f}function B(a){var b,c=ca,d=a.node.parentNode,e=S.parent(d,"h-char.biaodian"),f=S.parent(e,"h-jinze");return b=e.classList,c&&e.setAttribute("prev",c),da&&b.contains("bd-open")&&da.pop().setAttribute("next","bd-open"),da=void 0,a.isEnd?(ca=void 0,b.add(ga,"end-portion")):(ca=z(e.getAttribute("class")),b.add(ga)),f&&(da=D(f,{prev:c,"class":z(e.getAttribute("class"))})),a.text}function C(a){ba(a,".tou, .touwei")&&!ba(a.previousSibling,"h-cs.jiya-outer")&&a.insertAdjacentHTML("beforebegin",ha),ba(a,".wei, .touwei")&&!ba(a.nextSibling,"h-cs.jiya-outer")&&a.insertAdjacentHTML("afterend",ha)}function D(a,b){var c,d;return ba(a,".tou, .touwei")&&(c=a.previousSibling,ba(c,"h-cs")&&(c.className="jinze-outer jiya-outer",c.setAttribute("prev",b.prev))),ba(a,".wei, .touwei")&&(d=a.nextSibling,ba(d,"h-cs")&&(d.className="jinze-outer jiya-outer "+b["class"],d.removeAttribute("prev"))),[c,d]}function E(a,b,c){return function(){var d=O.localize.writeOnCanvas(b,a),e=O.localize.writeOnCanvas(c,a);return O.localize.compareCanvases(d,e)}}function F(){return E('"Romanization Sans"',"a\u030d","\udb80\udc61")}function G(){return E('"Romanization Sans"',"i\u030d","\udb80\udc69")}function H(){return E('"Zhuyin Kaiti"',"\u31b4\u0358","\udb8c\uddb4")}function I(a){return function(b){var b=b||J,c=O.find(b).avoid(ia);return a.forEach(function(a){c.replace(new RegExp(a[0],"ig"),function(b,c){var d=S.clone(ja);return d.innerHTML=""+c[0]+"",d.setAttribute("display-as",a[1]),0===b.index?d:""})}),c}}var J=a.document,K=J.documentElement,L=J.body,M="3.3.0",N=["initCond","renderElem","renderJiya","renderHanging","correctBiaodian","renderHWS","substCombLigaWithPUA"],O=function(a,b){return new O.fn.init(a,b)},P=function(){return arguments[0]&&(this.context=arguments[0]),arguments[1]&&(this.condition=arguments[1]),this};O.version=M,O.fn=O.prototype={version:M,constructor:O,context:L,condition:K,routine:N,init:P,setRoutine:function(a){return Array.isArray(a)&&(this.routine=a),this},render:function(a){var b=this,a=Array.isArray(a)?a:this.routine;return a.forEach(function(a){"string"==typeof a&&"function"==typeof b[a]?b[a]():Array.isArray(a)&&"function"==typeof b[a[0]]&&b[a.shift()].apply(b,a)}),this}},O.fn.init.prototype=O.fn,O.init=function(){return O.init=O().render()};var Q={punct:{base:"[\u2026,.;:!?\u203d_]",sing:"[\u2010-\u2014\u2026]",middle:"[\\/~\\-&\u2010-\u2014_]",open:"['\"\u2018\u201c\\(\\[\xa1\xbf\u2e18\xab\u2039\u201a\u201c\u201e]",close:"['\"\u201d\u2019\\)\\]\xbb\u203a\u201b\u201d\u201f]",end:"['\"\u201d\u2019\\)\\]\xbb\u203a\u201b\u201d\u201f\u203c\u203d\u2047-\u2049,.;:!?]"},biaodian:{base:"[\ufe30\uff0e\u3001\uff0c\u3002\uff1a\uff1b\uff1f\uff01\u30fc]",liga:"[\u2014\u2026\u22ef]",middle:"[\xb7\uff3c\uff0f\uff0d\u30a0\uff06\u30fb\uff3f]",open:"[\u300c\u300e\u300a\u3008\uff08\u3014\uff3b\uff5b\u3010\u3016]",close:"[\u300d\u300f\u300b\u3009\uff09\u3015\uff3d\uff5d\u3011\u3017]",end:"[\u300d\u300f\u300b\u3009\uff09\u3015\uff3d\uff5d\u3011\u3017\ufe30\uff0e\u3001\uff0c\u3002\uff1a\uff1b\uff1f\uff01\u30fc]"},hanzi:{base:"[\u4e00-\u9fff\u3400-\u4db5\u31c0-\u31e3\u3007\ufa0e\ufa0f\ufa11\ufa13\ufa14\ufa1f\ufa21\ufa23\ufa24\ufa27-\ufa29]|[\ud800-\udbff][\udc00-\udfff]",desc:"[\u2ff0-\u2ffa]",radical:"[\u2f00-\u2fd5\u2e80-\u2ef3]"},latin:{base:"[A-Za-z0-9\xc0-\xff\u0100-\u017f\u0180-\u024f\u2c60-\u2c7f\ua720-\ua7ff\u1e00-\u1eff]",combine:"[\u0300-\u0341\u1dc0-\u1dff]"},ellinika:{base:"[0-9\u0370-\u03ff\u1f00-\u1fff]",combine:"[\u0300-\u0345\u1dc0-\u1dff]"},kirillica:{base:"[0-9\u0400-\u0482\u048a-\u04ff\u0500-\u052f\ua640-\ua66e\ua67e-\ua697]",combine:"[\u0483-\u0489\u2de0-\u2dff\ua66f-\ua67d\ua69f]"},kana:{base:"[\u30a2\u30a4\u30a6\u30a8\u30aa-\u30fa\u3042\u3044\u3046\u3048\u304a-\u3094\u309f\u30ff]|\ud82c[\udc00-\udc01]",small:"[\u3041\u3043\u3045\u3047\u3049\u30a1\u30a3\u30a5\u30a7\u30a9\u3063\u3083\u3085\u3087\u308e\u3095\u3096\u30c3\u30e3\u30e5\u30e7\u30ee\u30f5\u30f6\u31f0-\u31ff]",combine:"[\u3099-\u309c]",half:"[\uff66-\uff9f]",mark:"[\u30a0\u309d\u309e\u30fb-\u30fe]"},eonmun:{base:"[\uac00-\ud7a3]",letter:"[\u1100-\u11ff\u314f-\u3163\u3131-\u318e\ua960-\ua97c\ud7b0-\ud7fb]",half:"[\uffa1-\uffdc]"},zhuyin:{base:"[\u3105-\u312d\u31a0-\u31ba]",initial:"[\u3105-\u3119\u312a-\u312c\u31a0-\u31a3]",medial:"[\u3127-\u3129]","final":"[\u311a-\u3129\u312d\u31a4-\u31b3\u31b8-\u31ba]",tone:"[\u02d9\u02ca\u02c5\u02c7\u02cb\u02ea\u02eb]",checked:"[\u31b4-\u31b7][\u0358\u030d]?"}},R=function(){var a="[\\x20\\t\\r\\n\\f]",b=Q.punct.open,c=(Q.punct.close,Q.punct.end),d=Q.punct.middle,e=Q.punct.sing,f=b+"|"+c+"|"+d,g=Q.biaodian.open,h=Q.biaodian.close,i=Q.biaodian.end,j=Q.biaodian.middle,k=Q.biaodian.liga+"{2}",l=g+"|"+i+"|"+j,m=Q.kana.base+Q.kana.combine+"?",n=Q.kana.small+Q.kana.combine+"?",o=Q.kana.half,p=Q.eonmun.base+"|"+Q.eonmun.letter,q=Q.eonmun.half,r=Q.hanzi.base+"|"+Q.hanzi.desc+"|"+Q.hanzi.radical+"|"+m,s=Q.ellinika.combine,t=Q.latin.base+s+"*",u=Q.ellinika.base+s+"*",v=Q.kirillica.combine,w=Q.kirillica.base+v+"*",x=t+"|"+u+"|"+w,y="['\u2019]",z=r+"|(?:"+x+"|"+y+")+",A=Q.zhuyin.initial,B=Q.zhuyin.medial,C=Q.zhuyin["final"],D=Q.zhuyin.tone+"|"+Q.zhuyin.checked;return{"char":{punct:{all:new RegExp("("+f+")","g"),open:new RegExp("("+b+")","g"),end:new RegExp("("+c+")","g"),sing:new RegExp("("+e+")","g")},biaodian:{all:new RegExp("("+l+")","g"),open:new RegExp("("+g+")","g"),close:new RegExp("("+h+")","g"),end:new RegExp("("+i+")","g"),liga:new RegExp("("+k+")","g")},hanzi:new RegExp("("+r+")","g"),latin:new RegExp("("+t+")","ig"),ellinika:new RegExp("("+u+")","ig"),kirillica:new RegExp("("+w+")","ig"),kana:new RegExp("("+m+"|"+n+"|"+o+")","g"),eonmun:new RegExp("("+p+"|"+q+")","g")},group:{biaodian:[new RegExp("(("+l+"){2,})","g"),new RegExp("("+k+g+")","g")],punct:null,hanzi:new RegExp("("+r+")+","g"),western:new RegExp("("+t+"|"+u+"|"+w+"|"+f+")+","ig"),kana:new RegExp("("+m+"|"+n+"|"+o+")+","g"),eonmun:new RegExp("("+p+"|"+q+"|"+f+")+","g")},jinze:{hanging:new RegExp(a+"*([\u3001\uff0c\u3002\uff0e])(?!"+i+")","ig"),touwei:new RegExp("("+g+"+)("+z+")("+i+"+)","ig"),tou:new RegExp("("+g+"+)("+z+")","ig"),wei:new RegExp("("+z+")("+i+"+)","ig"),middle:new RegExp("("+z+")("+j+")("+z+")","ig")},zhuyin:{form:new RegExp("^\u02d9?("+A+")?("+B+")?("+C+")?("+D+")?$"),diao:new RegExp("("+D+")","g")},hws:{base:[new RegExp("("+r+")("+x+"|"+b+")","ig"),new RegExp("("+x+"|"+c+")("+r+")","ig")],strict:[new RegExp("("+r+")"+a+"?("+x+"|"+b+")","ig"),new RegExp("("+x+"|"+c+")"+a+"?("+r+")","ig")]},"display-as":{"ja-font-for-hant":["\u67e5 \u67fb","\u555f \u5553","\u9109 \u9115","\u503c \u5024","\u6c61 \u6c5a"],"comb-liga-pua":[["a[\u030d\u0358]","\udb80\udc61"],["e[\u030d\u0358]","\udb80\udc65"],["i[\u030d\u0358]","\udb80\udc69"],["o[\u030d\u0358]","\udb80\udc6f"],["u[\u030d\u0358]","\udb80\udc75"],["\u31b4[\u030d\u0358]","\udb8c\uddb4"],["\u31b5[\u030d\u0358]","\udb8c\uddb5"],["\u31b6[\u030d\u0358]","\udb8c\uddb6"],["\u31b7[\u030d\u0358]","\udb8c\uddb7"]],"comb-liga-vowel":[["a[\u030d\u0358]","\udb80\udc61"],["e[\u030d\u0358]","\udb80\udc65"],["i[\u030d\u0358]","\udb80\udc69"],["o[\u030d\u0358]","\udb80\udc6f"],["u[\u030d\u0358]","\udb80\udc75"]],"comb-liga-zhuyin":[["\u31b4[\u030d\u0358]","\udb8c\uddb4"],["\u31b5[\u030d\u0358]","\udb8c\uddb5"],["\u31b6[\u030d\u0358]","\udb8c\uddb6"],["\u31b7[\u030d\u0358]","\udb8c\uddb7"]]},"inaccurate-char":[["[\u2022\u2027]","\xb7"],["\u22ef\u22ef","\u2026\u2026"],["\u2500\u2500","\u2014\u2014"],["\u2035","\u2018"],["\u2032","\u2019"],["\u2036","\u201c"],["\u2033","\u201d"]]}}();O.UNICODE=Q,O.TYPESET=R,O.UNICODE.cjk=O.UNICODE.hanzi,O.UNICODE.greek=O.UNICODE.ellinika,O.UNICODE.cyrillic=O.UNICODE.kirillica,O.UNICODE.hangul=O.UNICODE.eonmun,O.UNICODE.zhuyin.ruyun=O.UNICODE.zhuyin.checked,O.TYPESET["char"].cjk=O.TYPESET["char"].hanzi,O.TYPESET["char"].greek=O.TYPESET["char"].ellinika,O.TYPESET["char"].cyrillic=O.TYPESET["char"].kirillica,O.TYPESET["char"].hangul=O.TYPESET["char"].eonmun,O.TYPESET.group.hangul=O.TYPESET.group.eonmun,O.TYPESET.group.cjk=O.TYPESET.group.hanzi;var S={id:function(a,b){return(b||J).getElementById(a)},tag:function(a,b){return this.makeArray((b||J).getElementsByTagName(a))},qs:function(a,b){return(b||J).querySelector(a)},qsa:function(a,b){return this.makeArray((b||J).querySelectorAll(a))},parent:function(a,b){return b?function(){if("function"==typeof S.matches){for(;!S.matches(a,b);){if(!a||a===J.documentElement){a=void 0;break}a=a.parentNode}return a}}():a?a.parentNode:void 0},create:function(a,b){var c="!"===a?J.createDocumentFragment():""===a?J.createTextNode(b||""):J.createElement(a);try{b&&(c.className=b)}catch(d){}return c},clone:function(a,b){return a.cloneNode("boolean"==typeof b?b:!0)},remove:function(a){return a.parentNode.removeChild(a)},setAttr:function(a,b){if("object"==typeof b){var c=b.length;if("object"==typeof b[0]&&"name"in b[0])for(var d=0;c>d;d++)void 0!==b[d].value&&a.setAttribute(b[d].name,b[d].value);else for(var e in b)b.hasOwnProperty(e)&&void 0!==b[e]&&a.setAttribute(e,b[e]);return a}},isElmt:function(a){return a&&a.nodeType===Node.ELEMENT_NODE},isIgnorable:function(a){return a?"WBR"===a.nodeName||a.nodeType===Node.COMMENT_NODE:!1},makeArray:function(a){return Array.prototype.slice.call(a)},extend:function(a,b){if(("object"==typeof a||"function"==typeof a)&&"object"==typeof b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}},T=function(b){function c(a,b,c){var d=Element.prototype,e=d.matches||d.mozMatchesSelector||d.msMatchesSelector||d.webkitMatchesSelector;return a instanceof Element?e.call(a,b):c&&/^[39]$/.test(a.nodeType)?!0:!1}var d="0.2.1",e=b.NON_INLINE_PROSE,f=b.PRESETS.prose.filterElements,g=a||{},h=g.document||void 0;if("undefined"==typeof h)throw new Error("Fibre requires a DOM-supported environment.");var i=function(a,b){return new i.fn.init(a,b)};return i.version=d,i.matches=c,i.fn=i.prototype={constructor:i,version:d,finder:[],context:void 0,portionMode:"retain",selector:{},preset:"prose",init:function(a,b){if(b&&(this.preset=null),this.selector={context:null,filter:[],avoid:[],boundary:[]},!a)throw new Error("A context is required for Fibre to initialise.");return a instanceof Node?a instanceof Document?this.context=a.body||a:this.context=a:"string"==typeof a&&(this.context=h.querySelector(a),this.selector.context=a),this},filterFn:function(a){var b=this.selector.filter.join(", ")||"*",d=this.selector.avoid.join(", ")||null,e=c(a,b,!0)&&!c(a,d);return"prose"===this.preset?f(a)&&e:e},boundaryFn:function(a){var b=this.selector.boundary.join(", ")||null,d=c(a,b);return"prose"===this.preset?e(a)||d:d},filter:function(a){return"string"==typeof a&&this.selector.filter.push(a),this},endFilter:function(a){return a?this.selector.filter=[]:this.selector.filter.pop(),this},avoid:function(a){return"string"==typeof a&&this.selector.avoid.push(a),this},endAvoid:function(a){return a?this.selector.avoid=[]:this.selector.avoid.pop(),this},addBoundary:function(a){return"string"==typeof a&&this.selector.boundary.push(a),this},removeBoundary:function(){return this.selector.boundary=[],this},setMode:function(a){return this.portionMode="first"===a?"first":"retain",this},replace:function(a,c){var d=this;return d.finder.push(b(d.context,{find:a,replace:c,filterElements:function(a){return d.filterFn(a)},forceContext:function(a){return d.boundaryFn(a)},portionMode:d.portionMode})),d},wrap:function(a,c){var d=this;return d.finder.push(b(d.context,{find:a,wrap:c,filterElements:function(a){return d.filterFn(a)},forceContext:function(a){return d.boundaryFn(a)},portionMode:d.portionMode})),d},revert:function(a){var b=this.finder.length,a=Number(a)||(0===a?Number(0):"all"===a?b:1);if("undefined"==typeof b||0===b)return this;a>b&&(a=b);for(var c=a;c>0;c--)this.finder.pop().revert();return this}},i.fn.filterOut=i.fn.avoid,i.fn.init.prototype=i.fn,i}(function(){function a(a){return String(a).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")}function b(){return c.apply(null,arguments)||d.apply(null,arguments)}function c(a,c,e,f,g){if(c&&!c.nodeType&&arguments.length<=2)return!1;var h="function"==typeof e;h&&(e=function(a){return function(b,c){return a(b.text,c.startIndex)}}(e));var i=d(c,{find:a,wrap:h?null:e,replace:h?e:"$"+(f||"&"),prepMatch:function(a,b){if(!a[0])throw"findAndReplaceDOMText cannot handle zero-length matches";if(f>0){var c=a[f];a.index+=a[0].indexOf(c),a[0]=c}return a.endIndex=a.index+a[0].length,a.startIndex=a.index,a.index=b,a},filterElements:g});return b.revert=function(){return i.revert()},!0}function d(a,b){return new e(a,b)}function e(a,c){var d=c.preset&&b.PRESETS[c.preset];if(c.portionMode=c.portionMode||f,d)for(var e in d)i.call(d,e)&&!i.call(c,e)&&(c[e]=d[e]);this.node=a,this.options=c,this.prepMatch=c.prepMatch||this.prepMatch,this.reverts=[],this.matches=this.search(),this.matches.length&&this.processMatches()}var f="retain",g="first",h=J,i=({}.toString,{}.hasOwnProperty);return b.NON_PROSE_ELEMENTS={br:1,hr:1,script:1,style:1,img:1,video:1,audio:1,canvas:1,svg:1,map:1,object:1,input:1,textarea:1,select:1,option:1,optgroup:1,button:1},b.NON_CONTIGUOUS_PROSE_ELEMENTS={address:1,article:1,aside:1,blockquote:1,dd:1,div:1,dl:1,fieldset:1,figcaption:1,figure:1,footer:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,header:1,hgroup:1,hr:1,main:1,nav:1,noscript:1,ol:1,output:1,p:1,pre:1,section:1,ul:1,br:1,li:1,summary:1,dt:1,details:1,rp:1,rt:1,rtc:1,script:1,style:1,img:1,video:1,audio:1,canvas:1,svg:1,map:1,object:1,input:1,textarea:1,select:1,option:1,optgroup:1,button:1,table:1,tbody:1,thead:1,th:1,tr:1,td:1,caption:1,col:1,tfoot:1,colgroup:1},b.NON_INLINE_PROSE=function(a){return i.call(b.NON_CONTIGUOUS_PROSE_ELEMENTS,a.nodeName.toLowerCase())},b.PRESETS={prose:{forceContext:b.NON_INLINE_PROSE,filterElements:function(a){return!i.call(b.NON_PROSE_ELEMENTS,a.nodeName.toLowerCase())}}},b.Finder=e,e.prototype={search:function(){function b(a){for(var g=0,j=a.length;j>g;++g){var k=a[g];if("string"==typeof k){if(f.global)for(;c=f.exec(k);)h.push(i.prepMatch(c,d++,e));else(c=k.match(f))&&h.push(i.prepMatch(c,0,e));e+=k.length}else b(k)}}var c,d=0,e=0,f=this.options.find,g=this.getAggregateText(),h=[],i=this;return f="string"==typeof f?RegExp(a(f),"g"):f,b(g),h},prepMatch:function(a,b,c){if(!a[0])throw new Error("findAndReplaceDOMText cannot handle zero-length matches");return a.endIndex=c+a.index+a[0].length,a.startIndex=c+a.index,a.index=b,a},getAggregateText:function(){function a(d,e){if(3===d.nodeType)return[d.data];if(b&&!b(d))return[];var e=[""],f=0;if(d=d.firstChild)do if(3!==d.nodeType){var g=a(d);c&&1===d.nodeType&&(c===!0||c(d))?(e[++f]=g,e[++f]=""):("string"==typeof g[0]&&(e[f]+=g.shift()),g.length&&(e[++f]=g,e[++f]=""))}else e[f]+=d.data;while(d=d.nextSibling);return e}var b=this.options.filterElements,c=this.options.forceContext;return a(this.node)},processMatches:function(){var a,b,c,d=this.matches,e=this.node,f=this.options.filterElements,g=[],h=e,i=d.shift(),j=0,k=0,l=0,m=[e];a:for(;;){if(3===h.nodeType&&(!b&&h.length+j>=i.endIndex?b={node:h,index:l++,text:h.data.substring(i.startIndex-j,i.endIndex-j),indexInMatch:j-i.startIndex,indexInNode:i.startIndex-j,endIndexInNode:i.endIndex-j,isEnd:!0}:a&&g.push({node:h,index:l++,text:h.data,indexInMatch:j-i.startIndex,indexInNode:0}),!a&&h.length+j>i.startIndex&&(a={node:h,index:l++,indexInMatch:0,indexInNode:i.startIndex-j,endIndexInNode:i.endIndex-j,text:h.data.substring(i.startIndex-j,i.endIndex-j)}),j+=h.data.length),c=1===h.nodeType&&f&&!f(h),a&&b){if(h=this.replaceMatch(i,a,g,b),j-=b.node.data.length-b.endIndexInNode,a=null,b=null,g=[],i=d.shift(),l=0,k++,!i)break}else if(!c&&(h.firstChild||h.nextSibling)){h.firstChild?(m.push(h),h=h.firstChild):h=h.nextSibling;continue}for(;;){if(h.nextSibling){h=h.nextSibling;break}if(h=m.pop(),h===e)break a}}},revert:function(){for(var a=this.reverts.length;a--;)this.reverts[a]();this.reverts=[]},prepareReplacementString:function(a,b,c,d){var e=this.options.portionMode;return e===g&&b.indexInMatch>0?"":(a=a.replace(/\$(\d+|&|`|')/g,function(a,b){var d;switch(b){case"&":d=c[0];break;case"`":d=c.input.substring(0,c.startIndex);break;case"'":d=c.input.substring(c.endIndex);break;default:d=c[+b]}return d}),e===g?a:b.isEnd?a.substring(b.indexInMatch):a.substring(b.indexInMatch,b.indexInMatch+b.text.length))},getPortionReplacementNode:function(a,b,c){var d=this.options.replace||"$&",e=this.options.wrap;if(e&&e.nodeType){var f=h.createElement("div");f.innerHTML=e.outerHTML||(new XMLSerializer).serializeToString(e),e=f.firstChild}if("function"==typeof d)return d=d(a,b,c),d&&d.nodeType?d:h.createTextNode(String(d));var g="string"==typeof e?h.createElement(e):e;return d=h.createTextNode(this.prepareReplacementString(d,a,b,c)),d.data&&g?(g.appendChild(d),g):d},replaceMatch:function(a,b,c,d){var e,f,g=b.node,i=d.node;if(g===i){var j=g;b.indexInNode>0&&(e=h.createTextNode(j.data.substring(0,b.indexInNode)),j.parentNode.insertBefore(e,j));var k=this.getPortionReplacementNode(d,a);return j.parentNode.insertBefore(k,j),d.endIndexInNoden;++n){var p=c[n],q=this.getPortionReplacementNode(p,a);p.node.parentNode.replaceChild(q,p.node),this.reverts.push(function(a,b){return function(){b.parentNode.replaceChild(a.node,b)}}(p,q)),m.push(q)}var r=this.getPortionReplacementNode(d,a);return g.parentNode.insertBefore(e,g),g.parentNode.insertBefore(l,g),g.parentNode.removeChild(g),i.parentNode.insertBefore(r,i),i.parentNode.insertBefore(f,i),i.parentNode.removeChild(i),this.reverts.push(function(){e.parentNode.removeChild(e),l.parentNode.replaceChild(g,l),f.parentNode.removeChild(f),r.parentNode.replaceChild(i,r)}),r}},b}()),U=function(){var a=S.create("div");return a.appendChild(S.create("","0-")),a.appendChild(S.create("","2")),a.normalize(),2!==a.firstChild.length}();S.extend(T.fn,{normalize:function(){return U&&this.context.normalize(),this},jinzify:function(a){return this.filter(a||null).avoid("h-jinze").replace(R.jinze.touwei,function(a,b){var c=S.create("h-jinze","touwei");return c.innerHTML=b[0],0===a.index&&a.isEnd||1===a.index?c:""}).replace(R.jinze.wei,function(a,b){var c=S.create("h-jinze","wei");return c.innerHTML=b[0],0===a.index?c:""}).replace(R.jinze.tou,function(a,b){var c=S.create("h-jinze","tou");return c.innerHTML=b[0],0===a.index&&a.isEnd||1===a.index?c:""}).replace(R.jinze.middle,function(a,b){var c=S.create("h-jinze","middle");return c.innerHTML=b[0],0===a.index&&a.isEnd||1===a.index?c:""}).endAvoid().endFilter()},groupify:function(a){var a=S.extend({biaodian:!1,hanzi:!1,kana:!1,eonmun:!1,western:!1},a||{});return this.avoid("h-word, h-char-group"),a.biaodian&&this.replace(R.group.biaodian[0],d).replace(R.group.biaodian[1],d),(a.hanzi||a.cjk)&&this.wrap(R.group.hanzi,S.clone(S.create("h-char-group","hanzi cjk"))),a.western&&this.wrap(R.group.western,S.clone(S.create("h-word","western"))),a.kana&&this.wrap(R.group.kana,S.clone(S.create("h-char-group","kana"))),(a.eonmun||a.hangul)&&this.wrap(R.group.eonmun,S.clone(S.create("h-word","eonmun hangul"))),this.endAvoid(),this},charify:function(a){var a=S.extend({avoid:!0,biaodian:!1,punct:!1,hanzi:!1,latin:!1,ellinika:!1,kirillica:!1,kana:!1,eonmun:!1},a||{});return a.avoid&&this.avoid("h-char"),a.biaodian&&this.replace(R["char"].biaodian.all,c(a.biaodian)||function(a){return e(a.text)}).replace(R["char"].biaodian.liga,c(a.biaodian)||function(a){return e(a.text)}),(a.hanzi||a.cjk)&&this.wrap(R["char"].hanzi,c(a.hanzi||a.cjk)||S.clone(S.create("h-char","hanzi cjk"))),a.punct&&this.wrap(R["char"].punct.all,c(a.punct)||S.clone(S.create("h-char","punct"))),a.latin&&this.wrap(R["char"].latin,c(a.latin)||S.clone(S.create("h-char","alphabet latin"))),(a.ellinika||a.greek)&&this.wrap(R["char"].ellinika,c(a.ellinika||a.greek)||S.clone(S.create("h-char","alphabet ellinika greek"))),(a.kirillica||a.cyrillic)&&this.wrap(R["char"].kirillica,c(a.kirillica||a.cyrillic)||S.clone(S.create("h-char","alphabet kirillica cyrillic"))),a.kana&&this.wrap(R["char"].kana,c(a.kana)||S.clone(S.create("h-char","kana"))),(a.eonmun||a.hangul)&&this.wrap(R["char"].eonmun,c(a.eonmun||a.hangul)||S.clone(S.create("h-char","eonmun hangul"))),this.endAvoid(),this}}),S.extend(O,{isNodeNormalizeNormal:U,find:T,createBDGroup:d,createBDChar:e}),S.matches=O.find.matches,void["setMode","wrap","replace","revert","addBoundary","removeBoundary","avoid","endAvoid","filter","endFilter","jinzify","groupify","charify"].forEach(function(a){O.fn[a]=function(){return this.finder||(this.finder=O.find(this.context)),this.finder[a](arguments[0],arguments[1]),this}});var V={};V.writeOnCanvas=g,V.compareCanvases=h,V.detectFont=i,V.support=function(){function b(a){var b,c=a.charAt(0).toUpperCase()+a.slice(1),d=(a+" "+e.join(c+" ")+c).split(" ");return d.forEach(function(a){"string"==typeof f.style[a]&&(b=!0)}),b||!1}function c(a,b){var c,d,e,f=L||S.create("body"),g=S.create("div"),h=L?g:f,b="function"==typeof b?b:function(){};return c=[""].join(""),h.innerHTML+=c,f.appendChild(g),L||(f.style.background="",f.style.overflow="hidden",e=K.style.overflow,K.style.overflow="hidden",K.appendChild(f)),d=b(h,a),S.remove(h),L||(K.style.overflow=e),!!d}function d(b,c){var d;return a.getComputedStyle?d=J.defaultView.getComputedStyle(b,null).getPropertyValue(c):b.currentStyle&&(d=b.currentStyle[c]),d}var e="Webkit Moz ms".split(" "),f=S.create("h-test");return{columnwidth:b("columnWidth"),fontface:function(){var a;return c('@font-face { font-family: font; src: url("//"); }',function(b,c){var d=S.qsa("style",b)[0],e=d.sheet||d.styleSheet,f=e?e.cssRules&&e.cssRules[0]?e.cssRules[0].cssText:e.cssText||"":"";a=/src/i.test(f)&&0===f.indexOf(c.split(" ")[0])}),a}(),ruby:function(){var a,b=S.create("ruby"),c=S.create("rt"),e=S.create("rp");return b.appendChild(e),b.appendChild(c),K.appendChild(b),a="none"===d(e,"display")||"ruby"===d(b,"display")&&"ruby-text"===d(c,"display")?!0:!1,K.removeChild(b),b=null,c=null,e=null,a}(),"ruby-display":function(){var a=S.create("div");return a.innerHTML='',"ruby"===a.querySelector("h-test-a").style.display&&"ruby-text-container"===a.querySelector("h-test-b").style.display}(),"ruby-interchar":function(){var a,b="inter-character",c=S.create("div");return c.innerHTML='',a=c.querySelector("h-test").style,a.rubyPosition===b||a.WebkitRubyPosition===b||a.MozRubyPosition===b||a.msRubyPosition===b}(),textemphasis:b("textEmphasis"),unicoderange:function(){var a;return c('@font-face{font-family:test-for-unicode-range;src:local(Arial),local("Droid Sans")}@font-face{font-family:test-for-unicode-range;src:local("Times New Roman"),local(Times),local("Droid Serif");unicode-range:U+270C}',function(){a=!V.detectFont("test-for-unicode-range",'Arial, "Droid Sans"',"Q")}),a}(),writingmode:b("writingMode")}}(),V.initCond=function(a){var b,a=a||K,c="";for(var d in V.support)b=(V.support[d]?"":"no-")+d,a.classList.add(b),c+=b+" ";return c};var W=V.support["ruby-interchar"];S.extend(V,{renderRuby:function(a,b){var b=b||"ruby",c=S.qsa(b,a);S.qsa("rtc",a).concat(c).map(n),c.forEach(function(a){var b,c=a.classList;c.contains("complex")?b=l(a):c.contains("zhuyin")&&(b=W?k(a):j(a)),b&&a.parentNode.replaceChild(b,a)})},simplifyRubyClass:n,getZhuyinHTML:q,renderComplexRuby:l,renderSimpleRuby:j,renderInterCharRuby:k}),S.extend(V,{renderElem:function(a){this.renderRuby(a),this.renderDecoLine(a),this.renderDecoLine(a,"s, del"),this.renderEm(a)},renderDecoLine:function(a,b){var c=S.qsa(b||"u, ins",a),d=c.length;a:for(;d--;){var e=c[d],f=null;do{if(f=(f||e).previousSibling,!f)continue a;c[d-1]===f&&e.classList.add("adjacent")}while(S.isIgnorable(f))}},renderEm:function(a,b){var c=b?"qsa":"tag",b=b||"em",d=S[c](b,a);d.forEach(function(a){var b=O(a);V.support.textemphasis?b.avoid("rt, h-char").charify({biaodian:!0,punct:!0}):b.avoid("rt, h-char, h-char-group").jinzify().groupify({western:!0}).charify({hanzi:!0,biaodian:!0,punct:!0,latin:!0,ellinika:!0,kirillica:!0})})}}),O.normalize=V,O.localize=V,O.support=V.support,O.detectFont=V.detectFont,O.fn.initCond=function(){return this.condition.classList.add("han-js-rendered"),O.normalize.initCond(this.condition),this},void["Elem","DecoLine","Em","Ruby"].forEach(function(a){var b="render"+a;O.fn[b]=function(a){return O.normalize[b](this.context,a),this}}),S.extend(O.support,{heiti:!0,songti:O.detectFont('"Han Songti"'),"songti-gb":O.detectFont('"Han Songti GB"'),kaiti:O.detectFont('"Han Kaiti"'),fangsong:O.detectFont('"Han Fangsong"')}),O.correctBiaodian=function(a){var a=a||J,b=O.find(a);return b.avoid("h-char").replace(/([\u2018\u201c])/g,function(a){var b=O.createBDChar(a.text);return b.classList.add("bd-open","punct"),b}).replace(/([\u2019\u201d])/g,function(a){var b=O.createBDChar(a.text);return b.classList.add("bd-close","bd-end","punct"),b}),O.support.unicoderange?b:b.charify({biaodian:!0})},O.correctBasicBD=O.correctBiaodian,O.correctBD=O.correctBiaodian,S.extend(O.fn,{biaodian:null,correctBiaodian:function(){return this.biaodian=O.correctBiaodian(this.context),this},revertCorrectedBiaodian:function(){try{this.biaodian.revert("all")}catch(a){}return this}}),O.fn.correctBasicBD=O.fn.correctBiaodian,O.fn.revertBasicBD=O.fn.revertCorrectedBiaodian;var X="<>",Y=S.create("h-hws");Y.setAttribute("hidden",""),Y.innerHTML=" ";var Z;S.extend(O,{renderHWS:function(a,b){var c=b?"textarea, code, kbd, samp, pre":"textarea",d=b?"strict":"base",a=a||J,e=O.find(a); +return e.avoid(c).replace(O.TYPESET.hws[d][0],t).replace(O.TYPESET.hws[d][1],t).replace(new RegExp("("+X+")+","g"),u).replace(/([\'"])\s(.+?)\s\1/g,v).replace(/\s[\u2018\u201c]/g,w).replace(/[\u2019\u201d]\s/g,w).normalize(),e}}),S.extend(O.fn,{renderHWS:function(a){return O.renderHWS(this.context,a),this},revertHWS:function(){return S.tag("h-hws",this.context).forEach(function(a){S.remove(a)}),this.HWS=[],this}});var $="bd-hangable",_="h-char.bd-hangable",aa='',ba=O.find.matches;O.support["han-space"]=x(),S.extend(O,{detectSpaceFont:x,isSpaceFontLoaded:x(),renderHanging:function(a){var a=a||J,b=O.find(a);return b.avoid("textarea, code, kbd, samp, pre").avoid(_).replace(R.jinze.hanging,function(a){if(/^[\x20\t\r\n\f]+$/.test(a.text))return"";var b,c,d,e,f=a.node.parentNode;return(b=S.parent(f,"h-jinze"))&&y(b),e=a.text.trim(),c=O.createBDChar(e),c.innerHTML=""+e+"",c.classList.add($),d=S.parent(f,"h-char.biaodian"),d?function(){return d.classList.add($),ba(f,"h-inner, h-inner *")?e:c.firstChild}():c}),b}}),S.extend(O.fn,{renderHanging:function(){var a=this.condition.classList;return O.isSpaceFontLoaded=x(),O.isSpaceFontLoaded&&a.contains("no-han-space")&&(a.remove("no-han-space"),a.add("han-space")),O.renderHanging(this.context),this},revertHanging:function(){return S.qsa("h-char.bd-hangable, h-cs.hangable-outer",this.context).forEach(function(a){var b=a.classList;b.remove("bd-hangable"),b.remove("hangable-outer")}),this}});var ca,da,ea="bd-jiya",fa="h-char.bd-jiya",ga="bd-consecutive",ha='',ba=O.find.matches;O.renderJiya=function(a){var a=a||J,b=O.find(a);return b.avoid("textarea, code, kbd, samp, pre, h-cs").avoid(fa).charify({avoid:!1,biaodian:A}).endAvoid().avoid("textarea, code, kbd, samp, pre, h-cs").replace(R.group.biaodian[0],B).replace(R.group.biaodian[1],B),b},S.extend(O.fn,{renderJiya:function(){return O.renderJiya(this.context),this},revertJiya:function(){return S.qsa("h-char.bd-jiya, h-cs.jiya-outer",this.context).forEach(function(a){var b=a.classList;b.remove("bd-jiya"),b.remove("jiya-outer")}),this}});var ia="textarea, code, kbd, samp, pre",ja=S.create("h-char","comb-liga");return S.extend(O,{isVowelCombLigaNormal:F(),isVowelICombLigaNormal:G(),isZhuyinCombLigaNormal:H(),isCombLigaNormal:G()(),substVowelCombLiga:I(O.TYPESET["display-as"]["comb-liga-vowel"]),substZhuyinCombLiga:I(O.TYPESET["display-as"]["comb-liga-zhuyin"]),substCombLigaWithPUA:I(O.TYPESET["display-as"]["comb-liga-pua"]),substInaccurateChar:function(a){var a=a||J,b=O.find(a);b.avoid(ia),O.TYPESET["inaccurate-char"].forEach(function(a){b.replace(new RegExp(a[0],"ig"),a[1])})}}),S.extend(O.fn,{"comb-liga-vowel":null,"comb-liga-vowel-i":null,"comb-liga-zhuyin":null,"inaccurate-char":null,substVowelCombLiga:function(){return this["comb-liga-vowel"]=O.substVowelCombLiga(this.context),this},substVowelICombLiga:function(){return this["comb-liga-vowel-i"]=O.substVowelICombLiga(this.context),this},substZhuyinCombLiga:function(){return this["comb-liga-zhuyin"]=O.substZhuyinCombLiga(this.context),this},substCombLigaWithPUA:function(){return O.isVowelCombLigaNormal()?O.isVowelICombLigaNormal()||(this["comb-liga-vowel-i"]=O.substVowelICombLiga(this.context)):this["comb-liga-vowel"]=O.substVowelCombLiga(this.context),O.isZhuyinCombLigaNormal()||(this["comb-liga-zhuyin"]=O.substZhuyinCombLiga(this.context)),this},revertVowelCombLiga:function(){try{this["comb-liga-vowel"].revert("all")}catch(a){}return this},revertVowelICombLiga:function(){try{this["comb-liga-vowel-i"].revert("all")}catch(a){}return this},revertZhuyinCombLiga:function(){try{this["comb-liga-zhuyin"].revert("all")}catch(a){}return this},revertCombLigaWithPUA:function(){try{this["comb-liga-vowel"].revert("all"),this["comb-liga-vowel-i"].revert("all"),this["comb-liga-zhuyin"].revert("all")}catch(a){}return this},substInaccurateChar:function(){return this["inaccurate-char"]=O.substInaccurateChar(this.context),this},revertInaccurateChar:function(){try{this["inaccurate-char"].revert("all")}catch(a){}return this}}),a.addEventListener("DOMContentLoaded",function(){var a;K.classList.contains("han-init")?O.init():(a=J.querySelector(".han-init-context"))&&(O.init=O(a).render())}),("undefined"==typeof b||b===!1)&&(a.Han=O),O}); \ No newline at end of file diff --git a/lib/algolia-instant-search/instantsearch.min.css b/lib/algolia-instant-search/instantsearch.min.css new file mode 100644 index 0000000..590f6f9 --- /dev/null +++ b/lib/algolia-instant-search/instantsearch.min.css @@ -0,0 +1 @@ +/*! instantsearch.js 1.5.0 | © Algolia Inc. and other contributors; Licensed MIT | github.com/algolia/instantsearch.js */.ais-search-box--powered-by{font-size:.8em;text-align:right;margin-top:2px}.ais-search-box--powered-by-link{display:inline-block;width:45px;height:16px;text-indent:101%;overflow:hidden;white-space:nowrap;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAAAgCAYAAABwzXTcAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4wLjVlhTJlAAAIJElEQVRoQ+1Za2xURRTugqJVEBAlhICBRFEQeRfodssqiDZaS8vu3dsXVlAbxReJwVfAoqJ/sBqE3S1IgqgBrY9EQ6KJiUAokUfpvQUKogIBlKbyEEUolNL6ndkzw9129+72YaFJv+Rk737nzMyZ756dmXs3oQtd6EJ7oaioqJvX603kr1cl8vPzb+TLzo3MzMx+Xk0r03y+0x5Ne4vpqwoohjeQ4yHYcaYiwcGfVz+ysrIGQfBGsqtWdE37lvLz+nwnmVLIyMjoBd9GxPwL/wKmOw4zCgr6YPBNSGILEviYaVt0dtHxK/DK/BFXq2lad3Z1DJDUqzIBYZrmYldUdLToI4r29HCWmLozUPmEK2AUOgOmRysttRXKTnSPxzMWfD37q0B13DJTUFBwPQatlgKKJJAsu6Oio0VPDlQsTgmajWEWMOaxOyLsRCdQccGez87OHshUxwAJzZbiIYFKkaSmXdJ1fRiHRERHi+4MGk+mBMwXnSVGPj7nQPS3qeLZHRGxRL9ScCAxk8Ur92Rnj5VCItHlHBMRrRDdQRXl8/nG4eaOp5uKz57sC8OkoDEkOWCO5K8CtJRgabnT6TfuS/ZXOKet2duPXVHRDqI7svLz+yPnJCxH07ANuGFDiQ+5WwF0NkWJrOuziEOCm5n7Jy8v7yYRGAHxio4kEyHuK+j3oIyXRr8o2G/wrUXMGIonQbFe18Kq3Ms39By/orw3KnsxKr06fHkxLjkDxubkEuNhMVAE2Ikuni98vsMYtwafQaYVwLvQ9qg1X2mI/xXzyuXQlgGNP+NO/kxLS7tOcOhMda7rz4rACIhH9Ky8vEGY+G4ZZ2ua9hi1gbhvQvBDScu3DUC1j8X1YSV0wDgLsX9m7tJl3lw9onRPDzGoBTFFp1NLyL+WaQUU5GSZG+IuIeYCrhskJ3ivN6o+EYFJDuCOaNBipuXGepI73gMq4k8pluh0E5GsXLoo8U1IMgPLyhDYYExqNL6/Lv1S9FT/7sHOkp0TXCvNYbgBp0hUfB6A2D6rsKn+7YMh9nvOoHkxJL6xLiGhMSzXtoiOfHqDn41ch5MmFC+O1ihEtDnP7c5QHDeJDTSQx8QGTH4E0wLwLWVfo0fXU5kOQyzR0ecL0o/EvoI1O95ZlzcpugAmiKVjKwu+1f2+0Yc9As5VZb3gX4JfQn9XwEyH+HUi1m/kc4hAW0S3A3J9TeaNOWQybQ8aEA0O8IDbmFagM6zsFP5PmA5DTNF5WUH7c7QZMR2GaKK7Ssw0FvyMe2XlIKYVUkrMR4Q/YB6b4t85HKIv5Pj9CY2Xq/3/Ep2qX+aN4prPtD0w2ftlI0z2GaatsJ5qztLPinkFO9Fzc3P7ghfrH/r5nulmiCY6qnhVSEQz4gkKIvvJD2sQS8yqfb3wifWeuN2jOazdRIewibQszszJuYO0yMnJuUXmjbZFHGYPTHAdN7iQOWtWxKMXfPNkx5FujJ3oEHOk9KGfpUw3QzTRsWHuCAloZDFlQaMDN+Ugqrocy8tUJulG/Mg34lGm2iR6YWHhteDnIq8diLmo8gwV0zH5HTGxRcddu1kOhg6PotGCKKbWdVg5N1eIIfpo1VbT3mW6GWxE30cCulbscjOlkLRsb7+UQGUuVOvGlABu0JdC9IChCqS1olNlg9+ocqOY0PG2FrHi1YHi4xJd15+2NorTaLO9h7sQsBOdTieqLX5VTDdD9OXFLCMBm26MdqANV7QpMXWm2iK69VS1AXmm0AmGfOIX4PUmS398omPjFME0oKZtsTPEqDM22qljJcFOdLTtDv4E+2vkM0BT2FR6sRAwaJQyZYuJ2Gyx5NSj2htSPzDpiVGg1aLzfga+mqqeaQX6L0HmjRh70a27Lib5KdNRgZjelsSq3W73NewKEx1xYaITwJVY/IuYDkM00Scv2zGOBETF1+MkM4npqIDga8RNwhMqUwKtFt3n+13wmlbGVBhaJDom9o4MxoQfYtoW6PQLNYDXqx65cX2r4n2+j5hWoN0e/BmOoeUpgDFH0qsFXA+FPQ5/lezDKjoBoq8Ta3TQ/MPl3zWK6XBAOMQtCglu1qcsN8NeScvcIV5d01cadqIjF9o8qd0p+rODaYW4RedBjnBwjbVq7QChPJYBPmda9Ef9sO88fC/NnDnzLnYL4MFqBvk4xt6aiO5ebfSBoLu5gmtxXZzsr0hyBXb1xRFxYHKwwivXfrJkv/EyN1VAn4tk/8hvPebyIK3J5ItR6Qssee1Ageh4drkbn7dT4fC8ZL/RRUeDqZZA2zeIVqAd7eSnud05JKEee3GtnsyEYUlhlwK4MWi3HiZeOVjsF/g+VN+biE6gN4nOYOV3UtiIhvO5028+xU3CgD5vg7B/yzFwXSf3FzvR6Y9s+Lar3GwMbW1Ex7kbHW0iw12bwHRcQPILVVtdn8Y0wYF+52LwChhV+3PMN8N0TARVQu9bJtKLMFAO5HGvSh7VFIpsikaHeNQPGt9A5JMkNG2asP2wJfSuhgMjwpOdPQp5fY0xTiD/vUxL0X8Q88JphWkF8Q5K1+dj7hVoby2Yi+Bq0G4nPkvRdjo36XiI5aaF/zNiUur9DN0Mpu3gmFx8JHH8inKxRLQUcmlpKWhesN4Zc+b0aukcrwSivuynR2lUkHjHjqo53lpBumABKjcRolbBluJ6FpaWKVTNWJ4eQLXQXnD5DwJ852ZdaAsgsvoTwM5wU1Z3hp9spwCqeigELcbS8RPE/QvX9M6iAd/rcH0YtrbJptyFdoYD1dwjPT39hnifD7rQhTiRkPAfxnOcWpCmnRwAAAAASUVORK5CYII=);background-repeat:no-repeat;background-size:contain;vertical-align:middle}.ais-pagination--item{display:inline-block;padding:3px}.ais-range-slider--value,.ais-range-slider--value-sub{font-size:.8em;padding-top:15px}.ais-pagination--item__disabled{visibility:hidden}.ais-hierarchical-menu--list__lvl1,.ais-hierarchical-menu--list__lvl2{margin-left:10px}.ais-range-slider--target{position:relative;direction:ltr;background:#F3F4F7;height:6px;margin-top:2em;margin-bottom:2em}.ais-range-slider--base{height:100%;position:relative;z-index:1;border-top:1px solid #DDD;border-bottom:1px solid #DDD;border-left:2px solid #DDD;border-right:2px solid #DDD}.ais-range-slider--origin{position:absolute;right:0;top:0;left:0;bottom:0}.ais-range-slider--connect{background:#46AEDA}.ais-range-slider--background{background:#F3F4F7}.ais-range-slider--handle{width:20px;height:20px;position:relative;z-index:1;background:#FFF;border:1px solid #46AEDA;border-radius:50%;cursor:pointer}.ais-range-slider--handle-lower{left:-10px;bottom:7px}.ais-range-slider--handle-upper{right:10px;bottom:7px}.ais-range-slider--tooltip{position:absolute;background:#FFF;top:-22px;font-size:.8em}.ais-range-slider--pips{box-sizing:border-box;position:absolute;height:3em;top:100%;left:0;width:100%}.ais-range-slider--value{width:40px;position:absolute;text-align:center;margin-left:-20px}.ais-range-slider--marker{position:absolute;background:#DDD;margin-left:-1px;width:1px;height:5px}.ais-range-slider--marker-sub{background:#DDD;width:2px;margin-left:-2px;height:13px}.ais-range-slider--marker-large{background:#DDD;width:2px;margin-left:-2px;height:12px}.ais-star-rating--star,.ais-star-rating--star__empty{display:inline-block;width:1em;height:1em}.ais-range-slider--marker-large:first-child{margin-left:0}.ais-star-rating--item{vertical-align:middle}.ais-star-rating--item__active{font-weight:700}.ais-star-rating--star:before{content:'\2605';color:#FBAE00}.ais-star-rating--star__empty:before{content:'\2606';color:#FBAE00}.ais-star-rating--link__disabled .ais-star-rating--star:before,.ais-star-rating--link__disabled .ais-star-rating--star__empty:before{color:#C9C9C9}.ais-root__collapsible .ais-header{cursor:pointer}.ais-root__collapsed .ais-body,.ais-root__collapsed .ais-footer{display:none} \ No newline at end of file diff --git a/lib/algolia-instant-search/instantsearch.min.js b/lib/algolia-instant-search/instantsearch.min.js new file mode 100644 index 0000000..2bd5d59 --- /dev/null +++ b/lib/algolia-instant-search/instantsearch.min.js @@ -0,0 +1,15 @@ +/*! instantsearch.js 1.5.0 | © Algolia Inc. and other contributors; Licensed MIT | github.com/algolia/instantsearch.js */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.instantsearch=t():e.instantsearch=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}var o=n(1),i=r(o);e.exports=i["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0}),n(2),n(3);var o=n(4),i=r(o),a=n(5),s=r(a),u=n(99),l=r(u),c=n(222),f=r(c),p=n(400),d=r(p),h=n(404),m=r(h),v=n(408),g=r(v),y=n(411),b=r(y),_=n(416),C=r(_),w=n(420),x=r(w),P=n(422),E=r(P),R=n(424),S=r(R),O=n(425),T=r(O),k=n(432),N=r(k),j=n(437),A=r(j),M=n(439),F=r(M),I=n(443),D=r(I),U=n(444),L=r(U),H=n(447),V=r(H),B=n(450),q=r(B),W=n(220),K=r(W),Q=(0,i["default"])(s["default"]);Q.widgets={clearAll:f["default"],currentRefinedValues:d["default"],hierarchicalMenu:m["default"],hits:g["default"],hitsPerPageSelector:b["default"],menu:C["default"],refinementList:x["default"],numericRefinementList:E["default"],numericSelector:S["default"],pagination:T["default"],priceRanges:N["default"],searchBox:A["default"],rangeSlider:F["default"],sortBySelector:D["default"],starRating:L["default"],stats:V["default"],toggle:q["default"]},Q.version=K["default"],Q.createQueryString=l["default"].url.getQueryStringFromState,t["default"]=Q},function(e,t){"use strict";Object.freeze||(Object.freeze=function(e){if(Object(e)!==e)throw new TypeError("Object.freeze can only be called on Objects.");return e})},function(e,t){"use strict";var n={};if(!Object.setPrototypeOf&&!n.__proto__){var r=Object.getPrototypeOf;Object.getPrototypeOf=function(e){return e.__proto__?e.__proto__:r.call(Object,e)}}},function(e,t){"use strict";function n(e){var t=function(){for(var t=arguments.length,n=Array(t),o=0;t>o;o++)n[o]=arguments[o];return new(r.apply(e,[null].concat(n)))};return t.__proto__=e,t.prototype=e.prototype,t}var r=Function.prototype.bind;e.exports=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function s(){return"#"}function u(e,t){if(!t.getConfiguration)return e;var n=t.getConfiguration(e);return(0,y["default"])({},e,n,function(e,t){return Array.isArray(e)?(0,_["default"])(e,t):void 0})}Object.defineProperty(t,"__esModule",{value:!0});var l=Object.assign||function(e){for(var t=1;te;e+=2){var t=re[e],n=re[e+1];t(n),re[e]=void 0,re[e+1]=void 0}G=0}function v(){try{var e=n(11);return Q=e.runOnLoop||e.runOnContext,f()}catch(t){return h()}}function g(e,t){var n=this,r=n._state;if(r===se&&!e||r===ue&&!t)return this;var o=new this.constructor(b),i=n._result;if(r){var a=arguments[r-1];X(function(){F(r,o,a,i)})}else N(n,o,e,t);return o}function y(e){var t=this;if(e&&"object"==typeof e&&e.constructor===t)return e;var n=new t(b);return S(n,e),n}function b(){}function _(){return new TypeError("You cannot resolve a promise with itself")}function C(){return new TypeError("A promises callback cannot return that same promise.")}function w(e){try{return e.then}catch(t){return le.error=t,le}}function x(e,t,n,r){try{e.call(t,n,r)}catch(o){return o}}function P(e,t,n){X(function(e){var r=!1,o=x(n,t,function(n){r||(r=!0,t!==n?S(e,n):T(e,n))},function(t){r||(r=!0,k(e,t))},"Settle: "+(e._label||" unknown promise"));!r&&o&&(r=!0,k(e,o))},e)}function E(e,t){t._state===se?T(e,t._result):t._state===ue?k(e,t._result):N(t,void 0,function(t){S(e,t)},function(t){k(e,t)})}function R(e,t,n){t.constructor===e.constructor&&n===oe&&constructor.resolve===ie?E(e,t):n===le?k(e,le.error):void 0===n?T(e,t):s(n)?P(e,t,n):T(e,t)}function S(e,t){e===t?k(e,_()):a(t)?R(e,t,w(t)):T(e,t)}function O(e){e._onerror&&e._onerror(e._result),j(e)}function T(e,t){e._state===ae&&(e._result=t,e._state=se,0!==e._subscribers.length&&X(j,e))}function k(e,t){e._state===ae&&(e._state=ue,e._result=t,X(O,e))}function N(e,t,n,r){var o=e._subscribers,i=o.length;e._onerror=null,o[i]=t,o[i+se]=n,o[i+ue]=r,0===i&&e._state&&X(j,e)}function j(e){var t=e._subscribers,n=e._state;if(0!==t.length){for(var r,o,i=e._result,a=0;aa;a++)N(r.resolve(e[a]),void 0,t,n);return o}function L(e){var t=this,n=new t(b);return k(n,e),n}function H(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function V(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function B(e){this._id=he++,this._state=void 0,this._result=void 0,this._subscribers=[],b!==e&&("function"!=typeof e&&H(),this instanceof B?I(this,e):V())}function q(e,t){this._instanceConstructor=e,this.promise=new e(b),Array.isArray(t)?(this._input=t,this.length=t.length,this._remaining=t.length,this._result=new Array(this.length),0===this.length?T(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&T(this.promise,this._result))):k(this.promise,this._validationError())}function W(){var e;if("undefined"!=typeof o)e=o;else if("undefined"!=typeof self)e=self;else try{e=Function("return this")()}catch(t){throw new Error("polyfill failed because global object is unavailable in this environment")}var n=e.Promise;n&&"[object Promise]"===Object.prototype.toString.call(n.resolve())&&!n.cast||(e.Promise=me)}var K;K=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};var Q,$,z,Y=K,G=0,X=function(e,t){re[G]=e,re[G+1]=t,G+=2,2===G&&($?$(m):z())},J="undefined"!=typeof window?window:void 0,Z=J||{},ee=Z.MutationObserver||Z.WebKitMutationObserver,te="undefined"!=typeof e&&"[object process]"==={}.toString.call(e),ne="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,re=new Array(1e3);z=te?c():ee?p():ne?d():void 0===J?v():h();var oe=g,ie=y,ae=void 0,se=1,ue=2,le=new A,ce=new A,fe=D,pe=U,de=L,he=0,me=B;B.all=fe,B.race=pe,B.resolve=ie,B.reject=de,B._setScheduler=u,B._setAsap=l,B._asap=X,B.prototype={constructor:B,then:oe,"catch":function(e){return this.then(null,e)}};var ve=q;q.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},q.prototype._enumerate=function(){for(var e=this.length,t=this._input,n=0;this._state===ae&&e>n;n++)this._eachEntry(t[n],n)},q.prototype._eachEntry=function(e,t){var n=this._instanceConstructor,r=n.resolve;if(r===ie){var o=w(e);if(o===oe&&e._state!==ae)this._settledAt(e._state,t,e._result);else if("function"!=typeof o)this._remaining--,this._result[t]=e;else if(n===me){var i=new n(b);R(i,e,o),this._willSettleAt(i,t)}else this._willSettleAt(new n(function(t){t(e)}),t)}else this._willSettleAt(r(e),t)},q.prototype._settledAt=function(e,t,n){var r=this.promise;r._state===ae&&(this._remaining--,e===ue?k(r,n):this._result[t]=n),0===this._remaining&&T(r,this._result)},q.prototype._willSettleAt=function(e,t){var n=this;N(e,void 0,function(e){n._settledAt(se,t,e)},function(e){n._settledAt(ue,t,e)})};var ge=W,ye={Promise:me,polyfill:ge};n(12).amd?(r=function(){return ye}.call(t,n,t,i),!(void 0!==r&&(i.exports=r))):"undefined"!=typeof i&&i.exports?i.exports=ye:"undefined"!=typeof this&&(this.ES6Promise=ye),ge()}).call(this)}).call(t,n(9),function(){return this}(),n(10)(e))},function(e,t){function n(){l=!1,a.length?u=a.concat(u):c=-1,u.length&&r()}function r(){if(!l){var e=setTimeout(n);l=!0;for(var t=u.length;t;){for(a=u,u=[];++c1)for(var n=1;n=u.hosts[e.hostType].length&&(d||!h)?u._promise.reject(r):(u.hostIndex[e.hostType]=++u.hostIndex[e.hostType]%u.hosts[e.hostType].length,r instanceof c.RequestTimeout?v():(d||(f=1/0),t(n,s)))}function v(){return u.hostIndex[e.hostType]=++u.hostIndex[e.hostType]%u.hosts[e.hostType].length,s.timeout=u.requestTimeout*(f+1),t(n,s)}var g;if(u._useCache&&(g=e.url),u._useCache&&r&&(g+="_body_"+s.body),u._useCache&&a&&void 0!==a[g])return i("serving response from cache"),u._promise.resolve(JSON.parse(a[g]));if(f>=u.hosts[e.hostType].length)return!h||d?(i("could not get any response"),u._promise.reject(new c.AlgoliaSearchError("Cannot connect to the AlgoliaSearch API. Send an email to support@algolia.com to report and resolve the issue. Application id was: "+u.applicationID))):(i("switching to fallback"),f=0,s.method=e.fallback.method,s.url=e.fallback.url,s.jsonBody=e.fallback.body,s.jsonBody&&(s.body=l(s.jsonBody)),o=u._computeRequestHeaders(),s.timeout=u.requestTimeout*(f+1),u.hostIndex[e.hostType]=0,d=!0,t(u._request.fallback,s));var y=u.hosts[e.hostType][u.hostIndex[e.hostType]]+s.url,b={body:s.body,jsonBody:s.jsonBody,method:s.method,headers:o,timeout:s.timeout,debug:i};return i("method: %s, url: %s, headers: %j, timeout: %d",b.method,y,b.headers,b.timeout),n===u._request.fallback&&i("using fallback"),n.call(u,y,b).then(p,m)}var r,o,i=n(42)("algoliasearch:"+e.url),a=e.cache,u=this,f=0,d=!1,h=u._useFallback&&u._request.fallback&&e.fallback;this.apiKey.length>p&&void 0!==e.body&&void 0!==e.body.params?(e.body.apiKey=this.apiKey,o=this._computeRequestHeaders(!1)):o=this._computeRequestHeaders(),void 0!==e.body&&(r=l(e.body)),i("request start");var m=t(u._request,{url:e.url,method:e.method,body:r,jsonBody:e.body,timeout:u.requestTimeout*(f+1)});return e.callback?void m.then(function(t){s(function(){e.callback(null,t)},u._setTimeout||setTimeout)},function(t){s(function(){e.callback(t)},u._setTimeout||setTimeout)}):m},_getSearchParams:function(e,t){if(void 0===e||null===e)return t;for(var n in e)null!==n&&void 0!==e[n]&&e.hasOwnProperty(n)&&(t+=""===t?"":"&",t+=n+"="+encodeURIComponent("[object Array]"===Object.prototype.toString.call(e[n])?l(e[n]):e[n]));return t},_computeRequestHeaders:function(e){var t=n(15),r={"x-algolia-agent":this._ua,"x-algolia-application-id":this.applicationID};return e!==!1&&(r["x-algolia-api-key"]=this.apiKey),this.userToken&&(r["x-algolia-usertoken"]=this.userToken),this.securityTags&&(r["x-algolia-tagfilters"]=this.securityTags),this.extraHeaders&&t(this.extraHeaders,function(e){r[e.name]=e.value}),r}},r.prototype.Index.prototype={clearCache:function(){this.cache={}},addObject:function(e,t,n){var r=this;return 1!==arguments.length&&"function"!=typeof t||(n=t,t=void 0),this.as._jsonRequest({method:void 0!==t?"PUT":"POST",url:"/1/indexes/"+encodeURIComponent(r.indexName)+(void 0!==t?"/"+encodeURIComponent(t):""),body:e,hostType:"write",callback:n})},addObjects:function(e,t){var r=n(34),o="Usage: index.addObjects(arrayOfObjects[, callback])";if(!r(e))throw new Error(o);for(var i=this,a={requests:[]},s=0;sa&&(t=a),"published"!==e.status?c._promise.delay(t).then(n):e})}function r(e){s(function(){t(null,e)},c._setTimeout||setTimeout)}function o(e){s(function(){t(e)},c._setTimeout||setTimeout)}var i=100,a=5e3,u=0,l=this,c=l.as,f=n();return t?void f.then(r,o):f},clearIndex:function(e){var t=this;return this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(t.indexName)+"/clear",hostType:"write",callback:e})},getSettings:function(e){var t=this;return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(t.indexName)+"/settings",hostType:"read",callback:e})},setSettings:function(e,t){var n=this;return this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(n.indexName)+"/settings",hostType:"write",body:e,callback:t})},listUserKeys:function(e){var t=this;return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(t.indexName)+"/keys",hostType:"read",callback:e})},getUserKeyACL:function(e,t){var n=this;return this.as._jsonRequest({method:"GET",url:"/1/indexes/"+encodeURIComponent(n.indexName)+"/keys/"+e,hostType:"read",callback:t})},deleteUserKey:function(e,t){var n=this;return this.as._jsonRequest({method:"DELETE",url:"/1/indexes/"+encodeURIComponent(n.indexName)+"/keys/"+e,hostType:"write",callback:t})},addUserKey:function(e,t,r){var o=n(34),i="Usage: index.addUserKey(arrayOfAcls[, params, callback])";if(!o(e))throw new Error(i);1!==arguments.length&&"function"!=typeof t||(r=t,t=null);var a={acl:e};return t&&(a.validity=t.validity,a.maxQueriesPerIPPerHour=t.maxQueriesPerIPPerHour,a.maxHitsPerQuery=t.maxHitsPerQuery,a.description=t.description,t.queryParameters&&(a.queryParameters=this.as._getSearchParams(t.queryParameters,"")),a.referers=t.referers),this.as._jsonRequest({method:"POST",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/keys",body:a,hostType:"write",callback:r})},addUserKeyWithValidity:u(function(e,t,n){return this.addUserKey(e,t,n)},a("index.addUserKeyWithValidity()","index.addUserKey()")),updateUserKey:function(e,t,r,o){var i=n(34),a="Usage: index.updateUserKey(key, arrayOfAcls[, params, callback])";if(!i(t))throw new Error(a);2!==arguments.length&&"function"!=typeof r||(o=r,r=null);var s={acl:t};return r&&(s.validity=r.validity,s.maxQueriesPerIPPerHour=r.maxQueriesPerIPPerHour,s.maxHitsPerQuery=r.maxHitsPerQuery,s.description=r.description,r.queryParameters&&(s.queryParameters=this.as._getSearchParams(r.queryParameters,"")),s.referers=r.referers),this.as._jsonRequest({method:"PUT",url:"/1/indexes/"+encodeURIComponent(this.indexName)+"/keys/"+e,body:s,hostType:"write",callback:o})},_search:function(e,t,n){return this.as._jsonRequest({cache:this.cache,method:"POST",url:t||"/1/indexes/"+encodeURIComponent(this.indexName)+"/query",body:{params:e},hostType:"read",fallback:{method:"GET",url:"/1/indexes/"+encodeURIComponent(this.indexName),body:{params:e}},callback:n})},as:null,indexName:null,typeAheadArgs:null,typeAheadValueOption:null}},function(e,t,n){"use strict";function r(e,t){var r=n(15),o=this;"function"==typeof Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):o.stack=(new Error).stack||"Cannot get a stacktrace, browser is too old",this.name=this.constructor.name,this.message=e||"Unknown error",t&&r(t,function(e,t){o[t]=e})}function o(e,t){function n(){var n=Array.prototype.slice.call(arguments,0);"string"!=typeof n[0]&&n.unshift(t),r.apply(this,n),this.name="AlgoliaSearch"+e+"Error"}return i(n,r),n}var i=n(7);i(r,Error),e.exports={AlgoliaSearchError:r,UnparsableJSON:o("UnparsableJSON","Could not parse the incoming response as JSON, see err.more for details"),RequestTimeout:o("RequestTimeout","Request timedout before getting a response"),Network:o("Network","Network issue, see err.more for details"),JSONPScriptFail:o("JSONPScriptFail"," + + + + + + + + + + CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/index.html b/tags/index.html new file mode 100644 index 0000000..2aff937 --- /dev/null +++ b/tags/index.html @@ -0,0 +1,627 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tags | CoderShmily's Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +