├── test ├── test_helper.exs └── gc_nlp_test.exs ├── doc ├── fonts │ ├── icomoon.eot │ ├── icomoon.ttf │ ├── icomoon.woff │ └── icomoon.svg ├── index.html ├── .build ├── dist │ ├── sidebar_items.js │ ├── app-091c05798a.css │ └── app-574613960f.js ├── 404.html ├── api-reference.html ├── readme.html └── GcNLP.html ├── .gitignore ├── lib ├── gc_nlp │ └── application.ex ├── extra.ex └── gc_nlp.ex ├── mix.exs ├── config └── config.exs ├── README.md ├── mix.lock └── CONTRIBUTING.md /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /doc/fonts/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seymores/gc_nlp/HEAD/doc/fonts/icomoon.eot -------------------------------------------------------------------------------- /doc/fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seymores/gc_nlp/HEAD/doc/fonts/icomoon.ttf -------------------------------------------------------------------------------- /doc/fonts/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seymores/gc_nlp/HEAD/doc/fonts/icomoon.woff -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | gc_nlp v0.2.1 – Documentation 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/.build: -------------------------------------------------------------------------------- 1 | /Users/ping/Work/gc_nlp/doc/dist/app-091c05798a.css 2 | /Users/ping/Work/gc_nlp/doc/dist/app-574613960f.js 3 | /Users/ping/Work/gc_nlp/doc/fonts/icomoon.eot 4 | /Users/ping/Work/gc_nlp/doc/fonts/icomoon.svg 5 | /Users/ping/Work/gc_nlp/doc/fonts/icomoon.ttf 6 | /Users/ping/Work/gc_nlp/doc/fonts/icomoon.woff 7 | index.html 8 | api-reference.html 9 | 404.html 10 | dist/sidebar_items.js 11 | GcNLP.html 12 | GcNLP.Extra.html 13 | readme.html 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps 9 | 10 | # Where 3rd-party dependencies like ExDoc output generated docs. 11 | /doc 12 | 13 | # If the VM crashes, it generates a dump, let's ignore it too. 14 | erl_crash.dump 15 | 16 | # Also ignore archive artifacts (built via "mix archive.build"). 17 | *.ez 18 | 19 | *.swp 20 | *-secret.json 21 | -------------------------------------------------------------------------------- /doc/dist/sidebar_items.js: -------------------------------------------------------------------------------- 1 | sidebarNodes={"exceptions":[],"extras":[{"id":"api-reference","title":"API Reference","group":"","headers":[{"id":"Modules","anchor":"modules"}]},{"id":"readme","title":"GcNLP","group":"","headers":[{"id":"Installation","anchor":"installation"},{"id":"Using GcNLP","anchor":"using-gcnlp"}]}],"modules":[{"id":"GcNLP","title":"GcNLP","functions":[{"id":"analyze_entities/1","anchor":"analyze_entities/1"},{"id":"analyze_sentiment/1","anchor":"analyze_sentiment/1"},{"id":"annotate_text/4","anchor":"annotate_text/4"}]},{"id":"GcNLP.Extra","title":"GcNLP.Extra","functions":[{"id":"filter_labels/1","anchor":"filter_labels/1"}]}],"protocols":[]} -------------------------------------------------------------------------------- /lib/gc_nlp/application.ex: -------------------------------------------------------------------------------- 1 | defmodule GcNLP.Application do 2 | use Application 3 | 4 | @moduledoc false 5 | # Application callback to start any needed resources. 6 | 7 | # See http://elixir-lang.org/docs/stable/elixir/Application.html 8 | # for more information on OTP Applications 9 | def start(_type, _args) do 10 | import Supervisor.Spec, warn: false 11 | 12 | # Define workers and child supervisors to be supervised 13 | children = [ 14 | supervisor(Cachex, [GcNLP]) 15 | ] 16 | 17 | # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html 18 | # for other strategies and supported options 19 | opts = [strategy: :one_for_one, name: GcNLP.Supervisor] 20 | Supervisor.start_link(children, opts) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /test/gc_nlp_test.exs: -------------------------------------------------------------------------------- 1 | defmodule GcNLPTest do 2 | use ExUnit.Case 3 | 4 | test "sentiment analysis" do 5 | r = GcNLP.analyze_sentiment "There is a lot of new features coming in Elixir 1.4" 6 | # %{"documentSentiment" => %{"magnitude" => 0.1, "polarity" => 1}, "language" => "en"} 7 | assert Map.has_key?(r, "documentSentiment") 8 | end 9 | 10 | test "request caching" do 11 | # reset cache before test 12 | Cachex.reset!(GcNLP) 13 | 14 | # uncached 15 | {t1, r1} = :timer.tc(fn -> 16 | GcNLP.analyze_sentiment "There is a lot of new features coming in Elixir 1.4" 17 | end) 18 | 19 | # cached 20 | {t2, r2} = :timer.tc(fn -> 21 | GcNLP.analyze_sentiment "There is a lot of new features coming in Elixir 1.4" 22 | end) 23 | 24 | # both results are the same 25 | assert(r1 == r2) 26 | 27 | assert t1 > t2 28 | 29 | # the request is far slower than cached 30 | # assert(t1 > 500000) 31 | # assert(t2 < 100) 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule GcNLP.Mixfile do 2 | use Mix.Project 3 | 4 | def project do 5 | [app: :gc_nlp, 6 | version: "0.2.2", 7 | elixir: "~> 1.3", 8 | build_embedded: Mix.env == :prod, 9 | start_permanent: Mix.env == :prod, 10 | description: "Elixir wrapper for Google Cloud Natural Language API", 11 | package: package(), 12 | docs: [extras: ["README.md"]], 13 | deps: deps()] 14 | end 15 | 16 | defp package do 17 | [ name: :gc_nlp, 18 | files: ["lib", "mix.exs"], 19 | maintainers: ["Teo Choong Ping"], 20 | licenses: ["MIT"], 21 | links: %{"Github" => "https://github.com/seymores/gc_nlp"}, 22 | ] 23 | end 24 | 25 | def application do 26 | [ 27 | applications: [:logger, :cachex, :httpoison, :goth], 28 | mod: {GcNLP.Application, []} 29 | ] 30 | end 31 | 32 | defp deps do 33 | [{:httpoison, "~> 0.11"}, 34 | {:cachex, "~> 2.1"}, 35 | {:goth, "~> 0.3.1"}, 36 | {:ex_doc, "~> 0.15", only: :dev, override: true}, 37 | {:earmark, "~> 1.2.0", only: :dev, override: true}] 38 | end 39 | 40 | end 41 | -------------------------------------------------------------------------------- /config/config.exs: -------------------------------------------------------------------------------- 1 | # This file is responsible for configuring your application 2 | # and its dependencies with the aid of the Mix.Config module. 3 | use Mix.Config 4 | 5 | # This configuration is loaded before any dependency and is restricted 6 | # to this project. If another project depends on this project, this 7 | # file won't be loaded nor affect the parent project. For this reason, 8 | # if you want to provide default values for your application for 9 | # 3rd-party users, it should be done in your "mix.exs" file. 10 | 11 | # You can configure for your application as: 12 | # 13 | # config :gc_nlp, key: :value 14 | # 15 | # And access this configuration in your application as: 16 | # 17 | # Application.get_env(:gc_nlp, :key) 18 | # 19 | # Or configure a 3rd-party app: 20 | # 21 | # config :logger, level: :info 22 | # 23 | 24 | config :gc_nlp, 25 | cache_ttl: :timer.seconds(10), 26 | token_ttl: :timer.minutes(1) 27 | 28 | config :goth, 29 | json: "config/gcloud-secret.json" |> Path.expand |> File.read! 30 | 31 | # It is also possible to import configuration files, relative to this 32 | # directory. For example, you can emulate configuration per environment 33 | # by uncommenting the line below and defining dev.exs, test.exs and such. 34 | # Configuration from the imported file will override the ones defined 35 | # here (which is why it is important to import them last). 36 | # 37 | # import_config "#{Mix.env}.exs" 38 | -------------------------------------------------------------------------------- /lib/extra.ex: -------------------------------------------------------------------------------- 1 | defmodule GcNLP.Extra do 2 | @moduledoc """ 3 | *WARNING* Experimental 4 | Advance NLP goodies here. 5 | """ 6 | 7 | @doc """ 8 | Return the annoated text labels only. 9 | See [doc](https://cloud.google.com/natural-language/reference/rest/v1beta1/documents/annotateText#Label) 10 | 11 | """ 12 | def filter_labels(text) do 13 | result = GcNLP.annotate_text(text, true, false, false) 14 | for t <- result["tokens"] do 15 | dep_edge = t["dependencyEdge"] 16 | label = dep_edge["label"] 17 | pos = t["partOfSpeech"] 18 | tag = pos["tag"] 19 | lemma = t["lemma"] 20 | text = t["text"] 21 | word = text["content"] 22 | %{label: label, tag: tag, word: word, lemma: lemma} 23 | end 24 | end 25 | 26 | # def filter_ 27 | 28 | end 29 | 30 | 31 | # Where do I start with this? 32 | # ["ADVMOD", "AUX", "NSUBJ", "ROOT", "PREP", "POBJ", "P"] 33 | # 34 | # I love fish but why they are always so fishy? 35 | # ["NSUBJ", "ROOT", "DOBJ", "CC", "ADVMOD", "NSUBJ", "CONJ", "ADVMOD", "ADVMOD", "ACOMP", "P"] 36 | # 37 | # This is the best place to be now? 38 | # ["NSUBJ", "ROOT", "DET", "AMOD", "ATTR", "AUX", "VMOD", "ADVMOD", "P"] 39 | # 40 | # How is the food? 41 | # ["ADVMOD", "ROOT", "DET", "NSUBJ", "P"] 42 | # 43 | # This cant be right 44 | # ["NSUBJ", "AUX", "NEG", "ROOT", "ACOMP"] 45 | # 46 | # Best is the thing ever? 47 | # ["NSUBJ", "ROOT", "DET", "ATTR", "ADVMOD", "P"] 48 | # 49 | # This is a big fish. 50 | # ["NSUBJ", "ROOT", "DET", "AMOD", "ATTR", "P"] 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GcNLP 2 | 3 | Elixir wrapper for Google Cloud Natural Language API. See [Cloud Natural Language API](https://cloud.google.com/natural-language/) 4 | 5 | Latest version 0.2.2 [doc.](https://hexdocs.pm/gc_nlp/0.2.2) 6 | 7 | ## Installation 8 | 9 | The package can be installed as: 10 | 11 | 1. Add `gc_nlp` to your list of dependencies in `mix.exs`: 12 | 13 | ```elixir 14 | def deps do 15 | [{:gc_nlp, "~> 0.2.2"}] 16 | end 17 | ``` 18 | 19 | 2. Ensure `gc_nlp` is started before your application: 20 | 21 | ```elixir 22 | def application do 23 | [applications: [:gc_nlp]] 24 | end 25 | ``` 26 | 27 | 3. Put your Google Cloud credential json file in 'config/' or modify the appropriate Goth config. Refer to [this guide to get your credential file.](https://cloud.google.com/natural-language/docs/common/auth) Default to expect "gcloud-secret.json" inside config directory. 28 | 29 | ## Using GcNLP 30 | 31 | 1. Sentiment Analysis 32 | 33 | ```elixir 34 | iex> GcNLP.analyze_sentiment "There is a lot of new features coming in Elixir 1.4" 35 | %{"documentSentiment" => %{"magnitude" => 0.1, "polarity" => 1}, "language" => "en"} 36 | 37 | ``` 38 | 39 | 2. Entity Analysis 40 | 41 | ```elixir 42 | iex> GcNLP.analyze_entities "There is a lot of new features coming in Elixir 1.4" 43 | %{"entities" => [%{"mentions" => [%{"text" => %{"beginOffset" => 41, "content" => "Elixir 1.4"}}], "metadata" => %{}, "name" => "Elixir 1.4", "salience" => 0.16144496, "type" => "OTHER"}], "language" => "en"} 44 | ``` 45 | 46 | 3. Syntactic Analysis 47 | 48 | ```elixir 49 | iex> GcNLP.annotate_text "There is a lot of new features coming in Elixir 1.4" 50 | %{"documentSentiment" => %{"magnitude" => 0.1, "polarity" => 1}, "entities" => [%{"mentions" => [%{"text" => %{"beginOffset" => 41, "content" => "Elixir 1.4"}}], "metadata" => %{}, "name" => "Elixir 1.4", "salience" => 0.16144496, "type" => "OTHER"}], "language" => "en", "sentences" => [%{"text" => %{"beginOffset" => 0, "content" => "There is a lot of new features coming in Elixir 1.4"}}], "tokens" => [%{"dependencyEdge" => %{"headTokenIndex" => 1, "label" => "EXPL"}, "lemma" => "There", "partOfSpeech" => %{"tag" => "DET"}, "text" => %{"beginOffset" => 0, "content" => "There"}}, %{"dependencyEdge" => %{"headTokenIndex" => 1, "label" => "ROOT"}, "lemma" => "be", "partOfSpeech" => %{"tag" => "VERB"}, "text" => %{"beginOffset" => 6, "content" => "is"}}, ...} 51 | ``` 52 | -------------------------------------------------------------------------------- /mix.lock: -------------------------------------------------------------------------------- 1 | %{"cachex": {:hex, :cachex, "2.1.0", "fad49b4e78d11c6c314e75bd8c9408f5b78cb065c047442798caed10803ee3be", [:mix], [{:eternal, "~> 1.1", [hex: :eternal, optional: false]}]}, 2 | "certifi": {:hex, :certifi, "1.2.1", "c3904f192bd5284e5b13f20db3ceac9626e14eeacfbb492e19583cf0e37b22be", [:rebar3], []}, 3 | "deppie": {:hex, :deppie, "1.1.0", "cfb6fcee7dfb64eb78cb8505537971a0805131899326ad469ef10df04520f451", [:mix], []}, 4 | "earmark": {:hex, :earmark, "1.2.2", "f718159d6b65068e8daeef709ccddae5f7fdc770707d82e7d126f584cd925b74", [:mix], []}, 5 | "eternal": {:hex, :eternal, "1.1.4", "3a40fd9b9708f79216a6ec8ae886f2b17685dc26b119b9c0403c2b0d3dc1ac69", [:mix], [{:deppie, "~> 1.1", [hex: :deppie, optional: false]}]}, 6 | "ex_doc": {:hex, :ex_doc, "0.16.1", "b4b8a23602b4ce0e9a5a960a81260d1f7b29635b9652c67e95b0c2f7ccee5e81", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]}, 7 | "goth": {:hex, :goth, "0.3.2", "711a9dfdc5746ea78471aa55f10296441ab876d4754bdf6cadb7c060eaa1c242", [:mix], [{:httpoison, "~> 0.11", [hex: :httpoison, optional: false]}, {:json_web_token, "~> 0.2.5", [hex: :json_web_token, optional: false]}, {:poison, "~> 2.1", [hex: :poison, optional: false]}]}, 8 | "hackney": {:hex, :hackney, "1.8.3", "9148b2311f7d68aff2dc78f2be4da8f05b1a15421b9ef4199ba4935a1d39b3c1", [:rebar3], [{:certifi, "1.2.1", [hex: :certifi, optional: false]}, {:idna, "5.0.1", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]}, 9 | "httpoison": {:hex, :httpoison, "0.11.2", "9e59f17a473ef6948f63c51db07320477bad8ba88cf1df60a3eee01150306665", [:mix], [{:hackney, "~> 1.8.0", [hex: :hackney, optional: false]}]}, 10 | "idna": {:hex, :idna, "5.0.1", "5aa8fdce3f876f49d90daa13f071155a7c3259d02f7847dadd164da4a877da2a", [:rebar3], [{:unicode_util_compat, "0.1.0", [hex: :unicode_util_compat, optional: false]}]}, 11 | "json_web_token": {:hex, :json_web_token, "0.2.7", "b33cd43c578d582b77675870a3a8a0f5617bd6f728413ac4effe41be7e7da51a", [:mix], [{:poison, "~> 2.2", [hex: :poison, optional: false]}]}, 12 | "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [], []}, 13 | "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [], []}, 14 | "poison": {:hex, :poison, "2.2.0", "4763b69a8a77bd77d26f477d196428b741261a761257ff1cf92753a0d4d24a63", [], []}, 15 | "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []}, 16 | "unicode_util_compat": {:hex, :unicode_util_compat, "0.1.0", "f554c539c826eac8bcf101d2dbcc4a798ba8a960a176ca58d0b2f225c265b174", [:rebar3], []}} 17 | -------------------------------------------------------------------------------- /doc/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 404 – gc_nlp v0.2.1 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 22 | 56 | 57 |
58 |
59 |
60 | 61 | 62 |

Page not found

63 | 64 |

Sorry, but the page you were trying to get to, does not exist. You 65 | may want to try searching this site using the sidebar or using our 66 | API Reference page to find what 67 | you were looking for.

68 | 69 | 82 |
83 |
84 |
85 |
86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /doc/api-reference.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | API Reference – gc_nlp v0.2.1 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 22 | 56 | 57 |
58 |
59 |
60 | 61 |

62 | gc_nlp v0.2.1 63 | API Reference 64 |

65 | 66 | 67 |
68 |

Modules

69 |
70 |
71 | 72 | 73 |

Provides wrapper functions for Google Cloud Natural Language API. 74 | See full doc here

75 |
76 | 77 |
78 |
79 | 80 | 81 |

WARNING Experimental 82 | Advance NLP goodies here

83 |
84 | 85 |
86 | 87 |
88 |
89 | 90 | 91 | 92 | 93 | 94 | 107 |
108 |
109 |
110 |
111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /doc/fonts/icomoon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior and are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned to this Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /doc/readme.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | GcNLP – gc_nlp v0.2.1 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 22 | 56 | 57 |
58 |
59 |
60 | 61 | 62 |

GcNLP

63 |

Elixir wrapper for Google Cloud Natural Language API. See Cloud Natural Language API

64 |

Latest version 0.2.0 doc.

65 |

66 | 67 | Installation 68 |

69 | 70 |

The package can be installed as:

71 |
    72 |
  1. Add gc_nlp to your list of dependencies in mix.exs:

    73 |
    def deps do
     74 |   [{:gc_nlp, "~> 0.2.1"}]
     75 | end
    76 |
  2. 77 |
  3. Ensure gc_nlp is started before your application:

    78 |
    def application do
     79 |   [applications: [:gc_nlp]]
     80 | end
    81 |
  4. 82 |
  5. Put your Google Cloud credential json file in ‘config/‘ or modify the appropriate Goth config. Refer to this guide to get your credential file. Default to expect “gcloud-secret.json” inside config directory.

    83 |
  6. 84 |
85 |

86 | 87 | Using GcNLP 88 |

89 | 90 |
    91 |
  1. Sentiment Analysis

    92 |
    iex> GcNLP.analyze_sentiment "There is a lot of new features coming in Elixir 1.4"
     93 | %{"documentSentiment" => %{"magnitude" => 0.1, "polarity" => 1}, "language" => "en"}
     94 | 
    95 |
  2. 96 |
  3. Entity Analysis

    97 |
    iex> GcNLP.analyze_entities "There is a lot of new features coming in Elixir 1.4"
     98 | %{"entities" => [%{"mentions" => [%{"text" => %{"beginOffset" => 41, "content" => "Elixir 1.4"}}], "metadata" => %{}, "name" => "Elixir 1.4", "salience" => 0.16144496, "type" => "OTHER"}], "language" => "en"}
    99 |
  4. 100 |
  5. Syntactic Analysis

    101 |
    iex> GcNLP.annotate_text "There is a lot of new features coming in Elixir 1.4"
    102 | %{"documentSentiment" => %{"magnitude" => 0.1, "polarity" => 1}, "entities" => [%{"mentions" => [%{"text" => %{"beginOffset" => 41, "content" => "Elixir 1.4"}}], "metadata" => %{}, "name" => "Elixir 1.4", "salience" => 0.16144496, "type" => "OTHER"}], "language" => "en", "sentences" => [%{"text" => %{"beginOffset" => 0, "content" => "There is a lot of new features coming in Elixir 1.4"}}], "tokens" => [%{"dependencyEdge" => %{"headTokenIndex" => 1, "label" => "EXPL"}, "lemma" => "There", "partOfSpeech" => %{"tag" => "DET"}, "text" => %{"beginOffset" => 0, "content" => "There"}}, %{"dependencyEdge" => %{"headTokenIndex" => 1, "label" => "ROOT"}, "lemma" => "be", "partOfSpeech" => %{"tag" => "VERB"}, "text" => %{"beginOffset" => 6, "content" => "is"}}, ...}
    103 |
  6. 104 |
105 | 106 | 119 |
120 |
121 |
122 |
123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /lib/gc_nlp.ex: -------------------------------------------------------------------------------- 1 | defmodule GcNLP do 2 | @moduledoc """ 3 | Provides wrapper functions for Google Cloud Natural Language API. 4 | See [full doc here](https://cloud.google.com/natural-language/reference/rest/v1beta1/documents) 5 | """ 6 | require Logger 7 | alias Goth.Token 8 | 9 | @base_url "https://language.googleapis.com/v1beta1/" 10 | @cache_ttl Application.get_env(:gc_nlp, :cache_ttl) 11 | @token_ttl Application.get_env(:gc_nlp, :token_ttl) 12 | @request_opts [connect_timeout: 1000000, recv_timeout: 1000000, timeout: 1000000] 13 | 14 | @doc """ 15 | Finds named entities (currently finds proper names) in the text, entity types, salience, mentions for each entity, and other properties. See [doc](https://cloud.google.com/natural-language/reference/rest/v1beta1/documents/analyzeEntities) 16 | 17 | ## Example 18 | 19 | iex> GcNLP.analyze_sentiment "There is a lot of new features coming in Elixir 1.4" 20 | %{"documentSentiment" => %{"magnitude" => 0.1, "polarity" => 1}, "language" => "en"} 21 | 22 | """ 23 | def analyze_sentiment(text) do 24 | make_request("documents:analyzeSentiment", text) 25 | end 26 | 27 | @doc """ 28 | Finds named entities (currently finds proper names) in the text, entity types, salience, mentions for each entity, and other properties. See [doc](https://cloud.google.com/natural-language/reference/rest/v1beta1/documents/analyzeEntities) 29 | 30 | ## Example 31 | 32 | iex> GcNLP.analyze_entities "There is a lot of new features coming in Elixir 1.4" 33 | %{"entities" => [%{"mentions" => [%{"text" => %{"beginOffset" => 41, "content" => "Elixir 1.4"}}], "metadata" => %{}, "name" => "Elixir 1.4", "salience" => 0.16144496, "type" => "OTHER"}], "language" => "en"} 34 | 35 | """ 36 | def analyze_entities(text) do 37 | make_request("documents:analyzeEntities", text) 38 | end 39 | 40 | @doc """ 41 | Advanced API that analyzes the document and provides a full set of text annotations, including semantic, syntactic, and sentiment information. See [doc](https://cloud.google.com/natural-language/reference/rest/v1beta1/documents/annotateText) 42 | 43 | ## Example 44 | 45 | iex> GcNLP.annotate_text "There is a lot of new features coming in Elixir 1.4" 46 | %{"documentSentiment" => %{"magnitude" => 0.1, "polarity" => 1}, 47 | "entities" => [%{"mentions" => [%{"text" => %{"beginOffset" => 41, 48 | "content" => "Elixir 1.4"}}], "metadata" => %{}, 49 | "name" => "Elixir 1.4", "salience" => 0.16144496, 50 | "type" => "OTHER"}], "language" => "en", 51 | "sentences" => [%{"text" => %{"beginOffset" => 0, 52 | "content" => "There is a lot of new features coming in Elixir 1.4"}}], 53 | "tokens" => [%{"dependencyEdge" => %{"headTokenIndex" => 1, 54 | "label" => "EXPL"}, "lemma" => "There", 55 | "partOfSpeech" => %{"tag" => "DET"}, 56 | "text" => %{"beginOffset" => 0, "content" => "There"}}, 57 | %{"dependencyEdge" => %{"headTokenIndex" => 1, "label" => "ROOT"}, 58 | "lemma" => "be", "partOfSpeech" => %{"tag" => "VERB"}, 59 | "text" => %{"beginOffset" => 6, "content" => "is"}}, 60 | %{"dependencyEdge" => %{"headTokenIndex" => 3, "label" => "DET"}, 61 | "lemma" => "a", "partOfSpeech" => %{"tag" => "DET"}, 62 | "text" => %{"beginOffset" => 9, "content" => "a"}}, 63 | %{"dependencyEdge" => %{"headTokenIndex" => 1, 64 | "label" => "NSUBJ"}, "lemma" => "lot", 65 | "partOfSpeech" => %{"tag" => "NOUN"}, 66 | "text" => %{"beginOffset" => 11, "content" => "lot"}}, 67 | %{"dependencyEdge" => %{"headTokenIndex" => 3, "label" => "PREP"}, 68 | "lemma" => "of", "partOfSpeech" => %{"tag" => "ADP"}, 69 | "text" => %{"beginOffset" => 15, "content" => "of"}}, 70 | %{"dependencyEdge" => %{"headTokenIndex" => 6, "label" => "AMOD"}, 71 | "lemma" => "new", "partOfSpeech" => %{"tag" => "ADJ"}, 72 | "text" => %{"beginOffset" => 18, "content" => "new"}}, 73 | %{"dependencyEdge" => %{"headTokenIndex" => 4, "label" => "POBJ"}, 74 | "lemma" => "feature", "partOfSpeech" => %{"tag" => "NOUN"}, 75 | "text" => %{"beginOffset" => 22, "content" => "features"}}, 76 | %{"dependencyEdge" => %{"headTokenIndex" => 6, "label" => "VMOD"}, 77 | "lemma" => "come", "partOfSpeech" => %{"tag" => "VERB"}, 78 | "text" => %{"beginOffset" => 31, "content" => "coming"}}, 79 | %{"dependencyEdge" => %{"headTokenIndex" => 7, "label" => "PREP"}, 80 | "lemma" => "in", "partOfSpeech" => %{"tag" => "ADP"}, 81 | "text" => %{"beginOffset" => 38, "content" => "in"}}, 82 | %{"dependencyEdge" => %{"headTokenIndex" => 8, "label" => "POBJ"}, 83 | "lemma" => "Elixir", "partOfSpeech" => %{"tag" => "NOUN"}, 84 | "text" => %{"beginOffset" => 41, "content" => "Elixir"}}, 85 | %{"dependencyEdge" => %{"headTokenIndex" => 9, "label" => "NUM"}, 86 | "lemma" => "1.4", "partOfSpeech" => %{"tag" => "NUM"}, 87 | "text" => %{"beginOffset" => 48, "content" => "1.4"}}]} 88 | 89 | iex> GcNLP.annotate_text "Data science is the best name for this industry", false, false, true 90 | %{"documentSentiment" => %{"magnitude" => 0.8, "polarity" => 1}, "entities" => [], "language" => "en", "sentences" => [%{"text" => %{"beginOffset" => 0, "content" => "Data science is the best name for this industry"}}], "tokens" => []} 91 | """ 92 | def annotate_text(text, syntax \\true, entities \\true, sentiment \\true) do 93 | make_request("documents:annotateText", text, [ 94 | features: %{ 95 | "extractSyntax": syntax, 96 | "extractEntities": entities, 97 | "extractDocumentSentiment": sentiment, 98 | } 99 | ]) 100 | end 101 | 102 | defp make_request(type, content, options \\ []) do 103 | content_type = Keyword.get(options, :content_type, "plain_text") 104 | feature_set = Keyword.get(options, :features) 105 | 106 | url = @base_url <> type 107 | 108 | hash_key = get_hash_key(url, content) 109 | 110 | try_cache(hash_key, @cache_ttl, fn(_key) -> 111 | token = get_token() 112 | 113 | headers = %{ 114 | "Authorization" => "Bearer #{token.token}", 115 | "Content-type" => "application/json" 116 | } 117 | 118 | payload = %{ 119 | "document": %{ 120 | "type": content_type, 121 | "content": content 122 | }, 123 | "encodingType": "UTF8" 124 | } 125 | 126 | body = if feature_set != nil do 127 | payload 128 | |> Map.put(:features, feature_set) 129 | |> Poison.encode! 130 | else 131 | Poison.encode!(payload) 132 | end 133 | 134 | Logger.debug(url) 135 | 136 | case HTTPoison.post(url, body, headers, @request_opts) do 137 | {:ok, response} -> {:commit, Poison.decode!(response.body)} 138 | _ -> {:ignore,nil} 139 | end 140 | end) 141 | end 142 | 143 | defp get_hash_key(url, content) do 144 | :md5 145 | |> :crypto.hash_init 146 | |> :crypto.hash_update(url) 147 | |> :crypto.hash_update(content) 148 | |> :crypto.hash_final 149 | end 150 | 151 | defp get_token do 152 | try_cache("gauth_token", @token_ttl, &generate_token/1) 153 | end 154 | 155 | defp generate_token(_key) do 156 | scope = "https://www.googleapis.com/auth/cloud-platform" 157 | case Token.for_scope(scope) do 158 | {:ok, token} -> {:commit, token} 159 | _ -> {:ignore, nil} 160 | end 161 | end 162 | 163 | defp try_cache(key, ttl, action) do 164 | Cachex.execute(GcNLP, fn(state) -> 165 | {status, value} = Cachex.get(state, key, [fallback: action]) 166 | 167 | if status == :loaded do 168 | Cachex.expire!(state, key, ttl) 169 | end 170 | 171 | value 172 | end) 173 | end 174 | 175 | end 176 | -------------------------------------------------------------------------------- /doc/GcNLP.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | GcNLP – gc_nlp v0.2.1 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 22 | 56 | 57 |
58 |
59 |
60 | 61 | 62 |

63 | gc_nlp v0.2.1 64 | GcNLP 65 | 66 | 67 |

68 | 69 | 70 |
71 |

Provides wrapper functions for Google Cloud Natural Language API. 72 | See full doc here

73 | 74 |
75 | 76 | 77 | 78 |
79 |

80 | 81 | 82 | 83 | Summary 84 |

85 | 86 | 87 | 88 |
89 |

90 | Functions 91 |

92 |
93 | 96 | 97 |

Finds named entities (currently finds proper names) in the text, entity types, salience, mentions for each entity, and other properties. See doc

98 |
99 | 100 |
101 |
102 | 105 | 106 |

Finds named entities (currently finds proper names) in the text, entity types, salience, mentions for each entity, and other properties. See doc

107 |
108 | 109 |
110 |
111 | 114 | 115 |

Advanced API that analyzes the document and provides a full set of text annotations, including semantic, syntactic, and sentiment information. See doc

116 |
117 | 118 |
119 | 120 |
121 | 122 | 123 | 124 | 125 | 126 | 127 |
128 | 129 | 130 | 131 | 132 | 133 |
134 |

135 | 136 | 137 | 138 | Functions 139 |

140 |
141 | 142 |
143 | 144 | 145 | 146 | analyze_entities(text) 147 | 148 | 149 | 150 |
151 |
152 |

Finds named entities (currently finds proper names) in the text, entity types, salience, mentions for each entity, and other properties. See doc

153 |

154 | 155 | Example 156 |

157 | 158 |
iex> GcNLP.analyze_entities "There is a lot of new features coming in Elixir 1.4"
159 | %{"entities" => [%{"mentions" => [%{"text" => %{"beginOffset" => 41, "content" => "Elixir 1.4"}}], "metadata" => %{}, "name" => "Elixir 1.4", "salience" => 0.16144496, "type" => "OTHER"}], "language" => "en"}
160 | 161 |
162 |
163 |
164 | 165 |
166 | 167 | 168 | 169 | analyze_sentiment(text) 170 | 171 | 172 | 173 |
174 |
175 |

Finds named entities (currently finds proper names) in the text, entity types, salience, mentions for each entity, and other properties. See doc

176 |

177 | 178 | Example 179 |

180 | 181 |
iex> GcNLP.analyze_sentiment "There is a lot of new features coming in Elixir 1.4"
182 | %{"documentSentiment" => %{"magnitude" => 0.1, "polarity" => 1}, "language" => "en"}
183 | 184 |
185 |
186 |
187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 |
195 | 196 | 197 | 198 | annotate_text(text, syntax \\ true, entities \\ true, sentiment \\ true) 199 | 200 | 201 | 202 |
203 |
204 |

Advanced API that analyzes the document and provides a full set of text annotations, including semantic, syntactic, and sentiment information. See doc

205 |

206 | 207 | Example 208 |

209 | 210 |
iex> GcNLP.annotate_text "There is a lot of new features coming in Elixir 1.4"
211 | %{"documentSentiment" => %{"magnitude" => 0.1, "polarity" => 1},
212 |              "entities" => [%{"mentions" => [%{"text" => %{"beginOffset" => 41,
213 |                      "content" => "Elixir 1.4"}}], "metadata" => %{},
214 |                 "name" => "Elixir 1.4", "salience" => 0.16144496,
215 |                 "type" => "OTHER"}], "language" => "en",
216 |              "sentences" => [%{"text" => %{"beginOffset" => 0,
217 |                   "content" => "There is a lot of new features coming in Elixir 1.4"}}],
218 |              "tokens" => [%{"dependencyEdge" => %{"headTokenIndex" => 1,
219 |                   "label" => "EXPL"}, "lemma" => "There",
220 |                 "partOfSpeech" => %{"tag" => "DET"},
221 |                 "text" => %{"beginOffset" => 0, "content" => "There"}},
222 |               %{"dependencyEdge" => %{"headTokenIndex" => 1, "label" => "ROOT"},
223 |                 "lemma" => "be", "partOfSpeech" => %{"tag" => "VERB"},
224 |                 "text" => %{"beginOffset" => 6, "content" => "is"}},
225 |               %{"dependencyEdge" => %{"headTokenIndex" => 3, "label" => "DET"},
226 |                 "lemma" => "a", "partOfSpeech" => %{"tag" => "DET"},
227 |                 "text" => %{"beginOffset" => 9, "content" => "a"}},
228 |               %{"dependencyEdge" => %{"headTokenIndex" => 1,
229 |                   "label" => "NSUBJ"}, "lemma" => "lot",
230 |                 "partOfSpeech" => %{"tag" => "NOUN"},
231 |                 "text" => %{"beginOffset" => 11, "content" => "lot"}},
232 |               %{"dependencyEdge" => %{"headTokenIndex" => 3, "label" => "PREP"},
233 |                 "lemma" => "of", "partOfSpeech" => %{"tag" => "ADP"},
234 |                 "text" => %{"beginOffset" => 15, "content" => "of"}},
235 |               %{"dependencyEdge" => %{"headTokenIndex" => 6, "label" => "AMOD"},
236 |                 "lemma" => "new", "partOfSpeech" => %{"tag" => "ADJ"},
237 |                 "text" => %{"beginOffset" => 18, "content" => "new"}},
238 |               %{"dependencyEdge" => %{"headTokenIndex" => 4, "label" => "POBJ"},
239 |                 "lemma" => "feature", "partOfSpeech" => %{"tag" => "NOUN"},
240 |                 "text" => %{"beginOffset" => 22, "content" => "features"}},
241 |               %{"dependencyEdge" => %{"headTokenIndex" => 6, "label" => "VMOD"},
242 |                 "lemma" => "come", "partOfSpeech" => %{"tag" => "VERB"},
243 |                 "text" => %{"beginOffset" => 31, "content" => "coming"}},
244 |               %{"dependencyEdge" => %{"headTokenIndex" => 7, "label" => "PREP"},
245 |                 "lemma" => "in", "partOfSpeech" => %{"tag" => "ADP"},
246 |                 "text" => %{"beginOffset" => 38, "content" => "in"}},
247 |               %{"dependencyEdge" => %{"headTokenIndex" => 8, "label" => "POBJ"},
248 |                 "lemma" => "Elixir", "partOfSpeech" => %{"tag" => "NOUN"},
249 |                 "text" => %{"beginOffset" => 41, "content" => "Elixir"}},
250 |               %{"dependencyEdge" => %{"headTokenIndex" => 9, "label" => "NUM"},
251 |                 "lemma" => "1.4", "partOfSpeech" => %{"tag" => "NUM"},
252 |                 "text" => %{"beginOffset" => 48, "content" => "1.4"}}]}
253 | 
254 | iex> GcNLP.annotate_text "Data science is the best name for this industry", false, false, true
255 | %{"documentSentiment" => %{"magnitude" => 0.8, "polarity" => 1}, "entities" => [], "language" => "en", "sentences" => [%{"text" => %{"beginOffset" => 0, "content" => "Data science is the best name for this industry"}}], "tokens" => []}
256 | 257 |
258 |
259 | 260 |
261 | 262 | 263 | 264 | 265 | 266 | 279 |
280 |
281 |
282 |
283 | 284 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /doc/dist/app-091c05798a.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Lato:300,700|Merriweather:300italic,300|Inconsolata:400,700);.hljs,article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}img,legend{border:0}.results ul,.sidebar ul{list-style:none}.night-mode-toggle:focus,.sidebar .sidebar-search .sidebar-searchInput:focus,.sidebar .sidebar-search .sidebar-searchInput:hover,.sidebar-toggle:active,.sidebar-toggle:focus,.sidebar-toggle:hover,a:active,a:hover{outline:0}.hljs-comment{color:#8e908c}.css .hljs-class,.css .hljs-id,.css .hljs-pseudo,.hljs-attribute,.hljs-regexp,.hljs-tag,.hljs-variable,.html .hljs-doctype,.ruby .hljs-constant,.xml .hljs-doctype,.xml .hljs-pi,.xml .hljs-tag .hljs-title{color:#c82829}.hljs-built_in,.hljs-constant,.hljs-literal,.hljs-number,.hljs-params,.hljs-pragma,.hljs-preprocessor{color:#f5871f}.css .hljs-rule .hljs-attribute,.ruby .hljs-class .hljs-title{color:#eab700}.hljs-header,.hljs-inheritance,.hljs-name,.hljs-string,.hljs-value,.ruby .hljs-symbol,.xml .hljs-cdata{color:#718c00}.css .hljs-hexcolor,.hljs-title{color:#3e999f}.coffeescript .hljs-title,.hljs-function,.javascript .hljs-title,.perl .hljs-sub,.python .hljs-decorator,.python .hljs-title,.ruby .hljs-function .hljs-title,.ruby .hljs-title .hljs-keyword{color:#4271ae}.hljs-keyword,.javascript .hljs-function{color:#8959a8}.hljs{overflow-x:auto;background:#fff;color:#4d4d4c;padding:.5em;-webkit-text-size-adjust:none}legend,td,th{padding:0}.coffeescript .javascript,.javascript .xml,.tex .hljs-formula,.xml .css,.xml .hljs-cdata,.xml .javascript,.xml .vbscript{opacity:.5}/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}abbr[title]{border-bottom:1px dotted}b,optgroup,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}.content-outer,body{background-color:#fff}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre,textarea{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}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}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}table{border-collapse:collapse;border-spacing:0}@font-face{font-family:icomoon;src:url(../fonts/icomoon.eot?h5z89e);src:url(../fonts/icomoon.eot?#iefixh5z89e) format('embedded-opentype'),url(../fonts/icomoon.ttf?h5z89e) format('truetype'),url(../fonts/icomoon.woff?h5z89e) format('woff'),url(../fonts/icomoon.svg?h5z89e#icomoon) format('svg');font-weight:400;font-style:normal}.icon-elem,[class*=" icon-"],[class^=icon-]{font-family:icomoon;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.sidebar,body{font-family:Lato,sans-serif}.icon-link:before{content:"\e005"}.icon-search:before{content:"\e036"}.icon-cross:before{content:"\e117"}@media screen and (max-width:768px){.icon-menu{font-size:1em}}@media screen and (min-width:769px){.icon-menu{font-size:1.25em}}@media screen and (min-width:1281px){.icon-menu{font-size:1.5em}}.icon-menu:before{content:"\e120"}.icon-angle-right:before{content:"\f105"}.icon-code:before{content:"\f121"}body,html{box-sizing:border-box;height:100%;width:100%}body{margin:0;font-size:16px;line-height:1.6875em}*,:after,:before{box-sizing:inherit}.main{display:-webkit-flex;display:-ms-flexbox;display:-ms-flex;display:flex;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.sidebar{display:-webkit-flex;display:-ms-flexbox;display:-ms-flex;display:flex;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-box-direction:normal;-moz-box-direction:normal;min-height:0;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:300px;height:100%;position:fixed;top:0;left:0;z-index:4}.content{width:100%;padding-left:300px;overflow-y:auto;-webkit-overflow-scrolling:touch;height:100%;position:relative;z-index:3}@media screen and (max-width:768px){body .content{z-index:0;padding-left:0}body .sidebar{z-index:3;-webkit-transform:translateX(-102%);transform:translateX(-102%);will-change:transform}}body.sidebar-closed .sidebar,body.sidebar-closing .sidebar,body.sidebar-opening .sidebar{z-index:0}body.sidebar-opened .sidebar-toggle,body.sidebar-opening .sidebar-toggle{-webkit-transform:translateX(250px);transform:translateX(250px)}@media screen and (max-width:768px){body.sidebar-opened .sidebar,body.sidebar-opening .sidebar{-webkit-transform:translateX(0);transform:translateX(0)}}body.sidebar-closed .content,body.sidebar-closing .content{padding-left:0}body.sidebar-closed .sidebar-toggle,body.sidebar-closing .sidebar-toggle{-webkit-transform:none;transform:none}body.sidebar-closed .icon-menu{color:#000}.sidebar-toggle i,.sidebar-toggle:hover{color:#e1e1e1}body.sidebar-opening .sidebar-toggle{transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out}body.sidebar-opening .content{padding-left:300px;transition:padding-left .3s ease-in-out}@media screen and (max-width:768px){body.sidebar-opening .content{padding-left:0}body.sidebar-opening .sidebar{transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out;z-index:3}}body.sidebar-closing .sidebar-toggle{transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out}body.sidebar-closing .content{transition:padding-left .3s ease-in-out}@media screen and (max-width:768px){body.sidebar-closing .sidebar{z-index:3;transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out;-webkit-transform:translateX(-102%);transform:translateX(-102%)}}.sidebar a,.sidebar-toggle{transition:color .3s ease-in-out}body.sidebar-closed .sidebar{visibility:hidden}.content-inner{max-width:949px;margin:0 auto;padding:3px 60px}.content-outer{min-height:100%}@media screen and (max-width:768px){.content-inner{padding:27px 20px 27px 40px}}.sidebar-toggle{position:fixed;z-index:99;left:18px;top:8px;background-color:transparent;border:none;padding:0;font-size:16px;will-change:transform;-webkit-transform:translateX(250px);transform:translateX(250px)}@media screen and (max-width:768px){.sidebar-toggle{-webkit-transform:translateX(0);transform:translateX(0);left:5px;top:5px}.sidebar-opened .sidebar-toggle{left:18px;top:5px}}.sidebar{font-size:15px;line-height:18px;background:#373f52;color:#d5dae6;overflow:hidden}.sidebar .gradient{background:linear-gradient(#373f52,rgba(55,63,82,0));height:20px;margin-top:-20px;pointer-events:none;position:relative;top:20px;z-index:100}.sidebar ul li{margin:0;padding:0 10px}.sidebar a{color:#d5dae6;text-decoration:none}.sidebar a:hover{color:#fff}.sidebar .sidebar-projectLink{margin:23px 30px 0}.sidebar .sidebar-projectDetails{display:inline-block;text-align:right;vertical-align:top;margin-top:6px}.sidebar .sidebar-projectImage{display:inline-block;max-width:64px;max-height:64px;margin-left:15px;vertical-align:bottom}.sidebar .sidebar-projectName{font-weight:700;font-size:24px;line-height:30px;color:#fff;margin:0;padding:0;max-width:155px}.sidebar .sidebar-projectVersion{margin:0;padding:0;font-weight:300;font-size:16px;line-height:20px;color:#fff}.sidebar .sidebar-listNav{padding:10px 30px 20px;margin:0}.sidebar .sidebar-listNav li,.sidebar .sidebar-listNav li a{text-transform:uppercase;font-weight:300;font-size:14px}.sidebar .sidebar-listNav li{padding-left:17px;border-left:3px solid transparent;transition:all .3s linear;line-height:27px}.sidebar .sidebar-listNav li.selected,.sidebar .sidebar-listNav li.selected a,.sidebar .sidebar-listNav li:hover,.sidebar .sidebar-listNav li:hover a{border-color:#9768d1;color:#fff}.sidebar .sidebar-search{margin:23px 30px 18px;display:-webkit-flex;display:-ms-flexbox;display:-ms-flex;display:flex}.sidebar .sidebar-search i.icon-search{font-size:14px;color:#d5dae6}.sidebar .sidebar-search .sidebar-searchInput{background-color:transparent;border:none;border-radius:0;border-bottom:1px solid #959595;margin-left:5px;height:20px}.sidebar #full-list{margin:0 0 0 30px;padding:10px 20px 40px;overflow-y:auto;-webkit-overflow-scrolling:touch;-webkit-flex:1 1 .01%;-moz-flex:1 1 .01%;-ms-flex:1 1 .01%;flex:1 1 .01%;-ms-flex-positive:1;-ms-flex-negative:1;-ms-flex-preferred-size:.01%}.sidebar #full-list ul{display:none;margin:9px 15px;padding:0}.sidebar #full-list ul li{font-weight:300;line-height:18px;padding:2px 10px}.sidebar #full-list ul li a.expand:before{content:"+";font-family:monospaced;font-size:15px;float:left;width:13px;margin-left:-13px}.sidebar #full-list ul li.open a.expand:before{content:"−"}.sidebar #full-list ul li ul{display:none;margin:9px 6px}.sidebar #full-list li.open>ul,.sidebar #full-list ul li.open>ul{display:block}.sidebar #full-list ul li ul li{border-left:1px solid #959595;padding:0 10px}.sidebar #full-list ul li ul li.active:before{font-family:icomoon;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:"\f105";margin-left:-10px;font-size:16px;margin-right:5px}.sidebar #full-list li{padding:0;line-height:27px}.sidebar #full-list li.active{border-left:none}.sidebar #full-list li.active>a,.sidebar #full-list li.clicked>a{color:#fff}.sidebar #full-list li.group{text-transform:uppercase;font-weight:700;font-size:.8em;margin:2em 0 0;line-height:1.8em;color:#ddd}@media screen and (max-height:500px){.sidebar{overflow-y:auto}.sidebar #full-list{overflow:visible}}.content-inner{font-family:Merriweather,serif;font-size:1em;line-height:1.6875em}.content-inner h1,.content-inner h2,.content-inner h3,.content-inner h4,.content-inner h5,.content-inner h6{font-family:Lato,sans-serif;font-weight:700;line-height:1.5em;word-wrap:break-word}.content-inner h1{font-size:2em;margin:1em 0 .5em}.content-inner h1.section-heading{margin:1.5em 0 .5em}.content-inner h1 small{font-weight:300}.content-inner h1 a.view-source{font-size:1.2rem}.content-inner h2{font-size:1.6em;margin:1em 0 .5em;font-weight:700}.content-inner h3{font-size:1.375em;margin:1em 0 .5em;font-weight:700}.content-inner a{color:#000;text-decoration:none;text-shadow:.03em 0 #fff,-.03em 0 #fff,0 .03em #fff,0 -.03em #fff,.06em 0 #fff,-.06em 0 #fff,.09em 0 #fff,-.09em 0 #fff,.12em 0 #fff,-.12em 0 #fff,.15em 0 #fff,-.15em 0 #fff;background-image:linear-gradient(#fff,#fff),linear-gradient(#fff,#fff),linear-gradient(#000,#000);background-size:.05em 1px,.05em 1px,1px 1px;background-repeat:no-repeat,no-repeat,repeat-x;background-position:0 90%,100% 90%,0 90%}.content-inner a:selection{text-shadow:.03em 0 #b4d5fe,-.03em 0 #b4d5fe,0 .03em #b4d5fe,0 -.03em #b4d5fe,.06em 0 #b4d5fe,-.06em 0 #b4d5fe,.09em 0 #b4d5fe,-.09em 0 #b4d5fe,.12em 0 #b4d5fe,-.12em 0 #b4d5fe,.15em 0 #b4d5fe,-.15em 0 #b4d5fe;background:#b4d5fe}.content-inner a:-moz-selection{text-shadow:.03em 0 #b4d5fe,-.03em 0 #b4d5fe,0 .03em #b4d5fe,0 -.03em #b4d5fe,.06em 0 #b4d5fe,-.06em 0 #b4d5fe,.09em 0 #b4d5fe,-.09em 0 #b4d5fe,.12em 0 #b4d5fe,-.12em 0 #b4d5fe,.15em 0 #b4d5fe,-.15em 0 #b4d5fe;background:#b4d5fe}.content-inner a *,.content-inner a :after,.content-inner a :before,.content-inner a:after,.content-inner a:before{text-shadow:none}.content-inner a:visited{color:#000}.content-inner ul li{line-height:1.5em}.content-inner ul li>p{margin:0}.content-inner a.view-source{float:right;color:#959595;background:0 0;border:none;text-shadow:none;transition:color .3s ease-in-out;margin-top:1px}.content-inner a.view-source:hover{color:#373f52}.content-inner .note{color:#959595;margin:0 5px;font-size:14px;font-weight:400}.content-inner blockquote{font-style:italic;margin:.5em 0;padding:.25em 1.5em;border-left:3px solid #e1e1e1;display:inline-block}.content-inner blockquote :first-child{padding-top:0;margin-top:0}.content-inner blockquote :last-child{padding-bottom:0;margin-bottom:0}.content-inner table{margin:2em 0}.content-inner th{text-align:left;font-family:Lato,sans-serif;text-transform:uppercase;font-weight:700;padding-bottom:.5em}.content-inner tr{border-bottom:1px solid #d5dae6;vertical-align:bottom;height:2.5em}.content-inner .summary .summary-row .summary-signature a,.content-inner .summary h2 a{background:0 0;border:none;text-shadow:none}.content-inner td,.content-inner th{padding-left:1em;line-height:2em}.content-inner .section-heading:hover a.hover-link{opacity:1;text-decoration:none}.content-inner .section-heading a.hover-link{transition:opacity .3s ease-in-out;display:inline-block;opacity:0;padding:.3em .6em .6em;line-height:1em;margin-left:-2.7em;background:0 0;border:none;text-shadow:none;font-size:16px;vertical-align:middle}.content-inner .detail h2.section-heading{margin:1.5em 0 .5em .3em}.content-inner .visible-xs{display:none!important}@media screen and (max-width:767px){.content-inner .visible-xs{display:block!important}}.content-inner img{max-width:100%}.content-inner .summary h2{font-weight:700}.content-inner .summary .summary-row .summary-signature{font-family:Inconsolata,Menlo,Courier,monospace;font-weight:700}.content-inner .summary .summary-row .summary-synopsis{font-family:Merriweather,serif;font-style:italic;padding:0 1.2em;margin:0 0 .5em}.content-inner .summary .summary-row .summary-synopsis p{margin:0;padding:0}.content-inner .detail-header{margin:1.5em 0 1em;padding:.5em 1em;background:#f7f7f7;border-left:3px solid #9768d1;font-size:1em;font-family:Inconsolata,Menlo,Courier,monospace;position:relative}.content-inner .detail-header .note{float:right}.content-inner .detail-header .signature{font-size:1rem;font-weight:700}.content-inner .detail-header:hover a.detail-link{opacity:1;text-decoration:none}.content-inner .detail-header a.detail-link{transition:opacity .3s ease-in-out;position:absolute;top:0;left:0;display:block;opacity:0;padding:.6em;line-height:1.5em;margin-left:-2.5em;background:0 0;border:none;text-shadow:none}.content-inner .footer .line,.search-results h1{display:inline-block}.content-inner .specs pre,.content-inner code{font-family:Inconsolata,Menlo,Courier,monospace;font-style:normal;line-height:24px}.content-inner .specs{opacity:.7;padding-bottom:.05em}.content-inner .specs pre{font-size:.9em;margin:0;padding:0}.content-inner .docstring{margin:1.2em 0 2.1em 1.2em}.content-inner .docstring h2,.content-inner .docstring h3,.content-inner .docstring h4,.content-inner .docstring h5{font-weight:700}.content-inner .docstring h2{font-size:1em}.content-inner .docstring h3{font-size:.95em}.content-inner .docstring h4{font-size:.9em}.content-inner .docstring h5{font-size:.85em}.content-inner a.no-underline,.content-inner pre a{color:#9768d1;text-shadow:none;text-decoration:none;background-image:none}.content-inner a.no-underline:active,.content-inner a.no-underline:focus,.content-inner a.no-underline:hover,.content-inner a.no-underline:visited,.content-inner pre a:active,.content-inner pre a:focus,.content-inner pre a:hover,.content-inner pre a:visited{color:#9768d1;text-decoration:none}.content-inner code{font-weight:400;background-color:#f7f9fc;border:1px solid #e1e1e1;vertical-align:baseline;border-radius:2px;padding:0 .5em}.content-inner pre{margin:1.5em 0}.content-inner pre.spec{margin:0}.content-inner pre.spec code{padding:0}.content-inner pre code.hljs{white-space:inherit;padding:.5em 1em;background-color:#f7f9fc}.content-inner .footer{margin:4em auto 1em;text-align:center;font-style:italic;font-size:14px;color:#959595}.content-inner .footer a{color:#959595;text-decoration:none;text-shadow:.03em 0 #fff,-.03em 0 #fff,0 .03em #fff,0 -.03em #fff,.06em 0 #fff,-.06em 0 #fff,.09em 0 #fff,-.09em 0 #fff,.12em 0 #fff,-.12em 0 #fff,.15em 0 #fff,-.15em 0 #fff;background-image:linear-gradient(#fff,#fff),linear-gradient(#fff,#fff),linear-gradient(#959595,#959595);background-size:.05em 1px,.05em 1px,1px 1px;background-repeat:no-repeat,no-repeat,repeat-x;background-position:0 90%,100% 90%,0 90%}.content-inner .footer a:selection{text-shadow:.03em 0 #b4d5fe,-.03em 0 #b4d5fe,0 .03em #b4d5fe,0 -.03em #b4d5fe,.06em 0 #b4d5fe,-.06em 0 #b4d5fe,.09em 0 #b4d5fe,-.09em 0 #b4d5fe,.12em 0 #b4d5fe,-.12em 0 #b4d5fe,.15em 0 #b4d5fe,-.15em 0 #b4d5fe;background:#b4d5fe}.content-inner .footer a:-moz-selection{text-shadow:.03em 0 #b4d5fe,-.03em 0 #b4d5fe,0 .03em #b4d5fe,0 -.03em #b4d5fe,.06em 0 #b4d5fe,-.06em 0 #b4d5fe,.09em 0 #b4d5fe,-.09em 0 #b4d5fe,.12em 0 #b4d5fe,-.12em 0 #b4d5fe,.15em 0 #b4d5fe,-.15em 0 #b4d5fe;background:#b4d5fe}.results .result-id a,.search-results a.close-search{background-image:none;transition:color .3s ease-in-out;text-shadow:none}.content-inner .footer a *,.content-inner .footer a :after,.content-inner .footer a :before,.content-inner .footer a:after,.content-inner .footer a:before{text-shadow:none}.content-inner .footer a:visited{color:#959595}.search-results a.close-search{display:inline-block;float:right}.search-results a.close-search:active,.search-results a.close-search:focus,.search-results a.close-search:visited{color:#000}.search-results a.close-search:hover{color:#9768d1}.results .result-id{font-size:1.2em}.results .result-id a:active,.results .result-id a:focus,.results .result-id a:visited{color:#000}.results .result-id a:hover{color:#9768d1}.results .result-elem em,.results .result-id em{font-style:normal;color:#9768d1}.results ul{margin:0;padding:0}.night-mode-toggle{background:0 0;border:none}.night-mode-toggle:after{font-size:12px;content:'Switch to night mode';text-decoration:underline}body.night-mode{background:#212127}body.night-mode .hljs-comment{color:#969896}body.night-mode .css .hljs-class,body.night-mode .css .hljs-id,body.night-mode .css .hljs-pseudo,body.night-mode .hljs-attribute,body.night-mode .hljs-regexp,body.night-mode .hljs-tag,body.night-mode .hljs-variable,body.night-mode .html .hljs-doctype,body.night-mode .ruby .hljs-constant,body.night-mode .xml .hljs-doctype,body.night-mode .xml .hljs-pi,body.night-mode .xml .hljs-tag .hljs-title{color:#c66}body.night-mode .hljs-built_in,body.night-mode .hljs-constant,body.night-mode .hljs-literal,body.night-mode .hljs-number,body.night-mode .hljs-params,body.night-mode .hljs-pragma,body.night-mode .hljs-preprocessor{color:#de935f}body.night-mode .css .hljs-rule .hljs-attribute,body.night-mode .ruby .hljs-class .hljs-title{color:#f0c674}body.night-mode .hljs-header,body.night-mode .hljs-inheritance,body.night-mode .hljs-name,body.night-mode .hljs-string,body.night-mode .hljs-value,body.night-mode .ruby .hljs-symbol,body.night-mode .xml .hljs-cdata{color:#b5bd68}body.night-mode .css .hljs-hexcolor,body.night-mode .hljs-title{color:#8abeb7}body.night-mode .coffeescript .hljs-title,body.night-mode .hljs-function,body.night-mode .javascript .hljs-title,body.night-mode .perl .hljs-sub,body.night-mode .python .hljs-decorator,body.night-mode .python .hljs-title,body.night-mode .ruby .hljs-function .hljs-title,body.night-mode .ruby .hljs-title .hljs-keyword{color:#81a2be}body.night-mode .hljs-keyword,body.night-mode .javascript .hljs-function{color:#b294bb}body.night-mode .hljs{display:block;overflow-x:auto;background:#1d1f21;color:#c5c8c6;padding:.5em;-webkit-text-size-adjust:none}body.night-mode .coffeescript .javascript,body.night-mode .javascript .xml,body.night-mode .tex .hljs-formula,body.night-mode .xml .css,body.night-mode .xml .hljs-cdata,body.night-mode .xml .javascript,body.night-mode .xml .vbscript{opacity:.5}body.night-mode .content-outer{background:#212127}body.night-mode .night-mode-toggle:after{color:#959595;content:'Switch to day mode';text-decoration:underline}body.night-mode .close-search:active,body.night-mode .close-search:focus,body.night-mode .close-search:visited,body.night-mode .results .result-id a:active,body.night-mode .results .result-id a:focus,body.night-mode .results .result-id a:visited{color:#d2d2d2}body.night-mode .close-search:hover,body.night-mode .results .result-id a:hover{color:#9768d1}body.night-mode .content-inner{color:#b4b4b4}body.night-mode .content-inner h1,body.night-mode .content-inner h2,body.night-mode .content-inner h3,body.night-mode .content-inner h4,body.night-mode .content-inner h5,body.night-mode .content-inner h6{color:#d2d2d2}body.night-mode .content-inner a{color:#d2d2d2;text-decoration:none;text-shadow:none;background-image:none}body.night-mode .content-inner .detail-header{background:#3a4152;color:#d2d2d2}body.night-mode .content-inner code,body.night-mode .content-inner pre code.hljs{background-color:#2c2c31;border:1px solid #38383d}body.night-mode .content-inner .footer{color:#959595}body.night-mode .content-inner .footer .line{display:inline-block}body.night-mode .content-inner .footer a{color:#959595;text-shadow:none;background-image:none;text-decoration:underline}.night-mode .sidebar-toggle i{color:#d5dae6}@media print{#sidebar{display:none}} -------------------------------------------------------------------------------- /doc/dist/app-574613960f.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),r=e[t[0]];return function(e,t,i){r.apply(this,[e,t,i].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){"use strict";var r=n(1)["default"],i=n(2),a=r(i),o=n(3),s=r(o),l=n(4),u=n(95),c=n(96);window.$=a["default"],a["default"](function(){s["default"].configure({tabReplace:" ",languages:[]}),c.initialize(),u.initialize(),l.initialize(),s["default"].initHighlighting()})},function(e,t){"use strict";t["default"]=function(e){return e&&e.__esModule?e:{"default":e}},t.__esModule=!0},function(e,t,n){var r,i;!function(t,n){"object"==typeof e&&"object"==typeof e.exports?e.exports=t.document?n(t,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return n(e)}:n(t)}("undefined"!=typeof window?window:this,function(n,a){function o(e){var t="length"in e&&e.length,n=re.type(e);return"function"===n||re.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e}function s(e,t,n){if(re.isFunction(t))return re.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return re.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(fe.test(t))return re.filter(t,e,n);t=re.filter(t,e)}return re.grep(e,function(e){return V.call(t,e)>=0!==n})}function l(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}function u(e){var t=ye[e]={};return re.each(e.match(ve)||[],function(e,n){t[n]=!0}),t}function c(){te.removeEventListener("DOMContentLoaded",c,!1),n.removeEventListener("load",c,!1),re.ready()}function f(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=re.expando+f.uid++}function d(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Ne,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:Ee.test(n)?re.parseJSON(n):n}catch(i){}we.set(e,t,n)}else n=void 0;return n}function p(){return!0}function h(){return!1}function g(){try{return te.activeElement}catch(e){}}function m(e,t){return re.nodeName(e,"table")&&re.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function v(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function y(e){var t=Be.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function b(e,t){for(var n=0,r=e.length;r>n;n++)_e.set(e[n],"globalEval",!t||_e.get(t[n],"globalEval"))}function x(e,t){var n,r,i,a,o,s,l,u;if(1===t.nodeType){if(_e.hasData(e)&&(a=_e.access(e),o=_e.set(t,a),u=a.events)){delete o.handle,o.events={};for(i in u)for(n=0,r=u[i].length;r>n;n++)re.event.add(t,i,u[i][n])}we.hasData(e)&&(s=we.access(e),l=re.extend({},s),we.set(t,l))}}function _(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return void 0===t||t&&re.nodeName(e,t)?re.merge([e],n):n}function w(e,t){var n=t.nodeName.toLowerCase();"input"===n&&Se.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}function E(e,t){var r,i=re(t.createElement(e)).appendTo(t.body),a=n.getDefaultComputedStyle&&(r=n.getDefaultComputedStyle(i[0]))?r.display:re.css(i[0],"display");return i.detach(),a}function N(e){var t=te,n=We[e];return n||(n=E(e,t),"none"!==n&&n||(ze=(ze||re("