├── .gitignore ├── 0-install.Rmd ├── 1-clean-data.Rmd ├── 2-hdbscan.Rmd ├── 3-umap.Rmd ├── 4-glrm.Rmd ├── 5-lca.Rmd ├── 6-hopach.Rmd ├── 7-isolation-forests.Rmd ├── LICENSE ├── R └── lca-covariate-table.R ├── README.md ├── data-raw └── .gitignore ├── data └── .gitignore ├── docs ├── _config.yml ├── fonts_mtheme_max.css ├── libs │ ├── gitbook-2.6.7 │ │ ├── css │ │ │ ├── fontawesome │ │ │ │ └── fontawesome-webfont.ttf │ │ │ ├── plugin-bookdown.css │ │ │ ├── plugin-fontsettings.css │ │ │ ├── plugin-highlight.css │ │ │ ├── plugin-search.css │ │ │ ├── plugin-table.css │ │ │ └── style.css │ │ └── js │ │ │ ├── app.min.js │ │ │ ├── jquery.highlight.js │ │ │ ├── lunr.js │ │ │ ├── plugin-bookdown.js │ │ │ ├── plugin-fontsettings.js │ │ │ ├── plugin-search.js │ │ │ └── plugin-sharing.js │ ├── jquery-2.2.3 │ │ └── jquery.min.js │ ├── remark-css-0.0.1 │ │ ├── default-fonts.css │ │ └── default.css │ ├── remark-css │ │ └── robot.css │ └── remark-latest.min.js ├── mtheme_max.css ├── scrollable.css ├── slides.Rmd └── slides.html └── solutions ├── challenges-2-hbscan.Rmd └── challenges-6-hopach.Rmd /.gitignore: -------------------------------------------------------------------------------- 1 | *.RData 2 | *.csv 3 | 4 | # History files 5 | .Rhistory 6 | .Rapp.history 7 | 8 | # Session Data files 9 | .RData 10 | 11 | # User-specific files 12 | .Ruserdata 13 | 14 | # Example code in package build process 15 | *-Ex.R 16 | 17 | # Output files from R CMD build 18 | /*.tar.gz 19 | 20 | # Output files from R CMD check 21 | /*.Rcheck/ 22 | 23 | # RStudio files 24 | .Rproj.user/ 25 | 26 | # produced vignettes 27 | vignettes/*.html 28 | vignettes/*.pdf 29 | 30 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 31 | .httr-oauth 32 | 33 | # knitr and R markdown default cache directories 34 | *_cache/ 35 | /cache/ 36 | 37 | # Temporary files created by R markdown 38 | *.utf8.md 39 | *.knit.md 40 | 41 | # R Environment Variables 42 | .Renviron 43 | -------------------------------------------------------------------------------- /0-install.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "0. Setup" 3 | output: html_document 4 | --- 5 | 6 | ```{r setup, include=FALSE} 7 | knitr::opts_chunk$set(echo = TRUE) 8 | ``` 9 | 10 | This file will walk through the installation of any needed packages. We will consider three types of packages: 11 | 12 | * **CRAN** - this is where most R packages reside, and it has extensive automated testing to ensure quality. 13 | * **GitHub** - these are more "bleeding edge" packages that may not have as much testing. 14 | * **BioConductor** - these are packages designed for computational biology applications. 15 | 16 | General notes 17 | 18 | * If given the choice, do not compile packages from source (it's more error-prone). 19 | * If there's a corruption error message, try restarting your R session and trying again (Session -> Restart R). 20 | * If asked, try to update existing packages. But if that causes errors, run it again and don't update existing packages. 21 | 22 | ## Check requirements 23 | 24 | ```{r check_requirements} 25 | min_r_version = 3.6 26 | 27 | r_version = as.numeric(paste0(R.version["major"], ".", as.integer(R.version["minor"]))) 28 | 29 | if (r_version < min_r_version) { 30 | cat(paste0("Error: your R software is out of date.\n", 31 | "Minimum version required: ", min_r_version, "\n", 32 | "R version detected: ", r_version, "\n", 33 | "Please download and install the latest version from: https://cloud.r-project.org/")) 34 | } else { 35 | cat("Your R software is up to date:", r_version) 36 | } 37 | ``` 38 | 39 | ## Package installation 40 | 41 | ### Cran packages 42 | 43 | ```{r cran_packages} 44 | packages = list( 45 | cran = c("h2o", # glrm, anomaly forests 46 | "dbscan", # hdbscan 47 | "poLCA", # latent class analysis 48 | "umap", # umap 49 | "BiocManager", # needed to install hopach 50 | "rio", # import / export 51 | "dplyr", # data manipulation 52 | "ggplot2", # plotting 53 | "remotes") # installation of packages from GitHub 54 | ) 55 | 56 | # Try to load each package and save the result. 57 | (install_status = suppressWarnings(sapply(packages$cran, require, character.only = TRUE, quietly = TRUE))) 58 | 59 | # Check if any packages still need to be installed, and if so, try to install them. 60 | if (sum(!install_status) > 0) { 61 | cat("The following CRAN packages need to be installed:", 62 | paste0(paste(names(install_status)[!install_status], collapse = ", "), ".\n")) 63 | 64 | # Install any needed packages. 65 | install.packages(packages$cran[!install_status], 66 | # Specify repository so that we can install when knitting this file. 67 | repos = "http://cran.rstudio.com") 68 | 69 | # Load the newly installed packages. 70 | recheck = suppressWarnings(sapply(packages$cran[!install_status], require, character.only = TRUE, quietly = TRUE)) 71 | 72 | if (sum(!recheck) > 0) { 73 | cat("Failed to install the following CRAN packages:", 74 | paste0(paste(names(recheck)[!recheck], collapse = ", "), "."), 75 | "\nPlease try installing them manually with install.packages()", 76 | "and closely reviewing any error messages.\n") 77 | } else { 78 | cat("CRAN packages installed successfully.\n") 79 | } 80 | } else { 81 | cat("All CRAN packages are installed and loaded.\n") 82 | } 83 | 84 | ``` 85 | 86 | ### GitHub packages 87 | 88 | Note that the ck37r package is now also on CRAN, but it's good to show GitHub installation for posterity. 89 | 90 | ```{r github_packages} 91 | packages$github = c("ck37r" = "ck37/ck37r") 92 | 93 | # Try to load each package and save the result. 94 | install_status = suppressWarnings(sapply(names(packages$github), 95 | require, character.only = TRUE, quietly = TRUE)) 96 | 97 | # Check if any packages still need to be installed, and if so, try to install them. 98 | if (sum(!install_status) > 0) { 99 | cat("The following GitHub packages need to be installed:", 100 | paste0(paste(names(install_status)[!install_status], collapse = ", "), ".")) 101 | 102 | # Install any needed packages. 103 | remotes::install_github(packages$github[!install_status]) 104 | 105 | # Load the newly installed packages. 106 | recheck = suppressWarnings(sapply(names(packages$github)[!install_status], 107 | require, character.only = TRUE, quietly = TRUE)) 108 | 109 | if (sum(!recheck) > 0) { 110 | cat("Failed to install the following GitHub packages:", 111 | paste0(paste(packages$github[names(recheck)[!recheck]], collapse = ", "), "."), 112 | "\nPlease try installing them manually with remotes::install_github()", 113 | "and closely reviewing any error messages.\n") 114 | } else { 115 | cat("GitHub packages installed successfully.\n") 116 | } 117 | } else { 118 | cat("All GitHub packages are installed and loaded.\n") 119 | } 120 | ``` 121 | 122 | ### Bioconductor packages 123 | 124 | ```{r biocon_packages} 125 | packages$bioconductor = c("hopach") 126 | 127 | # Try to load each package and save the result. 128 | (install_status = suppressWarnings(sapply(packages$bioconductor, 129 | require, character.only = TRUE, quietly = TRUE))) 130 | 131 | # Check if any packages still need to be installed, and if so, try to install them. 132 | if (sum(!install_status) > 0) { 133 | cat("The following Bioconductor packages need to be installed:", 134 | paste0(paste(names(install_status)[!install_status], collapse = ", "), ".")) 135 | 136 | # Install any needed packages. 137 | BiocManager::install(packages$bioconductor[!install_status]) 138 | 139 | # Load the newly installed packages. 140 | recheck = suppressWarnings(sapply(packages$bioconductor[!install_status], 141 | require, character.only = TRUE, quietly = TRUE)) 142 | 143 | if (sum(!recheck) > 0) { 144 | cat("Failed to install the following Bioconductor packages:", 145 | paste0(paste(packages$github[names(recheck)[!recheck]], collapse = ", "), "."), 146 | "\nPlease try installing them manually with BiocManager::install()", 147 | "and closely reviewing any error messages.\n") 148 | } else { 149 | cat("Bioconductor packages installed successfully.\n") 150 | } 151 | } else { 152 | cat("All Bioconductor packages are installed and loaded.\n") 153 | } 154 | ``` 155 | 156 | ## Slides 157 | 158 | Now open up the slides available here: [https://dlab-berkeley.github.io/Unsupervised-Learning-in-R/slides.html](https://dlab-berkeley.github.io/Unsupervised-Learning-in-R/slides.html) 159 | -------------------------------------------------------------------------------- /1-clean-data.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Clean data" 3 | output: html_document 4 | --- 5 | 6 | ```{r setup, include=FALSE} 7 | knitr::opts_chunk$set(echo = TRUE) 8 | ``` 9 | 10 | ## Import data 11 | 12 | ```{r import_data} 13 | data_raw_dir = "data-raw/" 14 | filename = "processed.cleveland.csv" 15 | full_file = paste0(data_raw_dir, filename) 16 | 17 | if (!file.exists(full_file)) { 18 | url = "http://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/processed.cleveland.data" 19 | # Load the remote data. 20 | data = rio::import(url, header = FALSE, format = "csv", na.strings = '?') 21 | 22 | # Update column names. 23 | names(data) = c("age", "sex", "cp", "trestbps", "chol","fbs", "restecg", 24 | "thalach","exang", "oldpeak","slope", "ca", "thal", "num") 25 | 26 | # Save to local directory. 27 | rio::export(data, file = full_file) 28 | } else { 29 | data = rio::import(full_file) 30 | } 31 | ``` 32 | 33 | ## Categoricals to factors 34 | 35 | ```{r categoricals_to_factors} 36 | 37 | # Explicitly define certain variables as factors rather than numbers. 38 | data = ck37r::categoricals_to_factors(data, 39 | categoricals = c("ca", "cp", "slope", "thal"), 40 | verbose = TRUE) 41 | 42 | str(data) 43 | ``` 44 | 45 | ## Save unimputed version 46 | 47 | ```{r save_unimputed} 48 | save(data, file = "data/clean-data-unimputed.RData") 49 | ``` 50 | 51 | ## Missing values 52 | 53 | ```{r missing_values} 54 | 55 | # We have a few missing values. 56 | colSums(is.na(data)) 57 | 58 | # Omit missing values for now. 59 | data = na.omit(data) 60 | 61 | colSums(is.na(data)) 62 | ``` 63 | 64 | ## Save result 65 | 66 | ```{r save_data} 67 | save(data, file = "data/clean-data-imputed.RData") 68 | ``` 69 | -------------------------------------------------------------------------------- /2-hdbscan.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "HDBScan: density-based clustering" 3 | output: html_document 4 | --- 5 | 6 | ```{r setup, include=FALSE} 7 | knitr::opts_chunk$set(echo = TRUE) 8 | 9 | ``` 10 | 11 | ## Highlights 12 | 13 | * HDBScan is a **density-based clustering** algorithm, where observations that are near each other get assigned to clusters 14 | * Observations that are not near a group are considered noise or outliers. 15 | * The number of clusters is discovered automatically - nice! 16 | * It is hierarchical, meaning that clusters are linked and we can choose to select fewer clusters with more observations if preferred. 17 | * It is intended for continuous variables due to its focus on density. 18 | * It is expected to slow down once there are more than 50-100 covariates. 19 | * It provides a loose form of **soft clustering**: a score for how certain it is about cluster membership. 20 | 21 | ## Load processed data 22 | 23 | ```{r load_data} 24 | # From 1-clean-data.Rmd 25 | data = rio::import("data/clean-data-imputed.RData") 26 | 27 | # Convert factors to indicators. 28 | # This could also be done in dplyr in one line. 29 | result = ck37r::factors_to_indicators(data, verbose = TRUE) 30 | data = result$data 31 | 32 | str(data) 33 | ``` 34 | 35 | ## Data structure 36 | 37 | ```{r data_structure} 38 | (task = list( 39 | continuous = c("age", "trestbps", "chol", "thalach", "oldpeak"), 40 | all = names(data) 41 | )) 42 | 43 | 44 | ``` 45 | 46 | ## Basic hdbscan 47 | 48 | ```{r basic} 49 | library(dbscan) 50 | 51 | 52 | (groups = hdbscan(data[, task$continuous], minPts = 5L)) 53 | 54 | library(ggplot2) 55 | 56 | qplot(data$thalach, data$trestbps, color = factor(groups$cluster)) + 57 | theme_minimal() + theme(legend.position = c(1, 0.8)) 58 | 59 | # Plot the cluster hierarchy - may look a bit bad. 60 | plot(groups$hc, main = "HDBSCAN* Hierarchy") 61 | ``` 62 | 63 | ## Challenge 64 | 65 | 1. Try varying the minimum number of points needed for a cluster. What is your ranking of best values? 66 | 2. Try changing the variables plotted. Does any show clear clustering? 67 | 3. Try removing one of the continuous variables and re-running. Do you find better results? 68 | 69 | ## Investigating hdbscan 70 | 71 | Let's answer a few more questions: 72 | 73 | * What cluster is each observation assigned to, if any? 74 | * How confident is the algorithm in each observation's cluster membership? 75 | * How likely is an observation to be an outlier? 76 | 77 | ```{r more} 78 | # Cluster assignment for each observation. 79 | groups$cluster 80 | table(groups$cluster, useNA = "ifany") 81 | 82 | # Confidence score for membership in the cluster, where 1 is the max 0 = outlier. 83 | groups$membership_prob 84 | summary(groups$membership_prob) 85 | qplot(groups$membership_prob) + theme_minimal() 86 | 87 | # Higher scores are more likely to be outliers. 88 | groups$outlier_scores 89 | qplot(groups$outlier_scores) + theme_minimal() 90 | 91 | # Update our plot using cluster membership for transparency. 92 | qplot(data$chol, data$trestbps, color = factor(groups$cluster), 93 | # Scale by maximum membership probility so that max value is 100% opaque. 94 | alpha = groups$membership_prob / max(groups$membership_prob)) + 95 | theme_minimal() + theme(legend.position = c(1, 0.6)) 96 | 97 | 98 | # What are these cluster stability scores? Unknown to your instructor. 99 | groups$cluster_scores 100 | ``` 101 | 102 | The outlier score is estimated using the Global-Local Outlier Score from Hierarchies (GLOSH) algorithm. 103 | 104 | ## Additional hyperparameters 105 | 106 | Beyond what we've already covered, additional hyperparameters include: 107 | 108 | * **Distance metric** - could be euclidean (default), manhattan, l1, l2, or any other distance metric. 109 | * **Minimum samples** - unfortunately the R package doesn't support this paramter being different from "minPts", but in theory we could use a different value to choose how to smooth the density. 110 | 111 | ## Limitations 112 | 113 | The R package does not currently support prediction for hdbscan, although it can be done with dbscan. The python package does support prediction however. 114 | 115 | ## Challenge 116 | 117 | 1. Try running hdbscan with all variables instead of just the continuous ones. Can you achieve better results? 118 | 119 | ## Resources 120 | 121 | * https://cran.r-project.org/web/packages/dbscan/vignettes/hdbscan.html 122 | * https://hdbscan.readthedocs.io/en/latest/comparing_clustering_algorithms.html 123 | * https://hdbscan.readthedocs.io/en/latest/prediction_tutorial.html 124 | 125 | ## References 126 | 127 | L. McInnes, J. Healy, S. Astels, hdbscan: Hierarchical density based clustering In: Journal of Open Source Software, The Open Journal, volume 2, number 11. 2017 128 | 129 | Campello, Ricardo JGB, Davoud Moulavi, Arthur Zimek, and Jörg Sander. “Hierarchical density estimates for data clustering, visualization, and outlier detection.” ACM Transactions on Knowledge Discovery from Data (TKDD) 10, no. 1 (2015): 5. 130 | 131 | Hahsler M, Piekenbrock M, Doran D (2019). “dbscan: Fast Density-Based Clustering with R.” Journal of Statistical Software, 91(1), 1-30. doi: 10.18637/jss.v091.i01 132 | -------------------------------------------------------------------------------- /3-umap.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "UMAP: Uniform Manifold Approximation and Projection" 3 | output: html_document 4 | --- 5 | 6 | ```{r setup, include=FALSE} 7 | knitr::opts_chunk$set(echo = TRUE) 8 | ``` 9 | 10 | ## Highlights 11 | 12 | * UMAP is a nonlinear dimensionality reduction algorithm intended for data visualization. 13 | * It seeks to capture local distances (nearby points stay together) rather than global distances (all points transformed in the same way, as in principal component analysis). 14 | * It is inspired by **t-SNE** but arguably is preferable due to favorable properties: more scalable performance and better capture of local structure. 15 | * It originates from topology, and discovers **manifolds**: nonlinear surfaces that connect nearby points. 16 | 17 | ## Key assumptions 18 | 19 | * All data are locally connected. That is, the data distribution can be approximately by smoothing between observations with similar covariate profiles. 20 | 21 | ## Data prep 22 | 23 | We're trying out a separate birth weight dataset. 24 | 25 | ```{r data_prep} 26 | data = MASS::birthwt 27 | summary(data) 28 | ?MASS::birthwt 29 | data$race = factor(data$race, labels = c("white", "black", "other")) 30 | str(data) 31 | 32 | # Create a list to hold different variables. 33 | task = list( 34 | # Birth weight or low are generally our outcomes for supervised analyses. 35 | outcomes = c("bwt", "low"), 36 | 37 | # Variables we want to exclude from our analysis - none currently. 38 | exclude = NULL 39 | ) 40 | 41 | task$covariates = setdiff(names(data), task$outcomes) 42 | 43 | # Review our data structure. 44 | task 45 | 46 | dplyr::glimpse(data[task$covariates]) 47 | sapply(data[task$covariates], class) 48 | 49 | 50 | # Convert factor to indicators - don't run on outcomes though. 51 | result = ck37r::factors_to_indicators(data, predictors = task$covariates, verbose = TRUE) 52 | data = result$data 53 | ``` 54 | 55 | ## Basic UMAP 56 | 57 | ```{r basic_umap} 58 | library(umap) 59 | 60 | # Conduct UMAP analysis of our matrix data, setting a random seed. 61 | result = umap(data, random_state = 1) 62 | ``` 63 | 64 | ## Plot UMAP 65 | 66 | ```{r umap_plot} 67 | library(ggplot2) 68 | 69 | # Compile results into a dataframe. 70 | plot_data = data.frame(x = result$layout[, 1], 71 | y = result$layout[, 2], 72 | data[, task$outcomes]) 73 | 74 | # Create an initial plot object. 75 | p = ggplot(data = plot_data, aes(x = x, y = y, color = bwt)) + 76 | theme_minimal() 77 | 78 | p + geom_point() + ggtitle("Continuous birth weight") 79 | 80 | # Compare to the binarized outcome. 81 | p + geom_point(aes(color = low)) + ggtitle("Low birth weight = 1") 82 | ``` 83 | 84 | ## Hyperparameters 85 | 86 | The most important hyperparameter is the number of neighbors, which controls how UMAP balances the detection of local versus global structure. With a low number of neighbors we concentrate on the local structure (nearby observations), whereas with a high number of neighbors global structure (patterns between all observations). 87 | 88 | ```{r modify_hyperparameters} 89 | # Review default settings. 90 | umap.defaults 91 | 92 | config = umap.defaults 93 | 94 | # Set a seed. 95 | config$random_state = 1 96 | config$n_neighbors = 30 97 | 98 | # Run umap with new settings. 99 | result2 = umap(data, config) 100 | 101 | p + geom_point(aes(x = result2$layout[, 1], 102 | y = result2$layout[, 2])) 103 | 104 | # Try even more neighbors. 105 | config$n_neighbors = 60 106 | 107 | result3 = umap(data, config) 108 | 109 | p + geom_point(aes(x = result3$layout[, 1], 110 | y = result3$layout[, 2])) 111 | ``` 112 | 113 | ## Additional hyperparameters 114 | 115 | Noting a few other highlights: 116 | 117 | * **min_dist** - how tightly UMAP can pack points together in the embedded space, default 0.1. 118 | * **n_components** - dimensions to return, typically 2 but can be larger. 119 | * **metric** - distance metric, such as euclidean, manhattan, cosine, etc. 120 | * **n_epochs** - number of optimization iterations to perform, default 200. 121 | 122 | ## Challenge 123 | 124 | * Experiment with min_dist - what value strikes the right balance for visualization? 125 | 126 | ```{r review_defaults} 127 | # Review the many other hyperparameters. 128 | umap.defaults 129 | help(umap.defaults) 130 | ``` 131 | 132 | Also note that when calling umap, the function argument `method` can be changed to "umap-learn" to use the python package. 133 | 134 | More info on hyperparameters on the [umap-learn python documentation page](https://umap-learn.readthedocs.io/en/latest/parameters.html). 135 | 136 | ```{r check_help, eval=FALSE} 137 | ?umap 138 | ``` 139 | 140 | ## Challenge 141 | 142 | * Try out on heart dataset 143 | 144 | ## Resources 145 | 146 | * [Performance comparison of UMAP vs. tSNE, PCA, etc.](https://umap-learn.readthedocs.io/en/latest/benchmarking.html) 147 | * Arxiv paper: (https://arxiv.org/abs/1802.03426) 148 | * PyData 2018 talk (PCA, tSNE, and UMAP): (https://www.youtube.com/watch?v=YPJQydzTLwQ) 149 | * PyCon 2018 talk: (https://www.youtube.com/watch?v=nq6iPZVUxZU) 150 | 151 | ## References 152 | 153 | McInnes, L., Healy, J., & Melville, J. (2018). Umap: Uniform manifold approximation and projection for dimension reduction. arXiv preprint arXiv:1802.03426. 154 | -------------------------------------------------------------------------------- /4-glrm.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "GLRM: generalized low-rank models" 3 | output: html_document 4 | --- 5 | 6 | ```{r setup, include=FALSE} 7 | knitr::opts_chunk$set(echo = TRUE) 8 | ``` 9 | 10 | ## Highlights 11 | 12 | * GLRM is a linear dimensionality reduction algorithm similar to principal components analysis (PCA). 13 | * GLRM supports categorical, ordinal, and binary variables in addition to continuous variables. 14 | * It allows missing data, and can be used for missing data imputation. 15 | * It was invented in 2014 at Stanford and can be used in R through the java-based h2o.ai framework. 16 | 17 | 18 | ## Load processed data 19 | 20 | ```{r load_data} 21 | # From 1-clean-data.Rmd 22 | data = rio::import("data/clean-data-unimputed.RData") 23 | 24 | # Factors do not need to be converted to indicators. 25 | table(sapply(data, class)) 26 | 27 | # We do have some missing data. 28 | colSums(is.na(data)) 29 | ``` 30 | 31 | ## Start h2o server 32 | 33 | ```{r start_h2o} 34 | # Start h2o. 35 | h2o::h2o.no_progress() # Turn off progress bars 36 | h2o::h2o.init() # Could specify e.g. max_mem_size = "4g" 37 | 38 | 39 | # Import data into h2o (java). 40 | h2o_df = h2o::as.h2o(data) 41 | 42 | # Looks good. 43 | str(h2o_df) 44 | ``` 45 | 46 | ## Basic GLRM 47 | 48 | ```{r basic_glrm} 49 | library(h2o) 50 | library(dplyr) 51 | library(ggplot2) 52 | 53 | system.time({ 54 | glrm_result = 55 | h2o::h2o.glrm(training_frame = h2o_df, cols = colnames(h2o_df), 56 | loss = "Absolute", 57 | seed = 1, 58 | # Number of components, also called archetypes 59 | k = 10, 60 | max_iterations = 500, 61 | # This is necessary to ensure that the model can optimize, otherwise 62 | # there may be no improvement in the objective. 63 | transform = "STANDARDIZE") 64 | }) 65 | 66 | plot(glrm_result) 67 | 68 | # Review components that are extracted. 69 | # We should see a smooth contribution to the variance. 70 | glrm_result@model$importance 71 | 72 | # If only one component is important then the glrm may not be functioning 73 | # correctly (e.g. data may need to be standardized). 74 | 75 | # This code is via Hands-on Machine Learning in R. 76 | data.frame( 77 | component = glrm_result@model$importance %>% seq_along(), 78 | PVE = glrm_result@model$importance %>% .[2,] %>% unlist(), 79 | CVE = glrm_result@model$importance %>% .[3,] %>% unlist() 80 | ) %>% 81 | tidyr::gather(metric, variance_explained, -component) %>% 82 | ggplot(aes(component, variance_explained)) + 83 | geom_point() + theme_minimal() + 84 | facet_wrap(~ metric, ncol = 1, scales = "free") 85 | ``` 86 | 87 | ## Challenge 88 | 89 | 1. How many components would you use? 90 | 2. Try changing "Quadratic" to "Absolute". How many components would you use? 91 | 92 | ## What is each component made of? 93 | 94 | ```{r review_component} 95 | # This code is via Hands-on Machine Learning in R. 96 | p1 <- t(glrm_result@model$archetypes) %>% 97 | as.data.frame() %>% 98 | mutate(feature = row.names(.)) %>% 99 | ggplot(aes(Arch1, reorder(feature, Arch1))) + 100 | geom_point() + theme_minimal() 101 | 102 | p2 <- t(glrm_result@model$archetypes) %>% 103 | as.data.frame() %>% 104 | mutate(feature = row.names(.)) %>% 105 | ggplot(aes(Arch1, Arch2, label = feature)) + 106 | geom_text() + theme_minimal() 107 | 108 | gridExtra::grid.arrange(p1, p2, nrow = 1) 109 | ``` 110 | 111 | ## Challenge 112 | 113 | 1. Examine archetypes 2 and 3. How do they differ from archetype 1? 114 | 115 | ## Respecting our data structure 116 | 117 | We had some factor variables, actually some of which were ordinal, as well as binary variables. Let's use GLRM's support for improved data types to use it. 118 | 119 | ```{r glrm_v2} 120 | 121 | # When specifying the indices, the first variable must have index = 0 122 | (losses = data.frame("index" = seq(ncol(data)) - 1, 123 | "variable" = names(data), 124 | "loss" = "Quadratic", 125 | stringsAsFactors = FALSE)) 126 | 127 | # Review data 128 | str(data) 129 | 130 | task = list( 131 | binary = c("sex", "fbs", "exang"), 132 | ordinal = c("restecg", "num", "slope", "ca", "thal", "cp") 133 | ) 134 | 135 | # Customize loss for binary variables 136 | losses$loss[losses$variable %in% task$binary] = "Hinge" 137 | 138 | # Customize loss for ordinal variables 139 | losses$loss[losses$variable %in% task$ordinal] = "Ordinal" 140 | 141 | # Review our losses 142 | losses 143 | 144 | 145 | # Run with custom loss by variable type. 146 | system.time({ 147 | glrm_result = 148 | h2o::h2o.glrm(training_frame = h2o_df, cols = colnames(h2o_df), 149 | loss_by_col = losses$loss, 150 | loss_by_col_idx = losses$index, 151 | seed = 1, 152 | # Number of components, also called archetypes 153 | k = 10, 154 | max_iterations = 500, 155 | # This is necessary to ensure that the model can optimize, otherwise 156 | # there may be no improvement in the objective. 157 | transform = "STANDARDIZE") 158 | }) 159 | 160 | # NOTE: there will be an error that we have to fix. 161 | names(h2o_df)[c(7, 14)] 162 | 163 | # h2o_df$restecg = as.factor(h2o_df$restecg) 164 | # h2o_df$num = as.factor(h2o_df$num) 165 | 166 | 167 | plot(glrm_result) 168 | 169 | # Review components that are extracted. 170 | # We should see a smooth contribution to the variance. 171 | glrm_result@model$importance 172 | 173 | # If only one component is important then the glrm may not be functioning 174 | # correctly (e.g. data may need to be standardized). 175 | data.frame( 176 | component = glrm_result@model$importance %>% seq_along(), 177 | PVE = glrm_result@model$importance %>% .[2,] %>% unlist(), 178 | CVE = glrm_result@model$importance %>% .[3,] %>% unlist() 179 | ) %>% 180 | tidyr::gather(metric, variance_explained, -component) %>% 181 | ggplot(aes(component, variance_explained)) + 182 | geom_point() + theme_minimal() + 183 | facet_wrap(~ metric, ncol = 1, scales = "free") 184 | ``` 185 | 186 | What changed once we customized the loss functions? 187 | 188 | ## Missing value imputation 189 | 190 | We can use our GLRM model to impute all of the missing values in our dataframe. 191 | 192 | ```{r missing_val} 193 | # Reconstructed data from GLRM. 194 | recon_df = h2o::h2o.reconstruct(glrm_result, h2o_df, 195 | reverse_transform = TRUE) 196 | # Fix column names. 197 | names(recon_df) = names(data) 198 | 199 | # Convert from h2o object (java) back to an R df. 200 | recon_df = as.data.frame(recon_df) 201 | 202 | # Notice that our factors have less variation. 203 | str(recon_df) 204 | 205 | ### 206 | # Compare imputed values to known values. 207 | 208 | # Inspect the age variable as an example, even though we have all values. 209 | known_age = !is.na(data$age) 210 | 211 | # RMSE is very close to 0. 212 | sqrt(mean((data$age[known_age] - recon_df$age[known_age])^2)) 213 | # Compare to median imputation, RMSE = 9.2 214 | sqrt(mean((data$age[known_age] - median(data$age[known_age]))^2)) 215 | # Compare to mean imputation, RMSE = 9.0 216 | sqrt(mean((data$age[known_age] - mean(data$age[known_age]))^2)) 217 | 218 | 219 | # We could exclude certain variables. 220 | skip_vars = c() 221 | 222 | (vars_with_missingness = 223 | setdiff(names(data)[colSums(is.na(data)) > 0], skip_vars)) 224 | 225 | # Review losses for variables with missingness. 226 | losses[losses$variable %in% vars_with_missingness, ] 227 | 228 | # Bound GLRM variables back to the original bounds. 229 | for (var in vars_with_missingness) { 230 | 231 | # Analyze the rows in which the variable is not missing. 232 | missing_rows = is.na(data[[var]]) 233 | 234 | # TODO: double-check that the factor levels are being copied over correctly. 235 | # We may need to convert to a character first, and then to a factor 236 | # using the levels of the original data column. 237 | data[missing_rows, var] = recon_df[missing_rows, var] 238 | 239 | # NOTE: for continuous data, we would preferably bound the imputed values 240 | # to stay within the range of the observed data. Code to be added. 241 | 242 | } 243 | 244 | # Confirm that we have no missingness. 245 | colSums(is.na(data)) 246 | ``` 247 | 248 | ## Caveats 249 | 250 | Our evaluation of imputation accuracy is optimistic because we are evaluating on the training data. We should upgrade this to do a training/test split or cross-validation. 251 | 252 | ## Hyperparameter tuning 253 | 254 | There are many other hyperparameters for GLRM that would be preferably tuned to the characteristics of our dataset. See [Hands on Machine Learning](https://bradleyboehmke.github.io/HOML/GLRM.html#tuning-to-optimize-for-unseen-data) for code that implements a grid search. We also could try a random search or optimized search. 255 | 256 | ## Clustering after GLRM 257 | 258 | ```{r cluster} 259 | # Extract the components as a new condensed dataframe. 260 | new_data = as.data.frame(h2o.getFrame(glrm_result@model$representation_name)) 261 | dim(new_data) 262 | summary(new_data) 263 | str(new_data) 264 | ``` 265 | 266 | ## Challenge 267 | 268 | 1. Refit the model adding arguments `regularization_x = "L1"`, `gamma_x = 1`. Plot the first archetype. Do you notice anything different? 269 | 2. Apply hdbscan to our compressed dataframe. Can you find a more effective clustering than the original? 270 | 3. What about UMAP - how does it look? 271 | 272 | ## Resources 273 | 274 | * [GLRM in Hands-on Machine Learning](https://bradleyboehmke.github.io/HOML/GLRM.html) 275 | * [h2o GLRM manual](http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-science/glrm.html) 276 | * [Another h2o GLRM tutorial](http://docs.h2o.ai/h2o-tutorials/latest-stable/tutorials/glrm/glrm-tutorial.html) 277 | * [GLRM in Julia](https://github.com/madeleineudell/LowRankModels.jl) 278 | 279 | ## References 280 | 281 | Boehmke, B., & Greenwell, B. M. (2019). Hands-On Machine Learning with R. CRC Press. 282 | 283 | Udell, Madeline, Corinne Horn, Reza Zadeh, and Stephen Boyd. “Generalized low rank models.” arXiv preprint arXiv:1410.0342, 2014. 284 | -------------------------------------------------------------------------------- /5-lca.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Latent class analysis" 3 | output: html_document 4 | --- 5 | 6 | ```{r setup, include=FALSE} 7 | knitr::opts_chunk$set(echo = TRUE) 8 | ``` 9 | 10 | ## Highlights 11 | 12 | * Latent class analysis is designed for creating clusters out of binary or categorical variables. 13 | * It is a **model-based clustering** method based on maximum likelihood estimation. 14 | * It provides **soft-clustering**: each observation has a probability distribution over cluster membership. 15 | * It uses a **greedy algorithm** with performance that varies with each analysis. Therefore we often will re-run an analysis 10 or 20 times and select the iteration with the best model fit. 16 | * It originates from the broader class of **finite mixture models**. 17 | * Latent dirichlet allocation (LDA) is a Bayesian form of LCA. 18 | 19 | ## Load data 20 | 21 | ```{r load_data} 22 | # From 1-clean-data.Rmd 23 | data = rio::import("data/clean-data-imputed.RData") 24 | 25 | names(data) 26 | str(data) 27 | (task = list( 28 | factors = names(data)[sapply(data, is.factor)])) 29 | ``` 30 | 31 | ## Basic LCA 32 | 33 | ```{r run_lca} 34 | vars = task$factors 35 | 36 | # Specify the formula based on the variables we want to use for clustering. 37 | (f = as.formula(paste0("cbind(", paste(vars, collapse = ", "), ") ~ 1"))) 38 | 39 | model = poLCA(f, data, nclass = 2, maxiter = 100, nrep = 10, tol = 1e-7) 40 | ``` 41 | 42 | ## Compare number of classes 43 | 44 | ```{r compare_classes} 45 | library(knitr) 46 | library(kableExtra) 47 | 48 | run_lca = function(data, formula, nclass = 2, nrep = 10, 49 | maxiter = 5000, tolerance = 1e-7, verbose = FALSE) { 50 | # TODO: capture output if verbose = FALSE 51 | 52 | lca = try(poLCA(formula, data, nclass = nclass, maxiter = maxiter, nrep = reps, 53 | tol = tolerance)) 54 | 55 | if ("try-error" %in% class(lca)) { 56 | cat("Ran into error.\n") 57 | results = list(nclass = nclass, aic = NA, bic = NA, converged = NA, object = NULL) 58 | } else { 59 | 60 | converged = lca$numiter < lca$maxiter 61 | 62 | # TODO: return object. 63 | results = list(nclass = nclass, aic = lca$aic, bic = lca$bic, converged = converged, 64 | object = lca) 65 | } 66 | 67 | return(results) 68 | } 69 | 70 | reps = 5L 71 | 72 | results = data.frame(matrix(NA, nrow = 0, ncol = 5)) 73 | colnames = c("nclass", "aic", "bic", "converged", "description") 74 | colnames(results) = colnames 75 | 76 | set.seed(1) 77 | 78 | objects = list() 79 | outcome = NULL 80 | # We could use nicer names for the variables here. 81 | var_labels = vars 82 | 83 | # Try 2 to 6 classes (clusters) 84 | for (classes in 2:6) { 85 | cat("Running LCA for", classes, "classes.\n") 86 | 87 | #################### 88 | # Run the latent class analysis. 89 | result = run_lca(data, f, nclass = classes, nrep = reps) 90 | 91 | # Extract the return object and store separately. 92 | object = result$object 93 | 94 | # Remove the object from the list so that we can store everything else in a dataframe. 95 | result$object = NULL 96 | 97 | # Could put something in here. 98 | result$description = "" 99 | 100 | # Use a string list name so that we don't need a null [[1]] element. 101 | objects[[as.character(classes)]] = object 102 | 103 | # This will be a data.frame of summary statistics, 1 row per LCA. 104 | results = rbind(results, result, stringsAsFactors = FALSE) 105 | 106 | # Correct colnames again. 107 | colnames(results) = colnames 108 | 109 | ##### 110 | # Generate covariate table. 111 | 112 | # Currently restricting to complete cases. Could use imputed data instead possibly. 113 | temp_data = na.omit(data[, c(outcome, vars)]) 114 | 115 | # This function is defined in R/lca-covariate-table.R 116 | table = lca_covariate_table(object, var_labels = var_labels, 117 | outcome = NULL, 118 | format = "html", # could be latex instead. 119 | data = temp_data[, vars]) 120 | 121 | ################ 122 | print(kable(table, booktabs = TRUE, digits = c(rep(1, classes), 3, 3), 123 | col.names = linebreak(colnames(table), align = "c"), 124 | escape = FALSE) %>% 125 | kable_styling(latex_options = c("scale_down"#, 126 | # "striped" 127 | )) %>% 128 | row_spec(nrow(table) - 1L, hline_after = TRUE)) 129 | 130 | # TODO: generate Excel export also, ideally as a separate tab within a single file. 131 | 132 | } 133 | 134 | results 135 | 136 | ``` 137 | 138 | ## Resources 139 | 140 | * Collins and Lanza. (2009). [Latent class and latent transition analysis](https://smile.amazon.com/Latent-Class-Transition-Analysis-Applications/dp/0470228393/) 141 | * [Latent profile analysis in R](https://cran.r-project.org/web/packages/tidyLPA/vignettes/Introduction_to_tidyLPA.html) 142 | 143 | ## References 144 | 145 | Figueroa, S. C., Kennedy, C. J., Wesseling, C., Wiemels, J. M., Morimoto, L., & Mora, A. M. (2020). Early immune stimulation and childhood acute lymphoblastic leukemia in Costa Rica: A comparison of statistical approaches. Environmental Research, 182, 109023. 146 | -------------------------------------------------------------------------------- /6-hopach.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "HOPACH: hierarchical medoid clustering" 3 | output: html_document 4 | --- 5 | 6 | ```{r setup, include=FALSE} 7 | knitr::opts_chunk$set(echo = TRUE) 8 | ``` 9 | 10 | ## Highlights 11 | 12 | * Hierarchical cluster algorithm that is divisive (top down), but also will consider combining clusters if beneficial. 13 | * Based on medoids: each cluster is based on a representative observation with the smallest distance to other cluster members. 14 | * Orders clusters and observations within clusters based on the distance metric. 15 | * The hierarchical tree splits don't have to be binary - could split into 3 or more clusters. 16 | * It will automatically determine the recommended number of clusters. 17 | 18 | ## Load data 19 | 20 | ```{r load_data} 21 | # From 1-clean-data.Rmd 22 | data = rio::import("data/clean-data-imputed.RData") 23 | 24 | str(data) 25 | 26 | # Convert factors to indicators 27 | result = ck37r::factors_to_indicators(data, verbose = TRUE) 28 | data = result$data 29 | 30 | # Standardize the data so that distances are more comparable. 31 | # NOTE: we might skip binary variables in this step. 32 | data = ck37r::standardize(data) 33 | ``` 34 | 35 | ## Basic HOPACH 36 | 37 | ```{r basic_hopach} 38 | library(hopach) 39 | 40 | # We use the numeric data matrix here, which has converted factors to indicators. 41 | distances = distancematrix(data, 42 | d = "euclid", 43 | # d = "cosangle", 44 | na.rm = TRUE) 45 | 46 | # This is an n x n matrix. 47 | dim(distances) 48 | 49 | hobj = hopach(data, dmat = distances, newmed = "nn", 50 | d = "euclid") 51 | # d = "cosangle") 52 | 53 | 54 | # Number of clusters identified. 55 | hobj$clust$k 56 | 57 | # Review sizes of each cluster. 58 | hobj$clust$sizes 59 | 60 | # Review the cluster assignment vector. 61 | # These counts correspond to the cluster sizes that we reviewed. 62 | table(hobj$clustering$labels) 63 | 64 | # Extract medoids - representative observations for each cluster. 65 | # These are the row indices from the dataframe. 66 | hobj$clustering$medoids 67 | 68 | # This plot is recommended but does not seeem that useful. 69 | # Red = small distance, white = large distance. 70 | dplot(distances, hobj, ord = "final", 71 | main = "Distance matrix", showclusters = FALSE) 72 | 73 | ``` 74 | 75 | ## Bootstrap analysis 76 | 77 | ```{r bootstrap, fig.width = 6, fig.height = 6} 78 | 79 | # Bootstrap analysis 80 | # TODO: identify how to set seed. 81 | boot_result = boothopach(data, hobj, B = 100) 82 | 83 | # We want to see large bands of the same color, which indicate cluster stability. 84 | # May need to click "zoom" to view the plot. 85 | bootplot(boot_result, hobj, ord = "bootp", 86 | main = "Bootstrap plot", showclusters = FALSE) 87 | 88 | 89 | ``` 90 | 91 | ## Challenges 92 | 93 | 1. Change the distance metric to "cosangle" and re-run. How do your results compare? 94 | 2. Cluster the variables rather than the observations by transposing the data frame with `t()` and re-running the distance calculation and clustering. Examine the medoids to find the representative variables in the dataset. 95 | 3. Don't standardize the data and re-run. How do the results compare? What if you standardize everything except the binary variables? 96 | 97 | ## Resources 98 | 99 | * [Bioconductor's HOPACH package](https://www.bioconductor.org/packages/release/bioc/vignettes/hopach/inst/doc/hopach.pdf) 100 | 101 | ## References 102 | 103 | van der Laan, M. J., & Pollard, K. S. (2003). A new algorithm for hybrid hierarchical clustering with visualization and the bootstrap. Journal of Statistical Planning and Inference, 117(2), 275-303. 104 | 105 | Pollard, K. S., & van der Laan, M. J. (2005). Cluster analysis of genomic data. In Bioinformatics and Computational Biology Solutions Using R and Bioconductor (pp. 209-228). Springer, New York, NY. 106 | -------------------------------------------------------------------------------- /7-isolation-forests.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Isolation forest" 3 | output: html_document 4 | --- 5 | 6 | ```{r setup, include=FALSE} 7 | knitr::opts_chunk$set(echo = TRUE) 8 | ``` 9 | 10 | ## Load data 11 | 12 | ```{r load_data} 13 | # From 1-clean-data.Rmd 14 | data = rio::import("data/clean-data-imputed.RData") 15 | 16 | str(data) 17 | ``` 18 | 19 | ## Basic isolation forest 20 | 21 | ```{r basic_isolation} 22 | library(h2o) 23 | 24 | # Start up h2o. 25 | h2o.init() 26 | 27 | h2o_df = as.h2o(data) 28 | 29 | # Split dataset giving the training dataset 75% of the data 30 | h2o_split <- h2o.splitFrame(data = h2o_df, ratios=0.75) 31 | 32 | # Create a training set from the 1st dataset in the split 33 | train <- h2o_split[[1]] 34 | 35 | # Create a testing set from the 2nd dataset in the split 36 | test <- h2o_split[[2]] 37 | 38 | # Build an Isolation forest model 39 | model <- h2o.isolationForest(training_frame=train, 40 | sample_rate = 0.1, 41 | max_depth = 20, 42 | ntrees = 50) 43 | 44 | # Calculate score 45 | score <- h2o.predict(model, test) 46 | result_pred <- as.data.frame(score$predict) 47 | 48 | summary(result_pred) 49 | 50 | library(ggplot2) 51 | qplot(result_pred$predict) + theme_minimal() 52 | 53 | # Predict the leaf node assignment 54 | ln_pred <- h2o.predict_leaf_node_assignment(model, test) 55 | ``` 56 | 57 | ## Resources 58 | 59 | * [h2o blog post on isolation forests](https://www.h2o.ai/blog/anomaly-detection-with-isolation-forests-using-h2o/) - Nov. 2018 60 | * [h2o documentation for isolation forests](http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-science/if.html) 61 | 62 | ## References 63 | 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Creative Commons Attribution-NonCommercial 4.0 International Public License 3 | 4 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. 5 | 6 | Section 1 – Definitions. 7 | 8 | Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. 9 | Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. 10 | Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 11 | Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. 12 | Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. 13 | Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. 14 | Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. 15 | Licensor means the individual(s) or entity(ies) granting rights under this Public License. 16 | NonCommercial means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange. 17 | Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. 18 | Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. 19 | You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. 20 | Section 2 – Scope. 21 | 22 | License grant. 23 | Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: 24 | reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and 25 | produce, reproduce, and Share Adapted Material for NonCommercial purposes only. 26 | Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 27 | Term. The term of this Public License is specified in Section 6(a). 28 | Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 29 | Downstream recipients. 30 | Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. 31 | No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 32 | No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 33 | Other rights. 34 | 35 | Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 36 | Patent and trademark rights are not licensed under this Public License. 37 | To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes. 38 | Section 3 – License Conditions. 39 | 40 | Your exercise of the Licensed Rights is expressly made subject to the following conditions. 41 | 42 | Attribution. 43 | 44 | If You Share the Licensed Material (including in modified form), You must: 45 | 46 | retain the following if it is supplied by the Licensor with the Licensed Material: 47 | identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); 48 | a copyright notice; 49 | a notice that refers to this Public License; 50 | a notice that refers to the disclaimer of warranties; 51 | a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 52 | indicate if You modified the Licensed Material and retain an indication of any previous modifications; and 53 | indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 54 | You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 55 | If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 56 | If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. 57 | Section 4 – Sui Generis Database Rights. 58 | 59 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: 60 | 61 | for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only; 62 | if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and 63 | You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. 64 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. 65 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 66 | 67 | Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. 68 | To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. 69 | The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. 70 | Section 6 – Term and Termination. 71 | 72 | This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. 73 | Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 74 | 75 | automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 76 | upon express reinstatement by the Licensor. 77 | For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. 78 | For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. 79 | Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 80 | Section 7 – Other Terms and Conditions. 81 | 82 | The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 83 | Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. 84 | Section 8 – Interpretation. 85 | 86 | For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. 87 | To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. 88 | No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. 89 | Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. 90 | -------------------------------------------------------------------------------- /R/lca-covariate-table.R: -------------------------------------------------------------------------------- 1 | #' @param outcome vector of outcome values. 2 | lca_covariate_table = 3 | function(object, var_labels = NULL, outcome = NULL, 4 | data = NULL, 5 | format = "latex", 6 | outcome_name = 7 | paste0("Leukemia rate (", 8 | ifelse(format == "latex", "\\", ""), "%)")) { 9 | 10 | num_vars = length(object$probs) 11 | 12 | num_classes = length(object$P) 13 | 14 | # Our results table should have one row for each variable, plus 1 for the header. 15 | # It should have 1 column per class plus 1 for the variable name. 16 | table = data.frame(do.call(rbind, lapply(object$probs, function(mat) { 17 | # mat[, "Pr(2)"] 18 | mat[, 2] 19 | }))) 20 | 21 | 22 | # Add row of outcome means for each class. 23 | if (!is.null(outcome)) { 24 | 25 | # If outcome is {1, 2} convert to {0, 1} 26 | if (all(unique(outcome) %in% c(1, 2))) { 27 | outcome = outcome - 1 28 | } 29 | 30 | # Add row to table with outcome distribution. 31 | # This should work with a binary or continuous outcome. 32 | outcome_means = tapply(outcome, object$predclass, mean) 33 | 34 | # For binary variables convert to a percentage. 35 | if (FALSE && length(unique(outcome)) == 2) { 36 | outcome_means = round(outcome_means * 100, 1) 37 | } 38 | 39 | # Add as a final row in the table. 40 | table = rbind(table, outcome_means) 41 | rownames(table)[nrow(table)] = outcome_name 42 | table = table * 100 43 | } 44 | 45 | # Sort by ascending order of leukemia rate: 46 | # table columns, object$P, object$predclass. 47 | 48 | # Final row contains the outcome means, so sort in ascending order. 49 | tab_order = order(table[nrow(table), ]) 50 | 51 | table = table[, tab_order] 52 | proportions = object$P[tab_order] 53 | 54 | # Create custom header line which shows the overall class distrbution. 55 | colnames(table) = paste0("Class ", 1:num_classes, 56 | ifelse(format == "latex", "\n", "
"), 57 | "(", round(proportions * 100, 1), 58 | ifelse(format == "latex", "\\", ""), "%)") 59 | 60 | # Ideally have custom strings for each variable name. 61 | if (!is.null(var_labels)) { 62 | #lapply(names(var_labels), function(var_name) { 63 | for (var_name in names(var_labels)) { 64 | if (var_name %in% rownames(table)) { 65 | rownames(table)[rownames(table) == var_name] = var_labels[var_name] 66 | } 67 | }#) 68 | } 69 | 70 | # Turn this off for now. 71 | if (FALSE) { 72 | 73 | # Create a blank column to hold the ANOVA p-value. 74 | table$p_value = NA 75 | 76 | # Add ANOVA test for each variable? 77 | for (var_i in seq(nrow(table))) { 78 | 79 | if (var_i <= length(var_labels)) { 80 | var_data = data[, names(var_labels)[var_i]] 81 | } else { 82 | var_data = outcome 83 | # We don't actually have an outcome variable. 84 | if (!is.null(outcome)) { 85 | next 86 | } 87 | } 88 | 89 | # Create a dataframe just for this anova analysis. 90 | df = data.frame(var_data, class = object$predclass) 91 | 92 | # Restrict to non-missing values. 93 | df = na.omit(df) 94 | 95 | # Run anova. 96 | anova_result = stats::aov(class ~ ., data = df) 97 | 98 | table[var_i, "p_value"] = summary(anova_result)[[1]][1, 5] 99 | } 100 | 101 | # Add FDR-adjusted p-value column. 102 | table$p_value_adj = stats::p.adjust(table$p_value, method = "BH") 103 | 104 | # Update last two column names for better printing. 105 | colnames(table)[c(ncol(table) - 1, ncol(table))] = 106 | c(paste0("ANOVA", ifelse(format == "latex", "\n", "
"), "p-value"), 107 | paste0("FDR adj.", ifelse(format == "latex", "\n", "
"), "p-value")) 108 | 109 | } 110 | 111 | return(table) 112 | 113 | } 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unsupervised Learning in R 2 | 3 | 4 | Unsupervised machine learning is a class of algorithms that identifies patterns 5 | in unlabeled data, i.e. without considering an outcome or target. This workshop 6 | will describe and demonstrate powerful unsupervised learning algorithms used for 7 | **clustering** (hdbscan, latent class analysis, hopach), **dimensionality 8 | reduction** (umap, generalized low-rank models), and **anomaly detection** (isolation forests). 9 | Participants will learn how to structure unsupervised 10 | learning analyses and will gain familiarity with example code that can be 11 | adapted to their own projects. 12 | 13 | **Author**: [Chris Kennedy](http://github.com/ck37) 14 | 15 | ## Prerequisites 16 | 17 | This is an intermediate machine learning workshop. Participants should have 18 | significant prior experience with R and RStudio, including manipulation of data 19 | frames, installation of packages, and plotting. 20 | 21 | **Prerequisite workshops** 22 | 23 | * [R Fundamentals](https://github.com/dlab-berkeley/R-Fundamentals) or similar training in R basics. 24 | 25 | **Recommended workshops** 26 | 27 | * [Machine Learning in R](https://github.com/dlab-berkeley/Machine-Learning-in-R) or other supervised learning experience. 28 | 29 | ## Technology requirements 30 | 31 | Participants should have access to a computer with the following software: 32 | 33 | * [R version 3.6](https://cran.rstudio.com/) or greater 34 | * [RStudio](https://rstudio.com/products/rstudio/download/#download) 35 | * [RTools](https://cran.r-project.org/bin/windows/Rtools/) - if using Windows 36 | 37 | ## Initial steps for participants 38 | 39 | To prepare for the workshop, please download the materials and work through the package installation in `0-install.Rmd`. Please report any errors to the [GitHub issue queue](https://github.com/dlab-berkeley/Unsupervised-Learning-in-R/issues). 40 | 41 | There is also an [RStudio Cloud workspace](https://rstudio.cloud/project/930459) that can be used. 42 | 43 | ## Reporting errors or giving feedback 44 | 45 | Please [create a GitHub issue](https://github.com/dlab-berkeley/Unsupervised-Learning-in-R/issues) to report any errors or give feedback on this workshop. 46 | 47 | ## Resources 48 | 49 | Books 50 | 51 | * Boemke & Greenwell (2019). [Hands-on Machine Learning with R](https://bradleyboehmke.github.io/HOML/) - free online version 52 | * Hennig et al. (2015). [Handbook of Cluster Analysis](https://smile.amazon.com/Handbook-Cluster-Analysis-Handbooks-Statistical-ebook/dp/B019FNKOJ4) - thorough and highly recommended 53 | * Aggarwal & Reddy. (2014). [Data clustering: algorithms and applications](https://smile.amazon.com/Data-Clustering-Algorithms-Applications-Knowledge-ebook/dp/B00EYROAQU/) - great complement to Hennig et al. 54 | * Dolnicar et al. (2018). [Market segmentation analysis](https://smile.amazon.com/Market-Segmentation-Analysis-Understanding-Professionals-ebook/dp/B07FQDSF3X/) - free, closely tied to R, and chapter 7 is especially helpful 55 | * Izenman (2013). [Modern Multivariate Statistical Techniques](https://www.amazon.com/Modern-Multivariate-Statistical-Techniques-Classification-ebook/dp/B00HWUR9CS/) 56 | * Everitt et al. (2011). [Cluster Analysis](https://www.amazon.com/Cluster-Analysis-Wiley-Probability-Statistics-ebook/dp/B005CPJSME) 57 | -------------------------------------------------------------------------------- /data-raw/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dlab-berkeley/Unsupervised-Learning-in-R/6bd2430e11e3619245290238fc6ba8674ff5e79f/data-raw/.gitignore -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dlab-berkeley/Unsupervised-Learning-in-R/6bd2430e11e3619245290238fc6ba8674ff5e79f/data/.gitignore -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-modernist -------------------------------------------------------------------------------- /docs/fonts_mtheme_max.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz); 2 | @import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic); 3 | @import url(https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700); 4 | @import url(https://fonts.googleapis.com/css?family=Fira+Sans:300,300i,400,400i,500,500i,700,700i); 5 | @import url(https://cdn.rawgit.com/tonsky/FiraCode/1.204/distr/fira_code.css); 6 | 7 | @import url(https://fonts.googleapis.com/css?family=Noto+Serif); 8 | 9 | body { 10 | font-family: 'Fira Sans','Droid Serif', 'Palatino Linotype', 'Book Antiqua', Palatino, 'Microsoft YaHei', 'Songti SC', serif; 11 | font-size: 120%; 12 | } 13 | 14 | p { 15 | font-family: 'Fira Sans','Droid Serif', 'Palatino Linotype', 'Book Antiqua', Palatino, 'Microsoft YaHei', 'Songti SC', serif; 16 | font-size: 120%; 17 | } 18 | 19 | ul, ol { 20 | font-family: 'Fira Sans','Droid Serif', 'Palatino Linotype', 'Book Antiqua', Palatino, 'Microsoft YaHei', 'Songti SC', serif; 21 | font-size: 100%; 22 | } 23 | 24 | .remark-code, .remark-inline-code { 25 | font-family: 'Source Code Pro', 'Lucida Console', Monaco, monospace; 26 | font-size: 80%; 27 | } 28 | 29 | .remark-inline-code { 30 | /* background: #F5F5F5; /* lighter */ 31 | /* background: #e7e8e2; /* darker */ 32 | border-radius: 3px; 33 | padding: 4px; 34 | } 35 | 36 | .code10 .remark-code { 37 | font-size: 10%; 38 | } 39 | 40 | .code20 .remark-code { 41 | font-size: 20%; 42 | } 43 | 44 | .code30 .remark-code { 45 | font-size: 30%; 46 | } 47 | 48 | .code40 .remark-code { 49 | font-size: 40%; 50 | } 51 | 52 | .code50 .remark-code { 53 | font-size: 50%; 54 | } 55 | 56 | .code55 .remark-code { 57 | font-size: 55%; 58 | } 59 | 60 | .code60 .remark-code { 61 | font-size: 60%; 62 | } 63 | 64 | .code70 .remark-code { 65 | font-size: 70%; 66 | } 67 | 68 | .code80 .remark-code { 69 | font-size: 80%; 70 | } 71 | 72 | .code90 .remark-code { 73 | font-size: 90%; 74 | } 75 | 76 | .code100 .remark-code { 77 | font-size: 100%; 78 | } 79 | 80 | .font10 { 81 | font-size: 10%; 82 | } 83 | 84 | .font20 { 85 | font-size: 20%; 86 | } 87 | 88 | .font30 { 89 | font-size: 30%; 90 | } 91 | 92 | .font40 { 93 | font-size: 40%; 94 | } 95 | 96 | .font50 { 97 | font-size: 50%; 98 | } 99 | 100 | .font60 { 101 | font-size: 60%; 102 | } 103 | 104 | .font70 { 105 | font-size: 70%; 106 | } 107 | 108 | .font80 { 109 | font-size: 80%; 110 | } 111 | 112 | .font90 { 113 | font-size: 90%; 114 | } 115 | 116 | .font100 { 117 | font-size: 100%; 118 | } 119 | 120 | .font110 { 121 | font-size: 110%; 122 | } 123 | 124 | .font120 { 125 | font-size: 120%; 126 | } 127 | 128 | .font130 { 129 | font-size: 130%; 130 | } 131 | 132 | .font140 { 133 | font-size: 140%; 134 | } 135 | 136 | .font150 { 137 | font-size: 150%; 138 | } 139 | 140 | .font160 { 141 | font-size: 160%; 142 | } 143 | .font170 { 144 | font-size: 170%; 145 | } 146 | .font180 { 147 | font-size: 180%; 148 | } 149 | .font190 { 150 | font-size: 190%; 151 | } 152 | .font200 { 153 | font-size: 200%; 154 | } 155 | 156 | .font300 { 157 | font-size: 300%; 158 | } 159 | 160 | .opacity10{ 161 | opacity: 0.1; 162 | } 163 | 164 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dlab-berkeley/Unsupervised-Learning-in-R/6bd2430e11e3619245290238fc6ba8674ff5e79f/docs/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/plugin-bookdown.css: -------------------------------------------------------------------------------- 1 | .book .book-header h1 { 2 | padding-left: 20px; 3 | padding-right: 20px; 4 | } 5 | .book .book-header.fixed { 6 | position: fixed; 7 | right: 0; 8 | top: 0; 9 | left: 0; 10 | border-bottom: 1px solid rgba(0,0,0,.07); 11 | } 12 | span.search-highlight { 13 | background-color: #ffff88; 14 | } 15 | @media (min-width: 600px) { 16 | .book.with-summary .book-header.fixed { 17 | left: 300px; 18 | } 19 | } 20 | @media (max-width: 1240px) { 21 | .book .book-body.fixed { 22 | top: 50px; 23 | } 24 | .book .book-body.fixed .body-inner { 25 | top: auto; 26 | } 27 | } 28 | @media (max-width: 600px) { 29 | .book.with-summary .book-header.fixed { 30 | left: calc(100% - 60px); 31 | min-width: 300px; 32 | } 33 | .book.with-summary .book-body { 34 | transform: none; 35 | left: calc(100% - 60px); 36 | min-width: 300px; 37 | } 38 | .book .book-body.fixed { 39 | top: 0; 40 | } 41 | } 42 | 43 | .book .book-body.fixed .body-inner { 44 | top: 50px; 45 | } 46 | .book .book-body .page-wrapper .page-inner section.normal sub, .book .book-body .page-wrapper .page-inner section.normal sup { 47 | font-size: 85%; 48 | } 49 | 50 | @media print { 51 | .book .book-summary, .book .book-body .book-header, .fa { 52 | display: none !important; 53 | } 54 | .book .book-body.fixed { 55 | left: 0px; 56 | } 57 | .book .book-body,.book .book-body .body-inner, .book.with-summary { 58 | overflow: visible !important; 59 | } 60 | } 61 | .kable_wrapper { 62 | border-spacing: 20px 0; 63 | border-collapse: separate; 64 | border: none; 65 | margin: auto; 66 | } 67 | .kable_wrapper > tbody > tr > td { 68 | vertical-align: top; 69 | } 70 | .book .book-body .page-wrapper .page-inner section.normal table tr.header { 71 | border-top-width: 2px; 72 | } 73 | .book .book-body .page-wrapper .page-inner section.normal table tr:last-child td { 74 | border-bottom-width: 2px; 75 | } 76 | .book .book-body .page-wrapper .page-inner section.normal table td, .book .book-body .page-wrapper .page-inner section.normal table th { 77 | border-left: none; 78 | border-right: none; 79 | } 80 | .book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr, .book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr > td { 81 | border-top: none; 82 | } 83 | .book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr:last-child > td { 84 | border-bottom: none; 85 | } 86 | 87 | div.theorem, div.lemma, div.corollary, div.proposition, div.conjecture { 88 | font-style: italic; 89 | } 90 | span.theorem, span.lemma, span.corollary, span.proposition, span.conjecture { 91 | font-style: normal; 92 | } 93 | div.proof:after { 94 | content: "\25a2"; 95 | float: right; 96 | } 97 | .header-section-number { 98 | padding-right: .5em; 99 | } 100 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/plugin-fontsettings.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Theme 1 3 | */ 4 | .color-theme-1 .dropdown-menu { 5 | background-color: #111111; 6 | border-color: #7e888b; 7 | } 8 | .color-theme-1 .dropdown-menu .dropdown-caret .caret-inner { 9 | border-bottom: 9px solid #111111; 10 | } 11 | .color-theme-1 .dropdown-menu .buttons { 12 | border-color: #7e888b; 13 | } 14 | .color-theme-1 .dropdown-menu .button { 15 | color: #afa790; 16 | } 17 | .color-theme-1 .dropdown-menu .button:hover { 18 | color: #73553c; 19 | } 20 | /* 21 | * Theme 2 22 | */ 23 | .color-theme-2 .dropdown-menu { 24 | background-color: #2d3143; 25 | border-color: #272a3a; 26 | } 27 | .color-theme-2 .dropdown-menu .dropdown-caret .caret-inner { 28 | border-bottom: 9px solid #2d3143; 29 | } 30 | .color-theme-2 .dropdown-menu .buttons { 31 | border-color: #272a3a; 32 | } 33 | .color-theme-2 .dropdown-menu .button { 34 | color: #62677f; 35 | } 36 | .color-theme-2 .dropdown-menu .button:hover { 37 | color: #f4f4f5; 38 | } 39 | .book .book-header .font-settings .font-enlarge { 40 | line-height: 30px; 41 | font-size: 1.4em; 42 | } 43 | .book .book-header .font-settings .font-reduce { 44 | line-height: 30px; 45 | font-size: 1em; 46 | } 47 | .book.color-theme-1 .book-body { 48 | color: #704214; 49 | background: #f3eacb; 50 | } 51 | .book.color-theme-1 .book-body .page-wrapper .page-inner section { 52 | background: #f3eacb; 53 | } 54 | .book.color-theme-2 .book-body { 55 | color: #bdcadb; 56 | background: #1c1f2b; 57 | } 58 | .book.color-theme-2 .book-body .page-wrapper .page-inner section { 59 | background: #1c1f2b; 60 | } 61 | .book.font-size-0 .book-body .page-inner section { 62 | font-size: 1.2rem; 63 | } 64 | .book.font-size-1 .book-body .page-inner section { 65 | font-size: 1.4rem; 66 | } 67 | .book.font-size-2 .book-body .page-inner section { 68 | font-size: 1.6rem; 69 | } 70 | .book.font-size-3 .book-body .page-inner section { 71 | font-size: 2.2rem; 72 | } 73 | .book.font-size-4 .book-body .page-inner section { 74 | font-size: 4rem; 75 | } 76 | .book.font-family-0 { 77 | font-family: Georgia, serif; 78 | } 79 | .book.font-family-1 { 80 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 81 | } 82 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal { 83 | color: #704214; 84 | } 85 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal a { 86 | color: inherit; 87 | } 88 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, 89 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2, 90 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h3, 91 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h4, 92 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h5, 93 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { 94 | color: inherit; 95 | } 96 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, 97 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2 { 98 | border-color: inherit; 99 | } 100 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { 101 | color: inherit; 102 | } 103 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal hr { 104 | background-color: inherit; 105 | } 106 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal blockquote { 107 | border-color: #c4b29f; 108 | opacity: 0.9; 109 | } 110 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, 111 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { 112 | background: #fdf6e3; 113 | color: #657b83; 114 | border-color: #f8df9c; 115 | } 116 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal .highlight { 117 | background-color: inherit; 118 | } 119 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table th, 120 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table td { 121 | border-color: #f5d06c; 122 | } 123 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr { 124 | color: inherit; 125 | background-color: #fdf6e3; 126 | border-color: #444444; 127 | } 128 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { 129 | background-color: #fbeecb; 130 | } 131 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal { 132 | color: #bdcadb; 133 | } 134 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal a { 135 | color: #3eb1d0; 136 | } 137 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, 138 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2, 139 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h3, 140 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h4, 141 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h5, 142 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { 143 | color: #fffffa; 144 | } 145 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, 146 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2 { 147 | border-color: #373b4e; 148 | } 149 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { 150 | color: #373b4e; 151 | } 152 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal hr { 153 | background-color: #373b4e; 154 | } 155 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal blockquote { 156 | border-color: #373b4e; 157 | } 158 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, 159 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { 160 | color: #9dbed8; 161 | background: #2d3143; 162 | border-color: #2d3143; 163 | } 164 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal .highlight { 165 | background-color: #282a39; 166 | } 167 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table th, 168 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table td { 169 | border-color: #3b3f54; 170 | } 171 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr { 172 | color: #b6c2d2; 173 | background-color: #2d3143; 174 | border-color: #3b3f54; 175 | } 176 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { 177 | background-color: #35394b; 178 | } 179 | .book.color-theme-1 .book-header { 180 | color: #afa790; 181 | background: transparent; 182 | } 183 | .book.color-theme-1 .book-header .btn { 184 | color: #afa790; 185 | } 186 | .book.color-theme-1 .book-header .btn:hover { 187 | color: #73553c; 188 | background: none; 189 | } 190 | .book.color-theme-1 .book-header h1 { 191 | color: #704214; 192 | } 193 | .book.color-theme-2 .book-header { 194 | color: #7e888b; 195 | background: transparent; 196 | } 197 | .book.color-theme-2 .book-header .btn { 198 | color: #3b3f54; 199 | } 200 | .book.color-theme-2 .book-header .btn:hover { 201 | color: #fffff5; 202 | background: none; 203 | } 204 | .book.color-theme-2 .book-header h1 { 205 | color: #bdcadb; 206 | } 207 | .book.color-theme-1 .book-body .navigation { 208 | color: #afa790; 209 | } 210 | .book.color-theme-1 .book-body .navigation:hover { 211 | color: #73553c; 212 | } 213 | .book.color-theme-2 .book-body .navigation { 214 | color: #383f52; 215 | } 216 | .book.color-theme-2 .book-body .navigation:hover { 217 | color: #fffff5; 218 | } 219 | /* 220 | * Theme 1 221 | */ 222 | .book.color-theme-1 .book-summary { 223 | color: #afa790; 224 | background: #111111; 225 | border-right: 1px solid rgba(0, 0, 0, 0.07); 226 | } 227 | .book.color-theme-1 .book-summary .book-search { 228 | background: transparent; 229 | } 230 | .book.color-theme-1 .book-summary .book-search input, 231 | .book.color-theme-1 .book-summary .book-search input:focus { 232 | border: 1px solid transparent; 233 | } 234 | .book.color-theme-1 .book-summary ul.summary li.divider { 235 | background: #7e888b; 236 | box-shadow: none; 237 | } 238 | .book.color-theme-1 .book-summary ul.summary li i.fa-check { 239 | color: #33cc33; 240 | } 241 | .book.color-theme-1 .book-summary ul.summary li.done > a { 242 | color: #877f6a; 243 | } 244 | .book.color-theme-1 .book-summary ul.summary li a, 245 | .book.color-theme-1 .book-summary ul.summary li span { 246 | color: #877f6a; 247 | background: transparent; 248 | font-weight: normal; 249 | } 250 | .book.color-theme-1 .book-summary ul.summary li.active > a, 251 | .book.color-theme-1 .book-summary ul.summary li a:hover { 252 | color: #704214; 253 | background: transparent; 254 | font-weight: normal; 255 | } 256 | /* 257 | * Theme 2 258 | */ 259 | .book.color-theme-2 .book-summary { 260 | color: #bcc1d2; 261 | background: #2d3143; 262 | border-right: none; 263 | } 264 | .book.color-theme-2 .book-summary .book-search { 265 | background: transparent; 266 | } 267 | .book.color-theme-2 .book-summary .book-search input, 268 | .book.color-theme-2 .book-summary .book-search input:focus { 269 | border: 1px solid transparent; 270 | } 271 | .book.color-theme-2 .book-summary ul.summary li.divider { 272 | background: #272a3a; 273 | box-shadow: none; 274 | } 275 | .book.color-theme-2 .book-summary ul.summary li i.fa-check { 276 | color: #33cc33; 277 | } 278 | .book.color-theme-2 .book-summary ul.summary li.done > a { 279 | color: #62687f; 280 | } 281 | .book.color-theme-2 .book-summary ul.summary li a, 282 | .book.color-theme-2 .book-summary ul.summary li span { 283 | color: #c1c6d7; 284 | background: transparent; 285 | font-weight: 600; 286 | } 287 | .book.color-theme-2 .book-summary ul.summary li.active > a, 288 | .book.color-theme-2 .book-summary ul.summary li a:hover { 289 | color: #f4f4f5; 290 | background: #252737; 291 | font-weight: 600; 292 | } 293 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/plugin-highlight.css: -------------------------------------------------------------------------------- 1 | .book .book-body .page-wrapper .page-inner section.normal pre, 2 | .book .book-body .page-wrapper .page-inner section.normal code { 3 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 4 | /* Tomorrow Comment */ 5 | /* Tomorrow Red */ 6 | /* Tomorrow Orange */ 7 | /* Tomorrow Yellow */ 8 | /* Tomorrow Green */ 9 | /* Tomorrow Aqua */ 10 | /* Tomorrow Blue */ 11 | /* Tomorrow Purple */ 12 | } 13 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, 14 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-comment, 15 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-title, 16 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-title { 17 | color: #8e908c; 18 | } 19 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, 20 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-variable, 21 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, 22 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, 23 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, 24 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-tag, 25 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, 26 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, 27 | .book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-constant, 28 | .book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-constant, 29 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-tag .hljs-title, 30 | .book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-tag .hljs-title, 31 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-pi, 32 | .book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-pi, 33 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-doctype, 34 | .book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-doctype, 35 | .book .book-body .page-wrapper .page-inner section.normal pre .html .hljs-doctype, 36 | .book .book-body .page-wrapper .page-inner section.normal code .html .hljs-doctype, 37 | .book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-id, 38 | .book .book-body .page-wrapper .page-inner section.normal code .css .hljs-id, 39 | .book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-class, 40 | .book .book-body .page-wrapper .page-inner section.normal code .css .hljs-class, 41 | .book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, 42 | .book .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo { 43 | color: #c82829; 44 | } 45 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-number, 46 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-number, 47 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, 48 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, 49 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, 50 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, 51 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, 52 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, 53 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, 54 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-literal, 55 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-params, 56 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-params, 57 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, 58 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-constant { 59 | color: #f5871f; 60 | } 61 | .book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-class .hljs-title, 62 | .book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-class .hljs-title, 63 | .book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-rules .hljs-attribute, 64 | .book .book-body .page-wrapper .page-inner section.normal code .css .hljs-rules .hljs-attribute { 65 | color: #eab700; 66 | } 67 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-string, 68 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-string, 69 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-value, 70 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-value, 71 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-inheritance, 72 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-inheritance, 73 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-header, 74 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-header, 75 | .book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-symbol, 76 | .book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-symbol, 77 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, 78 | .book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { 79 | color: #718c00; 80 | } 81 | .book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-hexcolor, 82 | .book .book-body .page-wrapper .page-inner section.normal code .css .hljs-hexcolor { 83 | color: #3e999f; 84 | } 85 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-function, 86 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-function, 87 | .book .book-body .page-wrapper .page-inner section.normal pre .python .hljs-decorator, 88 | .book .book-body .page-wrapper .page-inner section.normal code .python .hljs-decorator, 89 | .book .book-body .page-wrapper .page-inner section.normal pre .python .hljs-title, 90 | .book .book-body .page-wrapper .page-inner section.normal code .python .hljs-title, 91 | .book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-function .hljs-title, 92 | .book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-function .hljs-title, 93 | .book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-title .hljs-keyword, 94 | .book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-title .hljs-keyword, 95 | .book .book-body .page-wrapper .page-inner section.normal pre .perl .hljs-sub, 96 | .book .book-body .page-wrapper .page-inner section.normal code .perl .hljs-sub, 97 | .book .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-title, 98 | .book .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-title, 99 | .book .book-body .page-wrapper .page-inner section.normal pre .coffeescript .hljs-title, 100 | .book .book-body .page-wrapper .page-inner section.normal code .coffeescript .hljs-title { 101 | color: #4271ae; 102 | } 103 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, 104 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, 105 | .book .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-function, 106 | .book .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-function { 107 | color: #8959a8; 108 | } 109 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs, 110 | .book .book-body .page-wrapper .page-inner section.normal code .hljs { 111 | display: block; 112 | background: white; 113 | color: #4d4d4c; 114 | padding: 0.5em; 115 | } 116 | .book .book-body .page-wrapper .page-inner section.normal pre .coffeescript .javascript, 117 | .book .book-body .page-wrapper .page-inner section.normal code .coffeescript .javascript, 118 | .book .book-body .page-wrapper .page-inner section.normal pre .javascript .xml, 119 | .book .book-body .page-wrapper .page-inner section.normal code .javascript .xml, 120 | .book .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, 121 | .book .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, 122 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .javascript, 123 | .book .book-body .page-wrapper .page-inner section.normal code .xml .javascript, 124 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .vbscript, 125 | .book .book-body .page-wrapper .page-inner section.normal code .xml .vbscript, 126 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .css, 127 | .book .book-body .page-wrapper .page-inner section.normal code .xml .css, 128 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, 129 | .book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { 130 | opacity: 0.5; 131 | } 132 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, 133 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { 134 | /* 135 | 136 | Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull 137 | 138 | */ 139 | /* Solarized Green */ 140 | /* Solarized Cyan */ 141 | /* Solarized Blue */ 142 | /* Solarized Yellow */ 143 | /* Solarized Orange */ 144 | /* Solarized Red */ 145 | /* Solarized Violet */ 146 | } 147 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs, 148 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs { 149 | display: block; 150 | padding: 0.5em; 151 | background: #fdf6e3; 152 | color: #657b83; 153 | } 154 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, 155 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-comment, 156 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-template_comment, 157 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-template_comment, 158 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-header, 159 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-header, 160 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-doctype, 161 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-doctype, 162 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-pi, 163 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-pi, 164 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .lisp .hljs-string, 165 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .lisp .hljs-string, 166 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-javadoc, 167 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-javadoc { 168 | color: #93a1a1; 169 | } 170 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, 171 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, 172 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-winutils, 173 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-winutils, 174 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .method, 175 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .method, 176 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, 177 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-addition, 178 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-tag, 179 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-tag, 180 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-request, 181 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-request, 182 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-status, 183 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-status, 184 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .nginx .hljs-title, 185 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .nginx .hljs-title { 186 | color: #859900; 187 | } 188 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-number, 189 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-number, 190 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-command, 191 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-command, 192 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-string, 193 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-string, 194 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag .hljs-value, 195 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-tag .hljs-value, 196 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-rules .hljs-value, 197 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-rules .hljs-value, 198 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-phpdoc, 199 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-phpdoc, 200 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, 201 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, 202 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, 203 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, 204 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-hexcolor, 205 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-hexcolor, 206 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_url, 207 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_url { 208 | color: #2aa198; 209 | } 210 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-title, 211 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-title, 212 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-localvars, 213 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-localvars, 214 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-chunk, 215 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-chunk, 216 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-decorator, 217 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-decorator, 218 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, 219 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, 220 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-identifier, 221 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-identifier, 222 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .vhdl .hljs-literal, 223 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .vhdl .hljs-literal, 224 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-id, 225 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-id, 226 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-function, 227 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-function { 228 | color: #268bd2; 229 | } 230 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, 231 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, 232 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, 233 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-variable, 234 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .lisp .hljs-body, 235 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .lisp .hljs-body, 236 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .smalltalk .hljs-number, 237 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .smalltalk .hljs-number, 238 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, 239 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-constant, 240 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-class .hljs-title, 241 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-class .hljs-title, 242 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-parent, 243 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-parent, 244 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .haskell .hljs-type, 245 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .haskell .hljs-type, 246 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_reference, 247 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_reference { 248 | color: #b58900; 249 | } 250 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, 251 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, 252 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor .hljs-keyword, 253 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor .hljs-keyword, 254 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, 255 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, 256 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-shebang, 257 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-shebang, 258 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol, 259 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol, 260 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol .hljs-string, 261 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol .hljs-string, 262 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-change, 263 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-change, 264 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-special, 265 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-special, 266 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attr_selector, 267 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attr_selector, 268 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-subst, 269 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-subst, 270 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-cdata, 271 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-cdata, 272 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .clojure .hljs-title, 273 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .clojure .hljs-title, 274 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, 275 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo, 276 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-header, 277 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-header { 278 | color: #cb4b16; 279 | } 280 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, 281 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-deletion, 282 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-important, 283 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-important { 284 | color: #dc322f; 285 | } 286 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_label, 287 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_label { 288 | color: #6c71c4; 289 | } 290 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, 291 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula { 292 | background: #eee8d5; 293 | } 294 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, 295 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { 296 | /* Tomorrow Night Bright Theme */ 297 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 298 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 299 | /* Tomorrow Comment */ 300 | /* Tomorrow Red */ 301 | /* Tomorrow Orange */ 302 | /* Tomorrow Yellow */ 303 | /* Tomorrow Green */ 304 | /* Tomorrow Aqua */ 305 | /* Tomorrow Blue */ 306 | /* Tomorrow Purple */ 307 | } 308 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, 309 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-comment, 310 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-title, 311 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-title { 312 | color: #969896; 313 | } 314 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, 315 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-variable, 316 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, 317 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, 318 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, 319 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-tag, 320 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, 321 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, 322 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-constant, 323 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-constant, 324 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-tag .hljs-title, 325 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-tag .hljs-title, 326 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-pi, 327 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-pi, 328 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-doctype, 329 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-doctype, 330 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .html .hljs-doctype, 331 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .html .hljs-doctype, 332 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-id, 333 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-id, 334 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-class, 335 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-class, 336 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, 337 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo { 338 | color: #d54e53; 339 | } 340 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-number, 341 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-number, 342 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, 343 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, 344 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, 345 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, 346 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, 347 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, 348 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, 349 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-literal, 350 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-params, 351 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-params, 352 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, 353 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-constant { 354 | color: #e78c45; 355 | } 356 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-class .hljs-title, 357 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-class .hljs-title, 358 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-rules .hljs-attribute, 359 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-rules .hljs-attribute { 360 | color: #e7c547; 361 | } 362 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-string, 363 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-string, 364 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-value, 365 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-value, 366 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-inheritance, 367 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-inheritance, 368 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-header, 369 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-header, 370 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-symbol, 371 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-symbol, 372 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, 373 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { 374 | color: #b9ca4a; 375 | } 376 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-hexcolor, 377 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-hexcolor { 378 | color: #70c0b1; 379 | } 380 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-function, 381 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-function, 382 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .python .hljs-decorator, 383 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .python .hljs-decorator, 384 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .python .hljs-title, 385 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .python .hljs-title, 386 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-function .hljs-title, 387 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-function .hljs-title, 388 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-title .hljs-keyword, 389 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-title .hljs-keyword, 390 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .perl .hljs-sub, 391 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .perl .hljs-sub, 392 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-title, 393 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-title, 394 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .coffeescript .hljs-title, 395 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .coffeescript .hljs-title { 396 | color: #7aa6da; 397 | } 398 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, 399 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, 400 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-function, 401 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-function { 402 | color: #c397d8; 403 | } 404 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs, 405 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs { 406 | display: block; 407 | background: black; 408 | color: #eaeaea; 409 | padding: 0.5em; 410 | } 411 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .coffeescript .javascript, 412 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .coffeescript .javascript, 413 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .xml, 414 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .xml, 415 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, 416 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, 417 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .javascript, 418 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .javascript, 419 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .vbscript, 420 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .vbscript, 421 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .css, 422 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .css, 423 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, 424 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { 425 | opacity: 0.5; 426 | } 427 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/plugin-search.css: -------------------------------------------------------------------------------- 1 | .book .book-summary .book-search { 2 | padding: 6px; 3 | background: transparent; 4 | position: absolute; 5 | top: -50px; 6 | left: 0px; 7 | right: 0px; 8 | transition: top 0.5s ease; 9 | } 10 | .book .book-summary .book-search input, 11 | .book .book-summary .book-search input:focus, 12 | .book .book-summary .book-search input:hover { 13 | width: 100%; 14 | background: transparent; 15 | border: 1px solid #ccc; 16 | box-shadow: none; 17 | outline: none; 18 | line-height: 22px; 19 | padding: 7px 4px; 20 | color: inherit; 21 | box-sizing: border-box; 22 | } 23 | .book.with-search .book-summary .book-search { 24 | top: 0px; 25 | } 26 | .book.with-search .book-summary ul.summary { 27 | top: 50px; 28 | } 29 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/plugin-table.css: -------------------------------------------------------------------------------- 1 | .book .book-body .page-wrapper .page-inner section.normal table{display:table;width:100%;border-collapse:collapse;border-spacing:0;overflow:auto}.book .book-body .page-wrapper .page-inner section.normal table td,.book .book-body .page-wrapper .page-inner section.normal table th{padding:6px 13px;border:1px solid #ddd}.book .book-body .page-wrapper .page-inner section.normal table tr{background-color:#fff;border-top:1px solid #ccc}.book .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n){background-color:#f8f8f8}.book .book-body .page-wrapper .page-inner section.normal table th{font-weight:700} 2 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/css/style.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.1.0 | MIT License | git.io/normalize */img,legend{border:0}*,.fa{-webkit-font-smoothing:antialiased}.fa-ul>li,sub,sup{position:relative}.book .book-body .page-wrapper .page-inner section.normal hr:after,.book-langs-index .inner .languages:after,.buttons:after,.dropdown-menu .buttons:after{clear:both}body,html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}.hidden,[hidden]{display:none}audio:not([controls]){display:none;height:0}html{font-family:sans-serif}body,figure{margin:0}a:focus{outline:dotted thin}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}svg:not(:root){overflow:hidden}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button{margin-right:10px;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}/*! 2 | * Preboot v2 3 | * 4 | * Open sourced under MIT license by @mdo. 5 | * Some variables and mixins from Bootstrap (Apache 2 license). 6 | */.link-inherit,.link-inherit:focus,.link-inherit:hover{color:inherit}.fa,.fa-stack{display:inline-block}/*! 7 | * Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome 8 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 9 | */@font-face{font-family:FontAwesome;src:url(./fontawesome/fontawesome-webfont.ttf?v=4.1.0) format('truetype');font-weight:400;font-style:normal}.fa{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale}.book .book-header,.book .book-summary{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=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)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=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)}.fa-stack{position:relative;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-repeat:before,.fa-rotate-right:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-floppy-o:before,.fa-save:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-bolt:before,.fa-flash:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-chain-broken:before,.fa-unlink:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\f150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\f151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\f152"}.fa-eur:before,.fa-euro:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-inr:before,.fa-rupee:before{content:"\f156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\f158"}.fa-krw:before,.fa-won:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-try:before,.fa-turkish-lira:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\f19c"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-square:before,.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\f1c5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\f1c6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-empire:before,.fa-ge:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-paper-plane:before,.fa-send:before{content:"\f1d8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.book-langs-index{width:100%;height:100%;padding:40px 0;margin:0;overflow:auto}@media (max-width:600px){.book-langs-index{padding:0}}.book-langs-index .inner{max-width:600px;width:100%;margin:0 auto;padding:30px;background:#fff;border-radius:3px}.book-langs-index .inner h3{margin:0}.book-langs-index .inner .languages{list-style:none;padding:20px 30px;margin-top:20px;border-top:1px solid #eee}.book-langs-index .inner .languages:after,.book-langs-index .inner .languages:before{content:" ";display:table;line-height:0}.book-langs-index .inner .languages li{width:50%;float:left;padding:10px 5px;font-size:16px}@media (max-width:600px){.book-langs-index .inner .languages li{width:100%;max-width:100%}}.book .book-header{overflow:visible;height:50px;padding:0 8px;z-index:2;font-size:.85em;color:#7e888b;background:0 0}.book .book-header .btn{display:block;height:50px;padding:0 15px;border-bottom:none;color:#ccc;text-transform:uppercase;line-height:50px;-webkit-box-shadow:none!important;box-shadow:none!important;position:relative;font-size:14px}.book .book-header .btn:hover{position:relative;text-decoration:none;color:#444;background:0 0}.book .book-header h1{margin:0;font-size:20px;font-weight:200;text-align:center;line-height:50px;opacity:0;padding-left:200px;padding-right:200px;-webkit-transition:opacity .2s ease;-moz-transition:opacity .2s ease;-o-transition:opacity .2s ease;transition:opacity .2s ease;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.book .book-header h1 a,.book .book-header h1 a:hover{color:inherit;text-decoration:none}@media (max-width:1000px){.book .book-header h1{display:none}}.book .book-header h1 i{display:none}.book .book-header:hover h1{opacity:1}.book.is-loading .book-header h1 i{display:inline-block}.book.is-loading .book-header h1 a{display:none}.dropdown{position:relative}.dropdown-menu{position:absolute;top:100%;left:0;z-index:100;display:none;float:left;min-width:160px;padding:0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fafafa;border:1px solid rgba(0,0,0,.07);border-radius:1px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.open{display:block}.dropdown-menu.dropdown-left{left:auto;right:4%}.dropdown-menu.dropdown-left .dropdown-caret{right:14px;left:auto}.dropdown-menu .dropdown-caret{position:absolute;top:-8px;left:14px;width:18px;height:10px;float:left;overflow:hidden}.dropdown-menu .dropdown-caret .caret-inner,.dropdown-menu .dropdown-caret .caret-outer{display:inline-block;top:0;border-left:9px solid transparent;border-right:9px solid transparent;position:absolute}.dropdown-menu .dropdown-caret .caret-outer{border-bottom:9px solid rgba(0,0,0,.1);height:auto;left:0;width:auto;margin-left:-1px}.dropdown-menu .dropdown-caret .caret-inner{margin-top:-1px;top:1px;border-bottom:9px solid #fafafa}.dropdown-menu .buttons{border-bottom:1px solid rgba(0,0,0,.07)}.dropdown-menu .buttons:after,.dropdown-menu .buttons:before{content:" ";display:table;line-height:0}.dropdown-menu .buttons:last-child{border-bottom:none}.dropdown-menu .buttons .button{border:0;background-color:transparent;color:#a6a6a6;width:100%;text-align:center;float:left;line-height:1.42857143;padding:8px 4px}.alert,.dropdown-menu .buttons .button:hover{color:#444}.dropdown-menu .buttons .button:focus,.dropdown-menu .buttons .button:hover{outline:0}.dropdown-menu .buttons .button.size-2{width:50%}.dropdown-menu .buttons .button.size-3{width:33%}.alert{padding:15px;margin-bottom:20px;background:#eee;border-bottom:5px solid #ddd}.alert-success{background:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-info{background:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-danger{background:#f2dede;border-color:#ebccd1;color:#a94442}.alert-warning{background:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.book .book-summary{position:absolute;top:0;left:-300px;bottom:0;z-index:1;width:300px;color:#364149;background:#fafafa;border-right:1px solid rgba(0,0,0,.07);-webkit-transition:left 250ms ease;-moz-transition:left 250ms ease;-o-transition:left 250ms ease;transition:left 250ms ease}.book .book-summary ul.summary{position:absolute;top:0;left:0;right:0;bottom:0;overflow-y:auto;list-style:none;margin:0;padding:0;-webkit-transition:top .5s ease;-moz-transition:top .5s ease;-o-transition:top .5s ease;transition:top .5s ease}.book .book-summary ul.summary li{list-style:none}.book .book-summary ul.summary li.divider{height:1px;margin:7px 0;overflow:hidden;background:rgba(0,0,0,.07)}.book .book-summary ul.summary li i.fa-check{display:none;position:absolute;right:9px;top:16px;font-size:9px;color:#3c3}.book .book-summary ul.summary li.done>a{color:#364149;font-weight:400}.book .book-summary ul.summary li.done>a i{display:inline}.book .book-summary ul.summary li a,.book .book-summary ul.summary li span{display:block;padding:10px 15px;border-bottom:none;color:#364149;background:0 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative}.book .book-summary ul.summary li span{cursor:not-allowed;opacity:.3;filter:alpha(opacity=30)}.book .book-summary ul.summary li a:hover,.book .book-summary ul.summary li.active>a{color:#008cff;background:0 0;text-decoration:none}.book .book-summary ul.summary li ul{padding-left:20px}@media (max-width:600px){.book .book-summary{width:calc(100% - 60px);bottom:0;left:-100%}}.book.with-summary .book-summary{left:0}.book.without-animation .book-summary{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.book{position:relative;width:100%;height:100%}.book .book-body,.book .book-body .body-inner{position:absolute;top:0;left:0;overflow-y:auto;bottom:0;right:0}.book .book-body{color:#000;background:#fff;-webkit-transition:left 250ms ease;-moz-transition:left 250ms ease;-o-transition:left 250ms ease;transition:left 250ms ease}.book .book-body .page-wrapper{position:relative;outline:0}.book .book-body .page-wrapper .page-inner{max-width:800px;margin:0 auto;padding:20px 0 40px}.book .book-body .page-wrapper .page-inner section{margin:0;padding:5px 15px;background:#fff;border-radius:2px;line-height:1.7;font-size:1.6rem}.book .book-body .page-wrapper .page-inner .btn-group .btn{border-radius:0;background:#eee;border:0}@media (max-width:1240px){.book .book-body{-webkit-transition:-webkit-transform 250ms ease;-moz-transition:-moz-transform 250ms ease;-o-transition:-o-transform 250ms ease;transition:transform 250ms ease;padding-bottom:20px}.book .book-body .body-inner{position:static;min-height:calc(100% - 50px)}}@media (min-width:600px){.book.with-summary .book-body{left:300px}}@media (max-width:600px){.book.with-summary{overflow:hidden}.book.with-summary .book-body{-webkit-transform:translate(calc(100% - 60px),0);-moz-transform:translate(calc(100% - 60px),0);-ms-transform:translate(calc(100% - 60px),0);-o-transform:translate(calc(100% - 60px),0);transform:translate(calc(100% - 60px),0)}}.book.without-animation .book-body{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.buttons:after,.buttons:before{content:" ";display:table;line-height:0}.button{border:0;background:#eee;color:#666;width:100%;text-align:center;float:left;line-height:1.42857143;padding:8px 4px}.button:hover{color:#444}.button:focus,.button:hover{outline:0}.button.size-2{width:50%}.button.size-3{width:33%}.book .book-body .page-wrapper .page-inner section{display:none}.book .book-body .page-wrapper .page-inner section.normal{display:block;word-wrap:break-word;overflow:hidden;color:#333;line-height:1.7;text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%}.book .book-body .page-wrapper .page-inner section.normal *{box-sizing:border-box;-webkit-box-sizing:border-box;}.book .book-body .page-wrapper .page-inner section.normal>:first-child{margin-top:0!important}.book .book-body .page-wrapper .page-inner section.normal>:last-child{margin-bottom:0!important}.book .book-body .page-wrapper .page-inner section.normal blockquote,.book .book-body .page-wrapper .page-inner section.normal code,.book .book-body .page-wrapper .page-inner section.normal figure,.book .book-body .page-wrapper .page-inner section.normal img,.book .book-body .page-wrapper .page-inner section.normal pre,.book .book-body .page-wrapper .page-inner section.normal table,.book .book-body .page-wrapper .page-inner section.normal tr{page-break-inside:avoid}.book .book-body .page-wrapper .page-inner section.normal h2,.book .book-body .page-wrapper .page-inner section.normal h3,.book .book-body .page-wrapper .page-inner section.normal h4,.book .book-body .page-wrapper .page-inner section.normal h5,.book .book-body .page-wrapper .page-inner section.normal p{orphans:3;widows:3}.book .book-body .page-wrapper .page-inner section.normal h1,.book .book-body .page-wrapper .page-inner section.normal h2,.book .book-body .page-wrapper .page-inner section.normal h3,.book .book-body .page-wrapper .page-inner section.normal h4,.book .book-body .page-wrapper .page-inner section.normal h5{page-break-after:avoid}.book .book-body .page-wrapper .page-inner section.normal b,.book .book-body .page-wrapper .page-inner section.normal strong{font-weight:700}.book .book-body .page-wrapper .page-inner section.normal em{font-style:italic}.book .book-body .page-wrapper .page-inner section.normal blockquote,.book .book-body .page-wrapper .page-inner section.normal dl,.book .book-body .page-wrapper .page-inner section.normal ol,.book .book-body .page-wrapper .page-inner section.normal p,.book .book-body .page-wrapper .page-inner section.normal table,.book .book-body .page-wrapper .page-inner section.normal ul{margin-top:0;margin-bottom:.85em}.book .book-body .page-wrapper .page-inner section.normal a{color:#4183c4;text-decoration:none;background:0 0}.book .book-body .page-wrapper .page-inner section.normal a:active,.book .book-body .page-wrapper .page-inner section.normal a:focus,.book .book-body .page-wrapper .page-inner section.normal a:hover{outline:0;text-decoration:underline}.book .book-body .page-wrapper .page-inner section.normal img{border:0;max-width:100%}.book .book-body .page-wrapper .page-inner section.normal hr{height:4px;padding:0;margin:1.7em 0;overflow:hidden;background-color:#e7e7e7;border:none}.book .book-body .page-wrapper .page-inner section.normal hr:after,.book .book-body .page-wrapper .page-inner section.normal hr:before{display:table;content:" "}.book .book-body .page-wrapper .page-inner section.normal h1,.book .book-body .page-wrapper .page-inner section.normal h2,.book .book-body .page-wrapper .page-inner section.normal h3,.book .book-body .page-wrapper .page-inner section.normal h4,.book .book-body .page-wrapper .page-inner section.normal h5,.book .book-body .page-wrapper .page-inner section.normal h6{margin-top:1.275em;margin-bottom:.85em;}.book .book-body .page-wrapper .page-inner section.normal h1{font-size:2em}.book .book-body .page-wrapper .page-inner section.normal h2{font-size:1.75em}.book .book-body .page-wrapper .page-inner section.normal h3{font-size:1.5em}.book .book-body .page-wrapper .page-inner section.normal h4{font-size:1.25em}.book .book-body .page-wrapper .page-inner section.normal h5{font-size:1em}.book .book-body .page-wrapper .page-inner section.normal h6{font-size:1em;color:#777}.book .book-body .page-wrapper .page-inner section.normal code,.book .book-body .page-wrapper .page-inner section.normal pre{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;direction:ltr;border:none;color:inherit}.book .book-body .page-wrapper .page-inner section.normal pre{overflow:auto;word-wrap:normal;margin:0 0 1.275em;padding:.85em 1em;background:#f7f7f7}.book .book-body .page-wrapper .page-inner section.normal pre>code{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;font-size:.85em;white-space:pre;background:0 0}.book .book-body .page-wrapper .page-inner section.normal pre>code:after,.book .book-body .page-wrapper .page-inner section.normal pre>code:before{content:normal}.book .book-body .page-wrapper .page-inner section.normal code{padding:.2em;margin:0;font-size:.85em;background-color:#f7f7f7}.book .book-body .page-wrapper .page-inner section.normal code:after,.book .book-body .page-wrapper .page-inner section.normal code:before{letter-spacing:-.2em;content:"\00a0"}.book .book-body .page-wrapper .page-inner section.normal ol,.book .book-body .page-wrapper .page-inner section.normal ul{padding:0 0 0 2em;margin:0 0 .85em}.book .book-body .page-wrapper .page-inner section.normal ol ol,.book .book-body .page-wrapper .page-inner section.normal ol ul,.book .book-body .page-wrapper .page-inner section.normal ul ol,.book .book-body .page-wrapper .page-inner section.normal ul ul{margin-top:0;margin-bottom:0}.book .book-body .page-wrapper .page-inner section.normal ol ol{list-style-type:lower-roman}.book .book-body .page-wrapper .page-inner section.normal blockquote{margin:0 0 .85em;padding:0 15px;opacity:0.75;border-left:4px solid #dcdcdc}.book .book-body .page-wrapper .page-inner section.normal blockquote:first-child{margin-top:0}.book .book-body .page-wrapper .page-inner section.normal blockquote:last-child{margin-bottom:0}.book .book-body .page-wrapper .page-inner section.normal dl{padding:0}.book .book-body .page-wrapper .page-inner section.normal dl dt{padding:0;margin-top:.85em;font-style:italic;font-weight:700}.book .book-body .page-wrapper .page-inner section.normal dl dd{padding:0 .85em;margin-bottom:.85em}.book .book-body .page-wrapper .page-inner section.normal dd{margin-left:0}.book .book-body .page-wrapper .page-inner section.normal .glossary-term{cursor:help;text-decoration:underline}.book .book-body .navigation{position:absolute;top:50px;bottom:0;margin:0;max-width:150px;min-width:90px;display:flex;justify-content:center;align-content:center;flex-direction:column;font-size:40px;color:#ccc;text-align:center;-webkit-transition:all 350ms ease;-moz-transition:all 350ms ease;-o-transition:all 350ms ease;transition:all 350ms ease}.book .book-body .navigation:hover{text-decoration:none;color:#444}.book .book-body .navigation.navigation-next{right:0}.book .book-body .navigation.navigation-prev{left:0}@media (max-width:1240px){.book .book-body .navigation{position:static;top:auto;max-width:50%;width:50%;display:inline-block;float:left}.book .book-body .navigation.navigation-unique{max-width:100%;width:100%}}.book .book-body .page-wrapper .page-inner section.glossary{margin-bottom:40px}.book .book-body .page-wrapper .page-inner section.glossary h2 a,.book .book-body .page-wrapper .page-inner section.glossary h2 a:hover{color:inherit;text-decoration:none}.book .book-body .page-wrapper .page-inner section.glossary .glossary-index{list-style:none;margin:0;padding:0}.book .book-body .page-wrapper .page-inner section.glossary .glossary-index li{display:inline;margin:0 8px;white-space:nowrap}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-overflow-scrolling:touch;-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:none;-webkit-touch-callout:none}a{text-decoration:none}body,html{height:100%}html{font-size:62.5%}body{text-rendering:optimizeLegibility;font-smoothing:antialiased;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;letter-spacing:.2px;text-size-adjust:100%} 10 | .book .book-summary ul.summary li a span {display:inline;padding:initial;overflow:visible;cursor:auto;opacity:1;} 11 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/js/jquery.highlight.js: -------------------------------------------------------------------------------- 1 | gitbook.require(["jQuery"], function(jQuery) { 2 | 3 | /* 4 | * jQuery Highlight plugin 5 | * 6 | * Based on highlight v3 by Johann Burkard 7 | * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html 8 | * 9 | * Code a little bit refactored and cleaned (in my humble opinion). 10 | * Most important changes: 11 | * - has an option to highlight only entire words (wordsOnly - false by default), 12 | * - has an option to be case sensitive (caseSensitive - false by default) 13 | * - highlight element tag and class names can be specified in options 14 | * 15 | * Copyright (c) 2009 Bartek Szopka 16 | * 17 | * Licensed under MIT license. 18 | * 19 | */ 20 | 21 | jQuery.extend({ 22 | highlight: function (node, re, nodeName, className) { 23 | if (node.nodeType === 3) { 24 | var match = node.data.match(re); 25 | if (match) { 26 | var highlight = document.createElement(nodeName || 'span'); 27 | highlight.className = className || 'highlight'; 28 | var wordNode = node.splitText(match.index); 29 | wordNode.splitText(match[0].length); 30 | var wordClone = wordNode.cloneNode(true); 31 | highlight.appendChild(wordClone); 32 | wordNode.parentNode.replaceChild(highlight, wordNode); 33 | return 1; //skip added node in parent 34 | } 35 | } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children 36 | !/(script|style)/i.test(node.tagName) && // ignore script and style nodes 37 | !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted 38 | for (var i = 0; i < node.childNodes.length; i++) { 39 | i += jQuery.highlight(node.childNodes[i], re, nodeName, className); 40 | } 41 | } 42 | return 0; 43 | } 44 | }); 45 | 46 | jQuery.fn.unhighlight = function (options) { 47 | var settings = { className: 'highlight', element: 'span' }; 48 | jQuery.extend(settings, options); 49 | 50 | return this.find(settings.element + "." + settings.className).each(function () { 51 | var parent = this.parentNode; 52 | parent.replaceChild(this.firstChild, this); 53 | parent.normalize(); 54 | }).end(); 55 | }; 56 | 57 | jQuery.fn.highlight = function (words, options) { 58 | var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false }; 59 | jQuery.extend(settings, options); 60 | 61 | if (words.constructor === String) { 62 | words = [words]; 63 | } 64 | words = jQuery.grep(words, function(word, i){ 65 | return word !== ''; 66 | }); 67 | words = jQuery.map(words, function(word, i) { 68 | return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 69 | }); 70 | if (words.length === 0) { return this; } 71 | 72 | var flag = settings.caseSensitive ? "" : "i"; 73 | var pattern = "(" + words.join("|") + ")"; 74 | if (settings.wordsOnly) { 75 | pattern = "\\b" + pattern + "\\b"; 76 | } 77 | var re = new RegExp(pattern, flag); 78 | 79 | return this.each(function () { 80 | jQuery.highlight(this, re, settings.element, settings.className); 81 | }); 82 | }; 83 | 84 | }); 85 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/js/lunr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 0.5.12 3 | * Copyright (C) 2015 Oliver Nightingale 4 | * MIT Licensed 5 | * @license 6 | */ 7 | !function(){var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.5.12",t.utils={},t.utils.warn=function(t){return function(e){t.console&&console.warn&&console.warn(e)}}(this),t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var t=Array.prototype.slice.call(arguments),e=t.pop(),n=t;if("function"!=typeof e)throw new TypeError("last argument must be a function");n.forEach(function(t){this.hasHandler(t)||(this.events[t]=[]),this.events[t].push(e)},this)},t.EventEmitter.prototype.removeListener=function(t,e){if(this.hasHandler(t)){var n=this.events[t].indexOf(e);this.events[t].splice(n,1),this.events[t].length||delete this.events[t]}},t.EventEmitter.prototype.emit=function(t){if(this.hasHandler(t)){var e=Array.prototype.slice.call(arguments,1);this.events[t].forEach(function(t){t.apply(void 0,e)})}},t.EventEmitter.prototype.hasHandler=function(t){return t in this.events},t.tokenizer=function(t){return arguments.length&&null!=t&&void 0!=t?Array.isArray(t)?t.map(function(t){return t.toLowerCase()}):t.toString().trim().toLowerCase().split(/[\s\-\/]+/):[]},t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.registeredFunctions[e];if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");this._stack.splice(i,0,n)},t.Pipeline.prototype.remove=function(t){var e=this._stack.indexOf(t);-1!=e&&this._stack.splice(e,1)},t.Pipeline.prototype.run=function(t){for(var e=[],n=t.length,i=this._stack.length,o=0;n>o;o++){for(var r=t[o],s=0;i>s&&(r=this._stack[s](r,o,t),void 0!==r);s++);void 0!==r&&e.push(r)}return e},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Vector=function(){this._magnitude=null,this.list=void 0,this.length=0},t.Vector.Node=function(t,e,n){this.idx=t,this.val=e,this.next=n},t.Vector.prototype.insert=function(e,n){this._magnitude=void 0;var i=this.list;if(!i)return this.list=new t.Vector.Node(e,n,i),this.length++;if(en.idx?n=n.next:(i+=e.val*n.val,e=e.next,n=n.next);return i},t.Vector.prototype.similarity=function(t){return this.dot(t)/(this.magnitude()*t.magnitude())},t.SortedSet=function(){this.length=0,this.elements=[]},t.SortedSet.load=function(t){var e=new this;return e.elements=t,e.length=t.length,e},t.SortedSet.prototype.add=function(){var t,e;for(t=0;t1;){if(r===t)return o;t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o]}return r===t?o:-1},t.SortedSet.prototype.locationFor=function(t){for(var e=0,n=this.elements.length,i=n-e,o=e+Math.floor(i/2),r=this.elements[o];i>1;)t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o];return r>t?o:t>r?o+1:void 0},t.SortedSet.prototype.intersect=function(e){for(var n=new t.SortedSet,i=0,o=0,r=this.length,s=e.length,a=this.elements,h=e.elements;;){if(i>r-1||o>s-1)break;a[i]!==h[o]?a[i]h[o]&&o++:(n.add(a[i]),i++,o++)}return n},t.SortedSet.prototype.clone=function(){var e=new t.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},t.SortedSet.prototype.union=function(t){var e,n,i;return this.length>=t.length?(e=this,n=t):(e=t,n=this),i=e.clone(),i.add.apply(i,n.toArray()),i},t.SortedSet.prototype.toJSON=function(){return this.toArray()},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.Store,this.tokenStore=new t.TokenStore,this.corpusTokens=new t.SortedSet,this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var t=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,t)},t.Index.prototype.off=function(t,e){return this.eventEmitter.removeListener(t,e)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;return n._fields=e.fields,n._ref=e.ref,n.documentStore=t.Store.load(e.documentStore),n.tokenStore=t.TokenStore.load(e.tokenStore),n.corpusTokens=t.SortedSet.load(e.corpusTokens),n.pipeline=t.Pipeline.load(e.pipeline),n},t.Index.prototype.field=function(t,e){var e=e||{},n={name:t,boost:e.boost||1};return this._fields.push(n),this},t.Index.prototype.ref=function(t){return this._ref=t,this},t.Index.prototype.add=function(e,n){var i={},o=new t.SortedSet,r=e[this._ref],n=void 0===n?!0:n;this._fields.forEach(function(n){var r=this.pipeline.run(t.tokenizer(e[n.name]));i[n.name]=r,t.SortedSet.prototype.add.apply(o,r)},this),this.documentStore.set(r,o),t.SortedSet.prototype.add.apply(this.corpusTokens,o.toArray());for(var s=0;s0&&(i=1+Math.log(this.documentStore.length/n)),this._idfCache[e]=i},t.Index.prototype.search=function(e){var n=this.pipeline.run(t.tokenizer(e)),i=new t.Vector,o=[],r=this._fields.reduce(function(t,e){return t+e.boost},0),s=n.some(function(t){return this.tokenStore.has(t)},this);if(!s)return[];n.forEach(function(e,n,s){var a=1/s.length*this._fields.length*r,h=this,l=this.tokenStore.expand(e).reduce(function(n,o){var r=h.corpusTokens.indexOf(o),s=h.idf(o),l=1,u=new t.SortedSet;if(o!==e){var c=Math.max(3,o.length-e.length);l=1/Math.log(c)}return r>-1&&i.insert(r,a*s*l),Object.keys(h.tokenStore.get(o)).forEach(function(t){u.add(t)}),n.union(u)},new t.SortedSet);o.push(l)},this);var a=o.reduce(function(t,e){return t.intersect(e)});return a.map(function(t){return{ref:t,score:i.similarity(this.documentVector(t))}},this).sort(function(t,e){return e.score-t.score})},t.Index.prototype.documentVector=function(e){for(var n=this.documentStore.get(e),i=n.length,o=new t.Vector,r=0;i>r;r++){var s=n.elements[r],a=this.tokenStore.get(s)[e].tf,h=this.idf(s);o.insert(this.corpusTokens.indexOf(s),a*h)}return o},t.Index.prototype.toJSON=function(){return{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),tokenStore:this.tokenStore.toJSON(),corpusTokens:this.corpusTokens.toJSON(),pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(t){var e=Array.prototype.slice.call(arguments,1);e.unshift(this),t.apply(this,e)},t.Store=function(){this.store={},this.length=0},t.Store.load=function(e){var n=new this;return n.length=e.length,n.store=Object.keys(e.store).reduce(function(n,i){return n[i]=t.SortedSet.load(e.store[i]),n},{}),n},t.Store.prototype.set=function(t,e){this.has(t)||this.length++,this.store[t]=e},t.Store.prototype.get=function(t){return this.store[t]},t.Store.prototype.has=function(t){return t in this.store},t.Store.prototype.remove=function(t){this.has(t)&&(delete this.store[t],this.length--)},t.Store.prototype.toJSON=function(){return{store:this.store,length:this.length}},t.stemmer=function(){var t={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},e={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,a="^("+o+")?"+r+o+"("+r+")?$",h="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,u=new RegExp(s),c=new RegExp(h),f=new RegExp(a),d=new RegExp(l),p=/^(.+?)(ss|i)es$/,m=/^(.+?)([^s])s$/,v=/^(.+?)eed$/,y=/^(.+?)(ed|ing)$/,g=/.$/,S=/(at|bl|iz)$/,w=new RegExp("([^aeiouylsz])\\1$"),x=new RegExp("^"+o+i+"[^aeiouwxy]$"),k=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,_=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,O=/^(.+?)e$/,P=/ll$/,N=new RegExp("^"+o+i+"[^aeiouwxy]$"),T=function(n){var i,o,r,s,a,h,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,a=m,s.test(n)?n=n.replace(s,"$1$2"):a.test(n)&&(n=n.replace(a,"$1$2")),s=v,a=y,s.test(n)){var T=s.exec(n);s=u,s.test(T[1])&&(s=g,n=n.replace(s,""))}else if(a.test(n)){var T=a.exec(n);i=T[1],a=d,a.test(i)&&(n=i,a=S,h=w,l=x,a.test(n)?n+="e":h.test(n)?(s=g,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=k,s.test(n)){var T=s.exec(n);i=T[1],n=i+"i"}if(s=b,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+t[o])}if(s=E,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+e[o])}if(s=_,a=F,s.test(n)){var T=s.exec(n);i=T[1],s=c,s.test(i)&&(n=i)}else if(a.test(n)){var T=a.exec(n);i=T[1]+T[2],a=c,a.test(i)&&(n=i)}if(s=O,s.test(n)){var T=s.exec(n);i=T[1],s=c,a=f,h=N,(s.test(i)||a.test(i)&&!h.test(i))&&(n=i)}return s=P,a=c,s.test(n)&&a.test(n)&&(s=g,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return T}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==e?e:void 0},t.stopWordFilter.stopWords={a:"a",able:"able",about:"about",across:"across",after:"after",all:"all",almost:"almost",also:"also",am:"am",among:"among",an:"an",and:"and",any:"any",are:"are",as:"as",at:"at",be:"be",because:"because",been:"been",but:"but",by:"by",can:"can",cannot:"cannot",could:"could",dear:"dear",did:"did","do":"do",does:"does",either:"either","else":"else",ever:"ever",every:"every","for":"for",from:"from",get:"get",got:"got",had:"had",has:"has",have:"have",he:"he",her:"her",hers:"hers",him:"him",his:"his",how:"how",however:"however",i:"i","if":"if","in":"in",into:"into",is:"is",it:"it",its:"its",just:"just",least:"least",let:"let",like:"like",likely:"likely",may:"may",me:"me",might:"might",most:"most",must:"must",my:"my",neither:"neither",no:"no",nor:"nor",not:"not",of:"of",off:"off",often:"often",on:"on",only:"only",or:"or",other:"other",our:"our",own:"own",rather:"rather",said:"said",say:"say",says:"says",she:"she",should:"should",since:"since",so:"so",some:"some",than:"than",that:"that",the:"the",their:"their",them:"them",then:"then",there:"there",these:"these",they:"they","this":"this",tis:"tis",to:"to",too:"too",twas:"twas",us:"us",wants:"wants",was:"was",we:"we",were:"were",what:"what",when:"when",where:"where",which:"which","while":"while",who:"who",whom:"whom",why:"why",will:"will","with":"with",would:"would",yet:"yet",you:"you",your:"your"},t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(t){var e=t.replace(/^\W+/,"").replace(/\W+$/,"");return""===e?void 0:e},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.TokenStore=function(){this.root={docs:{}},this.length=0},t.TokenStore.load=function(t){var e=new this;return e.root=t.root,e.length=t.length,e},t.TokenStore.prototype.add=function(t,e,n){var n=n||this.root,i=t[0],o=t.slice(1);return i in n||(n[i]={docs:{}}),0===o.length?(n[i].docs[e.ref]=e,void(this.length+=1)):this.add(o,e,n[i])},t.TokenStore.prototype.has=function(t){if(!t)return!1;for(var e=this.root,n=0;n's that are truncated 107 | $('a').each(function(i, el) { 108 | if (el.offsetWidth >= el.scrollWidth) return; 109 | if (typeof el.title === 'undefined') return; 110 | el.title = el.text; 111 | }); 112 | 113 | // restore TOC scroll position 114 | var pos = gs.get('tocScrollTop'); 115 | if (typeof pos !== 'undefined') summary.scrollTop(pos); 116 | 117 | // highlight the TOC item that has same text as the heading in view as scrolling 118 | if (toc && toc.scroll_highlight !== false) (function() { 119 | // scroll the current TOC item into viewport 120 | var ht = $(window).height(), rect = li[0].getBoundingClientRect(); 121 | if (rect.top >= ht || rect.top <= 0 || rect.bottom <= 0) { 122 | summary.scrollTop(li[0].offsetTop); 123 | } 124 | // current chapter TOC items 125 | var items = $('a[href^="' + href + '"]').parent('li.chapter'), 126 | m = items.length; 127 | if (m === 0) { 128 | items = summary.find('li.chapter'); 129 | m = items.length; 130 | } 131 | if (m === 0) return; 132 | // all section titles on current page 133 | var hs = bookInner.find('.page-inner').find('h1,h2,h3'), n = hs.length, 134 | ts = hs.map(function(i, el) { return $(el).text(); }); 135 | if (n === 0) return; 136 | var scrollHandler = function(e) { 137 | var ht = $(window).height(); 138 | clearTimeout($.data(this, 'scrollTimer')); 139 | $.data(this, 'scrollTimer', setTimeout(function() { 140 | // find the first visible title in the viewport 141 | for (var i = 0; i < n; i++) { 142 | var rect = hs[i].getBoundingClientRect(); 143 | if (rect.top >= 0 && rect.bottom <= ht) break; 144 | } 145 | if (i === n) return; 146 | items.removeClass('active'); 147 | for (var j = 0; j < m; j++) { 148 | if (items.eq(j).children('a').first().text() === ts[i]) break; 149 | } 150 | if (j === m) j = 0; // highlight the chapter title 151 | // search bottom-up for a visible TOC item to highlight; if an item is 152 | // hidden, we check if its parent is visible, and so on 153 | while (j > 0 && items.eq(j).is(':hidden')) j--; 154 | items.eq(j).addClass('active'); 155 | }, 250)); 156 | }; 157 | bookInner.on('scroll.bookdown', scrollHandler); 158 | bookBody.on('scroll.bookdown', scrollHandler); 159 | })(); 160 | 161 | // do not refresh the page if the TOC item points to the current page 162 | $('a[href="' + href + '"]').parent('li.chapter').children('a') 163 | .on('click', function(e) { 164 | bookInner.scrollTop(0); 165 | bookBody.scrollTop(0); 166 | return false; 167 | }); 168 | 169 | var toolbar = config.toolbar; 170 | if (!toolbar || toolbar.position !== 'static') { 171 | var bookHeader = $('.book-header'); 172 | bookBody.addClass('fixed'); 173 | bookHeader.addClass('fixed') 174 | .css('background-color', bookBody.css('background-color')) 175 | .on('click.bookdown', function(e) { 176 | // the theme may have changed after user clicks the theme button 177 | bookHeader.css('background-color', bookBody.css('background-color')); 178 | }); 179 | } 180 | 181 | }); 182 | 183 | gitbook.events.bind("page.change", function(e) { 184 | // store TOC scroll position 185 | var summary = $('ul.summary'); 186 | gs.set('tocScrollTop', summary.scrollTop()); 187 | }); 188 | 189 | var bookBody = $('.book-body'), bookInner = bookBody.find('.body-inner'); 190 | var chapterTitle = function() { 191 | return bookInner.find('.page-inner').find('h1,h2').first().text(); 192 | }; 193 | var bookTitle = function() { 194 | return bookInner.find('.book-header > h1').first().text(); 195 | }; 196 | var saveScrollPos = function(e) { 197 | // save scroll position before page is reloaded 198 | gs.set('bodyScrollTop', { 199 | body: bookBody.scrollTop(), 200 | inner: bookInner.scrollTop(), 201 | focused: document.hasFocus(), 202 | title: chapterTitle() 203 | }); 204 | }; 205 | $(document).on('servr:reload', saveScrollPos); 206 | 207 | // check if the page is loaded in an iframe (e.g. the RStudio preview window) 208 | var inIFrame = function() { 209 | var inIframe = true; 210 | try { inIframe = window.self !== window.top; } catch (e) {} 211 | return inIframe; 212 | }; 213 | $(window).on('blur unload', function(e) { 214 | if (inIFrame()) saveScrollPos(e); 215 | gs.set('bookTitle', bookTitle()); 216 | }); 217 | 218 | $(function(e) { 219 | if (gs.get('bookTitle', '') !== bookTitle()) localStorage.clear(); 220 | var pos = gs.get('bodyScrollTop'); 221 | if (pos) { 222 | if (pos.title === chapterTitle()) { 223 | if (pos.body !== 0) bookBody.scrollTop(pos.body); 224 | if (pos.inner !== 0) bookInner.scrollTop(pos.inner); 225 | } 226 | if (pos.focused) bookInner.find('.page-wrapper').focus(); 227 | } 228 | // clear book body scroll position 229 | gs.remove('bodyScrollTop'); 230 | }); 231 | 232 | }); 233 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/js/plugin-fontsettings.js: -------------------------------------------------------------------------------- 1 | gitbook.require(["gitbook", "lodash", "jQuery"], function(gitbook, _, $) { 2 | var fontState; 3 | 4 | var THEMES = { 5 | "white": 0, 6 | "sepia": 1, 7 | "night": 2 8 | }; 9 | 10 | var FAMILY = { 11 | "serif": 0, 12 | "sans": 1 13 | }; 14 | 15 | // Save current font settings 16 | function saveFontSettings() { 17 | gitbook.storage.set("fontState", fontState); 18 | update(); 19 | } 20 | 21 | // Increase font size 22 | function enlargeFontSize(e) { 23 | e.preventDefault(); 24 | if (fontState.size >= 4) return; 25 | 26 | fontState.size++; 27 | saveFontSettings(); 28 | }; 29 | 30 | // Decrease font size 31 | function reduceFontSize(e) { 32 | e.preventDefault(); 33 | if (fontState.size <= 0) return; 34 | 35 | fontState.size--; 36 | saveFontSettings(); 37 | }; 38 | 39 | // Change font family 40 | function changeFontFamily(index, e) { 41 | e.preventDefault(); 42 | 43 | fontState.family = index; 44 | saveFontSettings(); 45 | }; 46 | 47 | // Change type of color 48 | function changeColorTheme(index, e) { 49 | e.preventDefault(); 50 | 51 | var $book = $(".book"); 52 | 53 | if (fontState.theme !== 0) 54 | $book.removeClass("color-theme-"+fontState.theme); 55 | 56 | fontState.theme = index; 57 | if (fontState.theme !== 0) 58 | $book.addClass("color-theme-"+fontState.theme); 59 | 60 | saveFontSettings(); 61 | }; 62 | 63 | function update() { 64 | var $book = gitbook.state.$book; 65 | 66 | $(".font-settings .font-family-list li").removeClass("active"); 67 | $(".font-settings .font-family-list li:nth-child("+(fontState.family+1)+")").addClass("active"); 68 | 69 | $book[0].className = $book[0].className.replace(/\bfont-\S+/g, ''); 70 | $book.addClass("font-size-"+fontState.size); 71 | $book.addClass("font-family-"+fontState.family); 72 | 73 | if(fontState.theme !== 0) { 74 | $book[0].className = $book[0].className.replace(/\bcolor-theme-\S+/g, ''); 75 | $book.addClass("color-theme-"+fontState.theme); 76 | } 77 | }; 78 | 79 | function init(config) { 80 | var $bookBody, $book; 81 | 82 | //Find DOM elements. 83 | $book = gitbook.state.$book; 84 | $bookBody = $book.find(".book-body"); 85 | 86 | // Instantiate font state object 87 | fontState = gitbook.storage.get("fontState", { 88 | size: config.size || 2, 89 | family: FAMILY[config.family || "sans"], 90 | theme: THEMES[config.theme || "white"] 91 | }); 92 | 93 | update(); 94 | }; 95 | 96 | 97 | gitbook.events.bind("start", function(e, config) { 98 | var opts = config.fontsettings; 99 | 100 | // Create buttons in toolbar 101 | gitbook.toolbar.createButton({ 102 | icon: 'fa fa-font', 103 | label: 'Font Settings', 104 | className: 'font-settings', 105 | dropdown: [ 106 | [ 107 | { 108 | text: 'A', 109 | className: 'font-reduce', 110 | onClick: reduceFontSize 111 | }, 112 | { 113 | text: 'A', 114 | className: 'font-enlarge', 115 | onClick: enlargeFontSize 116 | } 117 | ], 118 | [ 119 | { 120 | text: 'Serif', 121 | onClick: _.partial(changeFontFamily, 0) 122 | }, 123 | { 124 | text: 'Sans', 125 | onClick: _.partial(changeFontFamily, 1) 126 | } 127 | ], 128 | [ 129 | { 130 | text: 'White', 131 | onClick: _.partial(changeColorTheme, 0) 132 | }, 133 | { 134 | text: 'Sepia', 135 | onClick: _.partial(changeColorTheme, 1) 136 | }, 137 | { 138 | text: 'Night', 139 | onClick: _.partial(changeColorTheme, 2) 140 | } 141 | ] 142 | ] 143 | }); 144 | 145 | 146 | // Init current settings 147 | init(opts); 148 | }); 149 | }); 150 | 151 | 152 | -------------------------------------------------------------------------------- /docs/libs/gitbook-2.6.7/js/plugin-search.js: -------------------------------------------------------------------------------- 1 | gitbook.require(["gitbook", "lodash", "jQuery"], function(gitbook, _, $) { 2 | var index = null; 3 | var $searchInput, $searchLabel, $searchForm; 4 | var $highlighted, hi = 0, hiOpts = { className: 'search-highlight' }; 5 | var collapse = false; 6 | 7 | // Use a specific index 8 | function loadIndex(data) { 9 | // [Yihui] In bookdown, I use a character matrix to store the chapter 10 | // content, and the index is dynamically built on the client side. 11 | // Gitbook prebuilds the index data instead: https://github.com/GitbookIO/plugin-search 12 | // We can certainly do that via R packages V8 and jsonlite, but let's 13 | // see how slow it really is before improving it. On the other hand, 14 | // lunr cannot handle non-English text very well, e.g. the default 15 | // tokenizer cannot deal with Chinese text, so we may want to replace 16 | // lunr with a dumb simple text matching approach. 17 | index = lunr(function () { 18 | this.ref('url'); 19 | this.field('title', { boost: 10 }); 20 | this.field('body'); 21 | }); 22 | data.map(function(item) { 23 | index.add({ 24 | url: item[0], 25 | title: item[1], 26 | body: item[2] 27 | }); 28 | }); 29 | } 30 | 31 | // Fetch the search index 32 | function fetchIndex() { 33 | return $.getJSON(gitbook.state.basePath+"/search_index.json") 34 | .then(loadIndex); // [Yihui] we need to use this object later 35 | } 36 | 37 | // Search for a term and return results 38 | function search(q) { 39 | if (!index) return; 40 | 41 | var results = _.chain(index.search(q)) 42 | .map(function(result) { 43 | var parts = result.ref.split("#"); 44 | return { 45 | path: parts[0], 46 | hash: parts[1] 47 | }; 48 | }) 49 | .value(); 50 | 51 | // [Yihui] Highlight the search keyword on current page 52 | hi = 0; 53 | $highlighted = results.length === 0 ? undefined : $('.page-inner') 54 | .unhighlight(hiOpts).highlight(q, hiOpts).find('span.search-highlight'); 55 | scrollToHighlighted(); 56 | toggleTOC(results.length > 0); 57 | 58 | return results; 59 | } 60 | 61 | // [Yihui] Scroll the chapter body to the i-th highlighted string 62 | function scrollToHighlighted() { 63 | if (!$highlighted) return; 64 | var n = $highlighted.length; 65 | if (n === 0) return; 66 | var $p = $highlighted.eq(hi), p = $p[0], rect = p.getBoundingClientRect(); 67 | if (rect.top < 0 || rect.bottom > $(window).height()) { 68 | ($(window).width() >= 1240 ? $('.body-inner') : $('.book-body')) 69 | .scrollTop(p.offsetTop - 100); 70 | } 71 | $highlighted.css('background-color', ''); 72 | // an orange background color on the current item and removed later 73 | $p.css('background-color', 'orange'); 74 | setTimeout(function() { 75 | $p.css('background-color', ''); 76 | }, 2000); 77 | } 78 | 79 | // [Yihui] Expand/collapse TOC 80 | function toggleTOC(show) { 81 | if (!collapse) return; 82 | var toc_sub = $('ul.summary').children('li[data-level]').children('ul'); 83 | if (show) return toc_sub.show(); 84 | var href = window.location.pathname; 85 | href = href.substr(href.lastIndexOf('/') + 1); 86 | if (href === '') href = 'index.html'; 87 | var li = $('a[href^="' + href + location.hash + '"]').parent('li.chapter').first(); 88 | toc_sub.hide().parent().has(li).children('ul').show(); 89 | li.children('ul').show(); 90 | } 91 | 92 | // Create search form 93 | function createForm(value) { 94 | if ($searchForm) $searchForm.remove(); 95 | if ($searchLabel) $searchLabel.remove(); 96 | if ($searchInput) $searchInput.remove(); 97 | 98 | $searchForm = $('
', { 99 | 'class': 'book-search', 100 | 'role': 'search' 101 | }); 102 | 103 | $searchLabel = $('